Files
the-littlest-jupyterhub/integration-tests/test_bootstrap.py

179 lines
6.1 KiB
Python
Raw Normal View History

"""
Test running bootstrap script in different circumstances
"""
2020-08-18 23:56:37 +03:00
import concurrent.futures
2020-08-21 18:03:57 +03:00
import os
import subprocess
2020-08-18 23:56:37 +03:00
import time
2020-08-21 18:03:57 +03:00
def install_pkgs(container_name, show_progress_page):
# Install python3 inside the ubuntu container
# There is no trusted Ubuntu+Python3 container we can use
2020-08-21 18:03:57 +03:00
pkgs = ["python3"]
if show_progress_page:
2020-08-24 13:01:54 +03:00
pkgs += ["systemd", "git", "curl"]
2020-08-21 18:03:57 +03:00
# Create the sudoers dir, so that the installer succesfully gets to the
# point of starting jupyterhub and stopping the progress page server.
subprocess.check_output(
["docker", "exec", container_name, "mkdir", "-p", "etc/sudoers.d"]
)
subprocess.check_output(["docker", "exec", container_name, "apt-get", "update"])
subprocess.check_output(
["docker", "exec", container_name, "apt-get", "install", "--yes"] + pkgs
2020-08-18 23:56:37 +03:00
)
2020-08-21 18:03:57 +03:00
def get_bootstrap_script_location(container_name, show_progress_page):
# Copy only the bootstrap script to container when progress page not enabled, to be faster
source_path = "bootstrap/"
bootstrap_script = "/srv/src/bootstrap.py"
if show_progress_page:
source_path = os.path.abspath(
os.path.join(os.path.dirname(__file__), os.pardir)
)
bootstrap_script = "/srv/src/bootstrap/bootstrap.py"
subprocess.check_call(["docker", "cp", source_path, f"{container_name}:/srv/src"])
return bootstrap_script
# FIXME: Refactor this function to easier to understand using the following
# parameters
#
# - param: container_apt_packages
# - param: bootstrap_tljh_source
# - local: copies local tljh repo to container and configures bootstrap to
# install tljh from copied repo
# - github: configures bootstrap to install tljh from the official github repo
# - <pip spec>: configures bootstrap to install tljh from any given remote location
# - param: bootstrap_flags
#
# FIXME: Consider stripping logic in this file to only testing if the bootstrap
# script successfully detects the too old Ubuntu version and the lack of
# systemd. The remaining test named test_progress_page could rely on
# running against the systemd container that cab be built by
# integration-test.py.
#
def run_bootstrap_after_preparing_container(container_name, image, show_progress_page=False):
"""
1. Stops old container
2. Starts --detached container
3. Installs apt packages in container
4. Two situations
A) limited test (--show-progress-page=false)
- Copies ./bootstrap/ folder content to container /srv/src
- Runs copied bootstrap/bootstrap.py without flags
B) full test (--show-progress-page=true)
- Copies ./ folder content to the container /srv/src
- Runs copied bootstrap/bootstrap.py with environment variables
- TLJH_BOOTSTRAP_DEV=yes
This makes --editable be used when installing the tljh package
- TLJH_BOOTSTRAP_PIP_SPEC=/srv/src
This makes us install tljh from the given location instead of from
github.com/jupyterhub/the-littlest-jupyterhub
"""
2020-08-21 18:03:57 +03:00
# stop container if it is already running
subprocess.run(["docker", "rm", "-f", container_name])
2020-08-24 13:01:54 +03:00
# Start a detached container
subprocess.check_call(
[
"docker",
"run",
"--env=DEBIAN_FRONTEND=noninteractive",
2020-08-24 13:01:54 +03:00
"--detach",
f"--name={container_name}",
2020-08-24 13:01:54 +03:00
image,
"/bin/bash",
"-c",
"sleep 1000s",
]
)
2020-08-21 18:03:57 +03:00
install_pkgs(container_name, show_progress_page)
bootstrap_script = get_bootstrap_script_location(container_name, show_progress_page)
exec_flags = ["-i", container_name, "python3", bootstrap_script]
if show_progress_page:
exec_flags = (
2020-08-22 15:57:40 +03:00
["-e", "TLJH_BOOTSTRAP_DEV=yes", "-e", "TLJH_BOOTSTRAP_PIP_SPEC=/srv/src"]
2020-08-21 18:03:57 +03:00
+ exec_flags
+ ["--show-progress-page"]
)
# Run bootstrap script, return the output
2020-08-21 18:03:57 +03:00
return subprocess.run(
["docker", "exec"] + exec_flags,
check=False,
stdout=subprocess.PIPE,
encoding="utf-8",
)
def test_ubuntu_too_old():
"""
Error with a useful message when running in older Ubuntu
"""
output = run_bootstrap_after_preparing_container("old-distro-test", "ubuntu:16.04")
2020-08-21 18:03:57 +03:00
assert output.stdout == "The Littlest JupyterHub requires Ubuntu 18.04 or higher\n"
assert output.returncode == 1
def test_inside_no_systemd_docker():
output = run_bootstrap_after_preparing_container(
"plain-docker-test",
f"ubuntu:{os.getenv('UBUNTU_VERSION', '20.04')}",
)
assert "Systemd is required to run TLJH" in output.stdout
assert output.returncode == 1
2020-08-18 23:56:37 +03:00
2020-08-19 02:33:17 +03:00
def verify_progress_page(expected_status_code, timeout):
2020-08-18 23:56:37 +03:00
progress_page_status = False
2020-08-19 02:33:17 +03:00
start = time.time()
while not progress_page_status and (time.time() - start < timeout):
2020-08-18 23:56:37 +03:00
try:
2020-08-24 13:01:54 +03:00
resp = subprocess.check_output(
[
"docker",
"exec",
"progress-page",
"curl",
"-i",
"http://localhost/index.html",
]
)
if b"HTTP/1.0 200 OK" in resp:
2020-08-18 23:56:37 +03:00
progress_page_status = True
2020-08-21 18:03:57 +03:00
break
2020-08-18 23:56:37 +03:00
except Exception as e:
2020-08-19 02:33:17 +03:00
time.sleep(2)
2020-08-21 18:03:57 +03:00
continue
2020-08-18 23:56:37 +03:00
return progress_page_status
2020-08-21 18:03:57 +03:00
2020-08-18 23:56:37 +03:00
def test_progress_page():
with concurrent.futures.ThreadPoolExecutor() as executor:
2020-08-21 18:03:57 +03:00
installer = executor.submit(
run_bootstrap_after_preparing_container,
"progress-page",
f"ubuntu:{os.getenv('UBUNTU_VERSION', '20.04')}",
True
2020-08-21 18:03:57 +03:00
)
2020-08-18 23:56:37 +03:00
# Check if progress page started
2020-08-19 02:33:17 +03:00
started = verify_progress_page(expected_status_code=200, timeout=120)
2020-08-18 23:56:37 +03:00
assert started
2020-08-21 18:03:57 +03:00
# This will fail start tljh but should successfully get to the point
# Where it stops the progress page server.
output = installer.result()
2020-08-19 02:33:17 +03:00
# Check if progress page stopped
2020-08-21 18:03:57 +03:00
assert "Progress page server stopped successfully." in output.stdout