From de2f057c10b1c18a323283910c293699e48143db Mon Sep 17 00:00:00 2001 From: Thomas LEVEIL Date: Tue, 21 Feb 2017 01:55:52 +0100 Subject: [PATCH] TESTS: add test for unreachable container resulting in an empty `upstream {}` block in the generated nginx config file --- .../test_unreachable_network/README.md | 59 +++++++++++++++++++ .../docker-compose.yml | 35 +++++++++++ .../test_unreachable_net.py | 35 +++++++++++ 3 files changed, 129 insertions(+) create mode 100644 test/stress_tests/test_unreachable_network/README.md create mode 100644 test/stress_tests/test_unreachable_network/docker-compose.yml create mode 100644 test/stress_tests/test_unreachable_network/test_unreachable_net.py diff --git a/test/stress_tests/test_unreachable_network/README.md b/test/stress_tests/test_unreachable_network/README.md new file mode 100644 index 0000000..aa09c4d --- /dev/null +++ b/test/stress_tests/test_unreachable_network/README.md @@ -0,0 +1,59 @@ +# nginx-proxy template is not considered when a container is not reachable + +Having a container with the `VIRTUAL_HOST` environment variable set but on a network not reachable from the nginx-proxy container will result in nginx-proxy serving the default nginx welcome page for all requests. + +Furthermore, if the nginx-proxy in such state is restarted, the nginx process will crash and the container stops. + +In the generated nginx config file, we can notice the presence of an empty `upstream {}` block. + +This can be fixed by merging [PR-585](https://github.com/jwilder/nginx-proxy/pull/585). + +## How to reproduce + +1. a first web container is created on network `netA` +1. a second web container is created on network `netB` +1. nginx-proxy is created with access to `netA` only + + +## Erratic behavior + +- nginx serves the default welcome page for all requests to `/` and error 404 for any other path +- nginx-container crash on restart + +Log shows: + +``` +webB_1 | starting a web server listening on port 82 +webA_1 | starting a web server listening on port 81 +reverseproxy | forego | starting dockergen.1 on port 5000 +reverseproxy | forego | starting nginx.1 on port 5100 +reverseproxy | dockergen.1 | 2017/02/20 01:10:24 Generated '/etc/nginx/conf.d/default.conf' from 3 containers +reverseproxy | dockergen.1 | 2017/02/20 01:10:24 Running 'nginx -s reload' +reverseproxy | dockergen.1 | 2017/02/20 01:10:24 Error running notify command: nginx -s reload, exit status 1 +reverseproxy | dockergen.1 | 2017/02/20 01:10:24 Watching docker events +reverseproxy | dockergen.1 | 2017/02/20 01:10:24 Contents of /etc/nginx/conf.d/default.conf did not change. Skipping notification 'nginx -s reload' +reverseproxy | reverseproxy | forego | starting dockergen.1 on port 5000 <---- nginx-proxy container restarted +reverseproxy | forego | starting nginx.1 on port 5100 +reverseproxy | dockergen.1 | 2017/02/20 01:10:24 Generated '/etc/nginx/conf.d/default.conf' from 3 containers +reverseproxy | dockergen.1 | 2017/02/20 01:10:24 Running 'nginx -s reload' +reverseproxy | dockergen.1 | 2017/02/20 01:10:24 Error running notify command: nginx -s reload, exit status 1 +reverseproxy | dockergen.1 | 2017/02/20 01:10:24 Watching docker events +reverseproxy | dockergen.1 | 2017/02/20 01:10:24 Contents of /etc/nginx/conf.d/default.conf did not change. Skipping notification 'nginx -s reload' +reverseproxy | forego | starting dockergen.1 on port 5000 +reverseproxy | forego | starting nginx.1 on port 5100 +reverseproxy | nginx.1 | 2017/02/20 01:11:02 [emerg] 17#17: no servers are inside upstream in /etc/nginx/conf.d/default.conf:64 +reverseproxy | forego | starting nginx.1 on port 5200 +reverseproxy | forego | sending SIGTERM to nginx.1 +reverseproxy | forego | sending SIGTERM to dockergen.1 +reverseproxy exited with code 0 +reverseproxy exited with code 0 + +``` + +## Expected behavior + +- no default nginx welcome page should be served +- nginx is able to forward requests to containers of `netA` +- nginx respond with error 503 for unknown virtual hosts +- nginx is not able to forward requests to containers of `netB` and responds with an error +- nginx should survive restarts diff --git a/test/stress_tests/test_unreachable_network/docker-compose.yml b/test/stress_tests/test_unreachable_network/docker-compose.yml new file mode 100644 index 0000000..0ca4f99 --- /dev/null +++ b/test/stress_tests/test_unreachable_network/docker-compose.yml @@ -0,0 +1,35 @@ +version: "2" + +networks: + netA: + netB: + +services: + reverseproxy: + container_name: reverseproxy + networks: + - netA + image: jwilder/nginx-proxy:test + volumes: + - /var/run/docker.sock:/tmp/docker.sock:ro + + webA: + networks: + - netA + image: web + expose: + - 81 + environment: + WEB_PORTS: 81 + VIRTUAL_HOST: webA.nginx-proxy + + webB: + networks: + - netB + image: web + expose: + - 82 + environment: + WEB_PORTS: 82 + VIRTUAL_HOST: webB.nginx-proxy + diff --git a/test/stress_tests/test_unreachable_network/test_unreachable_net.py b/test/stress_tests/test_unreachable_network/test_unreachable_net.py new file mode 100644 index 0000000..dbcfb14 --- /dev/null +++ b/test/stress_tests/test_unreachable_network/test_unreachable_net.py @@ -0,0 +1,35 @@ +from time import sleep + +import pytest +import requests + +pytestmark = pytest.mark.xfail() # TODO delete this marker once #585 is merged + + +def test_default_nginx_welcome_page_should_not_be_served(docker_compose, nginxproxy): + r = nginxproxy.get("http://whatever.nginx-proxy/", allow_redirects=False) + assert "Welcome to nginx!" not in r.text + + +def test_unknown_virtual_host_is_503(docker_compose, nginxproxy): + r = nginxproxy.get("http://unknown.nginx-proxy/", allow_redirects=False) + assert r.status_code == 503 + + +def test_http_web_a_is_forwarded(docker_compose, nginxproxy): + r = nginxproxy.get("http://webA.nginx-proxy/port", allow_redirects=False) + assert r.status_code == 200 + assert "answer from port 81\n" == r.text + + +def test_http_web_b_gets_an_error(docker_compose, nginxproxy): + r = nginxproxy.get("http://webB.nginx-proxy/", allow_redirects=False) + assert "Welcome to nginx!" not in r.text + with pytest.raises(requests.exceptions.HTTPError): + r.raise_for_status() + + +def test_reverseproxy_survive_restart(docker_compose): + docker_compose.containers.get("reverseproxy").restart() + sleep(2) # give time for the container to initialize + assert docker_compose.containers.get("reverseproxy").status == "running"