Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for installing TLJH on Arm64 systems and bump traefik (1.7.18 -> 1.7.33) #679

Merged
merged 3 commits into from
Nov 3, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
142 changes: 142 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
# We use circleci to test our support for the Arm64 architecture. This file
# should mimic what is done in the GitHub workflows.
#
# Configuration reference: https://circleci.com/docs/2.0/configuration-reference/
#
version: 2.1
consideRatio marked this conversation as resolved.
Show resolved Hide resolved

commands:
build_systemd_image:
steps:
- run:
name: build systemd image
command: |
.circleci/integration-test.py build-image

basic_tests:
parameters:
# Whether or not we should run update tests
upgrade:
type: string
default: ""

steps:
- run:
name: Run basic tests
command: |
if [ $CIRCLE_PR_USERNAME ]; then
BOOTSTRAP_PIP_SPEC=git+https://github.com/$CIRCLE_PR_USERNAME/the-littlest-jupyterhub.git@$CIRCLE_SHA1
else
BOOTSTRAP_PIP_SPEC=git+https://github.com/$CIRCLE_PROJECT_USERNAME/the-littlest-jupyterhub.git@$CIRCLE_SHA1
fi

.circleci/integration-test.py run-test \
--bootstrap-pip-spec "$BOOTSTRAP_PIP_SPEC" \
basic-tests test_hub.py test_proxy.py \
test_install.py test_extensions.py \
<< parameters.upgrade >>

admin_tests:
parameters:
upgrade:
type: string
default: ""

steps:
- run:
name: Run admin tests
command: |
if [ $CIRCLE_PR_USERNAME ]; then
BOOTSTRAP_PIP_SPEC=git+https://github.com/$CIRCLE_PR_USERNAME/the-littlest-jupyterhub.git@$CIRCLE_SHA1
else
BOOTSTRAP_PIP_SPEC=git+https://github.com/$CIRCLE_PROJECT_USERNAME/the-littlest-jupyterhub.git@$CIRCLE_SHA1
fi

.circleci/integration-test.py run-test \
--installer-args "--admin admin:admin" \
--bootstrap-pip-spec $BOOTSTRAP_PIP_SPEC \
basic-tests test_admin_installer.py \
<< parameters.upgrade >>

plugin_tests:
parameters:
upgrade:
type: string
default: ""

steps:
- run:
name: Run plugin tests
command: |
if [ $CIRCLE_PR_USERNAME ]; then
BOOTSTRAP_PIP_SPEC=git+https://github.com/$CIRCLE_PR_USERNAME/the-littlest-jupyterhub.git@$CIRCLE_SHA1
else
BOOTSTRAP_PIP_SPEC=git+https://github.com/$CIRCLE_PROJECT_USERNAME/the-littlest-jupyterhub.git@$CIRCLE_SHA1
fi

.circleci/integration-test.py run-test \
--bootstrap-pip-spec $BOOTSTRAP_PIP_SPEC \
--installer-args "--plugin /srv/src/integration-tests/plugins/simplest" \
plugins test_simplest_plugin.py \
<< parameters.upgrade >>

bootstrap_checks:
steps:
- run:
name: Run bootstrap checks
command: |
py.test integration-tests/test_bootstrap.py -s


jobs:
integration-test:
docker:
- image: docker:18.05.0-ce-git

steps:
- run:
name: setup python3
command: |
apk add --no-cache python3 pytest
- checkout
- setup_remote_docker
- build_systemd_image
- bootstrap_checks
- basic_tests
- admin_tests
- plugin_tests

upgrade-test:
docker:
- image: docker:18.05.0-ce-git

steps:
- run:
name: Check upgrade testing
command: |
if [ "$CIRCLE_BRANCH" == "master" ]; then
echo "On master, no upgrade to test..."
circleci-agent step halt
else
echo "PR detected, testing upgrade..."
fi
- run:
name: setup python3
command: |
apk add --no-cache python3 pytest
- checkout
- setup_remote_docker
- build_systemd_image
- basic_tests:
upgrade: "--upgrade"
- admin_tests:
upgrade: "--upgrade"
- plugin_tests:
upgrade: "--upgrade"

workflows:
version: 2
all-tests:
jobs:
- integration-test
- upgrade-test
3 changes: 1 addition & 2 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ might still make breaking changes that have no clear upgrade pathway.
Installation
============

The Littlest JupyterHub (TLJH) can run on any server that is running at least
**Ubuntu 18.04**. Earlier versions of Ubuntu are not supported.
The Littlest JupyterHub (TLJH) can run on any server that is running **Ubuntu 18.04** or **Ubuntu 20.04** on a amd64 or arm64 CPU architecture. Earlier versions of Ubuntu are not supported.
We have a bunch of tutorials to get you started.

- Tutorials to create a new server from scratch on a cloud provider & run TLJH
Expand Down
2 changes: 1 addition & 1 deletion docs/topic/installer-actions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ of `traefik <http://traefik.io/>`_. This virtual environment is completely manag
User environment
================

