{{ $isClusterInitEnabled := and (eq (len .Values.conf.join) 0) (not (index .Values.conf `single-node`)) }} {{ $isDatabaseProvisioningEnabled := .Values.init.provisioning.enabled }} {{- if or $isClusterInitEnabled $isDatabaseProvisioningEnabled }} {{ template "cockroachdb.tlsValidation" . }} kind: Job apiVersion: batch/v1 metadata: name: {{ template "cockroachdb.fullname" . }}-init namespace: {{ .Release.Namespace | quote }} labels: helm.sh/chart: {{ template "cockroachdb.chart" . }} app.kubernetes.io/name: {{ template "cockroachdb.name" . }} app.kubernetes.io/instance: {{ .Release.Name | quote }} app.kubernetes.io/managed-by: {{ .Release.Service | quote }} {{- with .Values.init.labels }} {{- toYaml . | nindent 4 }} {{- end }} {{- with .Values.labels }} {{- toYaml . | nindent 4 }} {{- end }} annotations: helm.sh/hook: post-install,post-upgrade helm.sh/hook-delete-policy: before-hook-creation {{- with .Values.init.jobAnnotations }} {{- toYaml . | nindent 4 }} {{- end }} spec: template: metadata: labels: app.kubernetes.io/name: {{ template "cockroachdb.name" . }} app.kubernetes.io/instance: {{ .Release.Name | quote }} {{- with .Values.init.labels }} {{- toYaml . | nindent 8 }} {{- end }} {{- with .Values.init.annotations }} annotations: {{- toYaml . | nindent 8 }} {{- end }} spec: {{- if eq (include "cockroachdb.securityContext.versionValidation" .) "true" }} {{- if and .Values.init.securityContext.enabled }} securityContext: runAsGroup: 1000 runAsUser: 1000 fsGroup: 1000 runAsNonRoot: true {{- end }} {{- end }} restartPolicy: OnFailure terminationGracePeriodSeconds: 0 {{- if or .Values.image.credentials (and .Values.tls.enabled .Values.tls.selfSigner.image.credentials (not .Values.tls.certs.provided) (not .Values.tls.certs.certManager)) }} imagePullSecrets: {{- if .Values.image.credentials }} - name: {{ template "cockroachdb.fullname" . }}.db.registry {{- end }} {{- if and .Values.tls.enabled .Values.tls.selfSigner.image.credentials (not .Values.tls.certs.provided) (not .Values.tls.certs.certManager) }} - name: {{ template "cockroachdb.fullname" . }}.self-signed-certs.registry {{- end }} {{- end }} serviceAccountName: {{ template "cockroachdb.serviceAccount.name" . }} {{- if .Values.tls.enabled }} initContainers: - name: copy-certs image: {{ .Values.tls.copyCerts.image | quote }} imagePullPolicy: {{ .Values.tls.selfSigner.image.pullPolicy | quote }} command: - /bin/sh - -c - "cp -f /certs/* /cockroach-certs/; chmod 0400 /cockroach-certs/*.key" env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace volumeMounts: - name: client-certs mountPath: /cockroach-certs/ - name: certs-secret mountPath: /certs/ {{- with .Values.tls.copyCerts.resources }} resources: {{- toYaml . | nindent 12 }} {{- end }} {{- end }} {{- with .Values.init.affinity }} affinity: {{- toYaml . | nindent 8 }} {{- end }} {{- with .Values.init.nodeSelector }} nodeSelector: {{- toYaml . | nindent 8 }} {{- end }} {{- with .Values.init.tolerations }} tolerations: {{- toYaml . | nindent 8 }} {{- end }} containers: - name: cluster-init image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" imagePullPolicy: {{ .Values.image.pullPolicy | quote }} # Run the command in an `while true` loop because this Job is bound # to come up before the CockroachDB Pods (due to the time needed to # get PersistentVolumes attached to Nodes), and sleeping 5 seconds # between attempts is much better than letting the Pod fail when # the init command does and waiting out Kubernetes' non-configurable # exponential back-off for Pod restarts. # Command completes either when cluster initialization succeeds, # or when cluster has been initialized already. command: - /bin/bash - -c - >- {{- if $isClusterInitEnabled }} initCluster() { while true; do local output=$( set -x; /cockroach/cockroach init \ {{- if .Values.tls.enabled }} --certs-dir=/cockroach-certs/ \ {{- else }} --insecure \ {{- end }} {{- with index .Values.conf "cluster-name" }} --cluster-name={{.}} \ {{- end }} --host={{ template "cockroachdb.fullname" . }}-0.{{ template "cockroachdb.fullname" . -}} :{{ .Values.service.ports.grpc.internal.port | int64 }} \ 2>&1); local exitCode="$?"; echo $output; if [[ "$output" =~ .*"Cluster successfully initialized".* || "$output" =~ .*"cluster has already been initialized".* ]]; then break; fi echo "Cluster is not ready to be initialized, retrying in 5 seconds" sleep 5; done } initCluster; {{- end }} {{- if $isDatabaseProvisioningEnabled }} provisionCluster() { while true; do /cockroach/cockroach sql \ {{- if .Values.tls.enabled }} --certs-dir=/cockroach-certs/ \ {{- else }} --insecure \ {{- end }} --host={{ template "cockroachdb.fullname" . }}-0.{{ template "cockroachdb.fullname" . -}} :{{ .Values.service.ports.grpc.internal.port | int64 }} \ --execute=" {{- range $clusterSetting, $clusterSettingValue := .Values.init.provisioning.clusterSettings }} SET CLUSTER SETTING {{ $clusterSetting }} = '${{ $clusterSetting | replace "." "_" }}_CLUSTER_SETTING'; {{- end }} {{- range $user := .Values.init.provisioning.users }} CREATE USER IF NOT EXISTS {{ $user.name }} WITH {{- if $user.password }} PASSWORD '${{ $user.name }}_PASSWORD' {{- else }} PASSWORD null {{- end }} {{ join " " $user.options }} ; {{- end }} {{- range $database := .Values.init.provisioning.databases }} CREATE DATABASE IF NOT EXISTS {{ $database.name }} {{- if $database.options }} {{ join " " $database.options }} {{- end }} ; {{- range $owner := $database.owners }} GRANT ALL ON DATABASE {{ $database.name }} TO {{ $owner }}; {{- end }} {{- range $owner := $database.owners_with_grant_option }} GRANT ALL ON DATABASE {{ $database.name }} TO {{ $owner }} WITH GRANT OPTION; {{- end }} {{- if $database.backup }} CREATE SCHEDULE IF NOT EXISTS {{ $database.name }}_scheduled_backup FOR BACKUP DATABASE {{ $database.name }} INTO '{{ $database.backup.into }}' {{- if $database.backup.options }} WITH {{ join "," $database.backup.options }} {{- end }} RECURRING '{{ $database.backup.recurring }}' {{- if $database.backup.fullBackup }} FULL BACKUP '{{ $database.backup.fullBackup }}' {{- else }} FULL BACKUP ALWAYS {{- end }} {{- if and $database.backup.schedule $database.backup.schedule.options }} WITH SCHEDULE OPTIONS {{ join "," $database.backup.schedule.options }} {{- end }} ; {{- end }} {{- end }} " &>/dev/null; local exitCode="$?"; if [[ "$exitCode" -eq "0" ]] then break; fi sleep 5; done echo "Provisioning completed successfully"; } provisionCluster; {{- end }} env: {{- $secretName := printf "%s-init" (include "cockroachdb.fullname" .) }} {{- range $user := .Values.init.provisioning.users }} {{- if $user.password }} - name: {{ $user.name }}_PASSWORD valueFrom: secretKeyRef: name: {{ $secretName }} key: {{ $user.name }}-password {{- end }} {{- end }} {{- range $clusterSetting, $clusterSettingValue := .Values.init.provisioning.clusterSettings }} {{- if $clusterSettingValue }} - name: {{ $clusterSetting | replace "." "_" }}_CLUSTER_SETTING valueFrom: secretKeyRef: name: {{ $secretName }} key: {{ $clusterSetting | replace "." "-" }}-cluster-setting {{- end }} {{- end }} {{- if .Values.tls.enabled }} volumeMounts: - name: client-certs mountPath: /cockroach-certs/ {{- end }} {{- with .Values.init.resources }} resources: {{- toYaml . | nindent 12 }} {{- end }} {{- if .Values.tls.enabled }} volumes: - name: client-certs emptyDir: {} {{- if or .Values.tls.certs.provided .Values.tls.certs.certManager .Values.tls.certs.selfSigner.enabled }} - name: certs-secret {{- if or .Values.tls.certs.tlsSecret .Values.tls.certs.certManager .Values.tls.certs.selfSigner.enabled }} projected: sources: - secret: {{- if .Values.tls.certs.selfSigner.enabled }} name: {{ template "cockroachdb.fullname" . }}-client-secret {{ else }} name: {{ .Values.tls.certs.clientRootSecret }} {{ end -}} items: - key: ca.crt path: ca.crt mode: 0400 - key: tls.crt path: client.root.crt mode: 0400 - key: tls.key path: client.root.key mode: 0400 {{- else }} secret: secretName: {{ .Values.tls.certs.clientRootSecret }} defaultMode: 0400 {{- end }} {{- end }} {{- end }} {{- end }}