diff --git a/helm-chart/binderhub/schema.yaml b/helm-chart/binderhub/schema.yaml index e9058b2b99..f55ffd1dfe 100644 --- a/helm-chart/binderhub/schema.yaml +++ b/helm-chart/binderhub/schema.yaml @@ -25,7 +25,6 @@ required: - service - config - extraConfig - - templates - jupyterhub - deployment - dind @@ -33,6 +32,7 @@ required: - ingress - initContainers - lifecycle + - extraFiles - extraVolumes - extraVolumeMounts - extraEnv @@ -261,13 +261,36 @@ properties: manifest as either the binder pod going into `Error` or `CrashLoopBackoff` states, or in some special cases, the binder pod running but... just doing very random things. Be careful! - templates: + extraFiles: type: object - additionalProperties: - type: string + additionalProperties: false description: | - Custom HTML page templates for BinderHub, - e.g. page.html. + A dictionary with extra files to be injected into the binder pod's container + on startup. This can for example be used to inject: configuration + files, custom user interface templates, images, and more. + + See zero-to-jupyterhub's extraFiles documentation for reference. + patternProperties: + ".*": + type: object + additionalProperties: false + required: [mountPath] + oneOf: + - required: [data] + - required: [stringData] + - required: [binaryData] + properties: + mountPath: + type: string + data: + type: object + additionalProperties: true + stringData: + type: string + binaryData: + type: string + mode: + type: number jupyterhub: type: object diff --git a/helm-chart/binderhub/templates/_helpers.tpl b/helm-chart/binderhub/templates/_helpers.tpl index 39780deb02..5fdf8402b1 100644 --- a/helm-chart/binderhub/templates/_helpers.tpl +++ b/helm-chart/binderhub/templates/_helpers.tpl @@ -46,3 +46,77 @@ Render docker config.json for the registry-publishing secret and other docker co {{- $dockerConfig | toPrettyJson }} {{- end }} + +{{- /* + binderhub.extraFiles.data: + Renders content for a k8s Secret's data field, coming from extraFiles with + binaryData entries. +*/}} +{{- define "binderhub.extraFiles.data.withNewLineSuffix" -}} + {{- range $file_key, $file_details := . }} + {{- include "binderhub.extraFiles.validate-file" (list $file_key $file_details) }} + {{- if $file_details.binaryData }} + {{- $file_key | quote }}: {{ $file_details.binaryData | nospace | quote }}{{ println }} + {{- end }} + {{- end }} +{{- end }} +{{- define "binderhub.extraFiles.data" -}} + {{- include "binderhub.extraFiles.data.withNewLineSuffix" . | trimSuffix "\n" }} +{{- end }} + + +{{- /* + binderhub.extraFiles.stringData: + Renders content for a k8s Secret's stringData field, coming from extraFiles + with either data or stringData entries. +*/}} +{{- define "binderhub.extraFiles.stringData.withNewLineSuffix" -}} + {{- range $file_key, $file_details := . }} + {{- include "binderhub.extraFiles.validate-file" (list $file_key $file_details) }} + {{- $file_name := $file_details.mountPath | base }} + {{- if $file_details.stringData }} + {{- $file_key | quote }}: | + {{- $file_details.stringData | trimSuffix "\n" | nindent 2 }}{{ println }} + {{- end }} + {{- if $file_details.data }} + {{- $file_key | quote }}: | + {{- if or (eq (ext $file_name) ".yaml") (eq (ext $file_name) ".yml") }} + {{- $file_details.data | toYaml | nindent 2 }}{{ println }} + {{- else if eq (ext $file_name) ".json" }} + {{- $file_details.data | toJson | nindent 2 }}{{ println }} + {{- else if eq (ext $file_name) ".toml" }} + {{- $file_details.data | toToml | trimSuffix "\n" | nindent 2 }}{{ println }} + {{- else }} + {{- print "\n\nextraFiles entries with 'data' (" $file_key " > " $file_details.mountPath ") needs to have a filename extension of .yaml, .yml, .json, or .toml!" | fail }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} +{{- define "binderhub.extraFiles.stringData" -}} + {{- include "binderhub.extraFiles.stringData.withNewLineSuffix" . | trimSuffix "\n" }} +{{- end }} + +{{- define "binderhub.extraFiles.validate-file" -}} + {{- $file_key := index . 0 }} + {{- $file_details := index . 1 }} + + {{- /* Use of mountPath. */}} + {{- if not ($file_details.mountPath) }} + {{- print "\n\nextraFiles entries (" $file_key ") must contain the field 'mountPath'." | fail }} + {{- end }} + + {{- /* Use one of stringData, binaryData, data. */}} + {{- $field_count := 0 }} + {{- if $file_details.data }} + {{- $field_count = add1 $field_count }} + {{- end }} + {{- if $file_details.stringData }} + {{- $field_count = add1 $field_count }} + {{- end }} + {{- if $file_details.binaryData }} + {{- $field_count = add1 $field_count }} + {{- end }} + {{- if ne $field_count 1 }} + {{- print "\n\nextraFiles entries (" $file_key ") must only contain one of the fields: 'data', 'stringData', and 'binaryData'." | fail }} + {{- end }} +{{- end }} diff --git a/helm-chart/binderhub/templates/deployment.yaml b/helm-chart/binderhub/templates/deployment.yaml index e3b86a83ee..46057a9c24 100644 --- a/helm-chart/binderhub/templates/deployment.yaml +++ b/helm-chart/binderhub/templates/deployment.yaml @@ -45,14 +45,19 @@ spec: - name: config secret: secretName: binder-secret - - name: templates + {{- if .Values.extraFiles }} + - name: files secret: secretName: binder-secret items: - {{- range $filename, $contents := .Values.templates }} - - key: "templates-{{ $filename }}" - path: {{ $filename | quote }} + {{- range $file_key, $file_details := .Values.extraFiles }} + - key: {{ $file_key | quote }} + path: {{ $file_key | quote }} + {{- with $file_details.mode }} + mode: {{ . }} + {{- end }} {{- end }} + {{- end }} {{- if .Values.config.BinderHub.use_registry }} - name: docker-secret secret: @@ -80,9 +85,11 @@ spec: - mountPath: /etc/binderhub/config/ name: config readOnly: true - - mountPath: /etc/binderhub/templates/ - name: templates - readOnly: true + {{- range $file_key, $file_details := .Values.extraFiles }} + - mountPath: {{ $file_details.mountPath }} + subPath: {{ $file_key | quote }} + name: files + {{- end }} {{- if .Values.config.BinderHub.use_registry }} - mountPath: /root/.docker name: docker-secret diff --git a/helm-chart/binderhub/templates/secret.yaml b/helm-chart/binderhub/templates/secret.yaml index ee905dceeb..f3d5d5ab03 100644 --- a/helm-chart/binderhub/templates/secret.yaml +++ b/helm-chart/binderhub/templates/secret.yaml @@ -18,15 +18,18 @@ stringData: values.yaml: | {{- pick .Values "config" "cors" "dind" "extraConfig" | toYaml | nindent 4 }} - {{- /* Custom HTML templates */ -}} - {{- range $filename, $contents := .Values.templates }} - templates-{{ $filename }}: | - {{ $contents | nindent 4 }} - {{- end }} - {{- /* Glob files to allow them to be mounted by the binderhub pod */}} {{- /* key=filename: value=content */}} {{- (.Files.Glob "files/*").AsConfig | nindent 2 }} + + {{- with include "binderhub.extraFiles.stringData" .Values.extraFiles }} + {{- . | nindent 2 }} + {{- end }} + +{{- with include "binderhub.extraFiles.data" .Values.extraFiles }} +data: + {{- . | nindent 2 }} +{{- end }} --- {{- if or .Values.config.BinderHub.use_registry .Values.config.BinderHub.buildDockerConfig }} kind: Secret diff --git a/helm-chart/binderhub/values.yaml b/helm-chart/binderhub/values.yaml index 3520a9ff3a..91c0eb1279 100644 --- a/helm-chart/binderhub/values.yaml +++ b/helm-chart/binderhub/values.yaml @@ -41,7 +41,7 @@ config: extraConfig: {} -templates: {} +extraFiles: {} # Two bits of config need to be set to fully enable cors. # config.BinderHub.cors_allow_origin controls the allowed origins for the diff --git a/testing/k8s-binder-k8s-hub/binderhub-chart-config.yaml b/testing/k8s-binder-k8s-hub/binderhub-chart-config.yaml index 5df1079c72..e9d29bfdc5 100644 --- a/testing/k8s-binder-k8s-hub/binderhub-chart-config.yaml +++ b/testing/k8s-binder-k8s-hub/binderhub-chart-config.yaml @@ -18,13 +18,15 @@ config: log_level: 10 cors_allow_origin: "*" -templates: - page.html: | - {% extends "templates/page.html" %} - {% block footer %} - {{ super() }} - test-template - {% endblock %} +extraFiles: + page.html: + mountPath: /etc/binderhub/templates/page.html + stringData: | + {% extends "templates/page.html" %} + {% block footer %} + {{ super() }} + test-template + {% endblock %} ingress: # Enabled to test the creation/update of the k8s Ingress resource, but not