Преглед изворни кода

Merge pull request #2649 from Sjerd/main

Nicolas Duchon пре 1 месец
родитељ
комит
a48d48ef71

+ 1 - 1
.github/workflows/test.yml

@@ -50,5 +50,5 @@ jobs:
         run: make build-nginx-proxy-test-${{ matrix.base_docker_image }}
 
       - name: Run tests
-        run: pytest
+        run: pytest --ignore-flaky
         working-directory: test

+ 10 - 10
nginx.tmpl

@@ -65,9 +65,9 @@
 #     (none)
     {{- end }}
 {{- else }}
-# /!\ WARNING: Failed to find the Docker container labeled "{{ $globals.config.nginx_container_label }}" or the one running docker-gen. 
+# /!\ WARNING: Failed to find the Docker container labeled "{{ $globals.config.nginx_container_label }}" or the one running docker-gen.
 #              All upstream (backend) application containers will appear to be unreachable.
-#              Try removing the -only-exposed and -only-published arguments to docker-gen if you pass either of those. 
+#              Try removing the -only-exposed and -only-published arguments to docker-gen if you pass either of those.
 #              See https://github.com/nginx-proxy/docker-gen/issues/458.
 {{- end }}
 
@@ -291,7 +291,7 @@
         {{- $override = printf "/etc/nginx/vhost.d/%s_location_override" .Host }}
     {{- end }}
     {{- if exists $override }}
