From 4af3be397af689aba32cd03e3f6e37fefb5dc0a9 Mon Sep 17 00:00:00 2001 From: Nicolas Duchon Date: Fri, 23 May 2025 20:55:29 +0200 Subject: [PATCH 1/6] test: wait for docker-gen container to be ready too --- test/conftest.py | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/test/conftest.py b/test/conftest.py index 15d18bc..83f5865 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -348,16 +348,26 @@ def docker_compose_down(compose_files: List[str], project_name: str): def wait_for_nginxproxy_to_be_ready(): """ - If one (and only one) container started from image nginxproxy/nginx-proxy:test is found, - wait for its log to contain substring "Watching docker events" + If one (and only one) container started from image nginxproxy/nginx-proxy:test + or nginxproxy/docker-gen:latest is found, wait for its log to contain the substring "Watching docker events" """ - containers = docker_client.containers.list(filters={"ancestor": "nginxproxy/nginx-proxy:test"}) - if len(containers) != 1: + nginx_proxy_containers = docker_client.containers.list(filters={"ancestor": "nginxproxy/nginx-proxy:test"}) + docker_gen_containers = docker_client.containers.list(filters={"ancestor": "nginxproxy/docker-gen:latest"}) + + container_name = "nginx-proxy" + + if len(nginx_proxy_containers) == 1: + container = nginx_proxy_containers.pop() + elif len(docker_gen_containers) == 1: + container = docker_gen_containers.pop() + container_name = "docker-gen" + else: + logging.debug("Either more than one or no nginx-proxy or docker-gen container found, skipping container readiness check") return - container = containers[0] + for line in container.logs(stream=True): if b"Watching docker events" in line: - logging.debug("nginx-proxy ready") + logging.debug(f"{container_name} ready") break From 0479cb02a2d6fec892ebd56b67706aace7b1c0e4 Mon Sep 17 00:00:00 2001 From: Nicolas Duchon Date: Fri, 23 May 2025 21:33:33 +0200 Subject: [PATCH 2/6] test: fix docker-gen flaky tests --- test/conftest.py | 34 +++++++++++++++---- test/test_dockergen/test_dockergen.base.yml | 2 +- test/test_dockergen/test_dockergen.py | 4 +-- ..._network_segregation-custom-label.base.yml | 2 +- ...kergen_network_segregation-custom-label.py | 4 +-- ...est_dockergen_network_segregation.base.yml | 2 +- .../test_dockergen_network_segregation.py | 4 +-- 7 files changed, 37 insertions(+), 15 deletions(-) diff --git a/test/conftest.py b/test/conftest.py index 83f5865..c0a060b 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -199,26 +199,48 @@ def container_ipv6(container: Container) -> str: def nginx_proxy_dns_resolver(domain_name: str) -> Optional[str]: """ if "nginx-proxy" if found in host, return the ip address of the docker container - issued from the docker image nginxproxy/nginx-proxy:test. + issued from the docker image nginxproxy/nginx-proxy:test or nginx:latest. :return: IP or None """ log = logging.getLogger('DNS') log.debug(f"nginx_proxy_dns_resolver({domain_name!r})") + if 'nginx-proxy' in domain_name: nginxproxy_containers = docker_client.containers.list(filters={"status": "running", "ancestor": "nginxproxy/nginx-proxy:test"}) - if len(nginxproxy_containers) == 0: - log.warning(f"no container found from image nginxproxy/nginx-proxy:test while resolving {domain_name!r}") + nginx_containers = docker_client.containers.list(filters={"status": "running", "ancestor": "nginx:latest"}) + + if len(nginxproxy_containers) == 0 and len(nginx_containers) == 0: + log.warning(f"no runninf container found from image nginxproxy/nginx-proxy:test or nginx:latest while resolving {domain_name!r}") + exited_nginxproxy_containers = docker_client.containers.list(filters={"status": "exited", "ancestor": "nginxproxy/nginx-proxy:test"}) + exited_nginx_containers = docker_client.containers.list(filters={"status": "exited", "ancestor": "nginx:latest"}) + if len(exited_nginxproxy_containers) > 0: exited_nginxproxy_container_logs = exited_nginxproxy_containers[0].logs() log.warning(f"nginxproxy/nginx-proxy:test container might have exited unexpectedly. Container logs: " + "\n" + exited_nginxproxy_container_logs.decode()) + if len(exited_nginx_containers) > 0: + exited_nginx_container_logs = exited_nginx_containers[0].logs() + log.warning(f"nginx:latest container might have exited unexpectedly. Container logs: " + "\n" + exited_nginx_container_logs.decode()) + return None - nginxproxy_container = nginxproxy_containers[0] - ip = container_ip(nginxproxy_container) - log.info(f"resolving domain name {domain_name!r} as IP address {ip} of nginx-proxy container {nginxproxy_container.name}") + + container = None + container_type = "nginx-proxy" + + if len(nginxproxy_containers) >= 1: + container = nginxproxy_containers[0] + if len(nginx_containers) >= 1: + container = nginx_containers[0] + container_type = "nginx" + + ip = container_ip(container) + log.info(f"resolving domain name {domain_name!r} as IP address {ip} of {container_type} container {container.name}") return ip + return None + + def docker_container_dns_resolver(domain_name: str) -> Optional[str]: """ if domain name is of the form "XXX.container.docker" or "anything.XXX.container.docker", diff --git a/test/test_dockergen/test_dockergen.base.yml b/test/test_dockergen/test_dockergen.base.yml index 69f6c85..3012abe 100644 --- a/test/test_dockergen/test_dockergen.base.yml +++ b/test/test_dockergen/test_dockergen.base.yml @@ -27,4 +27,4 @@ services: - "80" environment: WEB_PORTS: "80" - VIRTUAL_HOST: whoami.nginx.container.docker + VIRTUAL_HOST: whoami.nginx-proxy.tld diff --git a/test/test_dockergen/test_dockergen.py b/test/test_dockergen/test_dockergen.py index 6d419cd..8784ed5 100644 --- a/test/test_dockergen/test_dockergen.py +++ b/test/test_dockergen/test_dockergen.py @@ -11,12 +11,12 @@ pytestmark = pytest.mark.skipif( def test_unknown_virtual_host_is_503(docker_compose, nginxproxy): - r = nginxproxy.get("http://unknown.nginx.container.docker/") + r = nginxproxy.get("http://unknown.nginx-proxy.tld/") assert r.status_code == 503 def test_forwards_to_whoami(docker_compose, nginxproxy): - r = nginxproxy.get("http://whoami.nginx.container.docker/") + r = nginxproxy.get("http://whoami.nginx-proxy.tld/") assert r.status_code == 200 whoami_container = docker_compose.containers.get("whoami") assert r.text == f"I'm {whoami_container.id[:12]}\n" diff --git a/test/test_dockergen/test_dockergen_network_segregation-custom-label.base.yml b/test/test_dockergen/test_dockergen_network_segregation-custom-label.base.yml index 1429e9f..bc79d2d 100644 --- a/test/test_dockergen/test_dockergen_network_segregation-custom-label.base.yml +++ b/test/test_dockergen/test_dockergen_network_segregation-custom-label.base.yml @@ -40,6 +40,6 @@ services: - "80" environment: WEB_PORTS: "80" - VIRTUAL_HOST: whoami2.nginx.container.docker + VIRTUAL_HOST: whoami2.nginx-proxy.tld networks: - proxy diff --git a/test/test_dockergen/test_dockergen_network_segregation-custom-label.py b/test/test_dockergen/test_dockergen_network_segregation-custom-label.py index ad487d9..ed5c20b 100644 --- a/test/test_dockergen/test_dockergen_network_segregation-custom-label.py +++ b/test/test_dockergen/test_dockergen_network_segregation-custom-label.py @@ -11,12 +11,12 @@ pytestmark = pytest.mark.skipif( def test_unknown_virtual_host_is_503(docker_compose, nginxproxy): - r = nginxproxy.get("http://unknown.nginx.container.docker/") + r = nginxproxy.get("http://unknown.nginx-proxy.tld/") assert r.status_code == 503 def test_forwards_to_whoami(docker_compose, nginxproxy): - r = nginxproxy.get("http://whoami2.nginx.container.docker/") + r = nginxproxy.get("http://whoami2.nginx-proxy.tld/") assert r.status_code == 200 whoami_container = docker_compose.containers.get("whoami2") assert r.text == f"I'm {whoami_container.id[:12]}\n" diff --git a/test/test_dockergen/test_dockergen_network_segregation.base.yml b/test/test_dockergen/test_dockergen_network_segregation.base.yml index c0e85ac..10f61a7 100644 --- a/test/test_dockergen/test_dockergen_network_segregation.base.yml +++ b/test/test_dockergen/test_dockergen_network_segregation.base.yml @@ -38,6 +38,6 @@ services: - "80" environment: WEB_PORTS: "80" - VIRTUAL_HOST: whoami2.nginx.container.docker + VIRTUAL_HOST: whoami2.nginx-proxy.tld networks: - proxy diff --git a/test/test_dockergen/test_dockergen_network_segregation.py b/test/test_dockergen/test_dockergen_network_segregation.py index ad487d9..ed5c20b 100644 --- a/test/test_dockergen/test_dockergen_network_segregation.py +++ b/test/test_dockergen/test_dockergen_network_segregation.py @@ -11,12 +11,12 @@ pytestmark = pytest.mark.skipif( def test_unknown_virtual_host_is_503(docker_compose, nginxproxy): - r = nginxproxy.get("http://unknown.nginx.container.docker/") + r = nginxproxy.get("http://unknown.nginx-proxy.tld/") assert r.status_code == 503 def test_forwards_to_whoami(docker_compose, nginxproxy): - r = nginxproxy.get("http://whoami2.nginx.container.docker/") + r = nginxproxy.get("http://whoami2.nginx-proxy.tld/") assert r.status_code == 200 whoami_container = docker_compose.containers.get("whoami2") assert r.text == f"I'm {whoami_container.id[:12]}\n" From 0bb98ef41560543a071d3dd8757c1e6dd1589f90 Mon Sep 17 00:00:00 2001 From: Nicolas Duchon Date: Sat, 24 May 2025 14:43:35 +0200 Subject: [PATCH 3/6] test: simplify container readiness check --- test/conftest.py | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/test/conftest.py b/test/conftest.py index c0a060b..ccc46ed 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -370,27 +370,20 @@ def docker_compose_down(compose_files: List[str], project_name: str): def wait_for_nginxproxy_to_be_ready(): """ - If one (and only one) container started from image nginxproxy/nginx-proxy:test - or nginxproxy/docker-gen:latest is found, wait for its log to contain the substring "Watching docker events" + Wait for logs of running containers started from image nginxproxy/nginx-proxy:test and/or + nginxproxy/docker-gen:latest to contain the substring "Watching docker events" """ - nginx_proxy_containers = docker_client.containers.list(filters={"ancestor": "nginxproxy/nginx-proxy:test"}) - docker_gen_containers = docker_client.containers.list(filters={"ancestor": "nginxproxy/docker-gen:latest"}) + nginx_proxy_containers = docker_client.containers.list(filters={"status": "running", "ancestor": "nginxproxy/nginx-proxy:test"}) + docker_gen_containers = docker_client.containers.list(filters={"status": "running", "ancestor": "nginxproxy/docker-gen:latest"}) - container_name = "nginx-proxy" + containers = nginx_proxy_containers + docker_gen_containers - if len(nginx_proxy_containers) == 1: - container = nginx_proxy_containers.pop() - elif len(docker_gen_containers) == 1: - container = docker_gen_containers.pop() - container_name = "docker-gen" - else: - logging.debug("Either more than one or no nginx-proxy or docker-gen container found, skipping container readiness check") - return - - for line in container.logs(stream=True): - if b"Watching docker events" in line: - logging.debug(f"{container_name} ready") - break + for container in containers: + logging.debug(f"waiting for container {container.name} to be ready") + for line in container.logs(stream=True): + if b"Watching docker events" in line: + logging.debug(f"{container.name} ready") + break @pytest.fixture From def3131239408d0ff6f1039f70c36c8b6150a132 Mon Sep 17 00:00:00 2001 From: Nicolas Duchon Date: Sat, 24 May 2025 14:57:12 +0200 Subject: [PATCH 4/6] ci: disable fail-fast on test workflow --- .github/workflows/test.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 60e8331..390db4f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -21,6 +21,7 @@ jobs: strategy: matrix: base_docker_image: [alpine, debian] + fail-fast: false steps: - uses: actions/checkout@v4 From 3f17dd29497e5ece8529d710ab97c7b231a50b55 Mon Sep 17 00:00:00 2001 From: Nicolas Duchon Date: Sat, 24 May 2025 15:00:06 +0200 Subject: [PATCH 5/6] test: typo --- test/conftest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/conftest.py b/test/conftest.py index ccc46ed..c95e42c 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -211,7 +211,7 @@ def nginx_proxy_dns_resolver(domain_name: str) -> Optional[str]: nginx_containers = docker_client.containers.list(filters={"status": "running", "ancestor": "nginx:latest"}) if len(nginxproxy_containers) == 0 and len(nginx_containers) == 0: - log.warning(f"no runninf container found from image nginxproxy/nginx-proxy:test or nginx:latest while resolving {domain_name!r}") + log.warning(f"no running container found from image nginxproxy/nginx-proxy:test or nginx:latest while resolving {domain_name!r}") exited_nginxproxy_containers = docker_client.containers.list(filters={"status": "exited", "ancestor": "nginxproxy/nginx-proxy:test"}) exited_nginx_containers = docker_client.containers.list(filters={"status": "exited", "ancestor": "nginx:latest"}) From d3a3d32e183706ac9cc761d1d0069a3a57632691 Mon Sep 17 00:00:00 2001 From: Nicolas Duchon Date: Mon, 26 May 2025 22:56:28 +0200 Subject: [PATCH 6/6] test: drop old checks in docker-gen tests docker engine 1.13 has been out for more than 8 years now --- test/test_dockergen/test_dockergen.py | 17 ----------------- ...ockergen_network_segregation-custom-label.py | 17 ----------------- .../test_dockergen_network_segregation.py | 17 ----------------- 3 files changed, 51 deletions(-) diff --git a/test/test_dockergen/test_dockergen.py b/test/test_dockergen/test_dockergen.py index 8784ed5..8fd4be9 100644 --- a/test/test_dockergen/test_dockergen.py +++ b/test/test_dockergen/test_dockergen.py @@ -1,15 +1,3 @@ -import docker -import pytest -from packaging.version import Version - - -raw_version = docker.from_env().version()["Version"] -pytestmark = pytest.mark.skipif( - Version(raw_version) < Version("1.13"), - reason="Docker compose syntax v3 requires docker engine v1.13 or later (got {raw_version})" -) - - def test_unknown_virtual_host_is_503(docker_compose, nginxproxy): r = nginxproxy.get("http://unknown.nginx-proxy.tld/") assert r.status_code == 503 @@ -20,8 +8,3 @@ def test_forwards_to_whoami(docker_compose, nginxproxy): assert r.status_code == 200 whoami_container = docker_compose.containers.get("whoami") assert r.text == f"I'm {whoami_container.id[:12]}\n" - - -if __name__ == "__main__": - import doctest - doctest.testmod() diff --git a/test/test_dockergen/test_dockergen_network_segregation-custom-label.py b/test/test_dockergen/test_dockergen_network_segregation-custom-label.py index ed5c20b..7efd791 100644 --- a/test/test_dockergen/test_dockergen_network_segregation-custom-label.py +++ b/test/test_dockergen/test_dockergen_network_segregation-custom-label.py @@ -1,15 +1,3 @@ -import docker -import pytest -from packaging.version import Version - - -raw_version = docker.from_env().version()["Version"] -pytestmark = pytest.mark.skipif( - Version(raw_version) < Version("1.13"), - reason="Docker compose syntax v3 requires docker engine v1.13 or later (got {raw_version})" -) - - def test_unknown_virtual_host_is_503(docker_compose, nginxproxy): r = nginxproxy.get("http://unknown.nginx-proxy.tld/") assert r.status_code == 503 @@ -20,8 +8,3 @@ def test_forwards_to_whoami(docker_compose, nginxproxy): assert r.status_code == 200 whoami_container = docker_compose.containers.get("whoami2") assert r.text == f"I'm {whoami_container.id[:12]}\n" - - -if __name__ == "__main__": - import doctest - doctest.testmod() diff --git a/test/test_dockergen/test_dockergen_network_segregation.py b/test/test_dockergen/test_dockergen_network_segregation.py index ed5c20b..7efd791 100644 --- a/test/test_dockergen/test_dockergen_network_segregation.py +++ b/test/test_dockergen/test_dockergen_network_segregation.py @@ -1,15 +1,3 @@ -import docker -import pytest -from packaging.version import Version - - -raw_version = docker.from_env().version()["Version"] -pytestmark = pytest.mark.skipif( - Version(raw_version) < Version("1.13"), - reason="Docker compose syntax v3 requires docker engine v1.13 or later (got {raw_version})" -) - - def test_unknown_virtual_host_is_503(docker_compose, nginxproxy): r = nginxproxy.get("http://unknown.nginx-proxy.tld/") assert r.status_code == 503 @@ -20,8 +8,3 @@ def test_forwards_to_whoami(docker_compose, nginxproxy): assert r.status_code == 200 whoami_container = docker_compose.containers.get("whoami2") assert r.text == f"I'm {whoami_container.id[:12]}\n" - - -if __name__ == "__main__": - import doctest - doctest.testmod()