mirror of
https://github.com/jupyter/docker-stacks.git
synced 2025-10-07 01:54:04 +00:00
Make free_host_port a fixture (#2267)
* Make free_host_port a fixture * Remove redundant comment
This commit is contained in:
@@ -6,20 +6,20 @@ import time
|
|||||||
import pytest # type: ignore
|
import pytest # type: ignore
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
from tests.utils.find_free_port import find_free_port
|
|
||||||
from tests.utils.tracked_container import TrackedContainer
|
from tests.utils.tracked_container import TrackedContainer
|
||||||
|
|
||||||
LOGGER = logging.getLogger(__name__)
|
LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def test_cli_args(container: TrackedContainer, http_client: requests.Session) -> None:
|
def test_cli_args(
|
||||||
|
container: TrackedContainer, http_client: requests.Session, free_host_port: int
|
||||||
|
) -> None:
|
||||||
"""Image should respect command line args (e.g., disabling token security)"""
|
"""Image should respect command line args (e.g., disabling token security)"""
|
||||||
host_port = find_free_port()
|
|
||||||
container.run_detached(
|
container.run_detached(
|
||||||
command=["start-notebook.py", "--IdentityProvider.token=''"],
|
command=["start-notebook.py", "--IdentityProvider.token=''"],
|
||||||
ports={"8888/tcp": host_port},
|
ports={"8888/tcp": free_host_port},
|
||||||
)
|
)
|
||||||
resp = http_client.get(f"http://localhost:{host_port}")
|
resp = http_client.get(f"http://localhost:{free_host_port}")
|
||||||
resp.raise_for_status()
|
resp.raise_for_status()
|
||||||
logs = container.get_logs()
|
logs = container.get_logs()
|
||||||
LOGGER.debug(logs)
|
LOGGER.debug(logs)
|
||||||
@@ -54,22 +54,21 @@ def test_nb_user_change(container: TrackedContainer) -> None:
|
|||||||
|
|
||||||
@pytest.mark.filterwarnings("ignore:Unverified HTTPS request")
|
@pytest.mark.filterwarnings("ignore:Unverified HTTPS request")
|
||||||
def test_unsigned_ssl(
|
def test_unsigned_ssl(
|
||||||
container: TrackedContainer, http_client: requests.Session
|
container: TrackedContainer, http_client: requests.Session, free_host_port: int
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Container should generate a self-signed SSL certificate
|
"""Container should generate a self-signed SSL certificate
|
||||||
and Jupyter Server should use it to enable HTTPS.
|
and Jupyter Server should use it to enable HTTPS.
|
||||||
"""
|
"""
|
||||||
host_port = find_free_port()
|
|
||||||
container.run_detached(
|
container.run_detached(
|
||||||
environment=["GEN_CERT=yes"],
|
environment=["GEN_CERT=yes"],
|
||||||
ports={"8888/tcp": host_port},
|
ports={"8888/tcp": free_host_port},
|
||||||
)
|
)
|
||||||
# NOTE: The requests.Session backing the http_client fixture
|
# NOTE: The requests.Session backing the http_client fixture
|
||||||
# does not retry properly while the server is booting up.
|
# does not retry properly while the server is booting up.
|
||||||
# An SSL handshake error seems to abort the retry logic.
|
# An SSL handshake error seems to abort the retry logic.
|
||||||
# Forcing a long sleep for the moment until I have time to dig more.
|
# Forcing a long sleep for the moment until I have time to dig more.
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
resp = http_client.get(f"https://localhost:{host_port}", verify=False)
|
resp = http_client.get(f"https://localhost:{free_host_port}", verify=False)
|
||||||
resp.raise_for_status()
|
resp.raise_for_status()
|
||||||
assert "login_submit" in resp.text
|
assert "login_submit" in resp.text
|
||||||
logs = container.get_logs()
|
logs = container.get_logs()
|
||||||
@@ -94,18 +93,18 @@ def test_unsigned_ssl(
|
|||||||
def test_custom_internal_port(
|
def test_custom_internal_port(
|
||||||
container: TrackedContainer,
|
container: TrackedContainer,
|
||||||
http_client: requests.Session,
|
http_client: requests.Session,
|
||||||
|
free_host_port: int,
|
||||||
env: dict[str, str],
|
env: dict[str, str],
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Container should be accessible from the host
|
"""Container should be accessible from the host
|
||||||
when using custom internal port"""
|
when using custom internal port"""
|
||||||
host_port = find_free_port()
|
|
||||||
internal_port = env.get("JUPYTER_PORT", 8888)
|
internal_port = env.get("JUPYTER_PORT", 8888)
|
||||||
container.run_detached(
|
container.run_detached(
|
||||||
command=["start-notebook.py", "--IdentityProvider.token=''"],
|
command=["start-notebook.py", "--IdentityProvider.token=''"],
|
||||||
environment=env,
|
environment=env,
|
||||||
ports={internal_port: host_port},
|
ports={internal_port: free_host_port},
|
||||||
)
|
)
|
||||||
resp = http_client.get(f"http://localhost:{host_port}")
|
resp = http_client.get(f"http://localhost:{free_host_port}")
|
||||||
resp.raise_for_status()
|
resp.raise_for_status()
|
||||||
logs = container.get_logs()
|
logs = container.get_logs()
|
||||||
LOGGER.debug(logs)
|
LOGGER.debug(logs)
|
||||||
|
@@ -2,16 +2,14 @@
|
|||||||
# Distributed under the terms of the Modified BSD License.
|
# Distributed under the terms of the Modified BSD License.
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
from tests.utils.find_free_port import find_free_port
|
|
||||||
from tests.utils.tracked_container import TrackedContainer
|
from tests.utils.tracked_container import TrackedContainer
|
||||||
|
|
||||||
|
|
||||||
def test_secured_server(
|
def test_secured_server(
|
||||||
container: TrackedContainer, http_client: requests.Session
|
container: TrackedContainer, http_client: requests.Session, free_host_port: int
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Jupyter Server should eventually request user login."""
|
"""Jupyter Server should eventually request user login."""
|
||||||
host_port = find_free_port()
|
container.run_detached(ports={"8888/tcp": free_host_port})
|
||||||
container.run_detached(ports={"8888/tcp": host_port})
|
resp = http_client.get(f"http://localhost:{free_host_port}")
|
||||||
resp = http_client.get(f"http://localhost:{host_port}")
|
|
||||||
resp.raise_for_status()
|
resp.raise_for_status()
|
||||||
assert "login_submit" in resp.text, "User login not requested"
|
assert "login_submit" in resp.text, "User login not requested"
|
||||||
|
@@ -6,7 +6,6 @@ import time
|
|||||||
import pytest # type: ignore
|
import pytest # type: ignore
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
from tests.utils.find_free_port import find_free_port
|
|
||||||
from tests.utils.tracked_container import TrackedContainer
|
from tests.utils.tracked_container import TrackedContainer
|
||||||
|
|
||||||
LOGGER = logging.getLogger(__name__)
|
LOGGER = logging.getLogger(__name__)
|
||||||
@@ -32,6 +31,7 @@ LOGGER = logging.getLogger(__name__)
|
|||||||
def test_start_notebook(
|
def test_start_notebook(
|
||||||
container: TrackedContainer,
|
container: TrackedContainer,
|
||||||
http_client: requests.Session,
|
http_client: requests.Session,
|
||||||
|
free_host_port: int,
|
||||||
env: list[str] | None,
|
env: list[str] | None,
|
||||||
expected_command: str,
|
expected_command: str,
|
||||||
expected_start: bool,
|
expected_start: bool,
|
||||||
@@ -41,8 +41,7 @@ def test_start_notebook(
|
|||||||
LOGGER.info(
|
LOGGER.info(
|
||||||
f"Test that the start-notebook.py launches the {expected_command} server from the env {env} ..."
|
f"Test that the start-notebook.py launches the {expected_command} server from the env {env} ..."
|
||||||
)
|
)
|
||||||
host_port = find_free_port()
|
container.run_detached(environment=env, ports={"8888/tcp": free_host_port})
|
||||||
container.run_detached(environment=env, ports={"8888/tcp": host_port})
|
|
||||||
# sleeping some time to let the server start
|
# sleeping some time to let the server start
|
||||||
time.sleep(2)
|
time.sleep(2)
|
||||||
logs = container.get_logs()
|
logs = container.get_logs()
|
||||||
@@ -59,7 +58,7 @@ def test_start_notebook(
|
|||||||
assert len(expected_warnings) == len(warnings)
|
assert len(expected_warnings) == len(warnings)
|
||||||
# checking if the server is listening
|
# checking if the server is listening
|
||||||
if expected_start:
|
if expected_start:
|
||||||
resp = http_client.get(f"http://localhost:{host_port}")
|
resp = http_client.get(f"http://localhost:{free_host_port}")
|
||||||
assert resp.status_code == 200, "Server is not listening"
|
assert resp.status_code == 200, "Server is not listening"
|
||||||
|
|
||||||
|
|
||||||
|
@@ -7,7 +7,7 @@ from tests.utils.tracked_container import TrackedContainer
|
|||||||
|
|
||||||
|
|
||||||
def test_pluto_proxy(
|
def test_pluto_proxy(
|
||||||
container: TrackedContainer, http_client: requests.Session
|
container: TrackedContainer, http_client: requests.Session, free_host_port: int
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Pluto proxy starts Pluto correctly"""
|
"""Pluto proxy starts Pluto correctly"""
|
||||||
check_pluto_proxy(container, http_client)
|
check_pluto_proxy(container, http_client, free_host_port)
|
||||||
|
@@ -7,7 +7,7 @@ from tests.utils.tracked_container import TrackedContainer
|
|||||||
|
|
||||||
|
|
||||||
def test_pluto_proxy(
|
def test_pluto_proxy(
|
||||||
container: TrackedContainer, http_client: requests.Session
|
container: TrackedContainer, http_client: requests.Session, free_host_port: int
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Pluto proxy starts Pluto correctly"""
|
"""Pluto proxy starts Pluto correctly"""
|
||||||
check_pluto_proxy(container, http_client)
|
check_pluto_proxy(container, http_client, free_host_port)
|
||||||
|
@@ -2,7 +2,9 @@
|
|||||||
# Distributed under the terms of the Modified BSD License.
|
# Distributed under the terms of the Modified BSD License.
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
import socket
|
||||||
from collections.abc import Generator
|
from collections.abc import Generator
|
||||||
|
from contextlib import closing
|
||||||
|
|
||||||
import docker
|
import docker
|
||||||
import pytest # type: ignore
|
import pytest # type: ignore
|
||||||
@@ -54,3 +56,12 @@ def container(
|
|||||||
)
|
)
|
||||||
yield container
|
yield container
|
||||||
container.remove()
|
container.remove()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope="function")
|
||||||
|
def free_host_port() -> Generator[int]:
|
||||||
|
"""Finds a free port on the host machine"""
|
||||||
|
with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as s:
|
||||||
|
s.bind(("", 0))
|
||||||
|
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||||
|
yield s.getsockname()[1]
|
||||||
|
@@ -6,26 +6,24 @@ import time
|
|||||||
|
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
from tests.utils.find_free_port import find_free_port
|
|
||||||
from tests.utils.tracked_container import TrackedContainer
|
from tests.utils.tracked_container import TrackedContainer
|
||||||
|
|
||||||
LOGGER = logging.getLogger(__name__)
|
LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def check_pluto_proxy(
|
def check_pluto_proxy(
|
||||||
container: TrackedContainer, http_client: requests.Session
|
container: TrackedContainer, http_client: requests.Session, free_host_port: int
|
||||||
) -> None:
|
) -> None:
|
||||||
host_port = find_free_port()
|
|
||||||
token = secrets.token_hex()
|
token = secrets.token_hex()
|
||||||
container.run_detached(
|
container.run_detached(
|
||||||
command=[
|
command=[
|
||||||
"start-notebook.py",
|
"start-notebook.py",
|
||||||
f"--IdentityProvider.token={token}",
|
f"--IdentityProvider.token={token}",
|
||||||
],
|
],
|
||||||
ports={"8888/tcp": host_port},
|
ports={"8888/tcp": free_host_port},
|
||||||
)
|
)
|
||||||
# Give the server a bit of time to start
|
# Give the server a bit of time to start
|
||||||
time.sleep(2)
|
time.sleep(2)
|
||||||
resp = http_client.get(f"http://localhost:{host_port}/pluto?token={token}")
|
resp = http_client.get(f"http://localhost:{free_host_port}/pluto?token={token}")
|
||||||
resp.raise_for_status()
|
resp.raise_for_status()
|
||||||
assert "Pluto.jl notebooks" in resp.text, "Pluto.jl text not found in /pluto page"
|
assert "Pluto.jl notebooks" in resp.text, "Pluto.jl text not found in /pluto page"
|
||||||
|
@@ -1,12 +0,0 @@
|
|||||||
# Copyright (c) Jupyter Development Team.
|
|
||||||
# Distributed under the terms of the Modified BSD License.
|
|
||||||
import socket
|
|
||||||
from contextlib import closing
|
|
||||||
|
|
||||||
|
|
||||||
def find_free_port() -> str:
|
|
||||||
"""Returns the available host port. Can be called in multiple threads/processes."""
|
|
||||||
with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as s:
|
|
||||||
s.bind(("", 0))
|
|
||||||
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
|
||||||
return s.getsockname()[1] # type: ignore
|
|
Reference in New Issue
Block a user