{{- /* Returns an image-puller daemonset. Two daemonsets will be created like this. - hook-image-puller: for pre helm upgrade image pulling (lives temporarily) - continuous-image-puller: for newly added nodes image pulling */}} {{- define "jupyterhub.imagePuller.daemonset" -}} apiVersion: apps/v1 kind: DaemonSet metadata: {{- if .hook }} name: {{ include "jupyterhub.hook-image-puller.fullname" . }} {{- else }} name: {{ include "jupyterhub.continuous-image-puller.fullname" . }} {{- end }} labels: {{- include "jupyterhub.labels" . | nindent 4 }} {{- if .hook }} hub.jupyter.org/deletable: "true" {{- end }} {{- if .hook }} annotations: {{- /* Allows the daemonset to be deleted when the image-awaiter job is completed. */}} "helm.sh/hook": pre-install,pre-upgrade "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded "helm.sh/hook-weight": "-10" {{- end }} spec: selector: matchLabels: {{- include "jupyterhub.matchLabels" . | nindent 6 }} updateStrategy: type: RollingUpdate rollingUpdate: maxUnavailable: 100% {{- if not (typeIs "" .Values.prePuller.revisionHistoryLimit) }} revisionHistoryLimit: {{ .Values.prePuller.revisionHistoryLimit }} {{- end }} template: metadata: labels: {{- include "jupyterhub.matchLabels" . | nindent 8 }} {{- with .Values.prePuller.annotations }} annotations: {{- . | toYaml | nindent 8 }} {{- end }} spec: {{- /* image-puller pods are made evictable to save on the k8s pods per node limit all k8s clusters have and have a higher priority than user-placeholder pods that could block an entire node. */}} {{- if .Values.scheduling.podPriority.enabled }} priorityClassName: {{ include "jupyterhub.image-puller-priority.fullname" . }} {{- end }} {{- with .Values.singleuser.nodeSelector }} nodeSelector: {{- . | toYaml | nindent 8 }} {{- end }} {{- with concat .Values.scheduling.userPods.tolerations .Values.singleuser.extraTolerations .Values.prePuller.extraTolerations }} tolerations: {{- . | toYaml | nindent 8 }} {{- end }} {{- if include "jupyterhub.userNodeAffinityRequired" . }} affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: {{- include "jupyterhub.userNodeAffinityRequired" . | nindent 14 }} {{- end }} terminationGracePeriodSeconds: 0 automountServiceAccountToken: false {{- with include "jupyterhub.imagePullSecrets" (dict "root" . "image" .Values.singleuser.image) }} imagePullSecrets: {{ . }} {{- end }} initContainers: {{- /* --- Conditionally pull an image all user pods will use in an initContainer --- */}} {{- $blockWithIptables := hasKey .Values.singleuser.cloudMetadata "enabled" | ternary (not .Values.singleuser.cloudMetadata.enabled) .Values.singleuser.cloudMetadata.blockWithIptables }} {{- if $blockWithIptables }} - name: image-pull-metadata-block image: {{ .Values.singleuser.networkTools.image.name }}:{{ .Values.singleuser.networkTools.image.tag }} {{- with .Values.singleuser.networkTools.image.pullPolicy }} imagePullPolicy: {{ . }} {{- end }} command: - /bin/sh - -c - echo "Pulling complete" {{- with .Values.prePuller.resources }} resources: {{- . | toYaml | nindent 12 }} {{- end }} {{- with .Values.prePuller.containerSecurityContext }} securityContext: {{- . | toYaml | nindent 12 }} {{- end }} {{- end }} {{- /* --- Pull default image --- */}} - name: image-pull-singleuser image: {{ .Values.singleuser.image.name }}:{{ .Values.singleuser.image.tag }} command: - /bin/sh - -c - echo "Pulling complete" {{- with .Values.prePuller.resources }} resources: {{- . | toYaml | nindent 12 }} {{- end }} {{- with .Values.prePuller.containerSecurityContext }} securityContext: {{- . | toYaml | nindent 12 }} {{- end }} {{- /* --- Pull extra containers' images --- */}} {{- range $k, $container := concat .Values.singleuser.initContainers .Values.singleuser.extraContainers }} - name: image-pull-singleuser-init-and-extra-containers-{{ $k }} image: {{ $container.image }} command: - /bin/sh - -c - echo "Pulling complete" {{- with $.Values.prePuller.resources }} resources: {{- . | toYaml | nindent 12 }} {{- end }} {{- with $.Values.prePuller.containerSecurityContext }} securityContext: {{- . | toYaml | nindent 12 }} {{- end }} {{- end }} {{- /* --- Conditionally pull profileList images --- */}} {{- if .Values.prePuller.pullProfileListImages }} {{- range $k, $container := .Values.singleuser.profileList }} {{- /* profile's kubespawner_override */}} {{- if $container.kubespawner_override }} {{- if $container.kubespawner_override.image }} - name: image-pull-singleuser-profilelist-{{ $k }} image: {{ $container.kubespawner_override.image }} command: - /bin/sh - -c - echo "Pulling complete" {{- with $.Values.prePuller.resources }} resources: {{- . | toYaml | nindent 12 }} {{- end }} {{- with $.Values.prePuller.containerSecurityContext }} securityContext: {{- . | toYaml | nindent 12 }} {{- end }} {{- end }} {{- end }} {{- /* kubespawner_override in profile's profile_options */}} {{- if $container.profile_options }} {{- range $option, $option_spec := $container.profile_options }} {{- if $option_spec.choices }} {{- range $choice, $choice_spec := $option_spec.choices }} {{- if $choice_spec.kubespawner_override }} {{- if $choice_spec.kubespawner_override.image }} - name: image-pull-profile-{{ $k }}-option-{{ $option }}-{{ $choice }} image: {{ $choice_spec.kubespawner_override.image }} command: - /bin/sh - -c - echo "Pulling complete" {{- with $.Values.prePuller.resources }} resources: {{- . | toYaml | nindent 12 }} {{- end }} {{- with $.Values.prePuller.containerSecurityContext }} securityContext: {{- . | toYaml | nindent 12 }} {{- end }} {{- end }} {{- end }} {{- end }} {{- end }} {{- end }} {{- end }} {{- end }} {{- end }} {{- /* --- Pull extra images --- */}} {{- range $k, $v := .Values.prePuller.extraImages }} - name: image-pull-{{ $k }} image: {{ $v.name }}:{{ $v.tag }} command: - /bin/sh - -c - echo "Pulling complete" {{- with $.Values.prePuller.resources }} resources: {{- . | toYaml | nindent 12 }} {{- end }} {{- with $.Values.prePuller.containerSecurityContext }} securityContext: {{- . | toYaml | nindent 12 }} {{- end }} {{- end }} containers: - name: pause image: {{ .Values.prePuller.pause.image.name }}:{{ .Values.prePuller.pause.image.tag }} {{- with .Values.prePuller.resources }} resources: {{- . | toYaml | nindent 12 }} {{- end }} {{- with .Values.prePuller.pause.containerSecurityContext }} securityContext: {{- . | toYaml | nindent 12 }} {{- end }} {{- end }} {{- /* Returns a rendered k8s DaemonSet resource: continuous-image-puller */}} {{- define "jupyterhub.imagePuller.daemonset.continuous" -}} {{- $_ := merge (dict "hook" false "componentPrefix" "continuous-") . }} {{- include "jupyterhub.imagePuller.daemonset" $_ }} {{- end }} {{- /* Returns a rendered k8s DaemonSet resource: hook-image-puller */}} {{- define "jupyterhub.imagePuller.daemonset.hook" -}} {{- $_ := merge (dict "hook" true "componentPrefix" "hook-") . }} {{- include "jupyterhub.imagePuller.daemonset" $_ }} {{- end }} {{- /* Returns a checksum of the rendered k8s DaemonSet resource: hook-image-puller This checksum is used when prePuller.hook.pullOnlyOnChanges=true to decide if it is worth creating the hook-image-puller associated resources. */}} {{- define "jupyterhub.imagePuller.daemonset.hook.checksum" -}} {{- /* We pin componentLabel and Chart.Version as doing so can pin labels of no importance if they would change. Chart.Name is also pinned as a harmless technical workaround when we compute the checksum. */}} {{- $_ := merge (dict "componentLabel" "pinned" "Chart" (dict "Name" "jupyterhub" "Version" "pinned")) . -}} {{- $yaml := include "jupyterhub.imagePuller.daemonset.hook" $_ }} {{- $yaml | sha256sum }} {{- end }} {{- /* Returns a truthy string or a blank string depending on if the hook-image-puller should be installed. The truthy strings are comments that summarize the state that led to returning a truthy string. - prePuller.hook.enabled must be true - if prePuller.hook.pullOnlyOnChanges is true, the checksum of the hook-image-puller daemonset must differ since last upgrade */}} {{- define "jupyterhub.imagePuller.daemonset.hook.install" -}} {{- if .Values.prePuller.hook.enabled }} {{- if .Values.prePuller.hook.pullOnlyOnChanges }} {{- $new_checksum := include "jupyterhub.imagePuller.daemonset.hook.checksum" . }} {{- $k8s_state := lookup "v1" "ConfigMap" .Release.Namespace (include "jupyterhub.hub.fullname" .) | default (dict "data" (dict)) }} {{- $old_checksum := index $k8s_state.data "checksum_hook-image-puller" | default "" }} {{- if ne $new_checksum $old_checksum -}} # prePuller.hook.enabled={{ .Values.prePuller.hook.enabled }} # prePuller.hook.pullOnlyOnChanges={{ .Values.prePuller.hook.pullOnlyOnChanges }} # post-upgrade checksum != pre-upgrade checksum (of the hook-image-puller DaemonSet) # "{{ $new_checksum }}" != "{{ $old_checksum}}" {{- end }} {{- else -}} # prePuller.hook.enabled={{ .Values.prePuller.hook.enabled }} # prePuller.hook.pullOnlyOnChanges={{ .Values.prePuller.hook.pullOnlyOnChanges }} {{- end }} {{- end }} {{- end }}