mirror of
https://github.com/jupyterhub/the-littlest-jupyterhub.git
synced 2025-12-18 21:54:05 +08:00
Dynamically set authenticator properties from YAML
We don't wanna explicitly map keys from the YAML to traitlet config for the authentication - that's a lot of busywork for no gain. We instead switch to using snake_case everywhere, and dynamically set traitlet config from YAML config!
This commit is contained in:
@@ -7,10 +7,6 @@ be called many times per lifetime of a jupyterhub.
|
|||||||
Traitlets that modify the startup of JupyterHub should not be here.
|
Traitlets that modify the startup of JupyterHub should not be here.
|
||||||
FIXME: A strong feeling that JSON Schema should be involved somehow.
|
FIXME: A strong feeling that JSON Schema should be involved somehow.
|
||||||
"""
|
"""
|
||||||
import copy
|
|
||||||
import os
|
|
||||||
import yaml
|
|
||||||
|
|
||||||
# Default configuration for tljh
|
# Default configuration for tljh
|
||||||
# User provided config is merged into this
|
# User provided config is merged into this
|
||||||
default = {
|
default = {
|
||||||
@@ -18,7 +14,7 @@ default = {
|
|||||||
'type': 'firstuse',
|
'type': 'firstuse',
|
||||||
'dummy': {},
|
'dummy': {},
|
||||||
'firstuse': {
|
'firstuse': {
|
||||||
'createUsers': False
|
'create_users': False
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'users': {
|
'users': {
|
||||||
@@ -30,20 +26,18 @@ default = {
|
|||||||
'memory': '1G',
|
'memory': '1G',
|
||||||
'cpu': None
|
'cpu': None
|
||||||
},
|
},
|
||||||
'userEnvironment': {
|
'user_environment': {
|
||||||
'defaultApp': 'classic'
|
'default_app': 'classic'
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def apply_yaml_config(path, c):
|
def apply_config(config_overrides, c):
|
||||||
if os.path.exists(path):
|
"""
|
||||||
with open(path) as f:
|
Merge config_overrides with config defaults & apply to JupyterHub config c
|
||||||
# FIXME: Figure out correct order of merging here
|
"""
|
||||||
tljh_config = _merge_dictionaries(dict(default), yaml.safe_load(f))
|
tljh_config = _merge_dictionaries(dict(default), config_overrides)
|
||||||
else:
|
|
||||||
tljh_config = copy.deepcopy(default)
|
|
||||||
|
|
||||||
update_auth(c, tljh_config)
|
update_auth(c, tljh_config)
|
||||||
update_userlists(c, tljh_config)
|
update_userlists(c, tljh_config)
|
||||||
@@ -52,21 +46,33 @@ def apply_yaml_config(path, c):
|
|||||||
update_user_account_config(c, tljh_config)
|
update_user_account_config(c, tljh_config)
|
||||||
|
|
||||||
|
|
||||||
|
def set_if_not_none(parent, key, value):
|
||||||
|
"""
|
||||||
|
Set attribute 'key' on parent if value is not None
|
||||||
|
"""
|
||||||
|
if value is not None:
|
||||||
|
setattr(parent, key, value)
|
||||||
|
|
||||||
|
|
||||||
def update_auth(c, config):
|
def update_auth(c, config):
|
||||||
"""
|
"""
|
||||||
Set auth related configuration from YAML config file
|
Set auth related configuration from YAML config file
|
||||||
|
|
||||||
|
Use auth.type to determine authenticator to use. All parameters
|
||||||
|
in the config under auth.{auth.type} will be passed straight to the
|
||||||
|
authenticators themselves.
|
||||||
"""
|
"""
|
||||||
auth = config.get('auth')
|
auth = config.get('auth')
|
||||||
|
|
||||||
if auth['type'] == 'dummy':
|
if auth['type'] == 'dummy':
|
||||||
c.JupyterHub.authenticator_class = 'dummyauthenticator.DummyAuthenticator'
|
c.JupyterHub.authenticator_class = 'dummyauthenticator.DummyAuthenticator'
|
||||||
password = auth['dummy'].get('password')
|
authenticator_parent = c.DummyAuthenticator
|
||||||
if password is not None:
|
|
||||||
c.DummyAuthenticator.password = password
|
|
||||||
return
|
|
||||||
elif auth['type'] == 'firstuse':
|
elif auth['type'] == 'firstuse':
|
||||||
c.JupyterHub.authenticator_class = 'firstuseauthenticator.FirstUseAuthenticator'
|
c.JupyterHub.authenticator_class = 'firstuseauthenticator.FirstUseAuthenticator'
|
||||||
c.FirstUseAuthenticator.create_users = auth['firstuse']['createUsers']
|
authenticator_parent = c.FirstUseAuthenticator
|
||||||
|
|
||||||
|
for k, v in auth[auth['type']].items():
|
||||||
|
set_if_not_none(authenticator_parent, k, v)
|
||||||
|
|
||||||
|
|
||||||
def update_userlists(c, config):
|
def update_userlists(c, config):
|
||||||
@@ -94,12 +100,12 @@ def update_user_environment(c, config):
|
|||||||
"""
|
"""
|
||||||
Set user environment configuration
|
Set user environment configuration
|
||||||
"""
|
"""
|
||||||
user_env = config['userEnvironment']
|
user_env = config['user_environment']
|
||||||
|
|
||||||
# Set default application users are launched into
|
# Set default application users are launched into
|
||||||
if user_env['defaultApp'] == 'jupyterlab':
|
if user_env['default_app'] == 'jupyterlab':
|
||||||
c.Spawner.default_url = '/lab'
|
c.Spawner.default_url = '/lab'
|
||||||
elif user_env['defaultApp'] == 'nteract':
|
elif user_env['default_app'] == 'nteract':
|
||||||
c.Spawner.default_url = '/nteract'
|
c.Spawner.default_url = '/nteract'
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ JupyterHub config for the littlest jupyterhub.
|
|||||||
import os
|
import os
|
||||||
from systemdspawner import SystemdSpawner
|
from systemdspawner import SystemdSpawner
|
||||||
from tljh import user, configurer
|
from tljh import user, configurer
|
||||||
|
import yaml
|
||||||
|
import copy
|
||||||
|
|
||||||
INSTALL_PREFIX = os.environ.get('TLJH_INSTALL_PREFIX')
|
INSTALL_PREFIX = os.environ.get('TLJH_INSTALL_PREFIX')
|
||||||
USER_ENV_PREFIX = os.path.join(INSTALL_PREFIX, 'user')
|
USER_ENV_PREFIX = os.path.join(INSTALL_PREFIX, 'user')
|
||||||
@@ -40,4 +42,10 @@ c.SystemdSpawner.default_shell = '/bin/bash'
|
|||||||
# Drop the '-singleuser' suffix present in the default template
|
# Drop the '-singleuser' suffix present in the default template
|
||||||
c.SystemdSpawner.unit_name_template = 'jupyter-{USERNAME}'
|
c.SystemdSpawner.unit_name_template = 'jupyter-{USERNAME}'
|
||||||
|
|
||||||
configurer.apply_yaml_config(os.path.join(INSTALL_PREFIX, 'config.yaml'), c)
|
config_overrides_path = os.path.join(INSTALL_PREFIX, 'config.yaml')
|
||||||
|
if os.path.exists(config_overrides_path):
|
||||||
|
with open(config_overrides_path) as f:
|
||||||
|
config_overrides = yaml.safe_load(f)
|
||||||
|
else:
|
||||||
|
config_overrides = {}
|
||||||
|
configurer.apply_config(config_overrides, c)
|
||||||
|
|||||||
Reference in New Issue
Block a user