From 86aea653c82d308e1ddf19c256c94bb09f59808d Mon Sep 17 00:00:00 2001 From: Pit Kleyersburg Date: Tue, 22 Mar 2016 22:47:42 +0100 Subject: [PATCH] Update to docker-gen 0.7.0 Since [1] some timings seem to have changed. This caused the unit tests to fail intermittently, from my testings especially on Ubuntu systems (much less often on e.g. Arch). This commit adds the `dockergen_wait_for_event` helper-function to try and wait for the configuration to be generated by docker-gen before continuing on with the actual tests themselves. Additionally, at the end of every test file, all containers spun up by the bats-tests will be stopped. This required adding the `bats-type` label to every container started during the bats-tests. The stopping of the containers reduces the amount of events docker-gen has to process, thus resulting in lower wait times for the generation to happen. [1]: https://github.com/jwilder/docker-gen/commit/50435652b16b3874a5907765d33fa31150876d92 --- Dockerfile | 2 +- Makefile | 4 ++-- test/default-host.bats | 11 ++++++----- test/docker.bats | 18 ++++++++++++------ test/lib/docker_helpers.bash | 8 +++++++- test/multiple-hosts.bats | 13 ++++++++----- test/multiple-ports.bats | 17 ++++++++++++----- test/test_helpers.bash | 37 ++++++++++++++++++++++++++++++++++-- test/wildcard-hosts.bats | 17 ++++++++++++----- 9 files changed, 95 insertions(+), 32 deletions(-) diff --git a/Dockerfile b/Dockerfile index ce586bd..96602b0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -17,7 +17,7 @@ RUN echo "daemon off;" >> /etc/nginx/nginx.conf \ RUN wget -P /usr/local/bin https://godist.herokuapp.com/projects/ddollar/forego/releases/current/linux-amd64/forego \ && chmod u+x /usr/local/bin/forego -ENV DOCKER_GEN_VERSION 0.4.2 +ENV DOCKER_GEN_VERSION 0.7.0 RUN wget https://github.com/jwilder/docker-gen/releases/download/$DOCKER_GEN_VERSION/docker-gen-linux-amd64-$DOCKER_GEN_VERSION.tar.gz \ && tar -C /usr/local/bin -xvzf docker-gen-linux-amd64-$DOCKER_GEN_VERSION.tar.gz \ diff --git a/Makefile b/Makefile index 72e7984..213a441 100644 --- a/Makefile +++ b/Makefile @@ -2,8 +2,8 @@ .PHONY : test update-dependencies: - docker pull jwilder/docker-gen:latest - docker pull nginx:latest + docker pull jwilder/docker-gen:0.7.0 + docker pull nginx:1.9.12 docker pull python:3 docker pull rancher/socat-docker:latest docker pull appropriate/curl:latest diff --git a/test/default-host.bats b/test/default-host.bats index 4e9d84e..acdffc6 100644 --- a/test/default-host.bats +++ b/test/default-host.bats @@ -4,10 +4,7 @@ load test_helpers function setup { # make sure to stop any web container before each test so we don't # have any unexpected contaiener running with VIRTUAL_HOST or VIRUTAL_PORT set - CIDS=( $(docker ps -q --filter "label=bats-type=web") ) - if [ ${#CIDS[@]} -gt 0 ]; then - docker stop ${CIDS[@]} >&2 - fi + stop_bats_containers web } @@ -20,7 +17,7 @@ function setup { # WHEN nginx-proxy runs with DEFAULT_HOST set to web.bats run nginxproxy $SUT_CONTAINER -v /var/run/docker.sock:/tmp/docker.sock:ro -e DEFAULT_HOST=web.bats assert_success - docker_wait_for_log $SUT_CONTAINER 3 "Watching docker events" + docker_wait_for_log $SUT_CONTAINER 9 "Watching docker events" # THEN querying the proxy without Host header → 200 run curl_container $SUT_CONTAINER / --head @@ -30,3 +27,7 @@ function setup { run curl_container $SUT_CONTAINER / --head --header "Host: something.I.just.made.up" assert_output -l 0 $'HTTP/1.1 200 OK\r' } + +@test "[$TEST_FILE] stop all bats containers" { + stop_bats_containers +} diff --git a/test/docker.bats b/test/docker.bats index f4ec665..43be758 100644 --- a/test/docker.bats +++ b/test/docker.bats @@ -14,7 +14,7 @@ load test_helpers # WHEN nginx-proxy runs on our docker host using the default unix socket run nginxproxy $SUT_CONTAINER -v /var/run/docker.sock:/tmp/docker.sock:ro assert_success - docker_wait_for_log $SUT_CONTAINER 3 "Watching docker events" + docker_wait_for_log $SUT_CONTAINER 9 "Watching docker events" # THEN assert_nginxproxy_behaves $SUT_CONTAINER @@ -27,7 +27,7 @@ load test_helpers # WHEN nginx-proxy runs on our docker host using a custom unix socket run nginxproxy $SUT_CONTAINER -v /var/run/docker.sock:/f00.sock:ro -e DOCKER_HOST=unix:///f00.sock assert_success - docker_wait_for_log $SUT_CONTAINER 3 "Watching docker events" + docker_wait_for_log $SUT_CONTAINER 9 "Watching docker events" # THEN assert_nginxproxy_behaves $SUT_CONTAINER @@ -44,7 +44,7 @@ load test_helpers # WHEN nginx-proxy runs on our docker host using tcp to connect to our docker host run nginxproxy $SUT_CONTAINER -e DOCKER_HOST="tcp://bats-docker-tcp:2375" --link bats-docker-tcp:bats-docker-tcp assert_success - docker_wait_for_log $SUT_CONTAINER 3 "Watching docker events" + docker_wait_for_log $SUT_CONTAINER 9 "Watching docker events" # THEN assert_nginxproxy_behaves $SUT_CONTAINER @@ -57,28 +57,30 @@ load test_helpers # GIVEN a simple nginx container run docker run -d \ + --label bats-type="nginx" \ --name bats-nginx \ -v /etc/nginx/conf.d/ \ -v /etc/nginx/certs/ \ nginx:latest assert_success - run retry 5 1s docker run appropriate/curl --silent --fail --head http://$(docker_ip bats-nginx)/ + run retry 5 1s docker run --label bats-type="curl" appropriate/curl --silent --fail --head http://$(docker_ip bats-nginx)/ assert_output -l 0 $'HTTP/1.1 200 OK\r' # WHEN docker-gen runs on our docker host run docker run -d \ + --label bats-type="docker-gen" \ --name bats-docker-gen \ -v /var/run/docker.sock:/tmp/docker.sock:ro \ -v $BATS_TEST_DIRNAME/../nginx.tmpl:/etc/docker-gen/templates/nginx.tmpl:ro \ --volumes-from bats-nginx \ - jwilder/docker-gen:latest \ + jwilder/docker-gen:0.7.0 \ -notify-sighup bats-nginx \ -watch \ -only-exposed \ /etc/docker-gen/templates/nginx.tmpl \ /etc/nginx/conf.d/default.conf assert_success - docker_wait_for_log bats-docker-gen 6 "Watching docker events" + docker_wait_for_log bats-docker-gen 9 "Watching docker events" # Give some time to the docker-gen container to notify bats-nginx so it # reloads its config @@ -94,6 +96,10 @@ load test_helpers assert_nginxproxy_behaves bats-nginx } +@test "[$TEST_FILE] stop all bats containers" { + stop_bats_containers +} + # $1 nginx-proxy container function assert_nginxproxy_behaves { diff --git a/test/lib/docker_helpers.bash b/test/lib/docker_helpers.bash index 50e1d81..1735506 100644 --- a/test/lib/docker_helpers.bash +++ b/test/lib/docker_helpers.bash @@ -13,6 +13,11 @@ function docker_ip { docker inspect --format '{{ .NetworkSettings.IPAddress }}' $1 } +# get the ip of docker container $1 +function docker_id { + docker inspect --format '{{ .ID }}' $1 +} + # get the running state of container $1 # → true/false # fails if the container does not exist @@ -52,9 +57,10 @@ function docker_tcp { local container_name="$1" docker_clean $container_name docker run -d \ + --label bats-type="socat" \ --name $container_name \ --expose 2375 \ -v /var/run/docker.sock:/var/run/docker.sock \ rancher/socat-docker - docker run --link "$container_name:docker" docker:1.9 version + docker run --label bats-type="docker" --link "$container_name:docker" docker:1.9 version } diff --git a/test/multiple-hosts.bats b/test/multiple-hosts.bats index 695aec1..10487ae 100644 --- a/test/multiple-hosts.bats +++ b/test/multiple-hosts.bats @@ -5,22 +5,21 @@ SUT_CONTAINER=bats-nginx-proxy-${TEST_FILE} function setup { # make sure to stop any web container before each test so we don't # have any unexpected contaiener running with VIRTUAL_HOST or VIRUTAL_PORT set - CIDS=( $(docker ps -q --filter "label=bats-type=web") ) - if [ ${#CIDS[@]} -gt 0 ]; then - docker stop ${CIDS[@]} >&2 - fi + stop_bats_containers web } @test "[$TEST_FILE] start a nginx-proxy container" { run nginxproxy $SUT_CONTAINER -v /var/run/docker.sock:/tmp/docker.sock:ro assert_success - docker_wait_for_log $SUT_CONTAINER 3 "Watching docker events" + docker_wait_for_log $SUT_CONTAINER 9 "Watching docker events" } @test "[$TEST_FILE] nginx-proxy forwards requests for 2 hosts" { # WHEN a container runs a web server with VIRTUAL_HOST set for multiple hosts prepare_web_container bats-multiple-hosts-1 80 -e VIRTUAL_HOST=multiple-hosts-1-A.bats,multiple-hosts-1-B.bats + dockergen_wait_for_event $SUT_CONTAINER start bats-multiple-hosts-1 + sleep 1 # THEN querying the proxy without Host header → 503 run curl_container $SUT_CONTAINER / --head @@ -38,3 +37,7 @@ function setup { run curl_container $SUT_CONTAINER /data --header 'Host: multiple-hosts-1-B.bats' assert_output "answer from port 80" } + +@test "[$TEST_FILE] stop all bats containers" { + stop_bats_containers +} diff --git a/test/multiple-ports.bats b/test/multiple-ports.bats index a520571..a3c6fd0 100644 --- a/test/multiple-ports.bats +++ b/test/multiple-ports.bats @@ -5,10 +5,7 @@ SUT_CONTAINER=bats-nginx-proxy-${TEST_FILE} function setup { # make sure to stop any web container before each test so we don't # have any unexpected contaiener running with VIRTUAL_HOST or VIRUTAL_PORT set - CIDS=( $(docker ps -q --filter "label=bats-type=web") ) - if [ ${#CIDS[@]} -gt 0 ]; then - docker stop ${CIDS[@]} >&2 - fi + stop_bats_containers web } @@ -16,13 +13,15 @@ function setup { # GIVEN nginx-proxy run nginxproxy $SUT_CONTAINER -v /var/run/docker.sock:/tmp/docker.sock:ro assert_success - docker_wait_for_log $SUT_CONTAINER 3 "Watching docker events" + docker_wait_for_log $SUT_CONTAINER 9 "Watching docker events" } @test "[$TEST_FILE] nginx-proxy defaults to the service running on port 80" { # WHEN prepare_web_container bats-web-${TEST_FILE}-1 "80 90" -e VIRTUAL_HOST=web.bats + dockergen_wait_for_event $SUT_CONTAINER start bats-web-${TEST_FILE}-1 + sleep 1 # THEN assert_response_is_from_port 80 @@ -32,6 +31,8 @@ function setup { @test "[$TEST_FILE] VIRTUAL_PORT=90 while port 80 is also exposed" { # GIVEN prepare_web_container bats-web-${TEST_FILE}-2 "80 90" -e VIRTUAL_HOST=web.bats -e VIRTUAL_PORT=90 + dockergen_wait_for_event $SUT_CONTAINER start bats-web-${TEST_FILE}-2 + sleep 1 # THEN assert_response_is_from_port 90 @@ -41,11 +42,17 @@ function setup { @test "[$TEST_FILE] single exposed port != 80" { # GIVEN prepare_web_container bats-web-${TEST_FILE}-3 1234 -e VIRTUAL_HOST=web.bats + dockergen_wait_for_event $SUT_CONTAINER start bats-web-${TEST_FILE}-3 + sleep 1 # THEN assert_response_is_from_port 1234 } +@test "[$TEST_FILE] stop all bats containers" { + stop_bats_containers +} + # assert querying nginx-proxy provides a response from the expected port of the web container # $1 port we are expecting an response from diff --git a/test/test_helpers.bash b/test/test_helpers.bash index 5890677..2114557 100644 --- a/test/test_helpers.bash +++ b/test/test_helpers.bash @@ -33,6 +33,7 @@ function nginxproxy { shift docker_clean $container_name \ && docker run -d \ + --label bats-type="nginx-proxy" \ --name $container_name \ "$@" \ $SUT_IMAGE \ @@ -66,7 +67,7 @@ function curl_container { local -r container=$1 local -r path=$2 shift 2 - docker run appropriate/curl --silent \ + docker run --label bats-type="curl" appropriate/curl --silent \ --connect-timeout 5 \ --max-time 20 \ "$@" \ @@ -128,7 +129,39 @@ function prepare_web_container { # THEN querying directly port works IFS=$' \t\n' # See https://github.com/sstephenson/bats/issues/89 for port in $ports; do - run retry 5 1s docker run appropriate/curl --silent --fail http://$(docker_ip $container_name):$port/data + run retry 5 1s docker run --label bats-type="curl" appropriate/curl --silent --fail http://$(docker_ip $container_name):$port/data assert_output "answer from port $port" done } + +# stop all containers with the "bats-type" label (matching the optionally supplied value) +# +# $1 optional label value +function stop_bats_containers { + local -r value=$1 + + if [ -z "$value" ]; then + CIDS=( $(docker ps -q --filter "label=bats-type") ) + else + CIDS=( $(docker ps -q --filter "label=bats-type=$value") ) + fi + + if [ ${#CIDS[@]} -gt 0 ]; then + docker stop ${CIDS[@]} >&2 + fi +} + +# wait for a docker-gen container to receive a specified event from a +# container with the specified ID/name +# +# $1 docker-gen container name +# $2 event +# $3 ID/name of container to receive event from +function dockergen_wait_for_event { + local -r container=$1 + local -r event=$2 + local -r other=$3 + local -r did=$(docker_id "$other") + docker_wait_for_log "$container" 9 "Received event $event for container ${did:0:12}" +} + diff --git a/test/wildcard-hosts.bats b/test/wildcard-hosts.bats index 88ca1e7..8491e4b 100644 --- a/test/wildcard-hosts.bats +++ b/test/wildcard-hosts.bats @@ -5,10 +5,7 @@ SUT_CONTAINER=bats-nginx-proxy-${TEST_FILE} function setup { # make sure to stop any web container before each test so we don't # have any unexpected contaiener running with VIRTUAL_HOST or VIRUTAL_PORT set - CIDS=( $(docker ps -q --filter "label=bats-type=web") ) - if [ ${#CIDS[@]} -gt 0 ]; then - docker stop ${CIDS[@]} >&2 - fi + stop_bats_containers web } @@ -16,13 +13,15 @@ function setup { # GIVEN run nginxproxy $SUT_CONTAINER -v /var/run/docker.sock:/tmp/docker.sock:ro assert_success - docker_wait_for_log $SUT_CONTAINER 3 "Watching docker events" + docker_wait_for_log $SUT_CONTAINER 9 "Watching docker events" } @test "[$TEST_FILE] VIRTUAL_HOST=*.wildcard.bats" { # WHEN prepare_web_container bats-wildcard-hosts-1 80 -e VIRTUAL_HOST=*.wildcard.bats + dockergen_wait_for_event $SUT_CONTAINER start bats-wildcard-hosts-1 + sleep 1 # THEN assert_200 f00.wildcard.bats @@ -33,6 +32,8 @@ function setup { @test "[$TEST_FILE] VIRTUAL_HOST=wildcard.bats.*" { # WHEN prepare_web_container bats-wildcard-hosts-2 80 -e VIRTUAL_HOST=wildcard.bats.* + dockergen_wait_for_event $SUT_CONTAINER start bats-wildcard-hosts-2 + sleep 1 # THEN assert_200 wildcard.bats.f00 @@ -43,6 +44,8 @@ function setup { @test "[$TEST_FILE] VIRTUAL_HOST=~^foo\.bar\..*\.bats" { # WHEN prepare_web_container bats-wildcard-hosts-2 80 -e VIRTUAL_HOST=~^foo\.bar\..*\.bats + dockergen_wait_for_event $SUT_CONTAINER start bats-wildcard-hosts-2 + sleep 1 # THEN assert_200 foo.bar.whatever.bats @@ -51,6 +54,10 @@ function setup { } +@test "[$TEST_FILE] stop all bats containers" { + stop_bats_containers +} + # assert that querying nginx-proxy with the given Host header produces a `HTTP 200` response # $1 Host HTTP header to use when querying nginx-proxy