""" Test Port mappings work on running non-jupyter workflows """ import requests import time import os import tempfile import random from getpass import getuser import docker import pytest 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.attrs["NetworkSettings"]["Ports"] if all_ports: port = port_mapping["8888/tcp"][0]["HostPort"] url = "http://{}:{}".format(host, port) for i in range(5): try: r = requests.get(url) r.raise_for_status() except Exception as e: print("No response from {}: {}".format(url, e)) container.reload() assert container.status == "running" time.sleep(3) continue else: break else: pytest.fail("Never succeded in talking to %s" % 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)