-    include {{ $override }};
+    include {{  printf "%s" (replace $override "*" "\\*" -1) }};
     {{- else }}
         {{- $keepalive := $vpath.keepalive }}
     location {{ .Path }} {
@@ -339,9 +339,9 @@
         {{- end }}
 
         {{- if (exists (printf "/etc/nginx/vhost.d/%s_%s_location" .Host (sha1 .Path) )) }}
-        include {{ printf "/etc/nginx/vhost.d/%s_%s_location" .Host (sha1 .Path) }};
+        include {{ printf "/etc/nginx/vhost.d/%s_%s_location" (replace .Host "*" "\\*" -1) (sha1 .Path) }};
         {{- else if (exists (printf "/etc/nginx/vhost.d/%s_location" .Host)) }}
-        include {{ printf "/etc/nginx/vhost.d/%s_location" .Host}};
+        include {{ printf "/etc/nginx/vhost.d/%s_location" (replace .Host "*" "\\*" -1) }};
         {{- else if (exists "/etc/nginx/vhost.d/default_location") }}
         include /etc/nginx/vhost.d/default_location;
         {{- end }}
@@ -788,7 +788,7 @@ proxy_set_header Proxy "";
     {{- $ssl_policy := groupByKeys $vhost_containers "Env.SSL_POLICY" | first | default "" }}
 
     {{- /* Get ssl_verify_client defined by containers w/ the same vhost, falling back to "on" */}}
-    {{- $ssl_verify_client := groupByLabel $vhost_containers "com.github.nginx-proxy.nginx-proxy.ssl_verify_client" | keys | first | default "on" }}																						   
+    {{- $ssl_verify_client := groupByLabel $vhost_containers "com.github.nginx-proxy.nginx-proxy.ssl_verify_client" | keys | first | default "on" }}
 
     {{- /* Get the HSTS defined by containers w/ the same vhost, falling back to "max-age=31536000". */}}
     {{- $hsts := groupByKeys $vhost_containers "Env.HSTS" | first | default $globals.config.hsts }}
@@ -811,7 +811,7 @@ proxy_set_header Proxy "";
         "acme_http_challenge_enabled" $acme_http_challenge_enabled
         "server_tokens" $server_tokens
         "ssl_policy" $ssl_policy
-        "ssl_verify_client" $ssl_verify_client											  
+        "ssl_verify_client" $ssl_verify_client
         "trust_default_cert" $trust_default_cert
         "upstream_name" $upstream_name
         "vhost_root" $vhost_root
@@ -1067,7 +1067,7 @@ server {
     {{- $vhostFileName :=  $vhost.is_regexp | ternary (sha1 $hostname) $hostname }}
 
     {{- if (exists (printf "/etc/nginx/vhost.d/%s" $vhostFileName)) }}
-    include {{ printf "/etc/nginx/vhost.d/%s" $vhostFileName }};
+    include {{ printf "/etc/nginx/vhost.d/%s" (replace $vhostFileName "*" "\\*" -1) }};
     {{- else if (exists "/etc/nginx/vhost.d/default") }}
     include /etc/nginx/vhost.d/default;
     {{- end }}
@@ -1075,11 +1075,11 @@ server {
     {{/* SSL Client Certificate Validation */}}
     {{/* If vhost(hash).ca.crt exists, include CA */}}
     {{- if (exists (printf "/etc/nginx/certs/%s.ca.crt" $vhostFileName)) }}
-    ssl_client_certificate {{ printf "/etc/nginx/certs/%s.ca.crt" $vhostFileName }}; 
+    ssl_client_certificate {{ printf "/etc/nginx/certs/%s.ca.crt" $vhostFileName }};
     ssl_verify_client {{ $vhost.ssl_verify_client }};
         {{/* If vhost(hash).crl.pem exists, include CRL */}}
         {{- if (exists (printf "/etc/nginx/certs/%s.crl.pem" $vhostFileName)) }}
-    ssl_crl {{ printf "/etc/nginx/certs/%s.crl.pem" $vhostFileName }}; 
+    ssl_crl {{ printf "/etc/nginx/certs/%s.crl.pem" $vhostFileName }};
         {{ end }}
     {{/* Else if no vhost CA file exists, but a global ca.crt exists include it */}}
     {{ else if (exists "/etc/nginx/certs/ca.crt") }}

+ 1 - 0
test/requirements/python-requirements.txt

@@ -2,5 +2,6 @@ backoff==2.2.1
 docker==7.1.0
 packaging==25.0
 pytest==8.4.1
+pytest-ignore-flaky==2.2.1
 requests==2.32.4
 urllib3==2.5.0

+ 1 - 0
test/test_custom/my_custom_proxy_settings_baz.conf

@@ -0,0 +1 @@
+add_header X-test-2 baz;

+ 7 - 0
test/test_custom/test_defaults.py

@@ -16,3 +16,10 @@ def test_custom_conf_applies_to_web2(docker_compose, nginxproxy):
     assert r.text == "answer from port 82\n"
     assert "X-test" in r.headers
     assert "f00" == r.headers["X-test"]
+
+def test_custom_conf_applies_to_wildcard(docker_compose, nginxproxy):
+    r = nginxproxy.get("http://wildcard.nginx-proxy.example/port")
+    assert r.status_code == 200   
+    assert r.text == "answer from port 83\n"
+    assert "X-test" in r.headers
+    assert "f00" == r.headers["X-test"]

+ 8 - 0
test/test_custom/test_defaults.yml

@@ -19,3 +19,11 @@ services:
     environment:
       WEB_PORTS: "82"
       VIRTUAL_HOST: web2.nginx-proxy.example
+  
+  wildcard:
+    image: web
+    expose:
+      - "83"
+    environment:
+      WEB_PORTS: "83"
+      VIRTUAL_HOST: "*.nginx-proxy.example" # wildcard for all subdomains

+ 7 - 1
test/test_custom/test_defaults-location.py → test/test_custom/test_location-defaults.py

@@ -17,10 +17,16 @@ def test_custom_default_conf_applies_to_web2(docker_compose, nginxproxy):
     assert "X-test" in r.headers
     assert "f00" == r.headers["X-test"]
 
-
 def test_custom_default_conf_is_overriden_for_web3(docker_compose, nginxproxy):
     r = nginxproxy.get("http://web3.nginx-proxy.example/port")
     assert r.status_code == 200   
     assert r.text == "answer from port 83\n"
     assert "X-test" in r.headers
     assert "bar" == r.headers["X-test"]
+
+def test_custom_default_conf_applies_to_wildcard(docker_compose, nginxproxy):
+    r = nginxproxy.get("http://wildcard.nginx-proxy.example/port")
+    assert r.status_code == 200   
+    assert r.text == "answer from port 84\n"
+    assert "X-test" in r.headers
+    assert "f00" == r.headers["X-test"]

+ 8 - 0
test/test_custom/test_defaults-location.yml → test/test_custom/test_location-defaults.yml

@@ -28,3 +28,11 @@ services:
     environment:
       WEB_PORTS: "83"
       VIRTUAL_HOST: web3.nginx-proxy.example
+  
+  wildcard:
+    image: web
+    expose:
+      - "84"
+    environment:
+      WEB_PORTS: "84"
+      VIRTUAL_HOST: "*.nginx-proxy.example" # wildcard for all subdomains

+ 18 - 4
test/test_custom/test_location-per-vhost.py

@@ -2,26 +2,40 @@ def test_custom_conf_does_not_apply_to_unknown_vhost(docker_compose, nginxproxy)
     r = nginxproxy.get("http://nginx-proxy/")
     assert r.status_code == 503
     assert "X-test" not in r.headers
+    assert "X-test-2" not in r.headers
 
 def test_custom_conf_applies_to_web1(docker_compose, nginxproxy):
     r = nginxproxy.get("http://web1.nginx-proxy.example/port")
-    assert r.status_code == 200   
+    assert r.status_code == 200
     assert r.text == "answer from port 81\n"
     assert "X-test" in r.headers
+    assert "X-test-2" not in r.headers
     assert "f00" == r.headers["X-test"]
 
 def test_custom_conf_applies_to_regex(docker_compose, nginxproxy):
-    r = nginxproxy.get("http://regex.foo.nginx-proxy.example/port")
-    assert r.status_code == 200   
+    r = nginxproxy.get("http://foo.nginx-proxy.regex/port")
+    assert r.status_code == 200
     assert r.text == "answer from port 83\n"
     assert "X-test" in r.headers
+    assert "X-test-2" not in r.headers
     assert "bar" == r.headers["X-test"]
 
+def test_custom_conf_applies_to_wildcard(docker_compose, nginxproxy):
+    r = nginxproxy.get("http://foo.nginx-proxy.example/port")
+    assert r.status_code == 200
+    assert r.text == "answer from port 84\n"
+    # we should get the config from *.nginx-proxy.example_location.conf
+    assert "X-test-2" in r.headers
+    assert "baz" == r.headers["X-test-2"]
+    # but not the config from web1.nginx-proxy.example_location.conf
+    assert "X-test" not in r.headers
+
 def test_custom_conf_does_not_apply_to_web2(docker_compose, nginxproxy):
     r = nginxproxy.get("http://web2.nginx-proxy.example/port")
-    assert r.status_code == 200   
+    assert r.status_code == 200
     assert r.text == "answer from port 82\n"
     assert "X-test" not in r.headers
+    assert "X-test-2" not in r.headers
 
 def test_custom_block_is_present_in_nginx_generated_conf(docker_compose, nginxproxy):
     assert b"include /etc/nginx/vhost.d/web1.nginx-proxy.example_location;" in nginxproxy.get_conf()

+ 11 - 2
test/test_custom/test_location-per-vhost.yml

@@ -3,7 +3,8 @@ services:
     volumes:
       - /var/run/docker.sock:/tmp/docker.sock:ro
       - ${PYTEST_MODULE_PATH}/my_custom_proxy_settings_f00.conf:/etc/nginx/vhost.d/web1.nginx-proxy.example_location:ro
-      - ${PYTEST_MODULE_PATH}/my_custom_proxy_settings_bar.conf:/etc/nginx/vhost.d/561032515ede3ab3a015edfb244608b72409c430_location:ro
+      - ${PYTEST_MODULE_PATH}/my_custom_proxy_settings_bar.conf:/etc/nginx/vhost.d/97db860fb631ba3c047db9fec60638fd72a180b1_location:ro
+      - ${PYTEST_MODULE_PATH}/my_custom_proxy_settings_baz.conf:/etc/nginx/vhost.d/*.nginx-proxy.example_location:ro
 
   web1:
     image: web
@@ -27,4 +28,12 @@ services:
       - "83"
     environment:
       WEB_PORTS: "83"
-      VIRTUAL_HOST: ~^regex.*\.nginx-proxy\.example$$ # we need to double the `$` because of docker compose variable interpolation
+      VIRTUAL_HOST: ~^.*\.nginx-proxy\.regex$$ # we need to double the `$` because of docker compose variable interpolation
+  
+  wildcard:
+    image: web
+    expose:
+      - "84"
+    environment:
+      WEB_PORTS: "84"
+      VIRTUAL_HOST: "*.nginx-proxy.example" # wildcard for all subdomains

+ 18 - 4
test/test_custom/test_per-vhost.py

@@ -2,23 +2,37 @@ def test_custom_conf_does_not_apply_to_unknown_vhost(docker_compose, nginxproxy)
     r = nginxproxy.get("http://nginx-proxy/")
     assert r.status_code == 503
     assert "X-test" not in r.headers
+    assert "X-test-2" not in r.headers
 
 def test_custom_conf_applies_to_web1(docker_compose, nginxproxy):
     r = nginxproxy.get("http://web1.nginx-proxy.example/port")
-    assert r.status_code == 200   
+    assert r.status_code == 200
     assert r.text == "answer from port 81\n"
     assert "X-test" in r.headers
+    assert "X-test-2" not in r.headers
     assert "f00" == r.headers["X-test"]
 
 def test_custom_conf_applies_to_regex(docker_compose, nginxproxy):
-    r = nginxproxy.get("http://regex.foo.nginx-proxy.example/port")
-    assert r.status_code == 200   
+    r = nginxproxy.get("http://foo.nginx-proxy.regex/port")
+    assert r.status_code == 200
     assert r.text == "answer from port 83\n"
     assert "X-test" in r.headers
+    assert "X-test-2" not in r.headers
     assert "bar" == r.headers["X-test"]
 
+def test_custom_conf_applies_to_wildcard(docker_compose, nginxproxy):
+    r = nginxproxy.get("http://foo.nginx-proxy.example/port")
+    assert r.status_code == 200
+    assert r.text == "answer from port 84\n"
+    # we should get the config from *.nginx-proxy.example.conf
+    assert "X-test-2" in r.headers
+    assert "baz" == r.headers["X-test-2"]
+    # but not the config from web1.nginx-proxy.example.conf
+    assert "X-test" not in r.headers
+
 def test_custom_conf_does_not_apply_to_web2(docker_compose, nginxproxy):
     r = nginxproxy.get("http://web2.nginx-proxy.example/port")
-    assert r.status_code == 200   
+    assert r.status_code == 200
     assert r.text == "answer from port 82\n"
     assert "X-test" not in r.headers
+    assert "X-test-2" not in r.headers

+ 11 - 2
test/test_custom/test_per-vhost.yml

@@ -3,7 +3,8 @@ services:
     volumes:
       - /var/run/docker.sock:/tmp/docker.sock:ro
       - ${PYTEST_MODULE_PATH}/my_custom_proxy_settings_f00.conf:/etc/nginx/vhost.d/web1.nginx-proxy.example:ro
-      - ${PYTEST_MODULE_PATH}/my_custom_proxy_settings_bar.conf:/etc/nginx/vhost.d/561032515ede3ab3a015edfb244608b72409c430:ro
+      - ${PYTEST_MODULE_PATH}/my_custom_proxy_settings_bar.conf:/etc/nginx/vhost.d/97db860fb631ba3c047db9fec60638fd72a180b1:ro
+      - ${PYTEST_MODULE_PATH}/my_custom_proxy_settings_baz.conf:/etc/nginx/vhost.d/*.nginx-proxy.example:ro
 
   web1:
     image: web
@@ -27,4 +28,12 @@ services:
       - "83"
     environment:
       WEB_PORTS: "83"
-      VIRTUAL_HOST: ~^regex.*\.nginx-proxy\.example$$ # we need to double the `$` because of docker compose variable interpolation
+      VIRTUAL_HOST: ~^.*\.nginx-proxy\.regex$$ # we need to double the `$` because of docker compose variable interpolation
+
+  wildcard:
+    image: web
+    expose:
+      - "84"
+    environment:
+      WEB_PORTS: "84"
+      VIRTUAL_HOST: "*.nginx-proxy.example" # wildcard for all subdomains

+ 7 - 0
test/test_custom/test_proxy-wide.py

@@ -16,3 +16,10 @@ def test_custom_conf_applies_to_web2(docker_compose, nginxproxy):
     assert r.text == "answer from port 82\n"
     assert "X-test" in r.headers
     assert "f00" == r.headers["X-test"]
+
+def test_custom_conf_applies_to_wildcard(docker_compose, nginxproxy):
+    r = nginxproxy.get("http://wildcard.nginx-proxy.example/port")
+    assert r.status_code == 200   
+    assert r.text == "answer from port 83\n"
+    assert "X-test" in r.headers
+    assert "f00" == r.headers["X-test"]

+ 8 - 0
test/test_custom/test_proxy-wide.yml

@@ -19,3 +19,11 @@ services:
     environment:
       WEB_PORTS: "82"
       VIRTUAL_HOST: web2.nginx-proxy.example
+  
+  wildcard:
+    image: web
+    expose:
+      - "83"
+    environment:
+      WEB_PORTS: "83"
+      VIRTUAL_HOST: "*.nginx-proxy.example" # wildcard for all subdomains

+ 5 - 0
test/test_dockergen/test_dockergen_network_segregation-custom-label.py

@@ -1,8 +1,13 @@
+import pytest
+
+
+@pytest.mark.flaky
 def test_unknown_virtual_host_is_503(docker_compose, nginxproxy):
     r = nginxproxy.get("http://unknown.nginx-proxy.tld/")
     assert r.status_code == 503
 
 
+@pytest.mark.flaky
 def test_forwards_to_whoami(docker_compose, nginxproxy):
     r = nginxproxy.get("http://whoami2.nginx-proxy.tld/")
     assert r.status_code == 200

+ 5 - 0
test/test_dockergen/test_dockergen_network_segregation.py

@@ -1,8 +1,13 @@
+import pytest
+
+
+@pytest.mark.flaky
 def test_unknown_virtual_host_is_503(docker_compose, nginxproxy):
     r = nginxproxy.get("http://unknown.nginx-proxy.tld/")
     assert r.status_code == 503
 
 
+@pytest.mark.flaky
 def test_forwards_to_whoami(docker_compose, nginxproxy):
     r = nginxproxy.get("http://whoami2.nginx-proxy.tld/")
     assert r.status_code == 200