17
17
current_k8s_corev1_api_client ,
18
18
current_k8s_networking_api_client ,
19
19
)
20
+ from reana_commons .k8s .secrets import REANAUserSecretsStore
20
21
from reana_commons .k8s .volumes import (
21
22
get_k8s_cvmfs_volumes ,
22
23
get_workspace_volume ,
27
28
JUPYTER_INTERACTIVE_SESSION_DEFAULT_PORT ,
28
29
REANA_INGRESS_ANNOTATIONS ,
29
30
REANA_INGRESS_CLASS_NAME ,
31
+ REANA_INGRESS_HOST ,
30
32
)
31
33
32
34
@@ -77,6 +79,19 @@ def __init__(
77
79
name = deployment_name ,
78
80
labels = {"reana_workflow_mode" : "session" },
79
81
)
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
+
80
95
self .kubernetes_objects = {
81
96
"ingress" : self ._build_ingress (),
82
97
"service" : self ._build_service (metadata ),
@@ -104,7 +119,9 @@ def _build_ingress(self):
104
119
]
105
120
)
106
121
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
+ ]
108
125
)
109
126
if REANA_INGRESS_CLASS_NAME :
110
127
spec .ingress_class_name = REANA_INGRESS_CLASS_NAME
@@ -149,15 +166,6 @@ def _build_deployment(self, metadata):
149
166
:param metadata: Common Kubernetes metadata for the interactive
150
167
deployment.
151
168
"""
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
- )
161
169
labels = {
162
170
"app" : self .deployment_name ,
163
171
"reana_workflow_mode" : "session" ,
@@ -166,7 +174,7 @@ def _build_deployment(self, metadata):
166
174
}
167
175
template = client .V1PodTemplateSpec (
168
176
metadata = client .V1ObjectMeta (labels = labels ),
169
- spec = pod_spec ,
177
+ spec = self . _pod_spec ,
170
178
)
171
179
spec = client .V1DeploymentSpec (
172
180
selector = client .V1LabelSelector (match_labels = labels ),
@@ -184,36 +192,26 @@ def _build_deployment(self, metadata):
184
192
185
193
def add_command (self , command ):
186
194
"""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
190
196
191
197
def add_command_arguments (self , args ):
192
198
"""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
196
200
197
201
def add_reana_shared_storage (self ):
198
202
"""Add the REANA shared file system volume mount to the deployment."""
199
203
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 )
204
206
205
207
def add_cvmfs_repo_mounts (self , cvmfs_repos ):
206
208
"""Add mounts for the provided CVMFS repositories to the deployment.
207
209
208
210
:param cvmfs_mounts: List of CVMFS repos to make available.
209
211
"""
210
212
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 )
217
215
218
216
def add_environment_variable (self , name , value ):
219
217
"""Add an environment variable.
@@ -222,24 +220,25 @@ def add_environment_variable(self, name, value):
222
220
:param value: Environment variable value.
223
221
"""
224
222
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 )
236
224
237
225
def add_run_with_root_permissions (self ):
238
226
"""Run interactive session with root."""
239
227
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 ()
243
242
244
243
def get_deployment_objects (self ):
245
244
"""Return the alrady built Kubernetes objects."""
@@ -255,6 +254,7 @@ def build_interactive_jupyter_deployment_k8s_objects(
255
254
owner_id = None ,
256
255
workflow_id = None ,
257
256
image = None ,
257
+ expose_secrets = True ,
258
258
):
259
259
"""Build the Kubernetes specification for a Jupyter NB interactive session.
260
260
@@ -276,6 +276,8 @@ def build_interactive_jupyter_deployment_k8s_objects(
276
276
session belongs to.
277
277
:param image: Jupyter Notebook image to use, i.e.
278
278
``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.
279
281
"""
280
282
image = image or JUPYTER_INTERACTIVE_SESSION_DEFAULT_IMAGE
281
283
cvmfs_repos = cvmfs_repos or []
@@ -297,6 +299,8 @@ def build_interactive_jupyter_deployment_k8s_objects(
297
299
deployment_builder .add_reana_shared_storage ()
298
300
if cvmfs_repos :
299
301
deployment_builder .add_cvmfs_repo_mounts (cvmfs_repos )
302
+ if expose_secrets :
303
+ deployment_builder .add_user_secrets ()
300
304
deployment_builder .add_environment_variable ("NB_GID" , 0 )
301
305
# Changes umask so all files generated by the Jupyter Notebook can be
302
306
# modified by the root group users.
0 commit comments