Shared Folder for users with r/o access for some and r/w access for some in Jupyterhub

I am trying to achieve a shared directory for all users first. I created a shared-file folder in my Jupyterhub, through the dashboard.
Added this to my jupyterhub_config.py

notebook_dir = os.environ.get('DOCKER_NOTEBOOK_DIR') or 
'/home/jovyan/jupyter' 
c.DockerSpawner.notebook_dir = notebook_dir 
c.DockerSpawner.volumes = { 'jupyterhub-user-{username}': notebook_dir, 
'shared-data/volumes': '/home/jovyan/shared' }

I am launching JupyterHub from my terminal locally using jupyterhub -f jupyterhub_config.py
What am I missing?

Which dashboard are you referring to?

Could you please also tell us what is or isn’t working, this isn’t clear from your post. Thanks!

I guess this post is related to your previous post at Best way to manage user permissions ?

I was looking for a similar feature which would allow us to adjust volume mounts based on certain user attributes.

However it seems like that both DockerSpawner and KubeSpawner both only accept a static volume mount configuration.

We probably need to extend the spawners to allow Callable's for these settings like KubeSpawner already does it for the profile list. The user could then provide a function within the configuration which adjusts the volumes based on the group membership or other attributes.

Currently, KubeSpawner users could maybe use the pod_modify_hook to accomplish the same thing.

This is how I have created ‘shared-data/volumes’ folders.

This folder is only available to Admin - because I have created it from my admin account.
I want to make it readable to some users and read/writable for other group of users.
What is the best way to configure this?

Is there an example of such implementation I can look at?

I think the simplest case might be KubeSpawner.uid:

The setting is declared here: kubespawner/spawner.py#L492

And then evaluated here: kubespawner/spawner.py#L1369

The user can add a little helper function like so:

def get_uid(spawner):
    if spawner.user.admin:
         return 0
    else:
         return 1000

c.KubeSpawner.uid = get_uid

(This example is not tested)

For those who are interested, here is a little example on how to use the c.KubeSpawner.pod_modify_hook based on this post to mount additional PVCs into the users home dir.

Here I just use a static user -> volume map in a Python dict. Which allows you to also set the readOnly volumeMount option

erigrid = {
  'name': 'villas4erigrid',
  'pvc': 'group-villas4erigrid',
  'mountPath': '/home/jovyan/villas4erigrid',
  'readOnly': False
}
user_volume_map = {
  'lrsxpv3p': [ erigrid ],
  'vzi3jsam': [ erigrid ]
}

from kubernetes import client
from kubespawner.utils import get_k8s_model
from kubernetes.client.models import ( V1Volume, V1VolumeMount )

def modify_pod_hook(spawner, pod):
    try:
        user = spawner.user.name
        if user in user_volume_map:
            for volume in user_volume_map[user]:
                pod.spec.volumes.append(
                    get_k8s_model(V1Volume, {
                        'name' : volume['name'],
                        'persistentVolumeClaim': {
                            'claimName': volume['pvc']
                        }
                    })
                )

                # Note implicitly only 1 container...
                pod.spec.containers[0].volume_mounts.append(
                    get_k8s_model(V1VolumeMount, {
                        'name' : volume['name'],
                        'mountPath' : volume['mountPath'],
                        'readOnly': volume['readOnly']
                    })
                )
    except Exception as e:
        spawner.log.info("Exception in shared-mounts" + str(e))
        pass
    return pod

c.KubeSpawner.modify_pod_hook = modify_pod_hook

@stv0g Hi ~~ Thanks for your great method. I have tried out your method which works well to access the PVC at the home directly. The PVC can be seen at all users’ home directory that I defined. However, could I ask is that act like a sharedrive for all the user or it s a separate mount point (i.e. one user’s change under that directory wont be seen by other user). I would like to define it as a sharedrive that one user’s change can be seen by all users. Is that workable?