Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: refactor Jinja templates #147

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions controller/k8s_resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,19 @@ def get_urls(spec):
return host_url, full_url


def get_children_templates(pvc_enabled=False):
def get_children_templates(template_type="jupyterlab", pvc_enabled=False):
"""
Define a list of all resources that should be created.
"""
children_templates = {
"service": "service.yaml",
"ingress": "ingress.yaml",
"statefulset": "statefulset.yaml",
"configmap": "configmap.yaml",
"secret": "secret.yaml",
"service": f"{template_type}/service.yaml",
"ingress": f"{template_type}/ingress.yaml",
"statefulset": f"{template_type}/statefulset.yaml",
"configmap": f"{template_type}/configmap.yaml",
"secret": f"{template_type}/secret.yaml",
}
if pvc_enabled:
children_templates["pvc"] = "pvc.yaml"
children_templates["pvc"] = f"{template_type}/pvc.yaml"

return children_templates

Expand Down Expand Up @@ -109,6 +109,7 @@ def get_children_specs(name, spec, logger):
# Generate one big dictionary containing the specs of all child
# resources to be created.
children_templates = get_children_templates(
template_type=spec["type"],
pvc_enabled=spec["storage"]["pvc"]["enabled"],
)
children_specs = {
Expand Down
26 changes: 26 additions & 0 deletions controller/templates/base/configmap.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
kind: ConfigMap
apiVersion: v1
metadata:
name: {{ name }}
data:
{% block configmap %}
{% endblock %}

{% if oidc["enabled"] %}
authorized-users.txt: |
{%- for email in oidc["authorizedEmails"] %}
{{ email }}
{%- endfor %}
{% else %}
traefik-dynamic-config.yaml: |
http:
routers:
to-passthrough:
rule: "PathPrefix(`/`)"
service: passthrough
services:
passthrough:
loadBalancer:
servers:
- url: http://localhost:8888
{% endif %}
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,12 @@ metadata:
name: {{ name }}
type: Opaque
data:
jupyterServerAppToken: {{ jupyter_server_app_token | b64encode }}
jupyterServerCookieSecret: {{ jupyter_server_cookie_secret | b64encode }}
{% block secret %}
{% endblock %}

{% if auth["oidc"]["enabled"] %}
{% if "value" in auth["oidc"]["clientSecret"] %}
oidcClientSecret: {{ oidc["clientSecret"]["value"] | b64encode }}
{% endif %}
oauth2ProxyCookieSecret: {{ authentication_plugin_cookie_secret | b64encode }}
{% endif %}

Original file line number Diff line number Diff line change
Expand Up @@ -32,27 +32,8 @@ spec:
- key: traefik-dynamic-config.yaml
path: traefik-dynamic-config.yaml
{% endif %}
- name: jupyter-server-secrets
secret:
secretName: {{ name }}
items:
- key: jupyterServerCookieSecret
path: cookie_secret
- name: jupyter-config-notebook
configMap:
name: {{ name }}
items:
- key: jupyter_notebook_config.py
path: jupyter_notebook_config.py
- name: jupyter-config-server
configMap:
name: {{ name }}
items:
- key: jupyter_server_config.py
path: jupyter_server_config.py
- name: jupyter-config
emptyDir:
sizeLimit: "2Mi"
{% block volumes scoped %}
{% endblock %}
{% if pvc["enabled"] %}
- name: workspace
persistentVolumeClaim:
Expand All @@ -73,78 +54,8 @@ spec:
schedulerName: {{ scheduler_name }}
{% endif %}
containers:
- name: jupyter-server
image: {{ jupyter_server["image"] }}
workingDir: {{ jupyter_server["rootDir"] }}
volumeMounts:
- name: workspace
mountPath: {{ storage["pvc"]["mountPath"] }}
- name: jupyter-server-secrets
mountPath: /etc/jupyter_server_secrets
readOnly: true
- name: jupyter-config
mountPath: {{ storage["pvc"]["mountPath"] }}/.jupyter_config
- name: jupyter-config-server
mountPath: {{ storage["pvc"]["mountPath"] }}/.jupyter_config/jupyter_server_config.py
subPath: jupyter_server_config.py
- name: jupyter-config-notebook
mountPath: {{ storage["pvc"]["mountPath"] }}/.jupyter_config/jupyter_notebook_config.py
subPath: jupyter_notebook_config.py
env:
- name: SERVER_APP_TOKEN
valueFrom:
secretKeyRef:
name: {{ name }}
key: jupyterServerAppToken
- name: JUPYTER_CONFIG_PATH
value: {{ storage["pvc"]["mountPath"] }}/.jupyter_config
resources: {{ jupyter_server["resources"] | default({}) | tojson }}
securityContext:
runAsUser: 1000
runAsGroup: 100
fsGroup: 100
allowPrivilegeEscalation: false

# We allow quite some time (5 + 1 minutes) for the jupyter container to come up in
# case the entrypoint contains a lot of code which has to be executed before the
# Jupyter server can even accept connections. However, really long running tasks
# should be put into an init container.
livenessProbe:
httpGet:
path: {{ probe_path }}
port: 8888
{% if not oidc["enabled"] %}
httpHeaders:
- name: Authorization
value: {{ "token " ~ jupyter_server_app_token }}
{% endif %}
periodSeconds: 10
failureThreshold: 6
timeoutSeconds: 9
readinessProbe:
httpGet:
path: {{ probe_path }}
port: 8888
{% if not oidc["enabled"] %}
httpHeaders:
- name: Authorization
value: {{ "token " ~ jupyter_server_app_token }}
{% endif %}
periodSeconds: 10
failureThreshold: 2
timeoutSeconds: 9
startupProbe:
httpGet:
path: {{ probe_path }}
port: 8888
{% if not oidc["enabled"] %}
httpHeaders:
- name: Authorization
value: {{ "token " ~ jupyter_server_app_token }}
{% endif %}
periodSeconds: 10
failureThreshold: 30
timeoutSeconds: 9
{% block containers scoped required %}
{% endblock %}

{% if oidc["enabled"] %}
- name: oauth2-proxy
Expand All @@ -161,7 +72,8 @@ spec:
- "--cookie-path={{ path }}"
- "--proxy-prefix={{ path if path != '/' else '' }}/oauth2"
- "--authenticated-emails-file=/etc/oauth2-proxy/authorized-users.txt"
- "--skip-auth-route=^{{ path if path != '/' else '' }}/api/status$"
{% block extraAuthProxyArgs scoped %}
{% endblock %}
{% for group in oidc["authorizedGroups"] %}
- "--allowed-group={{ group }}"
{% endfor %}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
kind: ConfigMap
apiVersion: v1
metadata:
name: {{ name }}
data:
{% extends "base/configmap.yaml" %}
{% block configmap %}
jupyter_notebook_config.py: |
import os
c.NotebookApp.ip="0.0.0.0"
Expand All @@ -26,22 +23,4 @@ data:
c.ServerApp.root_dir="{{ jupyter_server["rootDir"] }}"
c.ServerApp.default_url="{{ jupyter_server["defaultUrl"] }}"
c.ServerApp.allow_remote_access=True

{% if oidc["enabled"] %}
authorized-users.txt: |
{%- for email in oidc["authorizedEmails"] %}
{{ email }}
{%- endfor %}
{% else %}
traefik-dynamic-config.yaml: |
http:
routers:
to-passthrough:
rule: "PathPrefix(`/`)"
service: passthrough
services:
passthrough:
loadBalancer:
servers:
- url: http://localhost:8888
{% endif %}
{% endblock %}
1 change: 1 addition & 0 deletions controller/templates/jupyterlab/ingress.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{% extends "base/ingress.yaml" %}
1 change: 1 addition & 0 deletions controller/templates/jupyterlab/pvc.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{% extends "base/pvc.yaml" %}
5 changes: 5 additions & 0 deletions controller/templates/jupyterlab/secret.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{% extends "base/secret.yaml" %}
{% block secret %}
jupyterServerAppToken: {{ jupyter_server_app_token | b64encode }}
jupyterServerCookieSecret: {{ jupyter_server_cookie_secret | b64encode }}
{% endblock %}
1 change: 1 addition & 0 deletions controller/templates/jupyterlab/service.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{% extends "base/service.yaml" %}
106 changes: 106 additions & 0 deletions controller/templates/jupyterlab/statefulset.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
{% extends "base/statefulset.yaml" %}

{% block volumes %}
- name: jupyter-server-secrets
secret:
secretName: {{ name }}
items:
- key: jupyterServerCookieSecret
path: cookie_secret
- name: jupyter-config-notebook
configMap:
name: {{ name }}
items:
- key: jupyter_notebook_config.py
path: jupyter_notebook_config.py
- name: jupyter-config-server
configMap:
name: {{ name }}
items:
- key: jupyter_server_config.py
path: jupyter_server_config.py
- name: jupyter-config
emptyDir:
sizeLimit: "2Mi"
{% endblock %}

{% block containers %}
- name: jupyter-server
image: {{ jupyter_server["image"] }}
workingDir: {{ jupyter_server["rootDir"] }}
volumeMounts:
- name: workspace
mountPath: {{ storage["pvc"]["mountPath"] }}
- name: jupyter-server-secrets
mountPath: /etc/jupyter_server_secrets
readOnly: true
- name: jupyter-config
mountPath: {{ storage["pvc"]["mountPath"] }}/.jupyter_config
- name: jupyter-config-server
mountPath: {{ storage["pvc"]["mountPath"] }}/.jupyter_config/jupyter_server_config.py
subPath: jupyter_server_config.py
- name: jupyter-config-notebook
mountPath: {{ storage["pvc"]["mountPath"] }}/.jupyter_config/jupyter_notebook_config.py
subPath: jupyter_notebook_config.py
env:
- name: SERVER_APP_TOKEN
valueFrom:
secretKeyRef:
name: {{ name }}
key: jupyterServerAppToken
- name: JUPYTER_CONFIG_PATH
value: {{ storage["pvc"]["mountPath"] }}/.jupyter_config
resources: {{ jupyter_server["resources"] | default({}) | tojson }}
securityContext:
runAsUser: 1000
runAsGroup: 100
fsGroup: 100
allowPrivilegeEscalation: false

# We allow quite some time (5 + 1 minutes) for the jupyter container to come up in
# case the entrypoint contains a lot of code which has to be executed before the
# Jupyter server can even accept connections. However, really long running tasks
# should be put into an init container.
livenessProbe:
httpGet:
path: {{ probe_path }}
port: 8888
{% if not oidc["enabled"] %}
httpHeaders:
- name: Authorization
value: {{ "token " ~ jupyter_server_app_token }}
{% endif %}
periodSeconds: 10
failureThreshold: 6
timeoutSeconds: 9
readinessProbe:
httpGet:
path: {{ probe_path }}
port: 8888
{% if not oidc["enabled"] %}
httpHeaders:
- name: Authorization
value: {{ "token " ~ jupyter_server_app_token }}
{% endif %}
periodSeconds: 10
failureThreshold: 2
timeoutSeconds: 9
startupProbe:
httpGet:
path: {{ probe_path }}
port: 8888
{% if not oidc["enabled"] %}
httpHeaders:
- name: Authorization
value: {{ "token " ~ jupyter_server_app_token }}
{% endif %}
periodSeconds: 10
failureThreshold: 30
timeoutSeconds: 9
{% endblock %}



{% block extraAuthProxyArgs %}
- "--skip-auth-route=^{{ path if path != '/' else '' }}/api/status$"
{% endblock %}
8 changes: 8 additions & 0 deletions helm-chart/amalthea/crd-spec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -230,4 +230,12 @@ spec:
session respectively.
x-kubernetes-int-or-string: true
type: object

type:
type: string
enum:
- base
- jupyterlab
default: jupyterlab
description: "The type of template (jupyterlab, rstudio, base) to be used for the session."
type: object
1 change: 1 addition & 0 deletions tests/unit/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ def default_spec():
},
"storage": {"size": "1G", "pvc": {"enabled": False}},
"patches": [],
"type": "jupyterlab",
}
return spec

Expand Down
Loading