Skip to content

Commit 3abeff0

Browse files
Add integration test for proxy (elastic#1029)
With this commit we migrate the integration test for HTTP proxy connections to the new integration test infrastructure and cleanup any remaining leftovers in the old script (which is still used for Docker release image tests). Relates elastic#975
1 parent acaedc5 commit 3abeff0

File tree

8 files changed

+267
-459
lines changed

8 files changed

+267
-459
lines changed

integration-test.sh

Lines changed: 0 additions & 456 deletions
This file was deleted.

it/__init__.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,10 @@ class ConfigFile:
123123
def __init__(self, config_name):
124124
self.user_home = os.getenv("RALLY_HOME", os.path.expanduser("~"))
125125
self.rally_home = os.path.join(self.user_home, ".rally")
126-
self.config_file_name = "rally-{}.ini".format(config_name)
126+
if config_name is not None:
127+
self.config_file_name = f"rally-{config_name}.ini"
128+
else:
129+
self.config_file_name = "rally.ini"
127130
self.source_path = os.path.join(os.path.dirname(__file__), "resources", self.config_file_name)
128131
self.target_path = os.path.join(self.rally_home, self.config_file_name)
129132

it/proxy_test.py

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
# Licensed to Elasticsearch B.V. under one or more contributor
2+
# license agreements. See the NOTICE file distributed with
3+
# this work for additional information regarding copyright
4+
# ownership. Elasticsearch B.V. licenses this file to you under
5+
# the Apache License, Version 2.0 (the "License"); you may
6+
# not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
17+
18+
import collections
19+
import os
20+
import shutil
21+
import tempfile
22+
23+
import pytest
24+
25+
import it
26+
from esrally.utils import process
27+
28+
HttpProxy = collections.namedtuple("HttpProxy", ["authenticated_url", "anonymous_url"])
29+
30+
31+
@pytest.fixture(scope="module")
32+
def http_proxy():
33+
config_dir = os.path.join(os.path.dirname(__file__), "resources", "squid")
34+
35+
lines = process.run_subprocess_with_output(f"docker run --rm --name squid -d "
36+
f"-v {config_dir}/squidpasswords:/etc/squid/squidpasswords "
37+
f"-v {config_dir}/squid.conf:/etc/squid/squid.conf "
38+
f"-p 3128:3128 datadog/squid")
39+
proxy_container_id = lines[0].strip()
40+
proxy = HttpProxy(authenticated_url=f"http://testuser:[email protected]:3128",
41+
anonymous_url=f"http://127.0.0.1:3128")
42+
yield proxy
43+
process.run_subprocess(f"docker stop {proxy_container_id}")
44+
45+
46+
# ensures that a fresh log file is available
47+
@pytest.fixture(scope="function")
48+
def fresh_log_file():
49+
cfg = it.ConfigFile(config_name=None)
50+
log_file = os.path.join(cfg.rally_home, "logs", "rally.log")
51+
52+
if os.path.exists(log_file):
53+
bak = os.path.join(tempfile.mkdtemp(), "rally.log")
54+
shutil.move(log_file, bak)
55+
yield log_file
56+
# append log lines to the original file and move it back to its original
57+
with open(log_file, "r") as src:
58+
with open(bak, "a") as dst:
59+
dst.write(src.read())
60+
shutil.move(bak, log_file)
61+
else:
62+
yield log_file
63+
64+
65+
def assert_log_line_present(log_file, text):
66+
with open(log_file, "r") as f:
67+
assert any(text in line for line in f), f"Could not find [{text}] in [{log_file}]."
68+
69+
70+
@it.rally_in_mem
71+
def test_run_with_direct_internet_connection(cfg, http_proxy, fresh_log_file):
72+
assert it.esrally(cfg, "list tracks") == 0
73+
assert_log_line_present(fresh_log_file, "Connecting directly to the Internet")
74+
75+
76+
@it.rally_in_mem
77+
def test_anonymous_proxy_no_connection(cfg, http_proxy, fresh_log_file):
78+
env = dict(os.environ)
79+
env["http_proxy"] = http_proxy.anonymous_url
80+
assert process.run_subprocess_with_logging(it.esrally_command_line_for(cfg, "list tracks"), env=env) == 0
81+
assert_log_line_present(fresh_log_file, f"Connecting via proxy URL [{http_proxy.anonymous_url}] to the Internet")
82+
# unauthenticated proxy access is prevented
83+
assert_log_line_present(fresh_log_file, "No Internet connection detected")
84+
85+
86+
@it.rally_in_mem
87+
def test_authenticated_proxy_user_can_connect(cfg, http_proxy, fresh_log_file):
88+
env = dict(os.environ)
89+
env["http_proxy"] = http_proxy.authenticated_url
90+
assert process.run_subprocess_with_logging(it.esrally_command_line_for(cfg, "list tracks"), env=env) == 0
91+
assert_log_line_present(fresh_log_file,
92+
f"Connecting via proxy URL [{http_proxy.authenticated_url}] to the Internet")
93+
# authenticated proxy access is allowed
94+
assert_log_line_present(fresh_log_file, "Detected a working Internet connection")

it/resources/squid/squid.conf

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
auth_param basic program /usr/lib/squid/basic_ncsa_auth /etc/squid/squidpasswords
2+
auth_param basic realm proxy
3+
acl authenticated proxy_auth REQUIRED
4+
http_access allow authenticated
5+
http_port 3128

it/resources/squid/squidpasswords

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
testuser:$apr1$GcQaaItl$lhi4JoDsWBpZbkXVbI51O/

release-docker-test.sh

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
#!/usr/bin/env bash
2+
3+
# Licensed to Elasticsearch B.V. under one or more contributor
4+
# license agreements. See the NOTICE file distributed with
5+
# this work for additional information regarding copyright
6+
# ownership. Elasticsearch B.V. licenses this file to you under
7+
# the Apache License, Version 2.0 (the "License"); you may
8+
# not use this file except in compliance with the License.
9+
# You may obtain a copy of the License at
10+
#
11+
# http://www.apache.org/licenses/LICENSE-2.0
12+
#
13+
# Unless required by applicable law or agreed to in writing,
14+
# software distributed under the License is distributed on an
15+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16+
# KIND, either express or implied. See the License for the
17+
# specific language governing permissions and limitations
18+
# under the License.
19+
20+
set -e
21+
22+
readonly MIN_DOCKER_MEM_BYTES=$(expr 6 \* 1024 \* 1024 \* 1024)
23+
24+
function check_prerequisites {
25+
exit_if_docker_not_running
26+
27+
DOCKER_MEM_BYTES=$(docker info --format="{{.MemTotal}}")
28+
if [[ ${DOCKER_MEM_BYTES} -lt ${MIN_DOCKER_MEM_BYTES} ]]; then
29+
echo "Error: Docker is not configured with enough memory. ($DOCKER_MEM_BYTES bytes)"
30+
echo "Please increase memory available to Docker to at least ${MIN_DOCKER_MEM_BYTES} bytes"
31+
exit 1
32+
fi
33+
34+
if ! type docker-compose > /dev/null; then
35+
echo "docker compose is necessary to run the integration tests"
36+
exit 1
37+
fi
38+
}
39+
40+
function log {
41+
local ts=$(date -u "+%Y-%m-%dT%H:%M:%SZ")
42+
echo "[${ts}] [${1}] ${2}"
43+
}
44+
45+
function info {
46+
log "INFO" "${1}"
47+
}
48+
49+
function warn {
50+
log "WARN" "${1}"
51+
}
52+
53+
function error {
54+
log "ERROR" "${1}"
55+
}
56+
57+
function stop_and_clean_docker_container {
58+
docker stop ${1} > /dev/null || true
59+
docker rm ${1} > /dev/null || true
60+
}
61+
62+
function kill_related_es_processes {
63+
# kill all lingering Rally instances that might still be hanging
64+
set +e
65+
# kill all lingering Elasticsearch Docker containers launched by Rally
66+
RUNNING_DOCKER_CONTAINERS=$(docker ps --filter "label=io.rally.description" --format "{{.ID}}")
67+
if [ -n "${RUNNING_DOCKER_CONTAINERS}" ]; then
68+
for container in "${RUNNING_DOCKER_CONTAINERS}"
69+
do
70+
stop_and_clean_docker_container ${container}
71+
done
72+
fi
73+
set -e
74+
}
75+
76+
function exit_if_docker_not_running {
77+
if ! docker ps >/dev/null 2>&1; then
78+
error "Docker is required to run integration tests. Install and run Docker and try again."
79+
exit 1
80+
fi
81+
}
82+
83+
function docker_compose {
84+
if [[ "$1" == "up" ]]; then
85+
docker-compose -f docker/docker-compose-tests.yml up --abort-on-container-exit
86+
elif [[ "$1" == "down" ]]; then
87+
docker-compose -f docker/docker-compose-tests.yml down -v
88+
else
89+
error "Unknown argument [$1] for docker-compose, exiting."
90+
fi
91+
}
92+
93+
# This function gets called by release-docker.sh and assumes the image has been already built
94+
function test_docker_release_image {
95+
if [[ -z "${RALLY_VERSION}" ]]; then
96+
error "Environment variable [RALLY_VERSION] needs to be set to test the release image; exiting."
97+
elif [[ -z "${RALLY_LICENSE}" ]]; then
98+
error "Environment variable [RALLY_LICENSE] needs to be set to test the release image; exiting."
99+
fi
100+
101+
docker_compose down
102+
103+
info "Testing Rally docker image uses the right version"
104+
actual_version=$(docker run --rm elastic/rally:${RALLY_VERSION} esrally --version | cut -d ' ' -f 2,2)
105+
if [[ ${actual_version} != ${RALLY_VERSION} ]]; then
106+
echo "Rally version in Docker image: [${actual_version}] doesn't match the expected version [${RALLY_VERSION}]"
107+
exit 1
108+
fi
109+
110+
info "Testing Rally docker image version label is correct"
111+
actual_version=$(docker inspect --format '{{ index .Config.Labels "org.label-schema.version"}}' elastic/rally:${RALLY_VERSION})
112+
if [[ ${actual_version} != ${RALLY_VERSION} ]]; then
113+
echo "org.label-schema.version label in Rally Docker image: [${actual_version}] doesn't match the expected version [${RALLY_VERSION}]"
114+
exit 1
115+
fi
116+
117+
info "Testing Rally docker image license label is correct"
118+
actual_license=$(docker inspect --format '{{ index .Config.Labels "license"}}' elastic/rally:${RALLY_VERSION})
119+
if [[ ${actual_license} != ${RALLY_LICENSE} ]]; then
120+
echo "license label in Rally Docker image: [${actual_license}] doesn't match the expected license [${RALLY_LICENSE}]"
121+
exit 1
122+
fi
123+
124+
export TEST_COMMAND="--pipeline=benchmark-only --test-mode --track=geonames --challenge=append-no-conflicts-index-only --target-hosts=es01:9200"
125+
info "Testing Rally docker image using parameters: ${TEST_COMMAND}"
126+
docker_compose up
127+
docker_compose down
128+
129+
# list should work
130+
export TEST_COMMAND="list tracks"
131+
info "Testing Rally docker image using parameters: ${TEST_COMMAND}"
132+
docker_compose up
133+
docker_compose down
134+
135+
# --help should work
136+
export TEST_COMMAND="--help"
137+
info "Testing Rally docker image using parameters: ${TEST_COMMAND}"
138+
docker_compose up
139+
docker_compose down
140+
141+
# allow overriding CMD too
142+
export TEST_COMMAND="esrally --pipeline=benchmark-only --test-mode --track=geonames --challenge=append-no-conflicts-index-only --target-hosts=es01:9200"
143+
info "Testing Rally docker image using parameters: ${TEST_COMMAND}"
144+
docker_compose up
145+
docker_compose down
146+
unset TEST_COMMAND
147+
}
148+
149+
function main {
150+
check_prerequisites
151+
test_docker_release_image
152+
}
153+
154+
155+
function tear_down {
156+
info "tearing down"
157+
kill_related_es_processes
158+
}
159+
160+
trap "tear_down" EXIT
161+
162+
main

release-docker.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ echo "======================================================="
4646
echo "Testing Docker image for Rally release $RALLY_VERSION "
4747
echo "======================================================="
4848

49-
./integration-test.sh test_docker_release_image
49+
./release-docker-test.sh
5050

5151
echo "======================================================="
5252
echo "Publishing Docker image elastic/rally:$RALLY_VERSION "

tox.ini

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ setenv =
3838
commands =
3939
pytest --junitxml=junit-{envname}.xml
4040
pytest -s it --junitxml=junit-{envname}-it.xml
41-
./integration-test.sh
4241

4342
whitelist_externals =
4443
pytest

0 commit comments

Comments
 (0)