diff --git a/birdhouse/config/jupyterhub/default.env b/birdhouse/config/jupyterhub/default.env index c949cff84..df9478ee3 100644 --- a/birdhouse/config/jupyterhub/default.env +++ b/birdhouse/config/jupyterhub/default.env @@ -43,6 +43,15 @@ export JUPYTER_LOGIN_BANNER_BOTTOM_SECTION="" # server for the change to take effect. export JUPYTERHUB_README="" +# Additional configuration to be provided by services or components managed by the stack. +# Any component extending this configuration using this variable *MUST* include it back to allow further +# components to extend it as well. Also, they *MUST* extend the variable with each new definitions applied on +# a new line (without indents) to ensure that Python configurations will be executable without syntax error. +# This variable differs from 'JUPYTERHUB_CONFIG_OVERRIDE' that does not require users to include it back to make +# its definition extensible by other components. However, 'JUPYTERHUB_CONFIG_OVERRIDE' will still be applied +# after 'JUPYTERHUB_CONFIG_EXTENDED' to ensure it can override anything as needed after all components were resolved. +export JUPYTERHUB_CONFIG_EXTENDED="" + # Allow for adding new config or override existing config in # config/jupyterhub/jupyterhub_config.py.template. export JUPYTERHUB_CONFIG_OVERRIDE="" @@ -65,6 +74,7 @@ OPTIONAL_VARS=" \$JUPYTER_LOGIN_BANNER_TOP_SECTION \$JUPYTER_LOGIN_BANNER_BOTTOM_SECTION \$JUPYTER_LOGIN_TERMS_URL + \$JUPYTERHUB_CONFIG_EXTENDED \$JUPYTERHUB_CONFIG_OVERRIDE \$JUPYTERHUB_DOCKER \$JUPYTERHUB_VERSION diff --git a/birdhouse/config/jupyterhub/jupyterhub_config.py.template b/birdhouse/config/jupyterhub/jupyterhub_config.py.template index e3f6d5ae7..2327d45ca 100644 --- a/birdhouse/config/jupyterhub/jupyterhub_config.py.template +++ b/birdhouse/config/jupyterhub/jupyterhub_config.py.template @@ -187,4 +187,5 @@ blocked_users = {'authtest', '${CATALOG_USERNAME}', 'anonymous'} c.Authenticator.blacklist = blocked_users # v0.9+ c.Authenticator.blocked_users = blocked_users # v1.2+ +${JUPYTERHUB_CONFIG_EXTENDED} # noqa ${JUPYTERHUB_CONFIG_OVERRIDE} # noqa diff --git a/birdhouse/optional-components/jupyterhub-stop-idle/default.env b/birdhouse/optional-components/jupyterhub-stop-idle/default.env new file mode 100644 index 000000000..4428b6bfe --- /dev/null +++ b/birdhouse/optional-components/jupyterhub-stop-idle/default.env @@ -0,0 +1,74 @@ +#!/bin/sh + +# All env in this default.env can be overridden by env.local. + +# All env in this default.env must NOT depend on any other env. If they do, they +# must use single quotes to avoid early expansion before overrides in env.local +# are applied and must be added to the list of DELAYED_EVAL. + +# idle timeout of a user jupyterhub server to be shut down automatically (default: 1 day) +export JUPYTERHUB_STOP_IDLE_TIMEOUT=${JUPYTERHUB_STOP_IDLE_TIMEOUT:-86400} + +# maximum age before stoping user servers (includiung active/running ones, regardless of last activity status) +# if not specified, this will not be defined by the utility +# (i.e.: users that provide activity status before timeout could run their server indefinitely) +export JUPYTERHUB_STOP_IDLE_MAX_AGE= + +# for details about the configuration, see https://github.com/jupyterhub/jupyterhub-idle-culler +# WARNING: be careful about indents here, Python code execution depends on it +export JUPYTERHUB_STOP_IDLE_CONFIG=" +import sys + +jupyterhub_stop_idle_timeout = ${JUPYTERHUB_STOP_IDLE_TIMEOUT} +c.JupyterHub.load_roles = [ + { + 'name': 'jupyterhub-idle-culler-role', + 'scopes': [ + 'list:users', + 'read:users:activity', + 'read:servers', + 'delete:servers', + ], + 'services': ['jupyterhub-idle-culler-service'], + } +] +jupyterhub_stop_idle_max_age = ${JUPYTERHUB_STOP_IDLE_MAX_AGE:-None} +jupyterhub_idle_culler_xargs = [] +if jupyterhub_stop_idle_max_age: + jupyterhub_idle_culler_xargs = ['--max-age', jupyterhub_stop_idle_max_age] +c.JupyterHub.services = [ + { + 'name': 'jupyterhub-idle-culler-service', + 'command': [ + sys.executable, + '-m', 'jupyterhub_idle_culler', + '--timeout', jupyterhub_stop_idle_timeout, + ] + jupyterhub_idle_culler_xargs, + } +] +# we need to ensure that the activity update interval is lower than the stop-idle timeout +# otherwise, the updated information will not be available for the utility to do its job +# however, jupyter has by default 5min intervals, which is usually much lower than 'JUPYTERHUB_STOP_IDLE_TIMEOUT' +c.JupyterHub.last_activity_interval = int(min(jupyterhub_stop_idle_timeout / 2, 300)) +" + +export JUPYTERHUB_CONFIG_EXTENDED=" +${JUPYTERHUB_CONFIG_EXTENDED} +${JUPYTERHUB_STOP_IDLE_CONFIG} +" + +#export DELAYED_EVAL=" +# $DELAYED_EVAL +# JUPYTERHUB_CONFIG_EXTENDED +#" + +OPTIONAL_VARS=" + $OPTIONAL_VARS + \$JUPYTERHUB_STOP_IDLE_TIMEOUT + \$JUPYTERHUB_STOP_IDLE_MAX_AGE +" + +# add any component that this component requires to run +COMPONENT_DEPENDENCIES=" + ./config/jupyterhub +"