By default, a ``miniconda`` environment is installed in ``/opt/tljh/user``. This contains
By default, a ``mambaforge`` conda environment is installed in ``/opt/tljh/user``. This contains
the notebook interface used to launch all users, and the various packages available to all
users. The environment is owned by the ``root`` user. JupyterHub admins may use
to ``sudo -E conda install`` or ``sudo -E pip install`` packages into this environment.
Expand Down
10 changes: 7 additions & 3 deletions tests/test_conda.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,15 @@
@pytest.fixture(scope='module')
def prefix():
"""
Provide a temporary directory with a conda environment
Provide a temporary directory with a mambaforge conda environment
"""
# see https://github.com/conda-forge/miniforge/releases
mambaforge_version = '4.10.3-7'
installer_sha256 = "fc872522ec427fcab10167a93e802efaf251024b58cc27b084b915a9a73c4474"
installer_url = "https://github.com/conda-forge/miniforge/releases/download/{v}/Mambaforge-{v}-Linux-x86_64.sh".format(v=mambaforge_version)
if os.uname().machine == 'aarch64':
installer_sha256 = "ac95f137b287b3408e4f67f07a284357b1119ee157373b788b34e770ef2392b2"
elif os.uname().machine == 'x86_64':
installer_sha256 = "fc872522ec427fcab10167a93e802efaf251024b58cc27b084b915a9a73c4474"
installer_url = "https://github.com/conda-forge/miniforge/releases/download/{v}/Mambaforge-{v}-Linux-{arch}.sh".format(v=mambaforge_version, arch=os.uname().machine)
with tempfile.TemporaryDirectory() as tmpdir:
with conda.download_miniconda_installer(installer_url, installer_sha256) as installer_path:
conda.install_miniconda(installer_path, tmpdir)
Expand Down
11 changes: 9 additions & 2 deletions tljh/installer.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,14 @@ def ensure_user_environment(user_requirements_txt_file):
# Install mambaforge using an installer from
# https://github.com/conda-forge/miniforge/releases
mambaforge_new_version = '4.10.3-7'
installer_sha256 = "fc872522ec427fcab10167a93e802efaf251024b58cc27b084b915a9a73c4474"
# Check system architecture, set appropriate installer checksum
if os.uname().machine == 'aarch64':
installer_sha256 = "ac95f137b287b3408e4f67f07a284357b1119ee157373b788b34e770ef2392b2"
elif os.uname().machine == 'x86_64':
installer_sha256 = "fc872522ec427fcab10167a93e802efaf251024b58cc27b084b915a9a73c4474"
# Check OS, set appropriate string for conda installer path
if os.uname().sysname != 'Linux':
raise OSError("TLJH is only supported on Linux platforms.")
# Then run `mamba --version` to get the conda and mamba versions
# Keep these in sync with tests/test_conda.py::prefix
mambaforge_conda_new_version = '4.10.3'
Expand All @@ -185,7 +192,7 @@ def ensure_user_environment(user_requirements_txt_file):
# If no prior miniconda installation is found, we can install a newer version
else:
logger.info('Downloading & setting up user environment...')
installer_url = "https://github.com/conda-forge/miniforge/releases/download/{v}/Mambaforge-{v}-Linux-x86_64.sh".format(v=mambaforge_new_version)
installer_url = "https://github.com/conda-forge/miniforge/releases/download/{v}/Mambaforge-{v}-Linux-{arch}.sh".format(v=mambaforge_new_version, arch=os.uname().machine)
with conda.download_miniconda_installer(installer_url, installer_sha256) as installer_path:
conda.install_miniconda(installer_path, USER_ENV_PREFIX)
conda_version = '4.10.3'
Expand Down
19 changes: 14 additions & 5 deletions tljh/traefik.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,21 @@
from .config import CONFIG_DIR
from tljh.configurer import load_config, _merge_dictionaries

# FIXME: support more than one platform here
plat = "linux-amd64"
traefik_version = "1.7.18"
# traefik 2.7.x is not supported yet, use v1.7.x for now
# see: https://github.com/jupyterhub/traefik-proxy/issues/97
machine = os.uname().machine
if machine == 'aarch64':
plat = "linux-arm64"
elif machine == 'x86_64':
plat = "linux-amd64"
else:
raise OSError(f"Error. Platform: {os.uname().sysname} / {machine} Not supported.")
traefik_version = "1.7.33"

# record sha256 hashes for supported platforms here
checksums = {
"linux-amd64": "3c2d153d80890b6fc8875af9f8ced32c4d684e1eb5a46d9815337cb343dfd92e"
"linux-amd64": "314ffeaa4cd8ed6ab7b779e9b6773987819f79b23c28d7ab60ace4d3683c5935",
"linux-arm64": "0640fa665125efa6b598fc08c100178e24de66c5c6035ce5d75668d3dc3706e1"
}

def checksum_file(path):
Expand All @@ -40,7 +48,7 @@ def fatal_error(e):
giveup=fatal_error
)
def ensure_traefik_binary(prefix):
"""Download and install the traefik binary"""
"""Download and install the traefik binary to a location identified by a prefix path such as '/opt/tljh/hub/'"""
traefik_bin = os.path.join(prefix, "bin", "traefik")
if os.path.exists(traefik_bin):
checksum = checksum_file(traefik_bin)
Expand All @@ -57,6 +65,7 @@ def ensure_traefik_binary(prefix):
"https://github.com/containous/traefik/releases"
f"/download/v{traefik_version}/traefik_{plat}"
)

print(f"Downloading traefik {traefik_version}...")
# download the file
response = requests.get(traefik_url)
Expand Down