1717 current_k8s_corev1_api_client ,
1818 current_k8s_networking_api_client ,
1919)
20+ from reana_commons .k8s .secrets import REANAUserSecretsStore
2021from reana_commons .k8s .volumes import (
2122 get_k8s_cvmfs_volumes ,
2223 get_workspace_volume ,
2728 JUPYTER_INTERACTIVE_SESSION_DEFAULT_PORT ,
2829 REANA_INGRESS_ANNOTATIONS ,
2930 REANA_INGRESS_CLASS_NAME ,
31+ REANA_INGRESS_HOST ,
3032)
3133
3234
@@ -77,6 +79,19 @@ def __init__(
7779 name = deployment_name ,
7880 labels = {"reana_workflow_mode" : "session" },
7981 )
82+ self ._session_container = client .V1Container (
83+ name = self .deployment_name , image = self .image , env = [], volume_mounts = []
84+ )
85+ self ._pod_spec = client .V1PodSpec (
86+ containers = [self ._session_container ],
87+ volumes = [],
88+ node_selector = REANA_RUNTIME_SESSIONS_KUBERNETES_NODE_LABEL ,
89+ # Disable service discovery with env variables, so that the environment is
90+ # not polluted with variables like `REANA_SERVER_SERVICE_HOST`
91+ enable_service_links = False ,
92+ automount_service_account_token = False ,
93+ )
94+
8095 self .kubernetes_objects = {
8196 "ingress" : self ._build_ingress (),
8297 "service" : self ._build_service (metadata ),
@@ -104,7 +119,9 @@ def _build_ingress(self):
104119 ]
105120 )
106121 spec = client .V1IngressSpec (
107- rules = [client .V1IngressRule (http = ingress_rule_value )]
122+ rules = [
123+ client .V1IngressRule (http = ingress_rule_value , host = REANA_INGRESS_HOST )
124+ ]
108125 )
109126 if REANA_INGRESS_CLASS_NAME :
110127 spec .ingress_class_name = REANA_INGRESS_CLASS_NAME
@@ -149,15 +166,6 @@ def _build_deployment(self, metadata):
149166 :param metadata: Common Kubernetes metadata for the interactive
150167 deployment.
151168 """
152- container = client .V1Container (name = self .deployment_name , image = self .image )
153- pod_spec = client .V1PodSpec (
154- containers = [container ],
155- node_selector = REANA_RUNTIME_SESSIONS_KUBERNETES_NODE_LABEL ,
156- # Disable service discovery with env variables, so that the environment is
157- # not polluted with variables like `REANA_SERVER_SERVICE_HOST`
158- enable_service_links = False ,
159- automount_service_account_token = False ,
160- )
161169 labels = {
162170 "app" : self .deployment_name ,
163171 "reana_workflow_mode" : "session" ,
@@ -166,7 +174,7 @@ def _build_deployment(self, metadata):
166174 }
167175 template = client .V1PodTemplateSpec (
168176 metadata = client .V1ObjectMeta (labels = labels ),
169- spec = pod_spec ,
177+ spec = self . _pod_spec ,
170178 )
171179 spec = client .V1DeploymentSpec (
172180 selector = client .V1LabelSelector (match_labels = labels ),
@@ -184,36 +192,26 @@ def _build_deployment(self, metadata):
184192
185193 def add_command (self , command ):
186194 """Add a command to the deployment."""
187- self .kubernetes_objects ["deployment" ].spec .template .spec .containers [
188- 0
189- ].command = command
195+ self ._session_container .command = command
190196
191197 def add_command_arguments (self , args ):
192198 """Add command line arguments in addition to the command."""
193- self .kubernetes_objects ["deployment" ].spec .template .spec .containers [
194- 0
195- ].args = args
199+ self ._session_container .args = args
196200
197201 def add_reana_shared_storage (self ):
198202 """Add the REANA shared file system volume mount to the deployment."""
199203 volume_mount , volume = get_workspace_volume (self .workspace )
200- self .kubernetes_objects ["deployment" ].spec .template .spec .containers [
201- 0
202- ].volume_mounts = [volume_mount ]
203- self .kubernetes_objects ["deployment" ].spec .template .spec .volumes = [volume ]
204+ self ._session_container .volume_mounts .append (volume_mount )
205+ self ._pod_spec .volumes .append (volume )
204206
205207 def add_cvmfs_repo_mounts (self , cvmfs_repos ):
206208 """Add mounts for the provided CVMFS repositories to the deployment.
207209
208210 :param cvmfs_mounts: List of CVMFS repos to make available.
209211 """
210212 cvmfs_volume_mounts , cvmfs_volumes = get_k8s_cvmfs_volumes (cvmfs_repos )
211- self .kubernetes_objects ["deployment" ].spec .template .spec .volumes .extend (
212- cvmfs_volumes
213- )
214- self .kubernetes_objects ["deployment" ].spec .template .spec .containers [
215- 0
216- ].volume_mounts .extend (cvmfs_volume_mounts )
213+ self ._pod_spec .volumes .extend (cvmfs_volumes )
214+ self ._session_container .volume_mounts .extend (cvmfs_volume_mounts )
217215
218216 def add_environment_variable (self , name , value ):
219217 """Add an environment variable.
@@ -222,24 +220,25 @@ def add_environment_variable(self, name, value):
222220 :param value: Environment variable value.
223221 """
224222 env_var = client .V1EnvVar (name , str (value ))
225- if isinstance (
226- self .kubernetes_objects ["deployment" ].spec .template .spec .containers [0 ].env ,
227- list ,
228- ):
229- self .kubernetes_objects ["deployment" ].spec .template .spec .containers [
230- 0
231- ].env .append (env_var )
232- else :
233- self .kubernetes_objects ["deployment" ].spec .template .spec .containers [
234- 0
235- ].env = [env_var ]
223+ self ._session_container .env .append (env_var )
236224
237225 def add_run_with_root_permissions (self ):
238226 """Run interactive session with root."""
239227 security_context = client .V1SecurityContext (run_as_user = 0 )
240- self .kubernetes_objects ["deployment" ].spec .template .spec .containers [
241- 0
242- ].security_context = security_context
228+ self ._session_container .security_context = security_context
229+
230+ def add_user_secrets (self ):
231+ """Mount the "file" secrets and set the "env" secrets in the container."""
232+ secrets_store = REANAUserSecretsStore (self .owner_id )
233+
234+ # mount file secrets
235+ secrets_volume = secrets_store .get_file_secrets_volume_as_k8s_specs ()
236+ secrets_volume_mount = secrets_store .get_secrets_volume_mount_as_k8s_spec ()
237+ self ._pod_spec .volumes .append (secrets_volume )
238+ self ._session_container .volume_mounts .append (secrets_volume_mount )
239+
240+ # set environment secrets
241+ self ._session_container .env += secrets_store .get_env_secrets_as_k8s_spec ()
243242
244243 def get_deployment_objects (self ):
245244 """Return the alrady built Kubernetes objects."""
@@ -255,6 +254,7 @@ def build_interactive_jupyter_deployment_k8s_objects(
255254 owner_id = None ,
256255 workflow_id = None ,
257256 image = None ,
257+ expose_secrets = True ,
258258):
259259 """Build the Kubernetes specification for a Jupyter NB interactive session.
260260
@@ -276,6 +276,8 @@ def build_interactive_jupyter_deployment_k8s_objects(
276276 session belongs to.
277277 :param image: Jupyter Notebook image to use, i.e.
278278 ``jupyter/tensorflow-notebook`` to enable ``tensorflow``.
279+ :param expose_secrets: If true, mount the "file" secrets and set the
280+ "env" secrets in jupyter's pod.
279281 """
280282 image = image or JUPYTER_INTERACTIVE_SESSION_DEFAULT_IMAGE
281283 cvmfs_repos = cvmfs_repos or []
@@ -297,6 +299,8 @@ def build_interactive_jupyter_deployment_k8s_objects(
297299 deployment_builder .add_reana_shared_storage ()
298300 if cvmfs_repos :
299301 deployment_builder .add_cvmfs_repo_mounts (cvmfs_repos )
302+ if expose_secrets :
303+ deployment_builder .add_user_secrets ()
300304 deployment_builder .add_environment_variable ("NB_GID" , 0 )
301305 # Changes umask so all files generated by the Jupyter Notebook can be
302306 # modified by the root group users.
0 commit comments