mirror of
https://github.com/thib8956/nginx-proxy
synced 2025-02-24 09:48:14 +00:00
Merge pull request #1572 from kmarilleau/travis_to_github_actions
Travis to GitHub actions
This commit is contained in:
commit
aa9386129d
37
.github/workflows/test.yml
vendored
Normal file
37
.github/workflows/test.yml
vendored
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
name: Test
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
unit:
|
||||||
|
name: Unit Test
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
fail-fast: true
|
||||||
|
matrix:
|
||||||
|
base_docker_image: [alpine, debian]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Set up Python 3.9
|
||||||
|
uses: actions/setup-python@v2
|
||||||
|
with:
|
||||||
|
python-version: 3.9
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
python -m pip install --upgrade pip
|
||||||
|
pip install -r python-requirements.txt
|
||||||
|
working-directory: test/requirements
|
||||||
|
|
||||||
|
- name: Build Docker web server image
|
||||||
|
run: make build-webserver
|
||||||
|
|
||||||
|
- name: Build Docker nginx proxy test image
|
||||||
|
run: make build-nginx-proxy-test-${{ matrix.base_docker_image }}
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
run: pytest
|
||||||
|
working-directory: test
|
14
Makefile
14
Makefile
@ -2,15 +2,19 @@
|
|||||||
.PHONY : test-debian test-alpine test
|
.PHONY : test-debian test-alpine test
|
||||||
|
|
||||||
|
|
||||||
update-dependencies:
|
build-webserver:
|
||||||
test/requirements/build.sh
|
docker build -t web test/requirements/web
|
||||||
|
|
||||||
test-debian: update-dependencies
|
build-nginx-proxy-test-debian:
|
||||||
docker build -t nginxproxy/nginx-proxy:test .
|
docker build -t nginxproxy/nginx-proxy:test .
|
||||||
|
|
||||||
|
build-nginx-proxy-test-alpine:
|
||||||
|
docker build -f Dockerfile.alpine -t nginxproxy/nginx-proxy:test .
|
||||||
|
|
||||||
|
test-debian: build-webserver build-nginx-proxy-test-debian
|
||||||
test/pytest.sh
|
test/pytest.sh
|
||||||
|
|
||||||
test-alpine: update-dependencies
|
test-alpine: build-webserver build-nginx-proxy-test-alpine
|
||||||
docker build -f Dockerfile.alpine -t nginxproxy/nginx-proxy:test .
|
|
||||||
test/pytest.sh
|
test/pytest.sh
|
||||||
|
|
||||||
test: test-debian test-alpine
|
test: test-debian test-alpine
|
||||||
|
21
README.md
21
README.md
@ -415,22 +415,15 @@ Before submitting pull requests or issues, please check github to make sure an e
|
|||||||
|
|
||||||
#### Running Tests Locally
|
#### Running Tests Locally
|
||||||
|
|
||||||
To run tests, you need to prepare the docker image to test which must be tagged `nginxproxy/nginx-proxy:test`:
|
To run tests, you just need to run the command below:
|
||||||
|
|
||||||
docker build -t nginxproxy/nginx-proxy:test . # build the Debian variant image
|
|
||||||
|
|
||||||
and call the [test/pytest.sh](test/pytest.sh) script.
|
|
||||||
|
|
||||||
Then build the Alpine variant of the image:
|
|
||||||
|
|
||||||
docker build -f Dockerfile.alpine -t nginxproxy/nginx-proxy:test . # build the Alpline variant image
|
|
||||||
|
|
||||||
and call the [test/pytest.sh](test/pytest.sh) script again.
|
|
||||||
|
|
||||||
|
|
||||||
If your system has the `make` command, you can automate those tasks by calling:
|
|
||||||
|
|
||||||
make test
|
make test
|
||||||
|
|
||||||
|
This commands run tests on two variants of the nginx-proxy docker image: Debian and Alpine.
|
||||||
|
|
||||||
|
You can run the tests for each of these images with their respective commands:
|
||||||
|
|
||||||
|
make test-debian
|
||||||
|
make test-alpine
|
||||||
|
|
||||||
You can learn more about how the test suite works and how to write new tests in the [test/README.md](test/README.md) file.
|
You can learn more about how the test suite works and how to write new tests in the [test/README.md](test/README.md) file.
|
||||||
|
@ -4,9 +4,8 @@ Nginx proxy test suite
|
|||||||
Install requirements
|
Install requirements
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
You need [python 2.7](https://www.python.org/) and [pip](https://pip.pypa.io/en/stable/installing/) installed. Then run the commands:
|
You need [python 3.9](https://www.python.org/) and [pip](https://pip.pypa.io/en/stable/installing/) installed. Then run the commands:
|
||||||
|
|
||||||
requirements/build.sh
|
|
||||||
pip install -r requirements/python-requirements.txt
|
pip install -r requirements/python-requirements.txt
|
||||||
|
|
||||||
If you can't install those requirements on your computer, you can alternatively use the _pytest.sh_ script which will run the tests from a Docker container which has those requirements.
|
If you can't install those requirements on your computer, you can alternatively use the _pytest.sh_ script which will run the tests from a Docker container which has those requirements.
|
||||||
@ -15,14 +14,11 @@ If you can't install those requirements on your computer, you can alternatively
|
|||||||
Prepare the nginx-proxy test image
|
Prepare the nginx-proxy test image
|
||||||
----------------------------------
|
----------------------------------
|
||||||
|
|
||||||
docker build -t nginxproxy/nginx-proxy:test ..
|
make build-nginx-proxy-test-debian
|
||||||
|
|
||||||
or if you want to test the alpine flavor:
|
or if you want to test the alpine flavor:
|
||||||
|
|
||||||
docker build -t nginxproxy/nginx-proxy:test -f Dockerfile.alpine ..
|
make build-nginx-proxy-test-alpine
|
||||||
|
|
||||||
make sure to tag that test image exactly `nginxproxy/nginx-proxy:test` or the test suite won't work.
|
|
||||||
|
|
||||||
|
|
||||||
Run the test suite
|
Run the test suite
|
||||||
------------------
|
------------------
|
||||||
@ -61,7 +57,7 @@ The fixture will run the _docker-compose_ command with the `-f` option to load t
|
|||||||
|
|
||||||
In the case you are running pytest from within a docker container, the `docker_compose` fixture will make sure the container running pytest is attached to all docker networks. That way, your test will be able to reach any of them.
|
In the case you are running pytest from within a docker container, the `docker_compose` fixture will make sure the container running pytest is attached to all docker networks. That way, your test will be able to reach any of them.
|
||||||
|
|
||||||
In your tests, you can use the `docker_compose` variable to query and command the docker daemon as it provides you with a [client from the docker python module](https://docker-py.readthedocs.io/en/2.0.2/client.html#client-reference).
|
In your tests, you can use the `docker_compose` variable to query and command the docker daemon as it provides you with a [client from the docker python module](https://docker-py.readthedocs.io/en/4.4.4/client.html#client-reference).
|
||||||
|
|
||||||
Also this fixture alters the way the python interpreter resolves domain names to IP addresses in the following ways:
|
Also this fixture alters the way the python interpreter resolves domain names to IP addresses in the following ways:
|
||||||
|
|
||||||
@ -99,8 +95,7 @@ Furthermore, the nginxproxy methods accept an additional keyword parameter: `ipv
|
|||||||
|
|
||||||
### The web docker image
|
### The web docker image
|
||||||
|
|
||||||
When you ran the `requirements/build.sh` script earlier, you built a [`web`](requirements/README.md) docker image which is convenient for running a small web server in a container. This image can produce containers that listens on multiple ports at the same time.
|
When you run the `make build-webserver` command, you built a [`web`](requirements/README.md) docker image which is convenient for running a small web server in a container. This image can produce containers that listens on multiple ports at the same time.
|
||||||
|
|
||||||
|
|
||||||
### Testing TLS
|
### Testing TLS
|
||||||
|
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
from __future__ import print_function
|
|
||||||
import contextlib
|
import contextlib
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
@ -133,7 +132,7 @@ def container_ip(container):
|
|||||||
pytest.skip("This system does not support IPv6")
|
pytest.skip("This system does not support IPv6")
|
||||||
ip = container_ipv6(container)
|
ip = container_ipv6(container)
|
||||||
if ip == '':
|
if ip == '':
|
||||||
pytest.skip("Container %s has no IPv6 address" % container.name)
|
pytest.skip(f"Container {container.name} has no IPv6 address")
|
||||||
else:
|
else:
|
||||||
return ip
|
return ip
|
||||||
else:
|
else:
|
||||||
@ -142,7 +141,7 @@ def container_ip(container):
|
|||||||
return net_info["bridge"]["IPAddress"]
|
return net_info["bridge"]["IPAddress"]
|
||||||
|
|
||||||
# not default bridge network, fallback on first network defined
|
# not default bridge network, fallback on first network defined
|
||||||
network_name = net_info.keys()[0]
|
network_name = list(net_info.keys())[0]
|
||||||
return net_info[network_name]["IPAddress"]
|
return net_info[network_name]["IPAddress"]
|
||||||
|
|
||||||
|
|
||||||
@ -155,7 +154,7 @@ def container_ipv6(container):
|
|||||||
return net_info["bridge"]["GlobalIPv6Address"]
|
return net_info["bridge"]["GlobalIPv6Address"]
|
||||||
|
|
||||||
# not default bridge network, fallback on first network defined
|
# not default bridge network, fallback on first network defined
|
||||||
network_name = net_info.keys()[0]
|
network_name = list(net_info.keys())[0]
|
||||||
return net_info[network_name]["GlobalIPv6Address"]
|
return net_info[network_name]["GlobalIPv6Address"]
|
||||||
|
|
||||||
|
|
||||||
@ -167,15 +166,15 @@ def nginx_proxy_dns_resolver(domain_name):
|
|||||||
:return: IP or None
|
:return: IP or None
|
||||||
"""
|
"""
|
||||||
log = logging.getLogger('DNS')
|
log = logging.getLogger('DNS')
|
||||||
log.debug("nginx_proxy_dns_resolver(%r)" % domain_name)
|
log.debug(f"nginx_proxy_dns_resolver({domain_name!r})")
|
||||||
if 'nginx-proxy' in domain_name:
|
if 'nginx-proxy' in domain_name:
|
||||||
nginxproxy_containers = docker_client.containers.list(filters={"status": "running", "ancestor": "nginxproxy/nginx-proxy:test"})
|
nginxproxy_containers = docker_client.containers.list(filters={"status": "running", "ancestor": "nginxproxy/nginx-proxy:test"})
|
||||||
if len(nginxproxy_containers) == 0:
|
if len(nginxproxy_containers) == 0:
|
||||||
log.warn("no container found from image nginxproxy/nginx-proxy:test while resolving %r", domain_name)
|
log.warn(f"no container found from image nginxproxy/nginx-proxy:test while resolving {domain_name!r}")
|
||||||
return
|
return
|
||||||
nginxproxy_container = nginxproxy_containers[0]
|
nginxproxy_container = nginxproxy_containers[0]
|
||||||
ip = container_ip(nginxproxy_container)
|
ip = container_ip(nginxproxy_container)
|
||||||
log.info("resolving domain name %r as IP address %s of nginx-proxy container %s" % (domain_name, ip, nginxproxy_container.name))
|
log.info(f"resolving domain name {domain_name!r} as IP address {ip} of nginx-proxy container {nginxproxy_container.name}")
|
||||||
return ip
|
return ip
|
||||||
|
|
||||||
def docker_container_dns_resolver(domain_name):
|
def docker_container_dns_resolver(domain_name):
|
||||||
@ -186,24 +185,24 @@ def docker_container_dns_resolver(domain_name):
|
|||||||
:return: IP or None
|
:return: IP or None
|
||||||
"""
|
"""
|
||||||
log = logging.getLogger('DNS')
|
log = logging.getLogger('DNS')
|
||||||
log.debug("docker_container_dns_resolver(%r)" % domain_name)
|
log.debug(f"docker_container_dns_resolver({domain_name!r})")
|
||||||
|
|
||||||
match = re.search('(^|.+\.)(?P<container>[^.]+)\.container\.docker$', domain_name)
|
match = re.search(r'(^|.+\.)(?P<container>[^.]+)\.container\.docker$', domain_name)
|
||||||
if not match:
|
if not match:
|
||||||
log.debug("%r does not match" % domain_name)
|
log.debug(f"{domain_name!r} does not match")
|
||||||
return
|
return
|
||||||
|
|
||||||
container_name = match.group('container')
|
container_name = match.group('container')
|
||||||
log.debug("looking for container %r" % container_name)
|
log.debug(f"looking for container {container_name!r}")
|
||||||
try:
|
try:
|
||||||
container = docker_client.containers.get(container_name)
|
container = docker_client.containers.get(container_name)
|
||||||
except docker.errors.NotFound:
|
except docker.errors.NotFound:
|
||||||
log.warn("container named %r not found while resolving %r" % (container_name, domain_name))
|
log.warn(f"container named {container_name!r} not found while resolving {domain_name!r}")
|
||||||
return
|
return
|
||||||
log.debug("container %r found (%s)" % (container.name, container.short_id))
|
log.debug(f"container {container.name!r} found ({container.short_id})")
|
||||||
|
|
||||||
ip = container_ip(container)
|
ip = container_ip(container)
|
||||||
log.info("resolving domain name %r as IP address %s of container %s" % (domain_name, ip, container.name))
|
log.info(f"resolving domain name {domain_name!r} as IP address {ip} of container {container.name}")
|
||||||
return ip
|
return ip
|
||||||
|
|
||||||
|
|
||||||
@ -216,7 +215,7 @@ def monkey_patch_urllib_dns_resolver():
|
|||||||
prv_getaddrinfo = socket.getaddrinfo
|
prv_getaddrinfo = socket.getaddrinfo
|
||||||
dns_cache = {}
|
dns_cache = {}
|
||||||
def new_getaddrinfo(*args):
|
def new_getaddrinfo(*args):
|
||||||
logging.getLogger('DNS').debug("resolving domain name %s" % repr(args))
|
logging.getLogger('DNS').debug(f"resolving domain name {repr(args)}")
|
||||||
_args = list(args)
|
_args = list(args)
|
||||||
|
|
||||||
# custom DNS resolvers
|
# custom DNS resolvers
|
||||||
@ -244,7 +243,7 @@ def remove_all_containers():
|
|||||||
for container in docker_client.containers.list(all=True):
|
for container in docker_client.containers.list(all=True):
|
||||||
if I_AM_RUNNING_INSIDE_A_DOCKER_CONTAINER and container.id.startswith(socket.gethostname()):
|
if I_AM_RUNNING_INSIDE_A_DOCKER_CONTAINER and container.id.startswith(socket.gethostname()):
|
||||||
continue # pytest is running within a Docker container, so we do not want to remove that particular container
|
continue # pytest is running within a Docker container, so we do not want to remove that particular container
|
||||||
logging.info("removing container %s" % container.name)
|
logging.info(f"removing container {container.name}")
|
||||||
container.remove(v=True, force=True)
|
container.remove(v=True, force=True)
|
||||||
|
|
||||||
|
|
||||||
@ -253,27 +252,30 @@ def get_nginx_conf_from_container(container):
|
|||||||
return the nginx /etc/nginx/conf.d/default.conf file content from a container
|
return the nginx /etc/nginx/conf.d/default.conf file content from a container
|
||||||
"""
|
"""
|
||||||
import tarfile
|
import tarfile
|
||||||
from cStringIO import StringIO
|
from io import BytesIO
|
||||||
strm, stat = container.get_archive('/etc/nginx/conf.d/default.conf')
|
|
||||||
with tarfile.open(fileobj=StringIO(strm.read())) as tf:
|
strm_generator, stat = container.get_archive('/etc/nginx/conf.d/default.conf')
|
||||||
|
strm_fileobj = BytesIO(b"".join(strm_generator))
|
||||||
|
|
||||||
|
with tarfile.open(fileobj=strm_fileobj) as tf:
|
||||||
conffile = tf.extractfile('default.conf')
|
conffile = tf.extractfile('default.conf')
|
||||||
return conffile.read()
|
return conffile.read()
|
||||||
|
|
||||||
|
|
||||||
def docker_compose_up(compose_file='docker-compose.yml'):
|
def docker_compose_up(compose_file='docker-compose.yml'):
|
||||||
logging.info('docker-compose -f %s up -d' % compose_file)
|
logging.info(f'docker-compose -f {compose_file} up -d')
|
||||||
try:
|
try:
|
||||||
subprocess.check_output(shlex.split('docker-compose -f %s up -d' % compose_file), stderr=subprocess.STDOUT)
|
subprocess.check_output(shlex.split(f'docker-compose -f {compose_file} up -d'), stderr=subprocess.STDOUT)
|
||||||
except subprocess.CalledProcessError, e:
|
except subprocess.CalledProcessError as e:
|
||||||
pytest.fail("Error while runninng 'docker-compose -f %s up -d':\n%s" % (compose_file, e.output), pytrace=False)
|
pytest.fail(f"Error while runninng 'docker-compose -f {compose_file} up -d':\n{e.output}", pytrace=False)
|
||||||
|
|
||||||
|
|
||||||
def docker_compose_down(compose_file='docker-compose.yml'):
|
def docker_compose_down(compose_file='docker-compose.yml'):
|
||||||
logging.info('docker-compose -f %s down' % compose_file)
|
logging.info(f'docker-compose -f {compose_file} down')
|
||||||
try:
|
try:
|
||||||
subprocess.check_output(shlex.split('docker-compose -f %s down' % compose_file), stderr=subprocess.STDOUT)
|
subprocess.check_output(shlex.split(f'docker-compose -f {compose_file} down'), stderr=subprocess.STDOUT)
|
||||||
except subprocess.CalledProcessError, e:
|
except subprocess.CalledProcessError as e:
|
||||||
pytest.fail("Error while runninng 'docker-compose -f %s down':\n%s" % (compose_file, e.output), pytrace=False)
|
pytest.fail(f"Error while runninng 'docker-compose -f {compose_file} down':\n{e.output}", pytrace=False)
|
||||||
|
|
||||||
|
|
||||||
def wait_for_nginxproxy_to_be_ready():
|
def wait_for_nginxproxy_to_be_ready():
|
||||||
@ -286,7 +288,7 @@ def wait_for_nginxproxy_to_be_ready():
|
|||||||
return
|
return
|
||||||
container = containers[0]
|
container = containers[0]
|
||||||
for line in container.logs(stream=True):
|
for line in container.logs(stream=True):
|
||||||
if "Watching docker events" in line:
|
if b"Watching docker events" in line:
|
||||||
logging.debug("nginx-proxy ready")
|
logging.debug("nginx-proxy ready")
|
||||||
break
|
break
|
||||||
|
|
||||||
@ -307,7 +309,7 @@ def find_docker_compose_file(request):
|
|||||||
if docker_compose_file_module_variable is not None:
|
if docker_compose_file_module_variable is not None:
|
||||||
docker_compose_file = os.path.join( test_module_dir, docker_compose_file_module_variable)
|
docker_compose_file = os.path.join( test_module_dir, docker_compose_file_module_variable)
|
||||||
if not os.path.isfile(docker_compose_file):
|
if not os.path.isfile(docker_compose_file):
|
||||||
raise ValueError("docker compose file %r could not be found. Check your test module `docker_compose_file` variable value." % docker_compose_file)
|
raise ValueError(f"docker compose file {docker_compose_file!r} could not be found. Check your test module `docker_compose_file` variable value.")
|
||||||
else:
|
else:
|
||||||
if os.path.isfile(yml_file):
|
if os.path.isfile(yml_file):
|
||||||
docker_compose_file = yml_file
|
docker_compose_file = yml_file
|
||||||
@ -319,7 +321,7 @@ def find_docker_compose_file(request):
|
|||||||
if not os.path.isfile(docker_compose_file):
|
if not os.path.isfile(docker_compose_file):
|
||||||
logging.error("Could not find any docker-compose file named either '{0}.yml', '{0}.yaml' or 'docker-compose.yml'".format(request.module.__name__))
|
logging.error("Could not find any docker-compose file named either '{0}.yml', '{0}.yaml' or 'docker-compose.yml'".format(request.module.__name__))
|
||||||
|
|
||||||
logging.debug("using docker compose file %s" % docker_compose_file)
|
logging.debug(f"using docker compose file {docker_compose_file}")
|
||||||
return docker_compose_file
|
return docker_compose_file
|
||||||
|
|
||||||
|
|
||||||
@ -333,15 +335,15 @@ def connect_to_network(network):
|
|||||||
try:
|
try:
|
||||||
my_container = docker_client.containers.get(socket.gethostname())
|
my_container = docker_client.containers.get(socket.gethostname())
|
||||||
except docker.errors.NotFound:
|
except docker.errors.NotFound:
|
||||||
logging.warn("container %r not found" % socket.gethostname())
|
logging.warn(f"container {socket.gethostname()!r} not found")
|
||||||
return
|
return
|
||||||
|
|
||||||
# figure out our container networks
|
# figure out our container networks
|
||||||
my_networks = my_container.attrs["NetworkSettings"]["Networks"].keys()
|
my_networks = list(my_container.attrs["NetworkSettings"]["Networks"].keys())
|
||||||
|
|
||||||
# make sure our container is connected to the nginx-proxy's network
|
# make sure our container is connected to the nginx-proxy's network
|
||||||
if network not in my_networks:
|
if network not in my_networks:
|
||||||
logging.info("Connecting to docker network: %s" % network.name)
|
logging.info(f"Connecting to docker network: {network.name}")
|
||||||
network.connect(my_container)
|
network.connect(my_container)
|
||||||
return network
|
return network
|
||||||
|
|
||||||
@ -356,15 +358,15 @@ def disconnect_from_network(network=None):
|
|||||||
try:
|
try:
|
||||||
my_container = docker_client.containers.get(socket.gethostname())
|
my_container = docker_client.containers.get(socket.gethostname())
|
||||||
except docker.errors.NotFound:
|
except docker.errors.NotFound:
|
||||||
logging.warn("container %r not found" % socket.gethostname())
|
logging.warn(f"container {socket.gethostname()!r} not found")
|
||||||
return
|
return
|
||||||
|
|
||||||
# figure out our container networks
|
# figure out our container networks
|
||||||
my_networks_names = my_container.attrs["NetworkSettings"]["Networks"].keys()
|
my_networks_names = list(my_container.attrs["NetworkSettings"]["Networks"].keys())
|
||||||
|
|
||||||
# disconnect our container from the given network
|
# disconnect our container from the given network
|
||||||
if network.name in my_networks_names:
|
if network.name in my_networks_names:
|
||||||
logging.info("Disconnecting from network %s" % network.name)
|
logging.info(f"Disconnecting from network {network.name}")
|
||||||
network.disconnect(my_container)
|
network.disconnect(my_container)
|
||||||
|
|
||||||
|
|
||||||
@ -378,7 +380,7 @@ def connect_to_all_networks():
|
|||||||
return []
|
return []
|
||||||
else:
|
else:
|
||||||
# find the list of docker networks
|
# find the list of docker networks
|
||||||
networks = filter(lambda network: len(network.containers) > 0 and network.name != 'bridge', docker_client.networks.list())
|
networks = [network for network in docker_client.networks.list() if len(network.containers) > 0 and network.name != 'bridge']
|
||||||
return [connect_to_network(network) for network in networks]
|
return [connect_to_network(network) for network in networks]
|
||||||
|
|
||||||
|
|
||||||
@ -388,7 +390,7 @@ def connect_to_all_networks():
|
|||||||
#
|
#
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
@pytest.yield_fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def docker_compose(request):
|
def docker_compose(request):
|
||||||
"""
|
"""
|
||||||
pytest fixture providing containers described in a docker compose file. After the tests, remove the created containers
|
pytest fixture providing containers described in a docker compose file. After the tests, remove the created containers
|
||||||
@ -412,7 +414,7 @@ def docker_compose(request):
|
|||||||
restore_urllib_dns_resolver(original_dns_resolver)
|
restore_urllib_dns_resolver(original_dns_resolver)
|
||||||
|
|
||||||
|
|
||||||
@pytest.yield_fixture()
|
@pytest.fixture()
|
||||||
def nginxproxy():
|
def nginxproxy():
|
||||||
"""
|
"""
|
||||||
Provides the `nginxproxy` object that can be used in the same way the requests module is:
|
Provides the `nginxproxy` object that can be used in the same way the requests module is:
|
||||||
@ -456,7 +458,7 @@ def pytest_runtest_makereport(item, call):
|
|||||||
def pytest_runtest_setup(item):
|
def pytest_runtest_setup(item):
|
||||||
previousfailed = getattr(item.parent, "_previousfailed", None)
|
previousfailed = getattr(item.parent, "_previousfailed", None)
|
||||||
if previousfailed is not None:
|
if previousfailed is not None:
|
||||||
pytest.xfail("previous test failed (%s)" % previousfailed.name)
|
pytest.xfail(f"previous test failed ({previousfailed.name})")
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
#
|
#
|
||||||
@ -469,5 +471,5 @@ try:
|
|||||||
except docker.errors.ImageNotFound:
|
except docker.errors.ImageNotFound:
|
||||||
pytest.exit("The docker image 'nginxproxy/nginx-proxy:test' is missing")
|
pytest.exit("The docker image 'nginxproxy/nginx-proxy:test' is missing")
|
||||||
|
|
||||||
if docker.__version__ != "2.1.0":
|
if docker.__version__ != "4.4.4":
|
||||||
pytest.exit("This test suite is meant to work with the python docker module v2.1.0")
|
pytest.exit("This test suite is meant to work with the python docker module v4.4.4")
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
[pytest]
|
[pytest]
|
||||||
# disable the creation of the `.cache` folders
|
# disable the creation of the `.cache` folders
|
||||||
addopts = -p no:cacheprovider --ignore=requirements --ignore=certs -r s -v
|
addopts = -p no:cacheprovider --ignore=requirements --ignore=certs -r s -v
|
||||||
|
markers =
|
||||||
|
incremental: mark a test as incremental.
|
@ -1,7 +1,4 @@
|
|||||||
FROM python:2.7-alpine
|
FROM python:3.9
|
||||||
|
|
||||||
# Note: we're using alpine because it has openssl 1.0.2, which we need for testing
|
|
||||||
RUN apk add --update bash openssl curl && rm -rf /var/cache/apk/*
|
|
||||||
|
|
||||||
COPY python-requirements.txt /requirements.txt
|
COPY python-requirements.txt /requirements.txt
|
||||||
RUN pip install -r /requirements.txt
|
RUN pip install -r /requirements.txt
|
||||||
|
@ -2,7 +2,7 @@ This directory contains resources to build Docker images tests depend on
|
|||||||
|
|
||||||
# Build images
|
# Build images
|
||||||
|
|
||||||
./build.sh
|
make build-webserver
|
||||||
|
|
||||||
|
|
||||||
# python-requirements.txt
|
# python-requirements.txt
|
||||||
|
@ -1,6 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
|
|
||||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|
||||||
|
|
||||||
docker build -t web $DIR/web
|
|
@ -1,5 +1,5 @@
|
|||||||
backoff==1.3.2
|
backoff==1.10.0
|
||||||
docker-compose==1.11.2
|
docker-compose==1.28.5
|
||||||
docker==2.1.0
|
docker==4.4.4
|
||||||
pytest==3.0.5
|
pytest==6.2.2
|
||||||
requests==2.11.1
|
requests==2.25.1
|
||||||
|
@ -13,13 +13,13 @@ class Handler(http.server.SimpleHTTPRequestHandler):
|
|||||||
if self.path == "/headers":
|
if self.path == "/headers":
|
||||||
response_body += self.headers.as_string()
|
response_body += self.headers.as_string()
|
||||||
elif self.path == "/port":
|
elif self.path == "/port":
|
||||||
response_body += "answer from port %s\n" % PORT
|
response_body += f"answer from port {PORT}\n"
|
||||||
elif re.match("/status/(\d+)", self.path):
|
elif re.match("/status/(\d+)", self.path):
|
||||||
result = re.match("/status/(\d+)", self.path)
|
result = re.match("/status/(\d+)", self.path)
|
||||||
response_code = int(result.group(1))
|
response_code = int(result.group(1))
|
||||||
response_body += "answer with response code %s\n" % response_code
|
response_body += f"answer with response code {response_code}\n"
|
||||||
elif self.path == "/":
|
elif self.path == "/":
|
||||||
response_body += "I'm %s\n" % os.environ['HOSTNAME']
|
response_body += f"I'm {os.environ['HOSTNAME']}\n"
|
||||||
else:
|
else:
|
||||||
response_body += "No route for this path!\n"
|
response_body += "No route for this path!\n"
|
||||||
response_code = 404
|
response_code = 404
|
||||||
|
@ -12,7 +12,7 @@ script_dir = os.path.dirname(__file__)
|
|||||||
pytestmark = pytest.mark.xfail() # TODO delete this marker once those issues are fixed
|
pytestmark = pytest.mark.xfail() # TODO delete this marker once those issues are fixed
|
||||||
|
|
||||||
|
|
||||||
@pytest.yield_fixture(scope="module", autouse=True)
|
@pytest.fixture(scope="module", autouse=True)
|
||||||
def certs():
|
def certs():
|
||||||
"""
|
"""
|
||||||
pytest fixture that provides cert and key files into the tmp_certs directory
|
pytest fixture that provides cert and key files into the tmp_certs directory
|
||||||
@ -43,7 +43,7 @@ def test_http_web_is_301(docker_compose, nginxproxy):
|
|||||||
def test_https_web_is_200(docker_compose, nginxproxy):
|
def test_https_web_is_200(docker_compose, nginxproxy):
|
||||||
r = nginxproxy.get("https://web.nginx-proxy/port")
|
r = nginxproxy.get("https://web.nginx-proxy/port")
|
||||||
assert r.status_code == 200
|
assert r.status_code == 200
|
||||||
assert 'answer from port 81\n' in r.text
|
assert "answer from port 81\n" in r.text
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.incremental
|
@pytest.mark.incremental
|
||||||
|
@ -19,4 +19,4 @@ def test_custom_conf_does_not_apply_to_web2(docker_compose, nginxproxy):
|
|||||||
assert "X-test" not in r.headers
|
assert "X-test" not in r.headers
|
||||||
|
|
||||||
def test_custom_block_is_present_in_nginx_generated_conf(docker_compose, nginxproxy):
|
def test_custom_block_is_present_in_nginx_generated_conf(docker_compose, nginxproxy):
|
||||||
assert "include /etc/nginx/vhost.d/web1.nginx-proxy.local_location;" in nginxproxy.get_conf()
|
assert b"include /etc/nginx/vhost.d/web1.nginx-proxy.local_location;" in nginxproxy.get_conf()
|
@ -10,7 +10,7 @@ web1:
|
|||||||
|
|
||||||
# WHEN nginx-proxy runs with DEFAULT_HOST set to web1.tld
|
# WHEN nginx-proxy runs with DEFAULT_HOST set to web1.tld
|
||||||
sut:
|
sut:
|
||||||
image: jwilder/nginx-proxy:test
|
image: nginxproxy/nginx-proxy:test
|
||||||
volumes:
|
volumes:
|
||||||
- /var/run/docker.sock:/tmp/docker.sock:ro
|
- /var/run/docker.sock:/tmp/docker.sock:ro
|
||||||
- ./lib/ssl/dhparam.pem:/etc/nginx/dhparam/dhparam.pem:ro
|
- ./lib/ssl/dhparam.pem:/etc/nginx/dhparam/dhparam.pem:ro
|
||||||
|
@ -4,7 +4,7 @@ import logging
|
|||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
@pytest.yield_fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def nginx_tmpl():
|
def nginx_tmpl():
|
||||||
"""
|
"""
|
||||||
pytest fixture which extracts the the nginx config template from
|
pytest fixture which extracts the the nginx config template from
|
||||||
@ -13,14 +13,18 @@ def nginx_tmpl():
|
|||||||
script_dir = os.path.dirname(__file__)
|
script_dir = os.path.dirname(__file__)
|
||||||
logging.info("extracting nginx.tmpl from nginxproxy/nginx-proxy:test")
|
logging.info("extracting nginx.tmpl from nginxproxy/nginx-proxy:test")
|
||||||
docker_client = docker.from_env()
|
docker_client = docker.from_env()
|
||||||
print(docker_client.containers.run(
|
print(
|
||||||
image='nginxproxy/nginx-proxy:test',
|
docker_client.containers.run(
|
||||||
|
image="nginxproxy/nginx-proxy:test",
|
||||||
remove=True,
|
remove=True,
|
||||||
volumes=['{current_dir}:{current_dir}'.format(current_dir=script_dir)],
|
volumes=["{current_dir}:{current_dir}".format(current_dir=script_dir)],
|
||||||
entrypoint='sh',
|
entrypoint="sh",
|
||||||
command='-xc "cp /app/nginx.tmpl {current_dir} && chmod 777 {current_dir}/nginx.tmpl"'.format(
|
command='-xc "cp /app/nginx.tmpl {current_dir} && chmod 777 {current_dir}/nginx.tmpl"'.format(
|
||||||
current_dir=script_dir),
|
current_dir=script_dir
|
||||||
stderr=True))
|
),
|
||||||
|
stderr=True,
|
||||||
|
)
|
||||||
|
)
|
||||||
yield
|
yield
|
||||||
logging.info("removing nginx.tmpl")
|
logging.info("removing nginx.tmpl")
|
||||||
os.remove(os.path.join(script_dir, "nginx.tmpl"))
|
os.remove(os.path.join(script_dir, "nginx.tmpl"))
|
||||||
@ -35,4 +39,4 @@ def test_forwards_to_whoami(nginx_tmpl, docker_compose, nginxproxy):
|
|||||||
r = nginxproxy.get("http://whoami.nginx.container.docker/")
|
r = nginxproxy.get("http://whoami.nginx.container.docker/")
|
||||||
assert r.status_code == 200
|
assert r.status_code == 200
|
||||||
whoami_container = docker_compose.containers.get("whoami")
|
whoami_container = docker_compose.containers.get("whoami")
|
||||||
assert r.text == "I'm %s\n" % whoami_container.id[:12]
|
assert r.text == f"I'm {whoami_container.id[:12]}\n"
|
||||||
|
@ -3,31 +3,17 @@ import docker
|
|||||||
import logging
|
import logging
|
||||||
import pytest
|
import pytest
|
||||||
import re
|
import re
|
||||||
|
from distutils.version import LooseVersion
|
||||||
def versiontuple(v):
|
|
||||||
"""
|
|
||||||
>>> versiontuple("1.12.3")
|
|
||||||
(1, 12, 3)
|
|
||||||
|
|
||||||
>>> versiontuple("1.13.0")
|
|
||||||
(1, 13, 0)
|
|
||||||
|
|
||||||
>>> versiontuple("17.03.0-ce")
|
|
||||||
(17, 3, 0)
|
|
||||||
|
|
||||||
>>> versiontuple("17.03.0-ce") < (1, 13)
|
|
||||||
False
|
|
||||||
"""
|
|
||||||
return tuple(map(int, (v.split('-')[0].split("."))))
|
|
||||||
|
|
||||||
|
|
||||||
raw_version = docker.from_env().version()['Version']
|
raw_version = docker.from_env().version()["Version"]
|
||||||
pytestmark = pytest.mark.skipif(
|
pytestmark = pytest.mark.skipif(
|
||||||
versiontuple(raw_version) < (1, 13),
|
LooseVersion(raw_version) < LooseVersion("1.13"),
|
||||||
reason="Docker compose syntax v3 requires docker engine v1.13 or later (got %s)" % raw_version)
|
reason="Docker compose syntax v3 requires docker engine v1.13 or later (got {raw_version})"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.yield_fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def nginx_tmpl():
|
def nginx_tmpl():
|
||||||
"""
|
"""
|
||||||
pytest fixture which extracts the the nginx config template from
|
pytest fixture which extracts the the nginx config template from
|
||||||
@ -36,14 +22,18 @@ def nginx_tmpl():
|
|||||||
script_dir = os.path.dirname(__file__)
|
script_dir = os.path.dirname(__file__)
|
||||||
logging.info("extracting nginx.tmpl from nginxproxy/nginx-proxy:test")
|
logging.info("extracting nginx.tmpl from nginxproxy/nginx-proxy:test")
|
||||||
docker_client = docker.from_env()
|
docker_client = docker.from_env()
|
||||||
print(docker_client.containers.run(
|
print(
|
||||||
image='nginxproxy/nginx-proxy:test',
|
docker_client.containers.run(
|
||||||
|
image="nginxproxy/nginx-proxy:test",
|
||||||
remove=True,
|
remove=True,
|
||||||
volumes=['{current_dir}:{current_dir}'.format(current_dir=script_dir)],
|
volumes=["{current_dir}:{current_dir}".format(current_dir=script_dir)],
|
||||||
entrypoint='sh',
|
entrypoint="sh",
|
||||||
command='-xc "cp /app/nginx.tmpl {current_dir} && chmod 777 {current_dir}/nginx.tmpl"'.format(
|
command='-xc "cp /app/nginx.tmpl {current_dir} && chmod 777 {current_dir}/nginx.tmpl"'.format(
|
||||||
current_dir=script_dir),
|
current_dir=script_dir
|
||||||
stderr=True))
|
),
|
||||||
|
stderr=True,
|
||||||
|
)
|
||||||
|
)
|
||||||
yield
|
yield
|
||||||
logging.info("removing nginx.tmpl")
|
logging.info("removing nginx.tmpl")
|
||||||
os.remove(os.path.join(script_dir, "nginx.tmpl"))
|
os.remove(os.path.join(script_dir, "nginx.tmpl"))
|
||||||
@ -58,9 +48,9 @@ def test_forwards_to_whoami(nginx_tmpl, docker_compose, nginxproxy):
|
|||||||
r = nginxproxy.get("http://whoami.nginx.container.docker/")
|
r = nginxproxy.get("http://whoami.nginx.container.docker/")
|
||||||
assert r.status_code == 200
|
assert r.status_code == 200
|
||||||
whoami_container = docker_compose.containers.get("whoami")
|
whoami_container = docker_compose.containers.get("whoami")
|
||||||
assert r.text == "I'm %s\n" % whoami_container.id[:12]
|
assert r.text == f"I'm {whoami_container.id[:12]}\n"
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == "__main__":
|
||||||
import doctest
|
import doctest
|
||||||
doctest.testmod()
|
doctest.testmod()
|
||||||
|
@ -7,7 +7,7 @@ import pytest
|
|||||||
from docker.errors import NotFound
|
from docker.errors import NotFound
|
||||||
|
|
||||||
|
|
||||||
@pytest.yield_fixture()
|
@pytest.fixture()
|
||||||
def web1(docker_compose):
|
def web1(docker_compose):
|
||||||
"""
|
"""
|
||||||
pytest fixture creating a web container with `VIRTUAL_HOST=web1.nginx-proxy` listening on port 81.
|
pytest fixture creating a web container with `VIRTUAL_HOST=web1.nginx-proxy` listening on port 81.
|
||||||
|
@ -26,7 +26,7 @@ def assert_log_contains(expected_log_line):
|
|||||||
"""
|
"""
|
||||||
sut_container = docker_client.containers.get("nginxproxy")
|
sut_container = docker_client.containers.get("nginxproxy")
|
||||||
docker_logs = sut_container.logs(stdout=True, stderr=True, stream=False, follow=False)
|
docker_logs = sut_container.logs(stdout=True, stderr=True, stream=False, follow=False)
|
||||||
assert expected_log_line in docker_logs
|
assert bytes(expected_log_line, encoding="utf8") in docker_logs
|
||||||
|
|
||||||
|
|
||||||
def require_openssl(required_version):
|
def require_openssl(required_version):
|
||||||
@ -42,7 +42,7 @@ def require_openssl(required_version):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def versiontuple(v):
|
def versiontuple(v):
|
||||||
clean_v = re.sub("[^\d\.]", "", v)
|
clean_v = re.sub(r"[^\d\.]", "", v)
|
||||||
return tuple(map(int, (clean_v.split("."))))
|
return tuple(map(int, (clean_v.split("."))))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -52,10 +52,10 @@ def require_openssl(required_version):
|
|||||||
else:
|
else:
|
||||||
if not command_output:
|
if not command_output:
|
||||||
raise Exception("Could not get openssl version")
|
raise Exception("Could not get openssl version")
|
||||||
openssl_version = command_output.split()[1]
|
openssl_version = str(command_output.split()[1])
|
||||||
return pytest.mark.skipif(
|
return pytest.mark.skipif(
|
||||||
versiontuple(openssl_version) < versiontuple(required_version),
|
versiontuple(openssl_version) < versiontuple(required_version),
|
||||||
reason="openssl v%s is less than required version %s" % (openssl_version, required_version))
|
reason=f"openssl v{openssl_version} is less than required version {required_version}")
|
||||||
|
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
@ -71,8 +71,8 @@ def test_dhparam_is_not_generated_if_present(docker_compose):
|
|||||||
assert_log_contains("Custom dhparam.pem file found, generation skipped")
|
assert_log_contains("Custom dhparam.pem file found, generation skipped")
|
||||||
|
|
||||||
# Make sure the dhparam in use is not the default, pre-generated one
|
# Make sure the dhparam in use is not the default, pre-generated one
|
||||||
default_checksum = sut_container.exec_run("md5sum /app/dhparam.pem.default").split()
|
default_checksum = sut_container.exec_run("md5sum /app/dhparam.pem.default").output.split()
|
||||||
current_checksum = sut_container.exec_run("md5sum /etc/nginx/dhparam/dhparam.pem").split()
|
current_checksum = sut_container.exec_run("md5sum /etc/nginx/dhparam/dhparam.pem").output.split()
|
||||||
assert default_checksum[0] != current_checksum[0]
|
assert default_checksum[0] != current_checksum[0]
|
||||||
|
|
||||||
|
|
||||||
@ -87,7 +87,7 @@ def test_web5_dhparam_is_used(docker_compose):
|
|||||||
sut_container = docker_client.containers.get("nginxproxy")
|
sut_container = docker_client.containers.get("nginxproxy")
|
||||||
assert sut_container.status == "running"
|
assert sut_container.status == "running"
|
||||||
|
|
||||||
host = "%s:443" % sut_container.attrs["NetworkSettings"]["IPAddress"]
|
host = f"{sut_container.attrs['NetworkSettings']['IPAddress']}:443"
|
||||||
r = subprocess.check_output(
|
r = subprocess.check_output(
|
||||||
"echo '' | openssl s_client -connect %s -cipher 'EDH' | grep 'Server Temp Key'" % host, shell=True)
|
f"echo '' | openssl s_client -connect {host} -cipher 'EDH' | grep 'Server Temp Key'", shell=True)
|
||||||
assert "Server Temp Key: X25519, 253 bits\n" == r
|
assert b"Server Temp Key: X25519, 253 bits\n" == r
|
||||||
|
@ -22,7 +22,7 @@ def assert_log_contains(expected_log_line):
|
|||||||
"""
|
"""
|
||||||
sut_container = docker_client.containers.get("nginxproxy")
|
sut_container = docker_client.containers.get("nginxproxy")
|
||||||
docker_logs = sut_container.logs(stdout=True, stderr=True, stream=False, follow=False)
|
docker_logs = sut_container.logs(stdout=True, stderr=True, stream=False, follow=False)
|
||||||
assert expected_log_line in docker_logs
|
assert bytes(expected_log_line, encoding="utf8") in docker_logs
|
||||||
|
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
@ -35,10 +35,10 @@ def test_dhparam_is_generated_if_missing(docker_compose):
|
|||||||
sut_container = docker_client.containers.get("nginxproxy")
|
sut_container = docker_client.containers.get("nginxproxy")
|
||||||
assert sut_container.status == "running"
|
assert sut_container.status == "running"
|
||||||
|
|
||||||
assert_log_contains("Generating DH parameters")
|
assert_log_contains("Generating DSA parameters")
|
||||||
assert_log_contains("dhparam generation complete, reloading nginx")
|
assert_log_contains("dhparam generation complete, reloading nginx")
|
||||||
|
|
||||||
# Make sure the dhparam in use is not the default, pre-generated one
|
# Make sure the dhparam in use is not the default, pre-generated one
|
||||||
default_checksum = sut_container.exec_run("md5sum /app/dhparam.pem.default").split()
|
default_checksum = sut_container.exec_run("md5sum /app/dhparam.pem.default").output.split()
|
||||||
generated_checksum = sut_container.exec_run("md5sum /etc/nginx/dhparam/dhparam.pem").split()
|
generated_checksum = sut_container.exec_run("md5sum /etc/nginx/dhparam/dhparam.pem").output.split()
|
||||||
assert default_checksum[0] != generated_checksum[0]
|
assert default_checksum[0] != generated_checksum[0]
|
||||||
|
@ -3,21 +3,21 @@ import pytest
|
|||||||
|
|
||||||
@pytest.mark.parametrize("subdomain", ["foo", "bar"])
|
@pytest.mark.parametrize("subdomain", ["foo", "bar"])
|
||||||
def test_web1_http_redirects_to_https(docker_compose, nginxproxy, subdomain):
|
def test_web1_http_redirects_to_https(docker_compose, nginxproxy, subdomain):
|
||||||
r = nginxproxy.get("http://%s.nginx-proxy.tld/" % subdomain, allow_redirects=False)
|
r = nginxproxy.get(f"http://{subdomain}.nginx-proxy.tld/", allow_redirects=False)
|
||||||
assert r.status_code == 301
|
assert r.status_code == 301
|
||||||
assert "Location" in r.headers
|
assert "Location" in r.headers
|
||||||
assert "https://%s.nginx-proxy.tld/" % subdomain == r.headers['Location']
|
assert f"https://{subdomain}.nginx-proxy.tld/" == r.headers['Location']
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("subdomain", ["foo", "bar"])
|
@pytest.mark.parametrize("subdomain", ["foo", "bar"])
|
||||||
def test_web1_https_is_forwarded(docker_compose, nginxproxy, subdomain):
|
def test_web1_https_is_forwarded(docker_compose, nginxproxy, subdomain):
|
||||||
r = nginxproxy.get("https://%s.nginx-proxy.tld/port" % subdomain, allow_redirects=False)
|
r = nginxproxy.get(f"https://{subdomain}.nginx-proxy.tld/port", allow_redirects=False)
|
||||||
assert r.status_code == 200
|
assert r.status_code == 200
|
||||||
assert "answer from port 81\n" in r.text
|
assert "answer from port 81\n" in r.text
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("subdomain", ["foo", "bar"])
|
@pytest.mark.parametrize("subdomain", ["foo", "bar"])
|
||||||
def test_web1_HSTS_policy_is_active(docker_compose, nginxproxy, subdomain):
|
def test_web1_HSTS_policy_is_active(docker_compose, nginxproxy, subdomain):
|
||||||
r = nginxproxy.get("https://%s.nginx-proxy.tld/port" % subdomain, allow_redirects=False)
|
r = nginxproxy.get(f"https://{subdomain}.nginx-proxy.tld/port", allow_redirects=False)
|
||||||
assert "answer from port 81\n" in r.text
|
assert "answer from port 81\n" in r.text
|
||||||
assert "Strict-Transport-Security" in r.headers
|
assert "Strict-Transport-Security" in r.headers
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import pytest
|
import pytest
|
||||||
from backports.ssl_match_hostname import CertificateError
|
from ssl import CertificateError
|
||||||
from requests.exceptions import SSLError
|
from requests.exceptions import SSLError
|
||||||
|
|
||||||
|
|
||||||
@ -9,19 +9,19 @@ from requests.exceptions import SSLError
|
|||||||
(3, False),
|
(3, False),
|
||||||
])
|
])
|
||||||
def test_http_redirects_to_https(docker_compose, nginxproxy, subdomain, should_redirect_to_https):
|
def test_http_redirects_to_https(docker_compose, nginxproxy, subdomain, should_redirect_to_https):
|
||||||
r = nginxproxy.get("http://%s.web.nginx-proxy.tld/port" % subdomain)
|
r = nginxproxy.get(f"http://{subdomain}.web.nginx-proxy.tld/port")
|
||||||
if should_redirect_to_https:
|
if should_redirect_to_https:
|
||||||
assert len(r.history) > 0
|
assert len(r.history) > 0
|
||||||
assert r.history[0].is_redirect
|
assert r.history[0].is_redirect
|
||||||
assert r.history[0].headers.get("Location") == "https://%s.web.nginx-proxy.tld/port" % subdomain
|
assert r.history[0].headers.get("Location") == f"https://{subdomain}.web.nginx-proxy.tld/port"
|
||||||
assert "answer from port 8%s\n" % subdomain == r.text
|
assert f"answer from port 8{subdomain}\n" == r.text
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("subdomain", [1, 2])
|
@pytest.mark.parametrize("subdomain", [1, 2])
|
||||||
def test_https_get_served(docker_compose, nginxproxy, subdomain):
|
def test_https_get_served(docker_compose, nginxproxy, subdomain):
|
||||||
r = nginxproxy.get("https://%s.web.nginx-proxy.tld/port" % subdomain, allow_redirects=False)
|
r = nginxproxy.get(f"https://{subdomain}.web.nginx-proxy.tld/port", allow_redirects=False)
|
||||||
assert r.status_code == 200
|
assert r.status_code == 200
|
||||||
assert "answer from port 8%s\n" % subdomain == r.text
|
assert f"answer from port 8{subdomain}\n" == r.text
|
||||||
|
|
||||||
|
|
||||||
def test_web3_https_is_500_and_SSL_validation_fails(docker_compose, nginxproxy):
|
def test_web3_https_is_500_and_SSL_validation_fails(docker_compose, nginxproxy):
|
||||||
|
@ -18,9 +18,9 @@ import pytest
|
|||||||
("web4.whatever.nginx-proxy.regexp", 84),
|
("web4.whatever.nginx-proxy.regexp", 84),
|
||||||
])
|
])
|
||||||
def test_wildcard_prefix(docker_compose, nginxproxy, host, expected_port):
|
def test_wildcard_prefix(docker_compose, nginxproxy, host, expected_port):
|
||||||
r = nginxproxy.get("http://%s/port" % host)
|
r = nginxproxy.get(f"http://{host}/port")
|
||||||
assert r.status_code == 200
|
assert r.status_code == 200
|
||||||
assert r.text == "answer from port %s\n" % expected_port
|
assert r.text == f"answer from port {expected_port}\n"
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("host", [
|
@pytest.mark.parametrize("host", [
|
||||||
@ -28,5 +28,5 @@ def test_wildcard_prefix(docker_compose, nginxproxy, host, expected_port):
|
|||||||
"web4.whatever.nginx-proxy.regexp-to-infinity-and-beyond"
|
"web4.whatever.nginx-proxy.regexp-to-infinity-and-beyond"
|
||||||
])
|
])
|
||||||
def test_non_matching_host_is_503(docker_compose, nginxproxy, host):
|
def test_non_matching_host_is_503(docker_compose, nginxproxy, host):
|
||||||
r = nginxproxy.get("http://%s/port" % host)
|
r = nginxproxy.get(f"http://{host}/port")
|
||||||
assert r.status_code == 503, r.text
|
assert r.status_code == 503, r.text
|
||||||
|
Loading…
x
Reference in New Issue
Block a user