diff --git a/kubespawner/__init__.py b/kubespawner/__init__.py index ac04a6323..b62e457f1 100644 --- a/kubespawner/__init__.py +++ b/kubespawner/__init__.py @@ -14,5 +14,6 @@ instead of the more verbose import kubespawner.spawner.KubeSpawner. """ from kubespawner.spawner import KubeSpawner +from kubespawner.profile_spawner import KubeProfileSpawner -__all__ = [KubeSpawner] +__all__ = [KubeSpawner, KubeProfileSpawner] diff --git a/kubespawner/profile_spawner.py b/kubespawner/profile_spawner.py new file mode 100644 index 000000000..859e46cec --- /dev/null +++ b/kubespawner/profile_spawner.py @@ -0,0 +1,74 @@ +from traitlets import ( + Instance, Type, Tuple, List, Dict, Integer, Unicode, Float, Any +) +from jupyterhub.spawner import Spawner +from kubespawner.spawner import KubeSpawner + +class KubeProfileSpawner(KubeSpawner): + + UNDEFINED_DISPLAY_NAME = "?? undefined 'display_name' ??" + + form_template = Unicode( + """ + + """, + config = True, + help = """Template to use to construct options_form text. {input_template} is replaced with + the result of formatting input_template against each item in the profiles list.""" + ) + + input_template = Unicode(""" + """, + config = True, + help = """Template to construct {input_template} in form_template. This text will be formatted + against each item in the profiles list, in order, using the following key names: + ( display, key, type ) for the first three items in the tuple, and additionally + first = "checked" (taken from first_template) for the first item in the list, so that + the first item starts selected.""" + ) + + first_template = Unicode('selected', + config=True, + help="Text to substitute as {first} in input_template" + ) + + options_form = Unicode() + + single_user_profile_list = List( + trait = Dict(), + default_value = [], + minlen = 1, + config = True, + help = """List of profiles to offer for selection. Signature is: + List(Dict()), where each item is a dictionary that has two keys: + - 'display_name': the human readable display name + - 'kubespawner_overrride': a dictionary with overrides to apply to the KubeSpawner + settings.""" + ) + + def __init__(self, *args, **kwargs): + Spawner.__init__(self, *args, **kwargs) + + def _options_form_default(self): + temp_keys = [ + { + 'display': p.get('display_name', self.UNDEFINED_DISPLAY_NAME), + 'key': i, + 'first': '', + } for i, p in enumerate(self.single_user_profile_list)] + temp_keys[0]['first'] = self.first_template + text = ''.join([ self.input_template.format(**tk) for tk in temp_keys ]) + return self.form_template.format(input_template=text) + + def options_from_form(self, formdata): + # Default to first profile if somehow none is provided + selected_profile = int(formdata.get('profile',[0])[0]) + options = self.single_user_profile_list[selected_profile] + self.log.debug("Applying KubeSpawner override for profile '%s'", + options.get('display_name', self.UNDEFINED_DISPLAY_NAME)) + kubespawner_overrride = options.get('kubespawner_overrride', {}) + for k, v in kubespawner_overrride.items(): + setattr(self, k, v) + return options \ No newline at end of file