jupyterhub / wrapspawner

Mechanism for runtime configuration of spawners for JupyterHub
BSD 3-Clause "New" or "Revised" License
60 stars 60 forks source link

User-dependent list of available profiles #7

Open andreas-h opened 7 years ago

andreas-h commented 7 years ago

I'm currently using ProfilesSpawner in combination with the batchspawner to offer our HPC cluster's users different BatchSpawner profiles.

Is there any way how I can make the list of profiles offered to the user dependent on the user's group?

If not, I would appreciate a pointer towards where I would need to implement this.

emmanuel commented 6 years ago

I am similarly trying to understand how to filter a list of profiles based on a user's group memberships. The basic/fundamental challenge (I believe) I'm facing is how/where I can pass information from an Authenticator to a Spawner in order to configure the form that is presented to the user. So far, I've looked at three different approaches, none of which work.

  1. Spawner.profiles is called without a handle to the Authenticator
  2. Authenticator.pre_spawn_start is called after the Spawner.user_options_form has been rendered
  3. Spawner.pre_spawn_hook is called after the Spawner.user_options_form has been rendered

Are there any other extension points in either the Authenticator or Spawner class interfaces that would enable customization of the Spawner with information supplied/discovered by the Authenticator?

emmanuel commented 6 years ago

I should mention that I've inspected #15, which is conceptually aligned with what I'm trying to accomplish, however its implementation does not demonstrate integration between Authenticator and Spawner, rather it demonstrates a synchronous call from the Spawner to discover the user's groups from the local system by shelling out. In my use-case, I want to get a list of groups that the Authenticator has fetched via an OAuth2 login flow.

rkdarst commented 5 years ago

options_form can be a callable, which is then executed with itself (the spawner) as an argument. This is done after spawner.user is set. KubeSpawner does this, and I use different functions to generate a user-dependent list of profiles.

wrapspawner could be modified to make this easier. I think right now options_form could just directly be set to a callable, but it won't validate because the trait is declared as a Unicode type only. Upstream does this:

The upstream option is this:

    options_form = Union(
        [Unicode(), Callable()],
)

We can directly copy some logic from kubespawner to make this a bit nicer.

The whole thing makes me wonder about deduplicating kubespawner and wrapspawner (and other similar things)...

benjimin commented 1 year ago

Was pointed to this repo from https://github.com/jupyterhub/kubespawner/issues/589

As that issue shows, there is a need for a similar feature (profile lists dependent on user's group memberships) in other contexts (such as kubernetes clusters, with users managed by AWS Cognito for example, and not only the traditional linux HPC context mentioned by OP here).

The docs for Zero to Jupyterhub with Kubernetes have a section about this feature. They currently advocate passing in localised python code (in via the helm chart value strings and kubernetes config objects) to monkey-patch kubespawner. The problem is their current solution is specific to kubespawner and extremely difficult to test or debug (as the code recipe is totally outside of version control).