1#!/usr/bin/env bash
2#
3# Launch one or more Elasticsearch nodes via the Docker image,
4# to form a cluster suitable for running the REST API tests.
5#
6# Export the STACK_VERSION variable, eg. '8.0.0-SNAPSHOT'.
7# Export the TEST_SUITE variable, eg. 'free' or 'platinum' defaults to 'free'.
8# Export the NUMBER_OF_NODES variable to start more than 1 node
9
10# Version 1.3.0
11# - Initial version of the run-elasticsearch.sh script
12# - Deleting the volume should not dependent on the container still running
13# - Fixed `ES_JAVA_OPTS` config
14# - Moved to STACK_VERSION and TEST_VERSION
15# - Refactored into functions and imports
16# - Support NUMBER_OF_NODES
17# - Added 5 retries on docker pull for fixing transient network errors
18# - Added flags to make local CCR configurations work
19# - Added action.destructive_requires_name=false as the default will be true in v8
20
21script_path=$(dirname $(realpath -s $0))
22source $script_path/functions/imports.sh
23set -euo pipefail
24
25echo -e "\033[34;1mINFO:\033[0m Take down node if called twice with the same arguments (DETACH=true) or on seperate terminals \033[0m"
26cleanup_node $es_node_name
27
28master_node_name=${es_node_name}
29cluster_name=${moniker}${suffix}
30
31declare -a volumes
32environment=($(cat <<-END
33  --env node.name=$es_node_name
34  --env cluster.name=$cluster_name
35  --env cluster.initial_master_nodes=$master_node_name
36  --env discovery.seed_hosts=$master_node_name
37  --env cluster.routing.allocation.disk.threshold_enabled=false
38  --env bootstrap.memory_lock=true
39  --env node.attr.testattr=test
40  --env path.repo=/tmp
41  --env repositories.url.allowed_urls=http://snapshot.test*
42  --env ingest.geoip.downloader.enabled=false
43  --env action.destructive_requires_name=false
44  --env ELASTIC_PASSWORD=$elastic_password
45  --env xpack.license.self_generated.type=trial
46  --env xpack.security.enabled=true
47  --env xpack.security.http.ssl.enabled=true
48  --env xpack.security.http.ssl.verification_mode=certificate
49  --env xpack.security.http.ssl.key=certs/testnode.key
50  --env xpack.security.http.ssl.certificate=certs/testnode.crt
51  --env xpack.security.http.ssl.certificate_authorities=certs/ca.crt
52  --env xpack.security.transport.ssl.enabled=true
53  --env xpack.security.transport.ssl.verification_mode=certificate
54  --env xpack.security.transport.ssl.key=certs/testnode.key
55  --env xpack.security.transport.ssl.certificate=certs/testnode.crt
56  --env xpack.security.transport.ssl.certificate_authorities=certs/ca.crt
57END
58))
59volumes+=($(cat <<-END
60  --volume $ssl_cert:/usr/share/elasticsearch/config/certs/testnode.crt
61  --volume $ssl_key:/usr/share/elasticsearch/config/certs/testnode.key
62  --volume $ssl_ca:/usr/share/elasticsearch/config/certs/ca.crt
63END
64))
65
66cert_validation_flags="--insecure --cacert /usr/share/elasticsearch/config/certs/ca.crt --resolve ${es_node_name}:443:127.0.0.1"
67
68# Pull the container, retry on failures up to 5 times with
69# short delays between each attempt. Fixes most transient network errors.
70docker_pull_attempts=0
71until [ "$docker_pull_attempts" -ge 5 ]
72do
73   docker pull docker.elastic.co/elasticsearch/"$elasticsearch_container" && break
74   docker_pull_attempts=$((docker_pull_attempts+1))
75   echo "Failed to pull image, retrying in 10 seconds (retry $docker_pull_attempts/5)..."
76   sleep 10
77done
78
79NUMBER_OF_NODES=${NUMBER_OF_NODES-1}
80http_port=9200
81for (( i=0; i<$NUMBER_OF_NODES; i++, http_port++ )); do
82  node_name=${es_node_name}$i
83  node_url=${external_elasticsearch_url/9200/${http_port}}$i
84  if [[ "$i" == "0" ]]; then node_name=$es_node_name; fi
85  environment+=($(cat <<-END
86    --env node.name=$node_name
87END
88))
89  echo "$i: $http_port $node_url "
90  volume_name=${node_name}-${suffix}-data
91  volumes+=($(cat <<-END
92    --volume $volume_name:/usr/share/elasticsearch/data${i}
93END
94))
95
96  # make sure we detach for all but the last node if DETACH=false (default) so all nodes are started
97  local_detach="true"
98  if [[ "$i" == "$((NUMBER_OF_NODES-1))" ]]; then local_detach=$DETACH; fi
99  echo -e "\033[34;1mINFO:\033[0m Starting container $node_name \033[0m"
100  set -x
101  docker run \
102    --name "$node_name" \
103    --network "$network_name" \
104    --env "ES_JAVA_OPTS=-Xms1g -Xmx1g -da:org.elasticsearch.xpack.ccr.index.engine.FollowingEngineAssertions" \
105    "${environment[@]}" \
106    "${volumes[@]}" \
107    --publish "$http_port":9200 \
108    --ulimit nofile=65536:65536 \
109    --ulimit memlock=-1:-1 \
110    --detach="$local_detach" \
111    --health-cmd="curl $cert_validation_flags --fail $elasticsearch_url/_cluster/health || exit 1" \
112    --health-interval=2s \
113    --health-retries=20 \
114    --health-timeout=2s \
115    --rm \
116    docker.elastic.co/elasticsearch/"$elasticsearch_container";
117
118  set +x
119  if wait_for_container "$es_node_name" "$network_name"; then
120    echo -e "\033[32;1mSUCCESS:\033[0m Running on: $node_url\033[0m"
121  fi
122
123done
124
125