diff --git a/swan-cern/Chart.lock b/swan-cern/Chart.lock index 0b4e8ac2..9f0db905 100644 --- a/swan-cern/Chart.lock +++ b/swan-cern/Chart.lock @@ -1,9 +1,9 @@ dependencies: - name: swan - repository: https://registry.cern.ch/chartrepo/swan - version: 0.1.6 + repository: file://../swan + version: 0.2.0 - name: fluentd repository: http://registry.cern.ch/chartrepo/cern version: 0.1.5 -digest: sha256:e3728208418e25f1b1cd3f2486eae02b3e640bb1354df411036835ee7ef6d26f -generated: "2022-02-01T09:20:32.294197039+01:00" +digest: sha256:75996331669b40fbdc6c92c87487e8e063fb7249a6082d73a1229ec766e64604 +generated: "2022-04-21T14:28:14.504289838+02:00" diff --git a/swan-cern/Chart.yaml b/swan-cern/Chart.yaml index ffbc2caf..1108d5ed 100644 --- a/swan-cern/Chart.yaml +++ b/swan-cern/Chart.yaml @@ -9,8 +9,8 @@ description: The chart to deploy SWAN at CERN # dependencies: - name: swan - version: 0.1.6 - repository: https://registry.cern.ch/chartrepo/swan + version: 0.2.0 + repository: file://../swan - name: fluentd repository: http://registry.cern.ch/chartrepo/cern version: 0.1.5 diff --git a/swan-cern/files/swan_config_cern.py b/swan-cern/files/swan_config_cern.py index c91b7a65..d381dac6 100644 --- a/swan-cern/files/swan_config_cern.py +++ b/swan-cern/files/swan_config_cern.py @@ -1,4 +1,4 @@ -import os, subprocess + from kubernetes import client from kubernetes.client.rest import ApiException @@ -190,6 +190,19 @@ def _init_eos_containers(self, eos_secret_name): ) ) + #the notebook container needs to run as root as it needs to + #add an user and switch to that user + #it also need to set command and args to none in order to + #run the systemuser.sh script as defined in the image + #(we set jupyterhub-singleuser in the values as that is what + #is needed for authenticated binder) + + run_as_root=client.V1SecurityContext(run_as_user=0) + + notebook_container.security_context=run_as_root + notebook_container.command=None + notebook_container.args=None + # add the base containers after side container (to start after side container) existing_containers = self.pod.spec.containers pod_spec_containers.extend(existing_containers) @@ -200,11 +213,11 @@ def _init_eos_containers(self, eos_secret_name): # https://jupyterhub-kubespawner.readthedocs.io/en/latest/spawner.html # This is defined in the configuration to allow overring iindependently # of which config file is loaded first -# c.SwanKubeSpawner.modify_pod_hook = swan_pod_hook +# c.SwanSpawner.modify_pod_hook = swan_pod_hook def swan_pod_hook_prod(spawner, pod): """ :param spawner: Swan Kubernetes Spawner - :type spawner: swanspawner.SwanKubeSpawner + :type spawner: swanspawner.SwanSpawner :param pod: default pod definition set by jupyterhub :type pod: client.V1Pod @@ -219,7 +232,4 @@ def swan_pod_hook_prod(spawner, pod): # Get configuration parameters from environment variables swan_container_namespace = os.environ.get('POD_NAMESPACE', 'default') -c.SwanKubeSpawner.modify_pod_hook = swan_pod_hook_prod - -# Required for swan systemuser.sh -c.SwanKubeSpawner.cmd = None \ No newline at end of file +c.SwanSpawner.modify_pod_hook = swan_pod_hook_prod diff --git a/swan-cern/files/swan_spark_config.py b/swan-cern/files/swan_spark_config.py index 1a6e3a85..1f8c4116 100644 --- a/swan-cern/files/swan_spark_config.py +++ b/swan-cern/files/swan_spark_config.py @@ -13,6 +13,12 @@ class SwanSparkPodHookHandler(SwanPodHookHandlerProd): def get_swan_user_pod(self): + + + if 'binder_ref_url' in self.spawner.user_options.keys(): + # we don't need any customization if running within binder + return self.pod + super().get_swan_user_pod() # get hadoop token @@ -170,8 +176,6 @@ def _spark_enabled(self): """ user_roles = self.spawner.user_roles - print(self.spawner.user_options) - print(self.spawner.user_roles) cluster = self.spawner.user_options[self.spawner.spark_cluster_field] if cluster == "analytix" and "analytix" not in user_roles: @@ -337,7 +341,7 @@ def _init_spark(self, pod_labels): def spark_modify_pod_hook(spawner, pod): """ :param spawner: Swan Kubernetes Spawner - :type spawner: swanspawner.SwanKubeSpawner + :type spawner: swanspawner.SwanSpawner :param pod: default pod definition set by jupyterhub :type pod: client.V1Pod @@ -350,4 +354,4 @@ def spark_modify_pod_hook(spawner, pod): # Get configuration parameters from environment variables # swan_container_namespace = os.environ.get('POD_NAMESPACE', 'default') -c.SwanKubeSpawner.modify_pod_hook = spark_modify_pod_hook +c.SwanSpawner.modify_pod_hook = spark_modify_pod_hook diff --git a/swan-cern/swan.dev.values.yaml b/swan-cern/swan.dev.values.yaml index 43ab435a..176fd298 100644 --- a/swan-cern/swan.dev.values.yaml +++ b/swan-cern/swan.dev.values.yaml @@ -1,126 +1,127 @@ swan: - jupyterhub: - hub: - image: - name: "gitlab-registry.cern.ch/swan/docker-images/jupyterhub" - tag: "v1.13" - config: - KeyCloakAuthenticator: - allowed_roles: - - swan-admins - - swan-qa - - swan-devs - extraVolumes: - - name: swan-jh - configMap: - name: swan-scripts - items: - - key: jupyterhub_form.html - path: jupyterhub_form.html - - key: swan_config.py - path: swan_config.py - - name: swan-jh-cern - configMap: - name: swan-scripts-cern - items: - - key: options_form_config.json - path: options_form_config.json - - key: swan_config_cern.py - path: swan_config_cern.py - - key: swan_spark_config.py - path: swan_spark_config.py - - name: swan-cull-scripts - configMap: - name: swan-scripts-cern - items: - - key: cull_check_ticket.sh - path: cull_check_ticket.sh - - key: cull_delete_ticket.sh - path: cull_delete_ticket.sh - defaultMode: 356 # 0544 perm - - name: swan-tokens-scripts - configMap: - name: swan-scripts-env-dev - items: - - key: webhdfs_token.sh - path: webhdfs_token.sh - - key: eos_token.sh - path: eos_token.sh - - key: sparkk8s_token.sh - path: sparkk8s_token.sh - defaultMode: 356 # 0544 perm - - name: swan-secrets - secret: - secretName: swan-cern - items: - - key: eos.cred - path: eos.cred - - key: hadoop.cred - path: hadoop.cred - - key: sparkk8s.cred - path: sparkk8s.cred - - name: cvmfs - hostPath: - path: /var/cvmfs - type: Directory - db: - type: sqlite-memory - custom: - cvmfs: - deployDaemonSet: true - deployCsiDriver: false - useCsiDriver: false - repositories: - - mount: cvmfs-config.cern.ch - - mount: sft.cern.ch - proxy: 'http://ca-proxy-sft.cern.ch:3128;http://ca-proxy.cern.ch:3128' - - mount: sft-nightlies.cern.ch - proxy: 'http://ca-proxy-sft.cern.ch:3128;http://ca-proxy.cern.ch:3128' - - mount: alice.cern.ch - proxy: 'http://ca-proxy-alice.cern.ch:3128;http://ca-proxy.cern.ch:3128' - - mount: alice-ocdb.cern.ch - proxy: 'http://ca-proxy-alice.cern.ch:3128;http://ca-proxy.cern.ch:3128' - - mount: alice-nightlies.cern.ch - proxy: 'http://ca-proxy-alice.cern.ch:3128;http://ca-proxy.cern.ch:3128' - - mount: alpha.cern.ch - - mount: ams.cern.ch - - mount: atlas.cern.ch - proxy: 'http://ca-proxy-atlas.cern.ch:3128;http://ca-proxy.cern.ch:3128' - - mount: atlas-condb.cern.ch - proxy: 'http://ca-proxy-atlas.cern.ch:3128;http://ca-proxy.cern.ch:3128' - - mount: atlas-nightlies.cern.ch - proxy: 'http://ca-proxy-atlas.cern.ch:3128;http://ca-proxy.cern.ch:3128' - - mount: clicbp.cern.ch - - mount: cms.cern.ch - proxy: 'http://cmsmeyproxy.cern.ch:3128;http://ca-proxy.cern.ch:3128' - - mount: cms-ib.cern.ch - proxy: 'http://cmsmeyproxy.cern.ch:3128;http://ca-proxy.cern.ch:3128' - - mount: cms-bril.cern.ch - proxy: 'http://cmsmeyproxy.cern.ch:3128;http://ca-proxy.cern.ch:3128' - - mount: compass.cern.ch - proxy: 'http://ca-proxy-compass.cern.ch:3128;http://ca-proxy.cern.ch:3128' - - mount: compass-condb.cern.ch - proxy: 'http://ca-proxy-compass.cern.ch:3128;http://ca-proxy.cern.ch:3128' - - mount: fcc.cern.ch - - mount: ganga.cern.ch - - mount: geant4.cern.ch - - mount: lhcb.cern.ch - proxy: 'http://ca-proxy-lhcb.cern.ch:3128;http://ca-proxy.cern.ch:3128' - - mount: lhcb-condb.cern.ch - proxy: 'http://ca-proxy-lhcb.cern.ch:3128;http://ca-proxy.cern.ch:3128' - - mount: lhcbdev.cern.ch - proxy: 'http://ca-proxy-lhcb.cern.ch:3128;http://ca-proxy.cern.ch:3128' - - mount: na61.cern.ch - - mount: na62.cern.ch - - mount: projects.cern.ch - - mount: sw.hsf.org - eos: - deployDaemonSet: false - deployCsiDriver: true - useCsiDriver: true - prePuller: - hook: - enabled: false + binderhub: + jupyterhub: + hub: + image: + name: "gitlab-registry.cern.ch/swan/docker-images/jupyterhub" + tag: "v1.13" + config: + KeyCloakAuthenticator: + allowed_roles: + - swan-admins + - swan-qa + - swan-devs + extraVolumes: + - name: swan-jh + configMap: + name: swan-scripts + items: + - key: jupyterhub_form.html + path: jupyterhub_form.html + - key: swan_config.py + path: swan_config.py + - name: swan-jh-cern + configMap: + name: swan-scripts-cern + items: + - key: options_form_config.json + path: options_form_config.json + - key: swan_config_cern.py + path: swan_config_cern.py + - key: swan_spark_config.py + path: swan_spark_config.py + - name: swan-cull-scripts + configMap: + name: swan-scripts-cern + items: + - key: cull_check_ticket.sh + path: cull_check_ticket.sh + - key: cull_delete_ticket.sh + path: cull_delete_ticket.sh + defaultMode: 356 # 0544 perm + - name: swan-tokens-scripts + configMap: + name: swan-scripts-env-dev + items: + - key: webhdfs_token.sh + path: webhdfs_token.sh + - key: eos_token.sh + path: eos_token.sh + - key: sparkk8s_token.sh + path: sparkk8s_token.sh + defaultMode: 356 # 0544 perm + - name: swan-secrets + secret: + secretName: swan-cern + items: + - key: eos.cred + path: eos.cred + - key: hadoop.cred + path: hadoop.cred + - key: sparkk8s.cred + path: sparkk8s.cred + - name: cvmfs + hostPath: + path: /var/cvmfs + type: Directory + db: + type: sqlite-memory + custom: + cvmfs: + deployDaemonSet: true + deployCsiDriver: false + useCsiDriver: false + repositories: + - mount: cvmfs-config.cern.ch + - mount: sft.cern.ch + proxy: 'http://ca-proxy-sft.cern.ch:3128;http://ca-proxy.cern.ch:3128' + - mount: sft-nightlies.cern.ch + proxy: 'http://ca-proxy-sft.cern.ch:3128;http://ca-proxy.cern.ch:3128' + - mount: alice.cern.ch + proxy: 'http://ca-proxy-alice.cern.ch:3128;http://ca-proxy.cern.ch:3128' + - mount: alice-ocdb.cern.ch + proxy: 'http://ca-proxy-alice.cern.ch:3128;http://ca-proxy.cern.ch:3128' + - mount: alice-nightlies.cern.ch + proxy: 'http://ca-proxy-alice.cern.ch:3128;http://ca-proxy.cern.ch:3128' + - mount: alpha.cern.ch + - mount: ams.cern.ch + - mount: atlas.cern.ch + proxy: 'http://ca-proxy-atlas.cern.ch:3128;http://ca-proxy.cern.ch:3128' + - mount: atlas-condb.cern.ch + proxy: 'http://ca-proxy-atlas.cern.ch:3128;http://ca-proxy.cern.ch:3128' + - mount: atlas-nightlies.cern.ch + proxy: 'http://ca-proxy-atlas.cern.ch:3128;http://ca-proxy.cern.ch:3128' + - mount: clicbp.cern.ch + - mount: cms.cern.ch + proxy: 'http://cmsmeyproxy.cern.ch:3128;http://ca-proxy.cern.ch:3128' + - mount: cms-ib.cern.ch + proxy: 'http://cmsmeyproxy.cern.ch:3128;http://ca-proxy.cern.ch:3128' + - mount: cms-bril.cern.ch + proxy: 'http://cmsmeyproxy.cern.ch:3128;http://ca-proxy.cern.ch:3128' + - mount: compass.cern.ch + proxy: 'http://ca-proxy-compass.cern.ch:3128;http://ca-proxy.cern.ch:3128' + - mount: compass-condb.cern.ch + proxy: 'http://ca-proxy-compass.cern.ch:3128;http://ca-proxy.cern.ch:3128' + - mount: fcc.cern.ch + - mount: ganga.cern.ch + - mount: geant4.cern.ch + - mount: lhcb.cern.ch + proxy: 'http://ca-proxy-lhcb.cern.ch:3128;http://ca-proxy.cern.ch:3128' + - mount: lhcb-condb.cern.ch + proxy: 'http://ca-proxy-lhcb.cern.ch:3128;http://ca-proxy.cern.ch:3128' + - mount: lhcbdev.cern.ch + proxy: 'http://ca-proxy-lhcb.cern.ch:3128;http://ca-proxy.cern.ch:3128' + - mount: na61.cern.ch + - mount: na62.cern.ch + - mount: projects.cern.ch + - mount: sw.hsf.org + eos: + deployDaemonSet: false + deployCsiDriver: true + useCsiDriver: true + prePuller: + hook: + enabled: false hadoopTokenGenerator: extraVolumes: - name: swan-tokens-scripts @@ -129,4 +130,4 @@ hadoopTokenGenerator: items: - key: hadoop_token.sh path: hadoop_token.sh - defaultMode: 500 \ No newline at end of file + defaultMode: 500 diff --git a/swan-cern/templates/hadoop-token-generator.yaml b/swan-cern/templates/hadoop-token-generator.yaml index bd83bc67..ef8a9c1c 100644 --- a/swan-cern/templates/hadoop-token-generator.yaml +++ b/swan-cern/templates/hadoop-token-generator.yaml @@ -31,13 +31,13 @@ spec: name: hub key: hub.services.hadoop-token-generator.apiToken - name: HADOOP_CONF_HOME - value: {{ .Values.swan.jupyterhub.custom.spark.configurationPath }} + value: {{ .Values.swan.binderhub.jupyterhub.custom.spark.configurationPath }} livenessProbe: exec: command: - ls - - {{ .Values.swan.jupyterhub.custom.spark.configurationPath }} + - {{ .Values.swan.binderhub.jupyterhub.custom.spark.configurationPath }} initialDelaySeconds: 5 periodSeconds: 5 diff --git a/swan-cern/values.yaml b/swan-cern/values.yaml index 6b5fb8e9..095c9cae 100644 --- a/swan-cern/values.yaml +++ b/swan-cern/values.yaml @@ -3,209 +3,247 @@ swan: deployDaemonSet: &cvmfsDeployDS true deployCsiDriver: &cvmfsDeployCSI false useCsiDriver: &cvmfsUseCSI false + prefetcher: + enabled: true + jobs: + cron_opennotebook_python2_ipy: + command: "source /cvmfs/sft.cern.ch/lcg/views/LCG_99python2/x86_64-centos7-gcc8-opt/setup.sh && ( timeout 20s python -m ipykernel > /dev/null 2>&1 || true )" + minute: '*/15' + cron_opennotebook_python2_root: + command: "source /cvmfs/sft.cern.ch/lcg/views/LCG_99python2/x86_64-centos7-gcc8-opt/setup.sh && ( timeout 20s python -m JupyROOT.kernel.rootkernel > /dev/null 2>&1 || true )" + minute: '*/15' + cron_opennotebook_python3_root: + command: "source /cvmfs/sft.cern.ch/lcg/views/LCG_101swan/x86_64-centos7-gcc8-opt/setup.sh && ( timeout 20s python -m JupyROOT.kernel.rootkernel > /dev/null 2>&1 || true )" + minute: '*/15' + cron_opennotebook_python3nx_ipy: + command: "source /cvmfs/sft.cern.ch/lcg/views/LCG_95apython3_nxcals/x86_64-centos7-gcc7-opt/setup.sh && ( timeout 20s python -m ipykernel > /dev/null 2>&1 || true )" + minute: '*/15' + cron_opennotebook_python3nx_spark: + command: "source /cvmfs/sft.cern.ch/lcg/views/LCG_100_nxcals/x86_64-centos7-gcc9-opt/setup.sh && ( timeout 20s python -c 'import pyspark' > /dev/null 2>&1 || true )" + minute: '*/15' + cron_opennotebook_cuda_tensorflow: + command: "(lsmod | grep nvidia) && source /cvmfs/sft.cern.ch/lcg/views/LCG_101cuda/x86_64-centos7-gcc8-opt/setup.sh && ( timeout 60s python -c 'import tensorflow' > /dev/null 2>&1 || true )" + minute: '5,20,35,50' + cron_opennoteook_cuda_torch: + command: "(lsmod | grep nvidia) && source /cvmfs/sft.cern.ch/lcg/views/LCG_101cuda/x86_64-centos7-gcc8-opt/setup.sh && ( timeout 60s python -c 'import torch' > /dev/null 2>&1 || true )" + minute: '10,25,40,55' eos: deployDaemonSet: &eosDeployDS false deployCsiDriver: &eosDeployCSI true useCsiDriver: &eosUseCSI true - jupyterhub: - hub: - extraVolumeMounts: - - name: swan-jh-cern - mountPath: /srv/jupyterhub/options_form_config.json - subPath: options_form_config.json - - name: swan-jh - mountPath: /srv/jupyterhub/jupyterhub_form.html - subPath: jupyterhub_form.html - - name: swan-jh - mountPath: /usr/local/etc/jupyterhub/jupyterhub_config.d/1_swan_config.py - subPath: swan_config.py - - name: swan-jh-cern - mountPath: /usr/local/etc/jupyterhub/jupyterhub_config.d/2_swan_config_cern.py - subPath: swan_config_cern.py - - name: swan-jh-cern - mountPath: /usr/local/etc/jupyterhub/jupyterhub_config.d/3_swan_spark_config.py - subPath: swan_spark_config.py - - name: swan-secrets - mountPath: /srv/jupyterhub/private/eos.cred - subPath: eos.cred - - name: swan-secrets - mountPath: /srv/jupyterhub/private/hadoop.cred - subPath: hadoop.cred - - name: swan-secrets - mountPath: /srv/jupyterhub/private/sparkk8s.cred - subPath: sparkk8s.cred - - name: swan-cull-scripts - mountPath: /srv/jupyterhub/culler/check_ticket.sh - subPath: cull_check_ticket.sh - - name: swan-cull-scripts - mountPath: /srv/jupyterhub/culler/delete_ticket.sh - subPath: cull_delete_ticket.sh - - name: swan-tokens-scripts - mountPath: /srv/jupyterhub/private/eos_token.sh - subPath: eos_token.sh - - name: swan-tokens-scripts - mountPath: /srv/jupyterhub/private/webhdfs_token.sh - subPath: webhdfs_token.sh - - name: swan-tokens-scripts - mountPath: /srv/jupyterhub/private/sparkk8s_token.sh - subPath: sparkk8s_token.sh - - name: cvmfs - mountPath: /cvmfs - extraVolumes: - - name: cvmfs - hostPath: - path: /var/cvmfs - type: Directory - - name: swan-jh - configMap: - name: swan-scripts - items: - - key: jupyterhub_form.html - path: jupyterhub_form.html - - key: swan_config.py - path: swan_config.py - - name: swan-jh-cern - configMap: - name: swan-scripts-cern - items: - - key: options_form_config.json - path: options_form_config.json - - key: swan_config_cern.py - path: swan_config_cern.py - - key: swan_spark_config.py - path: swan_spark_config.py - - name: swan-cull-scripts - configMap: - name: swan-scripts-cern - items: - - key: cull_check_ticket.sh - path: cull_check_ticket.sh - - key: cull_delete_ticket.sh - path: cull_delete_ticket.sh - defaultMode: 356 # 0544 perm - - name: swan-tokens-scripts - configMap: - name: swan-scripts-env-prod - items: - - key: webhdfs_token.sh - path: webhdfs_token.sh - - key: eos_token.sh - path: eos_token.sh - - key: sparkk8s_token.sh - path: sparkk8s_token.sh - defaultMode: 356 # 0544 perm - - name: swan-secrets - secret: - secretName: swan-cern - items: - - key: eos.cred - path: eos.cred - - key: hadoop.cred - path: hadoop.cred - - key: sparkk8s.cred - path: sparkk8s.cred - config: - KeyCloakAuthenticator: - oidc_issuer: https://auth.cern.ch/auth/realms/cern - exchange_tokens: - - eos-service - - cernbox-service - logout_redirect_uri: https://cern.ch/swan - auto_login: True - username_key: preferred_username - client_id: # placeholder, check secrets - client_secret: # placeholder, check secrets - oauth_callback_url: # placeholder, check secrets - JupyterHub: - allow_named_servers: False - extraConfig: - 00-authConf: | - def pre_spawn_hook(authenticator, spawner, auth_state): - spawner.environment['ACCESS_TOKEN'] = auth_state['exchanged_tokens']['eos-service'] - spawner.environment['OAUTH_INSPECTION_ENDPOINT'] = authenticator.userdata_url.replace('https://', '') - spawner.user_uid = str(str(auth_state['oauth_user']['cern_uid'])) # k8s only supports values as strings! - decoded_token = authenticator._decode_token(auth_state['access_token']) - spawner.user_roles = authenticator.claim_roles_key(authenticator, decoded_token) - c.KeyCloakAuthenticator.pre_spawn_hook = pre_spawn_hook - 02-spawnError: | - SPAWN_ERROR_MESSAGE = """SWAN could not start a session for your user, please try again. If the problem persists, please check: - """ - - # SWAN@CERN error message - c.SpawnHandlersConfigs.spawn_error_message = SPAWN_ERROR_MESSAGE - db: - type: postgres - # placeholder for postgres connection url - url: - # placeholder for postgres password - password: - services: - hadoop-token-generator: {} # apiToken is generated by the chart - - custom: - cull: - # 6 hours - timeout: 21600 - checkEosAuth: true - hooksDir: /srv/jupyterhub/culler - cvmfs: - deployDaemonSet: *cvmfsDeployDS - deployCsiDriver: *cvmfsDeployCSI - useCsiDriver: *cvmfsUseCSI - repositories: - - mount: cvmfs-config.cern.ch - - mount: sft.cern.ch - proxy: 'http://ca-proxy-sft.cern.ch:3128;http://ca-proxy.cern.ch:3128' - - mount: sft-nightlies.cern.ch - proxy: 'http://ca-proxy-sft.cern.ch:3128;http://ca-proxy.cern.ch:3128' - - mount: alice.cern.ch - proxy: 'http://ca-proxy-alice.cern.ch:3128;http://ca-proxy.cern.ch:3128' - - mount: alice-ocdb.cern.ch - proxy: 'http://ca-proxy-alice.cern.ch:3128;http://ca-proxy.cern.ch:3128' - - mount: alice-nightlies.cern.ch - proxy: 'http://ca-proxy-alice.cern.ch:3128;http://ca-proxy.cern.ch:3128' - - mount: alpha.cern.ch - - mount: ams.cern.ch - - mount: atlas.cern.ch - proxy: 'http://ca-proxy-atlas.cern.ch:3128;http://ca-proxy.cern.ch:3128' - - mount: atlas-condb.cern.ch - proxy: 'http://ca-proxy-atlas.cern.ch:3128;http://ca-proxy.cern.ch:3128' - - mount: atlas-nightlies.cern.ch - proxy: 'http://ca-proxy-atlas.cern.ch:3128;http://ca-proxy.cern.ch:3128' - - mount: clicbp.cern.ch - - mount: cms.cern.ch - proxy: 'http://cmsmeyproxy.cern.ch:3128;http://ca-proxy.cern.ch:3128' - - mount: cms-ib.cern.ch - proxy: 'http://cmsmeyproxy.cern.ch:3128;http://ca-proxy.cern.ch:3128' - - mount: cms-bril.cern.ch - proxy: 'http://cmsmeyproxy.cern.ch:3128;http://ca-proxy.cern.ch:3128' - - mount: compass.cern.ch - proxy: 'http://ca-proxy-compass.cern.ch:3128;http://ca-proxy.cern.ch:3128' - - mount: compass-condb.cern.ch - proxy: 'http://ca-proxy-compass.cern.ch:3128;http://ca-proxy.cern.ch:3128' - - mount: fcc.cern.ch - - mount: ganga.cern.ch - - mount: geant4.cern.ch - - mount: lhcb.cern.ch - proxy: 'http://ca-proxy-lhcb.cern.ch:3128;http://ca-proxy.cern.ch:3128' - - mount: lhcb-condb.cern.ch - proxy: 'http://ca-proxy-lhcb.cern.ch:3128;http://ca-proxy.cern.ch:3128' - - mount: lhcbdev.cern.ch - proxy: 'http://ca-proxy-lhcb.cern.ch:3128;http://ca-proxy.cern.ch:3128' - - mount: na61.cern.ch - - mount: na62.cern.ch - - mount: projects.cern.ch - - mount: sw.hsf.org - eos: - deployDaemonSet: *eosDeployDS - deployCsiDriver: *eosDeployCSI - useCsiDriver: *eosUseCSI - spark: - configurationPath: /cvmfs/sft.cern.ch/lcg/etc/hadoop-confext + binderhub: + jupyterhub: + hub: + extraVolumeMounts: + - name: swan-jh-cern + mountPath: /srv/jupyterhub/options_form_config.json + subPath: options_form_config.json + - name: swan-jh + mountPath: /srv/jupyterhub/jupyterhub_form.html + subPath: jupyterhub_form.html + - name: swan-jh + mountPath: /usr/local/etc/jupyterhub/jupyterhub_config.d/1_swan_config.py + subPath: swan_config.py + - name: swan-jh-cern + mountPath: /usr/local/etc/jupyterhub/jupyterhub_config.d/2_swan_config_cern.py + subPath: swan_config_cern.py + - name: swan-jh-cern + mountPath: /usr/local/etc/jupyterhub/jupyterhub_config.d/3_swan_spark_config.py + subPath: swan_spark_config.py + - name: swan-secrets + mountPath: /srv/jupyterhub/private/eos.cred + subPath: eos.cred + - name: swan-secrets + mountPath: /srv/jupyterhub/private/hadoop.cred + subPath: hadoop.cred + - name: swan-secrets + mountPath: /srv/jupyterhub/private/sparkk8s.cred + subPath: sparkk8s.cred + - name: swan-cull-scripts + mountPath: /srv/jupyterhub/culler/check_ticket.sh + subPath: cull_check_ticket.sh + - name: swan-cull-scripts + mountPath: /srv/jupyterhub/culler/delete_ticket.sh + subPath: cull_delete_ticket.sh + - name: swan-tokens-scripts + mountPath: /srv/jupyterhub/private/eos_token.sh + subPath: eos_token.sh + - name: swan-tokens-scripts + mountPath: /srv/jupyterhub/private/webhdfs_token.sh + subPath: webhdfs_token.sh + - name: swan-tokens-scripts + mountPath: /srv/jupyterhub/private/sparkk8s_token.sh + subPath: sparkk8s_token.sh + - name: cvmfs + mountPath: /cvmfs + extraVolumes: + - name: cvmfs + hostPath: + path: /var/cvmfs + type: Directory + - name: swan-jh + configMap: + name: swan-scripts + items: + - key: jupyterhub_form.html + path: jupyterhub_form.html + - key: swan_config.py + path: swan_config.py + - name: swan-jh-cern + configMap: + name: swan-scripts-cern + items: + - key: options_form_config.json + path: options_form_config.json + - key: swan_config_cern.py + path: swan_config_cern.py + - key: swan_spark_config.py + path: swan_spark_config.py + - name: swan-cull-scripts + configMap: + name: swan-scripts-cern + items: + - key: cull_check_ticket.sh + path: cull_check_ticket.sh + - key: cull_delete_ticket.sh + path: cull_delete_ticket.sh + defaultMode: 356 # 0544 perm + - name: swan-tokens-scripts + configMap: + name: swan-scripts-env-prod + items: + - key: webhdfs_token.sh + path: webhdfs_token.sh + - key: eos_token.sh + path: eos_token.sh + - key: sparkk8s_token.sh + path: sparkk8s_token.sh + defaultMode: 356 # 0544 perm + - name: swan-secrets + secret: + secretName: swan-cern + items: + - key: eos.cred + path: eos.cred + - key: hadoop.cred + path: hadoop.cred + - key: sparkk8s.cred + path: sparkk8s.cred + config: + KeyCloakAuthenticator: + oidc_issuer: https://auth.cern.ch/auth/realms/cern + exchange_tokens: + - eos-service + - cernbox-service + logout_redirect_uri: https://cern.ch/swan + auto_login: True + username_key: preferred_username + client_id: # placeholder, check secrets + client_secret: # placeholder, check secrets + oauth_callback_url: # placeholder, check secrets + JupyterHub: + allow_named_servers: False + extraConfig: + 00-authConf: | + def pre_spawn_hook(authenticator, spawner, auth_state): + try: + spawner.environment['ACCESS_TOKEN'] = auth_state['exchanged_tokens']['eos-service'] + spawner.environment['OAUTH_INSPECTION_ENDPOINT'] = authenticator.userdata_url.replace('https://', '') + spawner.user_uid = str(str(auth_state['oauth_user']['cern_uid'])) # k8s only supports values as strings! + decoded_token = authenticator._decode_token(auth_state['access_token']) + spawner.user_roles = authenticator.claim_roles_key(authenticator, decoded_token) + except: + pass + c.KeyCloakAuthenticator.pre_spawn_hook = pre_spawn_hook + 01-hook-swancern: | + 02-spawnError: | + SPAWN_ERROR_MESSAGE = """SWAN could not start a session for your user, please try again. If the problem persists, please check: + """ + + # SWAN@CERN error message + c.SpawnHandlersConfigs.spawn_error_message = SPAWN_ERROR_MESSAGE + 03-disableIPv6: | + c.KubeSpawner.init_containers = [{ + "name": "init-iptables", + "image": "cern/cc7-base:20181210", + "command": ["/bin/bash", "-c", "sysctl -w net.ipv6.conf.all.disable_ipv6=1"], + "securityContext": { + "privileged": True + } + }] + db: + type: postgres + # placeholder for postgres connection url + url: + # placeholder for postgres password + password: + services: + hadoop-token-generator: {} # apiToken is generated by the chart + + custom: + cull: + # 6 hours + timeout: 21600 + checkEosAuth: true + hooksDir: /srv/jupyterhub/culler + cvmfs: + deployDaemonSet: *cvmfsDeployDS + deployCsiDriver: *cvmfsDeployCSI + useCsiDriver: *cvmfsUseCSI + repositories: + - mount: cvmfs-config.cern.ch + - mount: sft.cern.ch + proxy: 'http://ca-proxy-sft.cern.ch:3128;http://ca-proxy.cern.ch:3128' + - mount: sft-nightlies.cern.ch + proxy: 'http://ca-proxy-sft.cern.ch:3128;http://ca-proxy.cern.ch:3128' + - mount: alice.cern.ch + proxy: 'http://ca-proxy-alice.cern.ch:3128;http://ca-proxy.cern.ch:3128' + - mount: alice-ocdb.cern.ch + proxy: 'http://ca-proxy-alice.cern.ch:3128;http://ca-proxy.cern.ch:3128' + - mount: alice-nightlies.cern.ch + proxy: 'http://ca-proxy-alice.cern.ch:3128;http://ca-proxy.cern.ch:3128' + - mount: alpha.cern.ch + - mount: ams.cern.ch + - mount: atlas.cern.ch + proxy: 'http://ca-proxy-atlas.cern.ch:3128;http://ca-proxy.cern.ch:3128' + - mount: atlas-condb.cern.ch + proxy: 'http://ca-proxy-atlas.cern.ch:3128;http://ca-proxy.cern.ch:3128' + - mount: atlas-nightlies.cern.ch + proxy: 'http://ca-proxy-atlas.cern.ch:3128;http://ca-proxy.cern.ch:3128' + - mount: clicbp.cern.ch + - mount: cms.cern.ch + proxy: 'http://cmsmeyproxy.cern.ch:3128;http://ca-proxy.cern.ch:3128' + - mount: cms-ib.cern.ch + proxy: 'http://cmsmeyproxy.cern.ch:3128;http://ca-proxy.cern.ch:3128' + - mount: cms-bril.cern.ch + proxy: 'http://cmsmeyproxy.cern.ch:3128;http://ca-proxy.cern.ch:3128' + - mount: compass.cern.ch + proxy: 'http://ca-proxy-compass.cern.ch:3128;http://ca-proxy.cern.ch:3128' + - mount: compass-condb.cern.ch + proxy: 'http://ca-proxy-compass.cern.ch:3128;http://ca-proxy.cern.ch:3128' + - mount: fcc.cern.ch + - mount: ganga.cern.ch + - mount: geant4.cern.ch + - mount: lhcb.cern.ch + proxy: 'http://ca-proxy-lhcb.cern.ch:3128;http://ca-proxy.cern.ch:3128' + - mount: lhcb-condb.cern.ch + proxy: 'http://ca-proxy-lhcb.cern.ch:3128;http://ca-proxy.cern.ch:3128' + - mount: lhcbdev.cern.ch + proxy: 'http://ca-proxy-lhcb.cern.ch:3128;http://ca-proxy.cern.ch:3128' + - mount: na61.cern.ch + - mount: na62.cern.ch + - mount: projects.cern.ch + - mount: sw.hsf.org + eos: + deployDaemonSet: *eosDeployDS + deployCsiDriver: *eosDeployCSI + useCsiDriver: *eosUseCSI + spark: + configurationPath: /cvmfs/sft.cern.ch/lcg/etc/hadoop-confext swanCern: secrets: eos: diff --git a/swan/Chart.lock b/swan/Chart.lock index 43e71849..21663983 100644 --- a/swan/Chart.lock +++ b/swan/Chart.lock @@ -1,7 +1,7 @@ dependencies: -- name: jupyterhub +- name: binderhub repository: https://jupyterhub.github.io/helm-chart/ - version: 1.2.0 + version: 0.2.0-n905.h3d3e24e - name: fusex repository: https://registry.cern.ch/chartrepo/eos version: 0.1.0 @@ -10,9 +10,9 @@ dependencies: version: 0.3.1 - name: cvmfs repository: https://registry.cern.ch/chartrepo/sciencebox - version: 0.0.4 + version: 0.0.5 - name: cvmfs-csi repository: http://registry.cern.ch/chartrepo/cern version: 0.1.0 -digest: sha256:b8c51c9df17635614483cc7a57c5b4936ff18cf2f3b830e6f8555cec7c1eff68 -generated: "2022-01-07T10:40:34.001728425+01:00" +digest: sha256:2b7545bef6fcaeb13c20f76ae5c44c69168e944a662c9a9650aeb082abc09d29 +generated: "2022-04-21T14:26:38.496141383+02:00" diff --git a/swan/Chart.yaml b/swan/Chart.yaml index 7450c893..184253d7 100644 --- a/swan/Chart.yaml +++ b/swan/Chart.yaml @@ -2,15 +2,15 @@ apiVersion: v2 # name: swan type: application -version: 0.1.6 +version: 0.2.0 appVersion: 0.1.2 # Using swanhub version # description: A fully-fledged SWAN instance with jupyterhub, EOS, and CVMFS icon: https://swan.docs.cern.ch/images/logos/logo_swan_letters.png # dependencies: - - name: jupyterhub - version: 1.2.0 + - name: binderhub + version: 0.2.0-n905.h3d3e24e repository: https://jupyterhub.github.io/helm-chart/ - name: fusex @@ -23,7 +23,7 @@ dependencies: condition: eos.deployCsiDriver - name: cvmfs - version: 0.0.4 + version: 0.0.5 repository: https://registry.cern.ch/chartrepo/sciencebox condition: cvmfs.deployDaemonSet - name: cvmfs-csi diff --git a/swan/files/swan_config.py b/swan/files/swan_config.py index f55d4add..72d9a40f 100644 --- a/swan/files/swan_config.py +++ b/swan/files/swan_config.py @@ -10,7 +10,7 @@ class SwanPodHookHandler: def __init__(self, spawner, pod): """ - :type spawner: swanspawner.SwanKubeSpawner + :type spawner: swanspawner.SwanSpawner :type pod: client.V1Pod """ self.spawner = spawner @@ -18,6 +18,11 @@ def __init__(self, spawner, pod): def get_swan_user_pod(self): + if 'binder_ref_url' in self.spawner.user_options.keys(): + # we don't need any customization if running within binder + return self.pod + + # pod labels pod_labels = dict( lcg_release = self.spawner.user_options[self.spawner.lcg_rel_field].split('/')[0], @@ -135,11 +140,11 @@ def _add_or_replace_by_name(self, list, element): # https://jupyterhub-kubespawner.readthedocs.io/en/latest/spawner.html # This is defined in the configuration to allow overring iindependently # of which config file is loaded first -# c.SwanKubeSpawner.modify_pod_hook = swan_pod_hook +# c.SwanSpawner.modify_pod_hook = swan_pod_hook def swan_pod_hook(spawner, pod): """ :param spawner: Swan Kubernetes Spawner - :type spawner: swanspawner.SwanKubeSpawner + :type spawner: swanspawner.SwanSpawner :param pod: default pod definition set by jupyterhub :type pod: client.V1Pod @@ -152,7 +157,7 @@ def swan_pod_hook(spawner, pod): """ Configuration for JupyterHub """ -c.SwanKubeSpawner.modify_pod_hook = swan_pod_hook +c.SwanSpawner.modify_pod_hook = swan_pod_hook # Hub services @@ -208,11 +213,11 @@ def swan_pod_hook(spawner, pod): # Init lists for volumes and volume_mounts -c.SwanKubeSpawner.volumes = [] -c.SwanKubeSpawner.volume_mounts = [] +c.SwanSpawner.volumes = [] +c.SwanSpawner.volume_mounts = [] # add /dev/shm (for pyTorch and others) -c.SwanKubeSpawner.volumes.append( +c.SwanSpawner.volumes.append( client.V1Volume( name='devshm', empty_dir=client.V1EmptyDirVolumeSource( @@ -220,7 +225,7 @@ def swan_pod_hook(spawner, pod): ) ) ) -c.SwanKubeSpawner.volume_mounts.append( +c.SwanSpawner.volume_mounts.append( client.V1VolumeMount( name='devshm', mount_path='/dev/shm', @@ -231,14 +236,14 @@ def swan_pod_hook(spawner, pod): if get_config("custom.eos.deployDaemonSet", False): # Access via bind-mount from the host logging.info("EOS access via DaemonSet") - c.SwanKubeSpawner.volume_mounts.append( + c.SwanSpawner.volume_mounts.append( client.V1VolumeMount( name='eos', mount_path='/eos', mount_propagation='HostToContainer' ), ) - c.SwanKubeSpawner.volumes.append( + c.SwanSpawner.volumes.append( client.V1Volume( name='eos', host_path=client.V1HostPathVolumeSource( @@ -250,14 +255,14 @@ def swan_pod_hook(spawner, pod): get_config("custom.eos.useCsiDriver", False)): # Access via CSI driver (still a bind-mount in practical terms) logging.info("EOS access via CSI driver") - c.SwanKubeSpawner.volume_mounts.append( + c.SwanSpawner.volume_mounts.append( client.V1VolumeMount( name='eos', mount_path='/eos', mount_propagation='HostToContainer' ), ) - c.SwanKubeSpawner.volumes.append( + c.SwanSpawner.volumes.append( client.V1Volume( name='eos', host_path=client.V1HostPathVolumeSource( @@ -274,7 +279,7 @@ def swan_pod_hook(spawner, pod): if get_config("custom.cvmfs.deployDaemonSet", False): # Access via bind-mount from the host logging.info("CVMFS access via DaemonSet") - c.SwanKubeSpawner.volumes.append( + c.SwanSpawner.volumes.append( client.V1Volume( name='cvmfs', host_path=client.V1HostPathVolumeSource( @@ -282,7 +287,7 @@ def swan_pod_hook(spawner, pod): ) ) ) - c.SwanKubeSpawner.volume_mounts.append( + c.SwanSpawner.volume_mounts.append( client.V1VolumeMount( name='cvmfs', mount_path='/cvmfs', @@ -296,7 +301,7 @@ def swan_pod_hook(spawner, pod): cvmfs_repos = get_config('custom.cvmfs.repositories', []) for cvmfs_repo_path in cvmfs_repos: cvmfs_repo_id = cvmfs_repo_path['mount'].replace('.', '-') - c.SwanKubeSpawner.volumes.append( + c.SwanSpawner.volumes.append( client.V1Volume( name='cvmfs-'+cvmfs_repo_id, persistent_volume_claim=client.V1PersistentVolumeClaimVolumeSource( @@ -304,7 +309,7 @@ def swan_pod_hook(spawner, pod): ) ) ) - c.SwanKubeSpawner.volume_mounts.append( + c.SwanSpawner.volume_mounts.append( client.V1VolumeMount( name='cvmfs-'+cvmfs_repo_id, mount_path='/cvmfs/'+cvmfs_repo_path['mount'], @@ -317,4 +322,4 @@ def swan_pod_hook(spawner, pod): pass # Required for swan systemuser.sh -c.SwanKubeSpawner.cmd = None +c.SwanSpawner.cmd = None diff --git a/swan/swan.secrets.template.yaml b/swan/swan.secrets.template.yaml index af7f48f4..644c86f2 100644 --- a/swan/swan.secrets.template.yaml +++ b/swan/swan.secrets.template.yaml @@ -1,36 +1,98 @@ -jupyterhub: - proxy: - # generate with openssl rand -hex 32 - # encrypt communications between the hub and the configurable-http-proxy - secretToken: - hub: - # database backend to use for the hub database - db: - url: - password: +swan: + binderhub: + image: + name: registry.cern.ch/binder/binderhub + tag: v1.0.0-alpha extraEnv: - # openssl rand -hex 32 - # to encrypt auth state - JUPYTERHUB_CRYPT_KEY: - # openssl rand -hex 32 - # to sign cookies - cookieSecret: + REQUESTS_CA_BUNDLE: /etc/pki/tls/certs/ca-bundle.crt config: - KeyCloakAuthenticator: - client_id: - client_secret: - # https:///hub/oauth_callback - oauth_callback_url: - ingress: - # List of hosts to route requests to the proxy - tls: - - secretName: swan-tls-cert - hosts: - - -swan: + Launcher: + allow_named_servers: true + BinderHub: + debug: true + base_url: /binder/ + auth_enabled: true + use_registry: true + image_prefix: registry.cern.ch/binder/exp1- + hub_url: https://swanrc.cern.ch/ + DockerRegistry: + token_url: "https://registry.cern.ch/v2/token?service=registry.cern.ch" + service: + type: NodePort + registry: + url: https://registry.cern.ch + username: robot-binder+binder + password: ...... + jupyterhub: + singleuser: + storage: + type: none + image: + tag: v5.15.4 + # understand why this is needed and what is in swan/values.yaml is not enough + hub: + redirectToServer: false + image: + name: gitlab-registry.cern.ch/rcastell/publicregistry/jupyterhub + tag: v2.0.alfa13 + # database backend to use for the hub database + db: + type: sqlite-memory + services: + binder: + oauth_no_confirm: true + oauth_redirect_uri: "http://swanrc.cern.ch/binder/oauth_callback" + oauth_client_id: "service-binder-oauth-client-test" + config: + JupyterHub: + allow_named_servers: true + named_server_limit_per_user: 5 + admin_access: true + SwanBinderSpawner: + default_url: 'lab' + auth_enabled: true + KeyCloakAuthenticator: + admin_users: + - ..... + client_id: + client_secret: + oauth_callback_url: https:///hub/oauth_callback + extraConfig: + 03-swanbinder: | + c.JupyterHub.spawner_class = swanspawner.SwanBinderSpawner + c.SwanBinderSpawner.cmd = 'jupyterhub-singleuser' + jupyterhub: + proxy: + # generate with openssl rand -hex 32 + # encrypt communications between the hub and the configurable-http-proxy + secretToken: + hub: + # database backend to use for the hub database (when commented use sqlite-memory for dev purposes) +# db: +# url: +# password: + extraEnv: + # openssl rand -hex 32 + # to encrypt auth state + JUPYTERHUB_CRYPT_KEY: + # openssl rand -hex 32 + # to sign cookies + cookieSecret: + config: + KeyCloakAuthenticator: + client_id: + client_secret: + # https:///hub/oauth_callback + oauth_callback_url: + ingress: + # List of hosts to route requests to the proxy (use the main alias if dns load balanced) + tls: + - secretName: swan-tls-cert + hosts: + - secrets: # ssl termination certificate ingress: - #this two keys are the output of "echo host{cert|key}.pem | base64 -w0" + #this two keys are the output of "cat host{cert|key}.pem | base64 -w0" cert: key: diff --git a/swan/templates/ingress.yaml b/swan/templates/ingress.yaml new file mode 100644 index 00000000..415172f9 --- /dev/null +++ b/swan/templates/ingress.yaml @@ -0,0 +1,33 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ include "jupyterhub.ingress.fullname" . }} + labels: + {{- include "jupyterhub.labels" . | nindent 4 }} + {{- with .Values.binderhub.jupyterhub.ingress.annotations }} + annotations: + {{- . | toYaml | nindent 4 }} + {{- end }} +spec: + {{- with .Values.binderhub.jupyterhub.ingress.ingressClassName }} + ingressClassName: "{{ . }}" + {{- end }} + rules: + {{- range $host := .Values.binderhub.jupyterhub.ingress.hosts | default (list "") }} + - http: + paths: + - path: {{ $.Values.binderhub.jupyterhub.hub.baseUrl | trimSuffix "/" }}/binder + pathType: {{ $.Values.binderhub.jupyterhub.ingress.pathType }} + backend: + service: + name: binder + port: + number: 80 + {{- if $host }} + host: {{ $host | quote }} + {{- end }} + {{- end }} + {{- with .Values.binderhub.jupyterhub.ingress.tls }} + tls: + {{- . | toYaml | nindent 4 }} + {{- end }} diff --git a/swan/templates/secrets.yaml b/swan/templates/secrets.yaml index afda13ee..13ee2d33 100644 --- a/swan/templates/secrets.yaml +++ b/swan/templates/secrets.yaml @@ -5,12 +5,12 @@ metadata: name: swan namespace: {{ .Release.Namespace }} data: -{{ if eq .Values.jupyterhub.hub.db.type "postgres" }} - jupyterhub.hub.db.password: {{ (required "PostgresDB password must be specified (helm --set jupyterhub.hub.db.password= ..)!" .Values.jupyterhub.hub.db.password) | b64enc | quote }} +{{ if eq .Values.binderhub.jupyterhub.hub.db.type "postgres" }} + jupyterhub.hub.db.password: {{ (required "PostgresDB password must be specified (helm --set jupyterhub.hub.db.password= ..)!" .Values.binderhub.jupyterhub.hub.db.password) | b64enc | quote }} {{ end }} --- -{{ if .Values.jupyterhub.ingress.enabled }} -{{ range .Values.jupyterhub.ingress.tls }} +{{ if .Values.binderhub.jupyterhub.ingress.enabled }} +{{ range .Values.binderhub.jupyterhub.ingress.tls }} apiVersion: v1 kind: Secret type: kubernetes.io/tls diff --git a/swan/templates/storageclasses.yaml b/swan/templates/storageclasses.yaml index 8d17e9b6..fb72b58f 100644 --- a/swan/templates/storageclasses.yaml +++ b/swan/templates/storageclasses.yaml @@ -1,5 +1,5 @@ -{{ if or .Values.jupyterhub.custom.cvmfs.deployCsiDriver .Values.jupyterhub.custom.cvmfs.useCsiDriver }} -{{- range .Values.jupyterhub.custom.cvmfs.repositories }} +{{ if or .Values.binderhub.jupyterhub.custom.cvmfs.deployCsiDriver .Values.binderhub.jupyterhub.custom.cvmfs.useCsiDriver }} +{{- range .Values.binderhub.jupyterhub.custom.cvmfs.repositories }} apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: diff --git a/swan/values.yaml b/swan/values.yaml index fbef7282..2cd8db69 100644 --- a/swan/values.yaml +++ b/swan/values.yaml @@ -29,6 +29,13 @@ cvmfs: - sft-nightlies.cern.ch mountOptions: hostMountpoint: /var/cvmfs + # Prefetcher is provided only by the daemonSet + prefetcher: + enabled: true + jobs: + cron_opennotebook_python3_ipy: + command: "source /cvmfs/sft.cern.ch/lcg/views/LCG_101swan/x86_64-centos7-gcc8-opt/setup.sh && ( timeout 20s python -m ipykernel > /dev/null 2>&1 || true )" + minute: '*/15' # # EOS access @@ -63,174 +70,169 @@ eosxd: # # JupyerHub # -jupyterhub: - singleuser: - uid: 0 - fsGid: 0 - storage: - type: none - image: - name: "gitlab-registry.cern.ch/swan/docker-images/systemuser" - tag: "v5.14.1" - pullPolicy: "Always" - cloudMetadata: - # until we configure networkPolicy - blockWithIptables: true - ip: 169.254.169.254 - networkPolicy: - enabled: false - ingress: - enabled: true - annotations: - kubernetes.io/ingress.class: nginx - #tls: - # - secretName: swan-tls-cert - # placeholder for hostname - hosts: - proxy: - service: - type: ClusterIP - chp: +binderhub: + jupyterhub: + singleuser: + fsGid: 0 + storage: + type: none image: - name: "jupyterhub/configurable-http-proxy" - tag: "4.5.0" - pullPolicy: "IfNotPresent" + name: "gitlab-registry.cern.ch/swan/docker-images/systemuser" + tag: "v5.14.1" + pullPolicy: "Always" + cloudMetadata: + # until we configure networkPolicy + blockWithIptables: true + ip: 169.254.169.254 + networkPolicy: + enabled: false + ingress: + enabled: true + annotations: + kubernetes.io/ingress.class: nginx + #tls: + # - secretName: swan-tls-cert + # placeholder for hostname + hosts: + proxy: + service: + type: ClusterIP + chp: + image: + name: "jupyterhub/configurable-http-proxy" + tag: "4.5.0" + pullPolicy: "IfNotPresent" + resources: + requests: + cpu: 200m + memory: 512Mi + # placeholder for hub secret token + secretToken: + hub: + fsGid: 0 + containerSecurityContext: + runAsUser: 0 + runAsGroup: 0 + deploymentStrategy: + type: RollingUpdate resources: requests: cpu: 200m memory: 512Mi - # placeholder for hub secret token - secretToken: - hub: - fsGid: 0 - containerSecurityContext: - runAsUser: 0 - runAsGroup: 0 - deploymentStrategy: - type: RollingUpdate - resources: - requests: - cpu: 200m - memory: 512Mi - livenessProbe: - enabled: false - readinessProbe: - enabled: false - image: - name: "gitlab-registry.cern.ch/swan/docker-images/jupyterhub" - tag: "v1.18" - pullPolicy: "Always" - extraVolumeMounts: - - name: swan-jh - mountPath: /srv/jupyterhub/options_form_config.json - subPath: options_form_config.json - - name: swan-jh - mountPath: /srv/jupyterhub/jupyterhub_form.html - subPath: jupyterhub_form.html - - name: swan-jh - mountPath: /usr/local/etc/jupyterhub/jupyterhub_config.d/1_swan_config.py - subPath: swan_config.py - extraVolumes: - - name: swan-jh - configMap: - name: swan-scripts - items: - - key: options_form_config.json - path: options_form_config.json - - key: jupyterhub_form.html - path: jupyterhub_form.html - - key: swan_config.py - path: swan_config.py - config: - KeyCloakAuthenticator: - # Config missing - oidc_issuer: - admin_role: swan-admins - scope: - - profile - - email - - offline_access - exchange_tokens: [] - logout_redirect_uri: https://cern.ch/swan - auto_login: True - username_key: preferred_username - client_id: # placeholder, check secrets - client_secret: # placeholder, check secrets - oauth_callback_url: # placeholder, check secrets - SwanSpawner: - options_form_config: /srv/jupyterhub/options_form_config.json - # Give notebook 45s to start a webserver and max 60s for whole spawn process - http_timeout: 45 - start_timeout: 60 - consecutive_failure_limit: 0 - SwanKubeSpawner: - # set home directory to EOS - local_home: False - SpawnHandlersConfigs: - # disable some defaults of swanspawner that do now work for kube-spawner - # FIXME remove this from the spawner once we support only k8s - metrics_on: False - local_home: True - JupyterHub: - authenticator_class: keycloakauthenticator.KeyCloakAuthenticator - spawner_class: swanspawner.SwanKubeSpawner - cleanup_servers: False - tornado_settings: - # currently we customize spawnhandler to stay in form before redirecting the user, as upstream does - # FIXME remove once we remove the the metrics from the spawn - slow_spawn_timeout: 15 - allow_named_servers: False - extraConfig: - 00-authConf: | - def pre_spawn_hook(authenticator, spawner, auth_state): - raise Exception("Please configure pre_spawn_hook") - c.KeyCloakAuthenticator.pre_spawn_hook = pre_spawn_hook - networkPolicy: - enabled: false - # placeholder for hub cookieSecret - # when empty, it generates a new randomly - cookieSecret: - rbac: - enabled: true - scheduling: - userScheduler: - enabled: false - podPriority: - enabled: false - prePuller: - hook: - enabled: true - continuous: - enabled: false - containerSecurityContext: - allowPrivilegeEscalation: true - debug: - enabled: true - # disable upstream cull, but enable custom one - cull: - enabled: false - custom: - cull: + livenessProbe: + enabled: false + readinessProbe: + enabled: false + image: + name: "gitlab-registry.cern.ch/swan/docker-images/jupyterhub" + tag: "v1.18" + pullPolicy: "Always" + extraVolumeMounts: + - name: swan-jh + mountPath: /srv/jupyterhub/options_form_config.json + subPath: options_form_config.json + - name: swan-jh + mountPath: /srv/jupyterhub/jupyterhub_form.html + subPath: jupyterhub_form.html + - name: swan-jh + mountPath: /usr/local/etc/jupyterhub/jupyterhub_config.d/1_swan_config.py + subPath: swan_config.py + extraVolumes: + - name: swan-jh + configMap: + name: swan-scripts + items: + - key: options_form_config.json + path: options_form_config.json + - key: jupyterhub_form.html + path: jupyterhub_form.html + - key: swan_config.py + path: swan_config.py + config: + KeyCloakAuthenticator: + # Config missing + oidc_issuer: + admin_role: swan-admins + scope: + - profile + - email + - offline_access + exchange_tokens: [] + logout_redirect_uri: https://cern.ch/swan + auto_login: True + username_key: preferred_username + client_id: # placeholder, check secrets + client_secret: # placeholder, check secrets + oauth_callback_url: # placeholder, check secrets + SwanSpawner: + options_form_config: /srv/jupyterhub/options_form_config.json + # Give notebook 45s to start a webserver and max 60s for whole spawn process + http_timeout: 45 + start_timeout: 60 + consecutive_failure_limit: 0 + SwanKubeSpawner: + # set home directory to EOS + local_home: False + SpawnHandlersConfigs: + # disable some defaults of swanspawner that do now work for kube-spawner + # FIXME remove this from the spawner once we support only k8s + metrics_on: False + local_home: True + JupyterHub: + authenticator_class: keycloakauthenticator.KeyCloakAuthenticator + spawner_class: swanspawner.SwanKubeSpawner + cleanup_servers: False + tornado_settings: + # currently we customize spawnhandler to stay in form before redirecting the user, as upstream does + # FIXME remove once we remove the the metrics from the spawn + slow_spawn_timeout: 15 + allow_named_servers: False + extraConfig: + 00-authConf: | + def pre_spawn_hook(authenticator, spawner, auth_state): + raise Exception("Please configure pre_spawn_hook") + c.KeyCloakAuthenticator.pre_spawn_hook = pre_spawn_hook + networkPolicy: + enabled: false + # placeholder for hub cookieSecret + # when empty, it generates a new randomly + cookieSecret: + rbac: enabled: true - every: 600 - # 2 hours - timeout: 7200 - users: true - checkEosAuth: false - cvmfs: - prefetcher: + scheduling: + userScheduler: enabled: false - image: - name: "gitlab-registry.cern.ch/swan/docker-images/cvmfs-prefetcher" - tag: "v1.1" - deployDaemonSet: *cvmfsDeployDS - deployCsiDriver: *cvmfsDeployCSI - useCsiDriver: *cvmfsUseCSI - repositories: *cvmfsRepos - eos: - deployDaemonSet: *eosDeployDS - deployCsiDriver: *eosDeployCSI - useCsiDriver: *eosUseCSI + podPriority: + enabled: false + prePuller: + hook: + enabled: true + continuous: + enabled: false + containerSecurityContext: + allowPrivilegeEscalation: true + debug: + enabled: true + # disable upstream cull, but enable custom one + cull: + enabled: false + custom: + cull: + enabled: true + every: 600 + # 2 hours + timeout: 7200 + users: true + checkEosAuth: false + cvmfs: + deployDaemonSet: *cvmfsDeployDS + deployCsiDriver: *cvmfsDeployCSI + useCsiDriver: *cvmfsUseCSI + repositories: *cvmfsRepos + eos: + deployDaemonSet: *eosDeployDS + deployCsiDriver: *eosDeployCSI + useCsiDriver: *eosUseCSI # placeholders for swan credentials swan: secrets: