repo2docker/tests/unit/test_ports.py

130 wiersze
3.3 KiB
Python

"""
Test Port mappings work on running non-jupyter workflows
"""
import os
import random
import tempfile
import time
from getpass import getuser
import pytest
import requests
import docker
from repo2docker.__main__ import make_r2d
from repo2docker.app import Repo2Docker
def read_port_mapping_response(
request, tmpdir, host=None, port="", all_ports=False, protocol=None
):
"""
Deploy container and test if port mappings work as expected
Args:
request: pytest request fixture
host: the host interface to bind to
port: the random host port to bind to
protocol: the protocol to use valid values /tcp or /udp
"""
port_protocol = "8888"
if protocol:
port_protocol += protocol
host_port = port
if host:
host_port = (host, port)
else:
host = "localhost"
if port:
ports = {port_protocol: host_port}
else:
ports = {}
# run in an empty temporary directory
td = tempfile.TemporaryDirectory()
# cleanup at the end of the test
request.addfinalizer(td.cleanup)
tmpdir.chdir()
username = getuser()
tmpdir.mkdir("username")
r2d = Repo2Docker(
repo=str(tmpdir.mkdir("repo")),
user_id=os.geteuid(),
user_name=username,
all_ports=all_ports,
ports=ports,
run=True,
run_cmd=["python", "-m", "http.server", "8888"],
)
r2d.initialize()
r2d.build()
# create container
container = r2d.start_container()
# register cleanup first thing so we don't leave it lying around
def _cleanup():
container.reload()
if container.status == "running":
container.kill()
try:
container.remove()
except docker.errors.NotFound:
pass
request.addfinalizer(_cleanup)
container.reload()
assert container.status == "running"
port_mapping = container._c.attrs["NetworkSettings"]["Ports"]
if all_ports:
port = port_mapping["8888/tcp"][0]["HostPort"]
url = f"http://{host}:{port}"
for i in range(5):
try:
r = requests.get(url)
r.raise_for_status()
except Exception as e:
print(f"No response from {url}: {e}")
container.reload()
assert container.status == "running"
time.sleep(3)
continue
else:
break
else:
pytest.fail(f"Never succeeded in talking to {url}")
assert "Directory listing" in r.text
def test_all_port_mapping_response(request, tmpdir):
"""
Deploy container and test if all port exposed works as expected
"""
read_port_mapping_response(request, tmpdir, all_ports=True)
@pytest.mark.parametrize(
"host, protocol", [(None, None), ("127.0.0.1", None), (None, "/tcp")]
)
def test_port_mapping(request, tmpdir, host, protocol):
"""Test a port mapping"""
port = str(random.randint(50000, 51000))
read_port_mapping_response(request, tmpdir, host=host, port=port, protocol=protocol)
@pytest.mark.parametrize(
"port_str, port_dict",
[
("8000", {"8000/tcp": "8000"}),
("8000:9000", {"9000/tcp": "8000"}),
("127.0.0.1:8000:9000", {"9000/tcp": ("127.0.0.1", "8000")}),
],
)
def test_port_args(port_str, port_dict):
app = make_r2d(["-p", port_str, "."])
assert app.ports == port_dict