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 the jupyterhub-configurator service #676

Merged
merged 6 commits into from
Apr 7, 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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/unit-test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ jobs:
- uses: actions/setup-python@v2
with:
python-version: 3.6
- name: Install and setup venv
- name: Install venv, git and setup venv
run: |
apt-get update --yes && apt-get install --yes python3-venv
apt-get update --yes && apt-get install --yes python3-venv git
python3 -m venv /srv/venv
echo '/srv/venv/bin' >> $GITHUB_PATH
- name: Cache pip deps
Expand Down
1 change: 1 addition & 0 deletions docs/topic/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ Topic guides provide in-depth explanations of specific topics.
authenticator-configuration
escape-hatch
idle-culler
jupyterhub-configurator
28 changes: 28 additions & 0 deletions docs/topic/jupyterhub-configurator.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
.. _topic/jupyterhub-configurator:

=======================
JupyterHub Configurator
=======================

The `JupyterHub configurator <https://github.com/yuvipanda/jupyterhub-configurator>`_ allows admins to change a subset of hub settings via a GUI.

.. image:: ../images/jupyterhub-configurator.png
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@GeorgianaElena this image was never added. Is it something available somewhere else?

:alt: Changing the default JupyterHub interface

Enabling the configurator
=========================

Because the configurator is under continue development and it might change over time, it is disabled by default in TLJH.
If you want to experiment with it, it can be enabled using ``tljh-config``:

.. code-block:: bash

sudo tljh-config set services.configurator.enabled True
sudo tljh-config reload

Accessing the Configurator
==========================

After enabling the configurator using ``tljh-config``, the service will only be available to hub admins, from within the control panel.
The configurator can be accessed from under ``Services`` in the top navigation bar. It will ask to authenticate, so it knows the user is an admin.
Once done, the configurator interface will be available.
2 changes: 0 additions & 2 deletions integration-tests/plugins/simplest/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,3 @@
entry_points={"tljh": ["simplest = tljh_simplest"]},
py_modules=["tljh_simplest"],
)


4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@
'backoff',
'requests',
'bcrypt',
'jupyterhub-traefik-proxy==0.2.*'
'jupyterhub-traefik-proxy==0.2.*',
],
entry_points={
'console_scripts': [
'tljh-config = tljh.config:main',
],
]
},
)
28 changes: 26 additions & 2 deletions tljh/configurer.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@
'concurrency': 5,
'users': False,
'max_age': 0
},
'configurator': {
'enabled': False
}
}
}
Expand Down Expand Up @@ -175,8 +178,8 @@ def update_userlists(c, config):
"""
users = config['users']

c.Authenticator.whitelist = set(users['allowed'])
c.Authenticator.blacklist = set(users['banned'])
c.Authenticator.allowed_users = set(users['allowed'])
c.Authenticator.blocked_users = set(users['banned'])
c.Authenticator.admin_users = set(users['admin'])


Expand Down Expand Up @@ -249,10 +252,31 @@ def set_cull_idle_service(config):
return cull_service


def set_configurator(config):
"""
Set the JupyterHub Configurator service
"""
HERE = os.path.abspath(os.path.dirname(__file__))
configurator_cmd = [
sys.executable, "-m", "jupyterhub_configurator.app",
f"--Configurator.config_file={HERE}/jupyterhub_configurator_config.py"
]
configurator_service = {
'name': 'configurator',
'url': 'http://127.0.0.1:10101',
'command': configurator_cmd,
}

return configurator_service


def update_services(c, config):
c.JupyterHub.services = []

if config['services']['cull']['enabled']:
c.JupyterHub.services.append(set_cull_idle_service(config))
if config['services']['configurator']['enabled']:
c.JupyterHub.services.append(set_configurator(config))


def _merge_dictionaries(a, b, path=None, update=True):
Expand Down
1 change: 1 addition & 0 deletions tljh/installer.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ def ensure_jupyterhub_package(prefix):
"oauthenticator==0.10.0",
"jupyterhub-idle-culler==1.0",
"chardet==3.0.4",
"git+https://github.com/yuvipanda/jupyterhub-configurator@317759e17c8e48de1b1352b836dac2a230536dba"
],
)
traefik.ensure_traefik_binary(prefix)
Expand Down
13 changes: 12 additions & 1 deletion tljh/user_creating_spawner.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
from tljh.normalize import generate_system_username
from tljh import user
from tljh import configurer
from systemdspawner import SystemdSpawner
from traitlets import Dict, Unicode, List
from jupyterhub_configurator.mixins import ConfiguratorSpawnerMixin

class UserCreatingSpawner(SystemdSpawner):
class CustomSpawner(SystemdSpawner):
"""
SystemdSpawner with user creation on spawn.

Expand Down Expand Up @@ -32,3 +34,12 @@ def start(self):
user.ensure_user_group(system_username, group)
return super().start()

cfg = configurer.load_config()
# Use the jupyterhub-configurator mixin only if configurator is enabled
# otherwise, any bugs in the configurator backend will stop new user spawns!
if cfg['services']['configurator']['enabled']:
GeorgianaElena marked this conversation as resolved.
Show resolved Hide resolved
# Dynamically create the Spawner class using `type`(https://docs.python.org/3/library/functions.html?#type),
# based on whether or not it should inherit from ConfiguratorSpawnerMixin
UserCreatingSpawner = type('UserCreatingSpawner', (ConfiguratorSpawnerMixin, CustomSpawner), {})
else:
UserCreatingSpawner = type('UserCreatingSpawner', (CustomSpawner,), {})