{{/* One pod spec for every workload, Deployment and Job alike. The chart is values-driven on purpose: `.Values.workloads` is a near-literal transcription of infra/docker-compose.yml, so the two stacks can be diffed by eye instead of by archaeology. Adding a service is a values edit, not a template edit. Called as: include "big.podspec" (dict "root" $ "name" $name "w" $w) */}} {{- define "big.podspec" -}} {{- $root := .root -}} {{- $name := .name -}} {{- $w := .w -}} {{- with $root.Values.imagePullSecrets }} imagePullSecrets: {{- toYaml . | nindent 2 }} {{- end }} {{- with $w.waitFor }} initContainers: - name: wait-for-deps image: {{ $root.Values.images.busybox }} command: - sh - -c - | for t in {{ join " " . }}; do echo "waiting for $t" until nc -z "${t%:*}" "${t#*:}"; do sleep 2; done done {{- end }} containers: - name: {{ $name }} image: {{ include "big.image" (dict "root" $root "name" $name "w" $w) }} # Only this repo's images get the configured policy: their `dev` tag is mutable. # Upstream tags are pinned, so IfNotPresent keeps them out of pod-template diffs — # which matters because a changed template makes a Job unpatchable (immutable). imagePullPolicy: {{ if $w.own }}{{ $root.Values.images.pullPolicy }}{{ else }}IfNotPresent{{ end }} {{- if $w.command }} {{- fail (printf "workload %s: use `args`, not `command` — compose's `command:` replaces CMD, but Kubernetes' `command:` replaces the image ENTRYPOINT (postgres would run as root, keycloak would exec `start-dev`)" $name) }} {{- end }} {{- with $w.args }} args: {{- toYaml . | nindent 6 }} {{- end }} {{- with $w.envFrom }} envFrom: {{- range . }} - configMapRef: # optional: an env group whose feature is disabled (e.g. otel) simply # isn't rendered, and the pod must still start. name: {{ printf "%s-env" . }} optional: true {{- end }} {{- end }} {{- with $w.env }} env: {{- include "big.env" (list $root .) | nindent 6 }} {{- end }} {{- with $w.ports }} ports: {{- range . }} - name: {{ .name }} containerPort: {{ .targetPort | default .port }} {{- end }} {{- end }} {{- with $w.probe }} readinessProbe: {{- toYaml . | nindent 6 }} {{- end }} {{- with $w.resources }} resources: {{- toYaml . | nindent 6 }} {{- end }} {{- if or $w.files $w.data }} volumeMounts: {{- range $w.files }} - name: {{ .configMap }} mountPath: {{ .mountPath }} {{- with .subPath }} subPath: {{ . }} {{- end }} readOnly: true {{- end }} {{- with $w.data }} - name: data mountPath: {{ .mountPath }} {{- end }} {{- end }} {{- if or $w.files $w.data }} volumes: {{- range $w.files }} - name: {{ .configMap }} configMap: name: {{ .configMap }} {{- with .defaultMode }} defaultMode: {{ . }} {{- end }} {{- end }} {{- with $w.data }} - name: data {{- if $root.Values.persistence.storageClass }} persistentVolumeClaim: claimName: {{ $name }}-data {{- else }} # No StorageClass configured: the databases are emptyDir, so the stack needs # no CSI driver to come up. Data then lives as long as the pod does — see # docs/runbooks/kubernetes-talos.md for switching on local-path. emptyDir: {} {{- end }} {{- end }} {{- end }} {{- end -}} {{/* Image ref: `own: true` workloads are built from this repo, everything else is upstream. */}} {{- define "big.image" -}} {{- $root := .root -}} {{- $w := .w -}} {{- if $w.own -}} {{- $ref := printf "%s/%s:%s" $root.Values.images.repositoryPrefix .name $root.Values.images.tag -}} {{- with $root.Values.images.registry }}{{ printf "%s/%s" . $ref }}{{ else }}{{ $ref }}{{ end }} {{- else -}} {{- $w.image -}} {{- end -}} {{- end -}} {{/* Env list from a map. Every value is run through `tpl`, so values.yaml can name cluster-internal hosts ({{ .Release.Namespace }}) and the node address ({{ .Values.host }}) without the chart hard-coding either. */}} {{- define "big.env" -}} {{- $root := index . 0 -}} {{- range $k, $v := index . 1 }} - name: {{ $k }} value: {{ tpl (toString $v) $root | quote }} {{- end }} {{- end -}} {{- define "big.labels" -}} app.kubernetes.io/name: {{ .name }} app.kubernetes.io/instance: {{ .root.Release.Name }} app.kubernetes.io/managed-by: Helm {{- end -}}