def test_set_uid_and_nb_user(container: TrackedContainer) -> None: """Container should run with the specified uid and NB_USER.""" logs = container.run_and_wait( timeout=5, no_warnings=False, user="******", environment=["NB_USER=kitten"], group_add=["users"], # Ensures write access to /home/jovyan command=["start.sh", "id"], ) assert "uid=1010(kitten) gid=0(root)" in logs warnings = TrackedContainer.get_warnings(logs) assert len(warnings) == 1 assert "user is kitten but home is /home/jovyan" in warnings[0]
def test_set_uid(container: TrackedContainer) -> None: """Container should run with the specified uid and NB_USER. The /home/jovyan directory will not be writable since it's owned by 1000:users. Additionally verify that "--group-add=users" is suggested in a warning to restore write access. """ logs = container.run_and_wait( timeout=5, no_warnings=False, user="******", command=["start.sh", "id"], ) assert "uid=1010(jovyan) gid=0(root)" in logs warnings = TrackedContainer.get_warnings(logs) assert len(warnings) == 1 assert "--group-add=users" in warnings[0]
def test_group_add(container: TrackedContainer) -> None: """Container should run with the specified uid, gid, and secondary group. It won't be possible to modify /etc/passwd since gid is nonzero, so additionally verify that setting gid=0 is suggested in a warning. """ logs = container.run_and_wait( timeout=5, no_warnings=False, user="******", group_add=["users"], # Ensures write access to /home/jovyan command=["start.sh", "id"], ) warnings = TrackedContainer.get_warnings(logs) assert len(warnings) == 1 assert "Try setting gid=0" in warnings[0] assert "uid=1010 gid=1010 groups=1010,100(users)" in logs
def test_cli_args(container: TrackedContainer, http_client: requests.Session) -> None: """Container should respect notebook server command line args (e.g., disabling token security)""" host_port = find_free_port() running_container = container.run_detached( command=["start-notebook.sh", "--NotebookApp.token=''"], ports={"8888/tcp": host_port}, ) resp = http_client.get(f"http://localhost:{host_port}") resp.raise_for_status() logs = running_container.logs().decode("utf-8") LOGGER.debug(logs) assert "ERROR" not in logs warnings = TrackedContainer.get_warnings(logs) assert not warnings assert "login_submit" not in resp.text
def test_unsigned_ssl(container: TrackedContainer, http_client: requests.Session) -> None: """Container should generate a self-signed SSL certificate and notebook server should use it to enable HTTPS. """ host_port = find_free_port() running_container = container.run_detached( environment=["GEN_CERT=yes"], ports={"8888/tcp": host_port}, ) # NOTE: The requests.Session backing the http_client fixture does not retry # properly while the server is booting up. An SSL handshake error seems to # abort the retry logic. Forcing a long sleep for the moment until I have # time to dig more. time.sleep(5) resp = http_client.get(f"https://localhost:{host_port}", verify=False) resp.raise_for_status() assert "login_submit" in resp.text logs = running_container.logs().decode("utf-8") assert "ERROR" not in logs warnings = TrackedContainer.get_warnings(logs) assert not warnings
def test_start_notebook( container: TrackedContainer, http_client: requests.Session, env: Optional[list[str]], expected_command: str, expected_start: bool, expected_warnings: list[str], ) -> None: """Test the notebook start-notebook script""" LOGGER.info( f"Test that the start-notebook launches the {expected_command} server from the env {env} ..." ) host_port = find_free_port() running_container = container.run_detached( tty=True, environment=env, command=["start-notebook.sh"], ports={"8888/tcp": host_port}, ) # sleeping some time to let the server start time.sleep(3) logs = running_container.logs().decode("utf-8") LOGGER.debug(logs) # checking that the expected command is launched assert ( f"Executing the command: {expected_command}" in logs), f"Not the expected command ({expected_command}) was launched" # checking errors and warnings in logs assert "ERROR" not in logs, "ERROR(s) found in logs" for exp_warning in expected_warnings: assert exp_warning in logs, f"Expected warning {exp_warning} not found in logs" warnings = TrackedContainer.get_warnings(logs) assert len(expected_warnings) == len(warnings) # checking if the server is listening if expected_start: resp = http_client.get(f"http://localhost:{host_port}") assert resp.status_code == 200, "Server is not listening"