mirror of
https://github.com/jupyterhub/the-littlest-jupyterhub.git
synced 2025-12-18 21:54:05 +08:00
Merge remote-tracking branch 'upstream/master' into tania-azure-docs
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -102,3 +102,6 @@ venv.bak/
|
|||||||
|
|
||||||
# mypy
|
# mypy
|
||||||
.mypy_cache/
|
.mypy_cache/
|
||||||
|
|
||||||
|
# OS X stuff
|
||||||
|
.DS_Store
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import os
|
|||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
import logging
|
import logging
|
||||||
|
import shutil
|
||||||
|
|
||||||
|
|
||||||
def get_os_release_variable(key):
|
def get_os_release_variable(key):
|
||||||
@@ -31,8 +32,10 @@ def get_os_release_variable(key):
|
|||||||
"source /etc/os-release && echo ${{{key}}}".format(key=key)
|
"source /etc/os-release && echo ${{{key}}}".format(key=key)
|
||||||
]).decode().strip()
|
]).decode().strip()
|
||||||
|
|
||||||
def main():
|
def validate_host():
|
||||||
|
"""
|
||||||
|
Make sure TLJH is installable in current host
|
||||||
|
"""
|
||||||
# Support only Ubuntu 18.04+
|
# Support only Ubuntu 18.04+
|
||||||
distro = get_os_release_variable('ID')
|
distro = get_os_release_variable('ID')
|
||||||
version = float(get_os_release_variable('VERSION_ID'))
|
version = float(get_os_release_variable('VERSION_ID'))
|
||||||
@@ -43,6 +46,21 @@ def main():
|
|||||||
print('The Littlest JupyterHub requires Ubuntu 18.04 or higher')
|
print('The Littlest JupyterHub requires Ubuntu 18.04 or higher')
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
if sys.version_info < (3, 5):
|
||||||
|
print("bootstrap.py must be run with at least Python 3.5")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
if not (shutil.which('systemd') and shutil.which('systemctl')):
|
||||||
|
print("Systemd is required to run TLJH")
|
||||||
|
# Only fail running inside docker if systemd isn't present
|
||||||
|
if os.path.exists('/.dockerenv'):
|
||||||
|
print("Running inside a docker container without systemd isn't supported")
|
||||||
|
print("We recommend against running a production TLJH instance inside a docker container")
|
||||||
|
print("For local development, see http://tljh.jupyter.org/en/latest/contributing/dev-setup.html")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
def main():
|
||||||
|
validate_host()
|
||||||
install_prefix = os.environ.get('TLJH_INSTALL_PREFIX', '/opt/tljh')
|
install_prefix = os.environ.get('TLJH_INSTALL_PREFIX', '/opt/tljh')
|
||||||
hub_prefix = os.path.join(install_prefix, 'hub')
|
hub_prefix = os.path.join(install_prefix, 'hub')
|
||||||
|
|
||||||
|
|||||||
BIN
docs/.DS_Store
vendored
BIN
docs/.DS_Store
vendored
Binary file not shown.
@@ -1,4 +1,4 @@
|
|||||||
.. _contributing_dev_setup:
|
.. _contributing/dev-setup:
|
||||||
|
|
||||||
==================================
|
==================================
|
||||||
Setting up Development Environment
|
Setting up Development Environment
|
||||||
|
|||||||
BIN
docs/images/.DS_Store
vendored
BIN
docs/images/.DS_Store
vendored
Binary file not shown.
BIN
docs/images/providers/.DS_Store
vendored
BIN
docs/images/providers/.DS_Store
vendored
Binary file not shown.
@@ -4,11 +4,21 @@
|
|||||||
Installing on your own server
|
Installing on your own server
|
||||||
=============================
|
=============================
|
||||||
|
|
||||||
|
|
||||||
|
Follow this guide if your cloud provider doesn't have a direct tutorial, or
|
||||||
|
you are setting this up on a bare metal server.
|
||||||
|
|
||||||
|
.. warning::
|
||||||
|
|
||||||
|
Do **not** install TLJH directly on your laptop or personal computer!
|
||||||
|
It will most likely open up exploitable security holes when run directly
|
||||||
|
on your personal computer.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
You should use this if your cloud provider does not already have a direct tutorial,
|
Running TLJH *inside* a docker container is not supported, since we depend
|
||||||
or if you have experience setting up servers.
|
on systemd. If you want to run TLJH locally for development, see
|
||||||
|
:ref:`contributing/dev-setup`.
|
||||||
|
|
||||||
Goal
|
Goal
|
||||||
====
|
====
|
||||||
|
|||||||
BIN
docs/troubleshooting/.DS_Store
vendored
BIN
docs/troubleshooting/.DS_Store
vendored
Binary file not shown.
@@ -2,14 +2,9 @@
|
|||||||
Test running bootstrap script in different circumstances
|
Test running bootstrap script in different circumstances
|
||||||
"""
|
"""
|
||||||
import subprocess
|
import subprocess
|
||||||
|
from textwrap import dedent
|
||||||
|
|
||||||
|
def run_bootstrap(container_name, image):
|
||||||
def test_ubuntu_too_old():
|
|
||||||
"""
|
|
||||||
Error with a useful message when running in older Ubuntu
|
|
||||||
"""
|
|
||||||
container_name = 'old-distro-test'
|
|
||||||
|
|
||||||
# stop container if it is already running
|
# stop container if it is already running
|
||||||
subprocess.run([
|
subprocess.run([
|
||||||
'docker', 'rm', '-f', container_name
|
'docker', 'rm', '-f', container_name
|
||||||
@@ -17,7 +12,7 @@ def test_ubuntu_too_old():
|
|||||||
|
|
||||||
# Start a detached Ubuntu 16.04 container
|
# Start a detached Ubuntu 16.04 container
|
||||||
subprocess.check_call([
|
subprocess.check_call([
|
||||||
'docker', 'run', '--detach', '--name', container_name, 'ubuntu:16.04',
|
'docker', 'run', '--detach', '--name', container_name, image,
|
||||||
'/bin/bash', '-c', 'sleep 1000s'
|
'/bin/bash', '-c', 'sleep 1000s'
|
||||||
])
|
])
|
||||||
# Install python3 inside the ubuntu container
|
# Install python3 inside the ubuntu container
|
||||||
@@ -35,10 +30,27 @@ def test_ubuntu_too_old():
|
|||||||
'bootstrap/', f'{container_name}:/srv'
|
'bootstrap/', f'{container_name}:/srv'
|
||||||
])
|
])
|
||||||
|
|
||||||
# Run bootstrap script, validate that it fails appropriately
|
# Run bootstrap script, return the output
|
||||||
output = subprocess.run([
|
return subprocess.run([
|
||||||
'docker', 'exec', '-i', container_name,
|
'docker', 'exec', '-i', container_name,
|
||||||
'python3', '/srv/bootstrap/bootstrap.py'
|
'python3', '/srv/bootstrap/bootstrap.py'
|
||||||
], check=False, stdout=subprocess.PIPE, encoding='utf-8')
|
], 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('old-distro-test', 'ubuntu:16.04')
|
||||||
assert output.stdout == 'The Littlest JupyterHub requires Ubuntu 18.04 or higher\n'
|
assert output.stdout == 'The Littlest JupyterHub requires Ubuntu 18.04 or higher\n'
|
||||||
assert output.returncode == 1
|
assert output.returncode == 1
|
||||||
|
|
||||||
|
|
||||||
|
def test_inside_no_systemd_docker():
|
||||||
|
output = run_bootstrap('plain-docker-test', 'ubuntu:18.04')
|
||||||
|
assert output.stdout.strip() == dedent("""
|
||||||
|
Systemd is required to run TLJH
|
||||||
|
Running inside a docker container without systemd isn't supported
|
||||||
|
We recommend against running a production TLJH instance inside a docker container
|
||||||
|
For local development, see http://tljh.jupyter.org/en/latest/contributing/dev-setup.html
|
||||||
|
""").strip()
|
||||||
|
assert output.returncode == 1
|
||||||
|
|||||||
1
setup.py
1
setup.py
@@ -15,6 +15,7 @@ setup(
|
|||||||
'jinja2',
|
'jinja2',
|
||||||
'pluggy>0.7<1.0',
|
'pluggy>0.7<1.0',
|
||||||
'passlib',
|
'passlib',
|
||||||
|
'backoff',
|
||||||
'jupyterhub-traefik-proxy==0.1.*'
|
'jupyterhub-traefik-proxy==0.1.*'
|
||||||
],
|
],
|
||||||
entry_points={
|
entry_points={
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ def test_default_memory_limit():
|
|||||||
Test default per user memory limit
|
Test default per user memory limit
|
||||||
"""
|
"""
|
||||||
c = apply_mock_config({})
|
c = apply_mock_config({})
|
||||||
assert c.SystemdSpawner.mem_limit is None
|
assert c.Spawner.mem_limit is None
|
||||||
|
|
||||||
|
|
||||||
def test_set_memory_limit():
|
def test_set_memory_limit():
|
||||||
@@ -74,7 +74,7 @@ def test_set_memory_limit():
|
|||||||
Test setting per user memory limit
|
Test setting per user memory limit
|
||||||
"""
|
"""
|
||||||
c = apply_mock_config({'limits': {'memory': '42G'}})
|
c = apply_mock_config({'limits': {'memory': '42G'}})
|
||||||
assert c.SystemdSpawner.mem_limit == '42G'
|
assert c.Spawner.mem_limit == '42G'
|
||||||
|
|
||||||
|
|
||||||
def test_app_default():
|
def test_app_default():
|
||||||
|
|||||||
@@ -162,8 +162,8 @@ def update_limits(c, config):
|
|||||||
"""
|
"""
|
||||||
limits = config['limits']
|
limits = config['limits']
|
||||||
|
|
||||||
c.SystemdSpawner.mem_limit = limits['memory']
|
c.Spawner.mem_limit = limits['memory']
|
||||||
c.SystemdSpawner.cpu_limit = limits['cpu']
|
c.Spawner.cpu_limit = limits['cpu']
|
||||||
|
|
||||||
|
|
||||||
def update_user_environment(c, config):
|
def update_user_environment(c, config):
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
"""Traefik installation and setup"""
|
"""Traefik installation and setup"""
|
||||||
import hashlib
|
import hashlib
|
||||||
import os
|
import os
|
||||||
from urllib.request import urlretrieve
|
from urllib.request import urlretrieve, ContentTooShortError
|
||||||
|
|
||||||
from jinja2 import Template
|
from jinja2 import Template
|
||||||
from passlib.apache import HtpasswdFile
|
from passlib.apache import HtpasswdFile
|
||||||
|
import backoff
|
||||||
|
|
||||||
from tljh.configurer import load_config
|
from tljh.configurer import load_config
|
||||||
|
|
||||||
@@ -26,7 +27,12 @@ def checksum_file(path):
|
|||||||
hasher.update(chunk)
|
hasher.update(chunk)
|
||||||
return hasher.hexdigest()
|
return hasher.hexdigest()
|
||||||
|
|
||||||
|
@backoff.on_exception(
|
||||||
|
backoff.expo,
|
||||||
|
# Retry when connection is reset or we think we didn't download entire file
|
||||||
|
(ConnectionResetError, ContentTooShortError),
|
||||||
|
max_tries=2
|
||||||
|
)
|
||||||
def ensure_traefik_binary(prefix):
|
def ensure_traefik_binary(prefix):
|
||||||
"""Download and install the traefik binary"""
|
"""Download and install the traefik binary"""
|
||||||
traefik_bin = os.path.join(prefix, "bin", "traefik")
|
traefik_bin = os.path.join(prefix, "bin", "traefik")
|
||||||
|
|||||||
Reference in New Issue
Block a user