# _helpers.tpl
{{/* vim: set filetype=mustache: */}}
{{/*
Expand the name of the chart.
*/}}
{{- define "stolon.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
{{- end -}}

{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "stolon.fullname" -}}
{{- if .Values.fullnameOverride -}}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- $name := default .Chart.Name .Values.nameOverride -}}
{{- if contains $name .Release.Name -}}
{{- .Release.Name | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{- end -}}
{{- end -}}

{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "stolon.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
{{- end -}}


{{/* Create the name of the service account to use */}}
{{- define "stolon.serviceAccountName" -}}
{{- if .Values.serviceAccount.create -}}
    {{ default (include "stolon.fullname" .) .Values.serviceAccount.name }}
{{- else -}}
    {{ default "default" .Values.serviceAccount.name }}
{{- end -}}
{{- end -}}

{{- define "stolon.clusterName" -}}
{{- if .Values.clusterName -}}
    {{- .Values.clusterName | trunc 63 | trimSuffix "-" -}}
{{- else -}}
    {{- template "stolon.fullname" . -}}
{{- end -}}
{{- end -}}
 # certs.yaml
{{ if and (not .Values.tls.existingSecret) ( .Values.tls.enabled) }}
apiVersion: v1
kind: Secret
metadata:
  name: {{ template "stolon.fullname" . }}-certs
  labels:
    app: {{ template "stolon.name" . }}
    chart: {{ template "stolon.chart" . }}
    release: {{ .Release.Name }}
    heritage: {{ .Release.Service }}
type: Opaque
data:
  rootCa.crt:
    {{ .Values.tls.rootCa | b64enc | quote }}
  serverCrt.crt:
    {{ .Values.tls.serverCrt| b64enc | quote }}
  serverKey.key:
    {{ .Values.tls.serverKey | b64enc | quote }}
{{- end }}
 # configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ template "stolon.fullname" . }}
  labels:
    app: {{ template "stolon.name" . }}
    chart: {{ template "stolon.chart" . }}
    release: {{ .Release.Name }}
    heritage: {{ .Release.Service }}
data:
{{- if .Values.keeper.hooks.failKeeper.enabled }}
  pre-stop-hook.sh: |-
    #!/bin/bash
    exec &> >(tee -a "/var/log/stolon-hooks.log")

    NODE_NAME=${HOSTNAME}
    IFS='-' read -ra ADDR <<< "$(hostname)"
    STKEEPER_UID="{{ .Values.keeper.uid_prefix }}${ADDR[-1]}"

    echo "keeper [${STKEEPER_UID}] is failing"
    stolonctl \
      --cluster-name={{ template "stolon.clusterName" . }} \
      --store-backend={{ .Values.store.backend }} \
      {{- if eq .Values.store.backend "kubernetes" }}
      --kube-resource-kind={{ .Values.store.kubeResourceKind }} \
      {{- else }}
      --store-endpoints={{ .Values.store.endpoints }} \
      {{- end }}
      failkeeper ${STKEEPER_UID} || true

    echo "Node ${NODE_NAME} is ready to shutdown"
{{- end }}
{{- with .Values.nodePostStartScript }}
{{ toYaml . | indent 2 }}
{{- end }}
 # create-cluster-job.yaml
{{ if and .Release.IsInstall .Values.job.autoCreateCluster }}
apiVersion: batch/v1
kind: Job
metadata:
  name: {{ template "stolon.fullname" . }}-create-cluster
  labels:
    app: {{ template "stolon.name" . }}
    chart: {{ template "stolon.chart" . }}
    release: {{ .Release.Name }}
    heritage: {{ .Release.Service }}
  annotations:
    "helm.sh/hook": post-install
    "helm.sh/hook-delete-policy": before-hook-creation
spec:
  template:
    metadata:
      labels:
        app: {{ template "stolon.fullname" . }}
        release: {{ .Release.Name }}
{{- if .Values.job.annotations }}
      annotations:
{{ toYaml .Values.job.annotations | indent 8 }}
{{- end }}
    spec:
      restartPolicy: OnFailure
      serviceAccountName: {{ template "stolon.serviceAccountName" . }}
  {{- if eq .Values.store.backend "etcdv2" "etcdv3" }}
      initContainers:
        - name: {{ .Chart.Name }}-etcd-wait
          image: "{{ .Values.etcdImage.repository }}:{{ .Values.etcdImage.tag }}"
          imagePullPolicy: {{ .Values.etcdImage.pullPolicy }}
          command: ["sh", "-c", "while ! etcdctl --endpoints {{ .Values.store.endpoints }} cluster-health; do sleep 1 && echo -n .; done"]
  {{- end }}
      containers:
        - name: {{ template "stolon.fullname" . }}-create-cluster
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
          imagePullPolicy: {{ .Values.image.pullPolicy }}
          command: ["/usr/local/bin/stolonctl"]
          args:
            - init
            - --cluster-name={{ template "stolon.clusterName" . }}
            - --store-backend={{ .Values.store.backend }}
            {{- if eq .Values.store.backend "kubernetes" }}
            - --kube-resource-kind={{ .Values.store.kubeResourceKind }}
            {{- else }}
            - --store-endpoints={{ .Values.store.endpoints }}
            {{- end }}
            - --yes
            - '{ "initMode": "new", {{- range $key, $value := .Values.clusterSpec }} {{ $key | quote }}: {{ if typeIs "string" $value }} {{ $value | quote }} {{ else }} {{ $value }} {{ end }}, {{- end }} {{ if .Values.tls.enabled }} "pgParameters": {{- $pgParameters := .Values.pgParameters -}}{{ $all_init := set $pgParameters "ssl" "on" }}{{ $all_init := set $all_init "ssl_cert_file" "/certs/serverCrt.crt" }} {{ $all_init := set $all_init "ssl_key_file" "/certs/serverKey.key" }}{{ $all_init := set $all_init "ssl_ca_file" "/certs/rootCa.crt" }}{{ toJson $all_init }}{{ else }}"pgParameters": {{ toJson .Values.pgParameters }} {{ end}} }'
{{ end }}
 # init-db-job.yaml
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ template "stolon.fullname" . }}-init-scripts
data:
{{- with .Values.initdbScripts }}
{{ toYaml . | indent 2 }}
{{- end }}
---
{{- if .Values.initdbScripts }}
apiVersion: batch/v1
kind: Job
metadata:
  name: '{{template "stolon.clusterName" .}}-createdb'
  labels:
    heritage: {{.Release.Service | quote }}
    release: {{.Release.Name | quote }}
    chart: "{{.Chart.Name}}-{{.Chart.Version}}"
  annotations:
    "helm.sh/hook": post-install
    "helm.sh/hook-weight": "2"
    "helm.sh/hook-delete-policy": hook-succeeded
spec:
  template:
    metadata:
      name: "{{.Release.Name}}"
      labels:
        heritage: {{.Release.Service | quote }}
        release: {{.Release.Name | quote }}
        chart: "{{.Chart.Name}}-{{.Chart.Version}}"
{{- if .Values.job.annotations }}
      annotations:
{{ toYaml .Values.job.annotations | indent 8 }}
{{- end }}
    spec:
      restartPolicy: Never
      containers:
      - name: create-database-job
        image: 'postgres'
        env:
          - name: USERNAME
{{- if not (empty .Values.superuserSecret.name) }}
            valueFrom:
              secretKeyRef:
                name: {{ .Values.superuserSecret.name }}
                key: {{ .Values.superuserSecret.usernameKey }}
{{- else }}
            value: {{ .Values.superuserUsername | quote }}
{{- end }}
          - name: PGPASSWORD
{{- if not (empty .Values.superuserSecret.name) }}
            valueFrom:
              secretKeyRef:
                name: {{ .Values.superuserSecret.name }}
                key: {{ .Values.superuserSecret.passwordKey }}
{{- else }}
            value: {{ .Values.superuserPassword | quote }}
{{- end }}
          - name: HOST
            value: {{ template "stolon.fullname" . }}-proxy
        command: ["/bin/bash", "-e", "/tmp/sql-script/create_script.sh"]
        volumeMounts:
          - mountPath: "/tmp/sql-script"
            readOnly: true
            name: sql-script
      volumes:
        - name: sql-script
          configMap:
            name: {{ template "stolon.fullname" . }}-init-scripts
            defaultMode: 420
      initContainers:
        - name: wait-for-database
          image: jwilder/dockerize
          command: ['dockerize', '-timeout', '30s', '-wait', 'tcp://{{ template "stolon.fullname" . }}-proxy:5432']
{{- end }} # keeper-headless-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: {{ template "stolon.fullname" . }}-keeper-headless
  labels:
    app: {{ template "stolon.name" . }}
    chart: {{ template "stolon.chart" . }}
    release: {{ .Release.Name }}
    heritage: {{ .Release.Service }}
  annotations:
{{- with .Values.keeper.service.annotations }}
{{ toYaml . | indent 4 }}
{{- end }}
spec:
  clusterIP: None
  ports:
  {{- range $key, $value := .Values.keeper.service.ports }}
    - name: {{ $key }}
{{ toYaml $value | indent 6 }}
{{- end }}
  selector:
    app: {{ template "stolon.name" . }}
    release: {{ .Release.Name }}
    component: stolon-keeper
 # keeper-pdb.yaml
{{- if .Values.keeper.podDisruptionBudget }}
apiVersion: policy/v1beta1
kind: PodDisruptionBudget
metadata:
  name: {{ template "stolon.fullname" . }}-keeper
  labels:
    app: {{ template "stolon.name" . }}
    chart: {{ template "stolon.chart" . }}
    release: {{ .Release.Name }}
    heritage: {{ .Release.Service }}
spec:
  selector:
    matchLabels:
      app: {{ template "stolon.name" . }}
      release: {{ .Release.Name }}
      component: stolon-keeper
{{ toYaml .Values.keeper.podDisruptionBudget | indent 2 }}
{{- end }}
 # keeper-statefulset.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: {{ template "stolon.fullname" . }}-keeper
  labels:
    app: {{ template "stolon.name" . }}
    chart: {{ template "stolon.chart" . }}
    release: {{ .Release.Name }}
    heritage: {{ .Release.Service }}
spec:
  serviceName: {{ template "stolon.fullname" . }}-keeper-headless
  replicas: {{ .Values.keeper.replicaCount }}
  selector:
    matchLabels:
      app: {{ template "stolon.name" . }}
      release: {{ .Release.Name }}
      component: stolon-keeper
  template:
    metadata:
      labels:
        app: {{ template "stolon.name" . }}
        release: {{ .Release.Name }}
        component: stolon-keeper
        stolon-cluster: {{ template "stolon.fullname" . }}
      annotations:
{{- with .Values.keeper.annotations }}
{{ toYaml . | indent 8 }}
{{- end }}
    spec:
{{- if .Values.keeper.priorityClassName }}
      priorityClassName: "{{ .Values.keeper.priorityClassName }}"
{{- end }}
      serviceAccountName: {{ template "stolon.serviceAccountName" . }}
      terminationGracePeriodSeconds: 10
{{- if .Values.keeper.fsGroup }}
      securityContext:
        fsGroup: {{ .Values.keeper.fsGroup }}
{{- end }}
{{- if .Values.image.pullSecrets }}
      imagePullSecrets:
{{ toYaml .Values.image.pullSecrets | indent 8 }}
{{- end }}
      containers:
        - name: {{ .Chart.Name }}
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
          imagePullPolicy: {{ .Values.image.pullPolicy }}
          command:
            - "/bin/bash"
            - "-ec"
            - |
              # Generate our keeper uid using the pod index
              IFS='-' read -ra ADDR <<< "$(hostname)"
              export STKEEPER_UID="{{ .Values.keeper.uid_prefix }}${ADDR[-1]}"
              export POD_IP=$(hostname -i)
              export STKEEPER_PG_ADVERTISE_ADDRESS=$POD_IP
              export STKEEPER_PG_LISTEN_ADDRESS=${STKEEPER_PG_LISTEN_ADDRESS:-$POD_IP}
              export STOLON_DATA=/stolon-data
              chown stolon:stolon $STOLON_DATA
              {{- if .Values.shmVolume.enabled }}
              chmod -R 777 /dev/shm
              {{- end }}
              exec gosu stolon stolon-keeper --data-dir $STOLON_DATA
          env:
            - name: POD_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
            - name: STKEEPER_CLUSTER_NAME
              value: {{ template "stolon.clusterName" . }}
            - name: STKEEPER_STORE_BACKEND
              value: {{ .Values.store.backend | quote }}
            {{- if eq .Values.store.backend "kubernetes" }}
            - name: STKEEPER_KUBE_RESOURCE_KIND
              value: {{ .Values.store.kubeResourceKind  | quote }}
            {{- else }}
            - name: STKEEPER_STORE_ENDPOINTS
              value: {{ .Values.store.endpoints | quote }}
            {{- end }}
            - name: STKEEPER_PG_REPL_USERNAME
{{ if not (empty .Values.replicationSecret.name) }}
              valueFrom:
                secretKeyRef:
                  name: {{ .Values.replicationSecret.name }}
                  key: {{ .Values.replicationSecret.usernameKey }}
{{ else }}
              value: {{ .Values.replicationUsername | quote}}
{{ end }}
            - name: STKEEPER_PG_REPL_PASSWORDFILE
{{ if not (empty .Values.replicationSecret.name) }}
              value: /etc/secrets/stolon-{{ .Values.replicationSecret.name }}/{{ .Values.replicationSecret.passwordKey }}
{{ else if not (empty .Values.replicationPasswordFile) }}
              value: {{ .Values.replicationPasswordFile }}
{{ else }}
              value: "/etc/secrets/stolon/pg_repl_password"
{{ end }}
            - name: STKEEPER_PG_SU_USERNAME
{{ if not (empty .Values.superuserSecret.name) }}
              valueFrom:
                secretKeyRef:
                  name: {{ .Values.superuserSecret.name }}
                  key: {{ .Values.superuserSecret.usernameKey }}
{{ else }}
              value: {{ .Values.superuserUsername | quote }}
{{ end }}
            - name: STKEEPER_PG_SU_PASSWORDFILE
{{ if not (empty .Values.superuserSecret.name) }}
              value: /etc/secrets/stolon-{{ .Values.superuserSecret.name }}/{{ .Values.superuserSecret.passwordKey }}
{{ else if not (empty .Values.superuserPasswordFile) }}
              value: {{ .Values.superuserPasswordFile }}
{{ else }}
              value: "/etc/secrets/stolon/pg_su_password"
{{ end }}
            - name: STKEEPER_METRICS_LISTEN_ADDRESS
              value: "0.0.0.0:{{ .Values.ports.metrics.containerPort }}"
            - name: STKEEPER_DEBUG
              value: {{ .Values.debug | quote}}
{{- if .Values.keeper.extraEnv }}
{{ toYaml .Values.keeper.extraEnv | indent 12 }}
{{- end }}
          ports:
{{- range $key, $value := .Values.ports }}
            - name: {{ $key }}
{{ toYaml $value | indent 14 }}
{{- end }}
          resources:
{{ toYaml .Values.keeper.resources | indent 12 }}
          volumeMounts:
{{- if .Values.shmVolume.enabled }}
          - name: dshm
            mountPath: /dev/shm
{{- end }}
          - name: data
            mountPath: /stolon-data
{{- if .Values.tls.enabled }}
          - name: certs
            mountPath: /certs
{{- end }}
{{ if and (or (empty .Values.superuserSecret.name) (empty .Values.replicationSecret.name)) (or (empty .Values.superuserPasswordFile) (empty .Values.replicationPasswordFile)) }}
          - name: stolon-secrets
            mountPath: /etc/secrets/stolon
{{ end }}
{{ if not (empty .Values.superuserSecret.name) }}
          - name: stolon-secret-{{ .Values.superuserSecret.name }}
            mountPath: /etc/secrets/stolon-{{ .Values.superuserSecret.name }}
{{ end }}
{{ if and (not (empty .Values.replicationSecret.name)) (not (eq .Values.superuserSecret.name .Values.replicationSecret.name)) }}
          - name: stolon-secret-{{ .Values.replicationSecret.name }}
            mountPath: /etc/secrets/stolon-{{ .Values.replicationSecret.name }}
{{ end }}
{{- range $key, $value := .Values.keeper.volumeMounts }}
          - name: {{ $key }}
{{ toYaml $value | indent 12 }}
{{- end }}
{{- if .Values.keeper.hooks.failKeeper.enabled }}
          - name: config
            mountPath: /pre-stop-hook.sh
            subPath: pre-stop-hook.sh
{{- end }}
{{- if .Values.nodePostStartScript }}
          - name: config
            mountPath: /postStartScript.sh
            subPath: postStartScript.sh
{{- end }}
          lifecycle:
{{- if .Values.keeper.hooks.failKeeper.enabled }}
            preStop:
              exec:
                command: ["/bin/bash", "-e", "/pre-stop-hook.sh"]
{{- end }}
{{- if .Values.nodePostStartScript }}
            postStart:
              exec:
                command: ["/bin/bash", "-e", "/postStartScript.sh"]
{{- end }}
{{- with .Values.keeper.nodeSelector }}
      nodeSelector:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.keeper.affinity }}
      affinity:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.keeper.tolerations }}
      tolerations:
{{ toYaml . | indent 8 }}
{{- end }}
      volumes:
{{- if .Values.shmVolume.enabled }}
        - name: dshm
          emptyDir:
            medium: Memory
{{- end }}
{{- if .Values.tls.enabled }}
        - name: certs
          secret:
            defaultMode: 0600
            secretName: {{ if .Values.tls.existingSecret }}{{ .Values.tls.existingSecret }}{{ else }}{{ template "stolon.fullname" . }}-certs{{end}}
{{ end }}
        - name: config
          configMap:
            name: {{ template "stolon.fullname" . }}
{{ if or (empty .Values.superuserSecret.name) (empty .Values.replicationSecret.name) }}
        - name: stolon-secrets
          secret:
            secretName: {{ template "stolon.fullname" . }}
{{ end }}
{{ if not (empty .Values.superuserSecret.name) }}
        - name: stolon-secret-{{ .Values.superuserSecret.name }}
          secret:
            secretName: {{ .Values.superuserSecret.name }}
{{ end }}
{{ if and (not (empty .Values.replicationSecret.name)) (not (eq .Values.superuserSecret.name .Values.replicationSecret.name)) }}
        - name: stolon-secret-{{ .Values.replicationSecret.name }}
          secret:
            secretName: {{ .Values.replicationSecret.name }}
{{ end }}
{{- range $key, $value := .Values.keeper.volumes }}
        - name: {{ $key }}
{{ toYaml $value | indent 10 }}
{{- end }}
{{- if .Values.persistence.enabled }}
  volumeClaimTemplates:
    - metadata:
        name: data
      spec:
        accessModes:
  {{- range .Values.persistence.accessModes }}
          - {{ . | quote }}
  {{- end }}
        resources:
          requests:
            storage: {{ .Values.persistence.size | quote }}
  {{- if .Values.persistence.storageClassName }}
    {{- if (eq "-" .Values.persistence.storageClassName) }}
        storageClassName: ""
    {{- else }}
        storageClassName: "{{ .Values.persistence.storageClassName }}"
    {{- end }}
  {{- end }}
{{- else }}
        - name: data
          emptyDir: {}
{{- end }}
 # metrics-service.yaml
{{- if .Values.serviceMonitor.enabled  }}
apiVersion: v1
kind: Service
metadata:
  name: {{ template "stolon.fullname" . }}-metrics
  labels:
    app: {{ template "stolon.name" . }}
    chart: {{ template "stolon.chart" . }}
    release: {{ .Release.Name }}
    heritage: {{ .Release.Service }}
    component: "all"
spec:
  ports:
    - name: metrics
      port: {{ .Values.ports.metrics.containerPort }}
  selector:
    app: {{ template "stolon.name" . }}
    release: {{ .Release.Name }}
{{- end  }}
 # metrics-servicemonitor.yaml
{{- if .Values.serviceMonitor.enabled  }}
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: {{ template "stolon.fullname" . }}
  labels:
  {{- if .Values.serviceMonitor.labels }}
    {{ toYaml .Values.serviceMonitor.labels | nindent 4 }}
  {{- else }}
    app: {{ template "stolon.name" . }}
    chart: {{ template "stolon.chart" . }}
    release: {{ .Release.Name }}
    heritage: {{ .Release.Service }}
  {{- end }}
  {{- if .Values.serviceMonitor.namespace }}
  namespace: {{ .Values.serviceMonitor.namespace }}
  {{- end }}
spec:
  endpoints:
    - targetPort: "metrics"
      {{- if .Values.serviceMonitor.interval }}
      interval: {{ .Values.serviceMonitor.interval }}
      {{- end }}
      {{- if .Values.serviceMonitor.scrapeTimeout }}
      scrapeTimeout: {{ .Values.serviceMonitor.scrapeTimeout }}
      {{- end }}
  namespaceSelector:
    matchNames:
      - {{ .Release.Namespace }}
  selector:
    matchLabels:
      app: {{ template "stolon.name" . }}
      release: {{ .Release.Name }}
      component: "all"
{{- end }}
 # proxy-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ template "stolon.fullname" . }}-proxy
  labels:
    app: {{ template "stolon.name" . }}
    chart: {{ template "stolon.chart" . }}
    release: {{ .Release.Name }}
    heritage: {{ .Release.Service }}
spec:
  replicas: {{ .Values.proxy.replicaCount }}
  selector:
    matchLabels:
      app: {{ template "stolon.name" . }}
      release: {{ .Release.Name }}
      component: stolon-proxy
  template:
    metadata:
      labels:
        app: {{ template "stolon.name" . }}
        release: {{ .Release.Name }}
        component: stolon-proxy
        stolon-cluster: {{ template "stolon.fullname" . }}
      annotations:
{{- with .Values.proxy.annotations }}
{{ toYaml . | indent 8 }}
{{- end }}
    spec:
{{- if .Values.proxy.priorityClassName }}
      priorityClassName: "{{ .Values.proxy.priorityClassName }}"
{{- end }}
      serviceAccountName: {{ template "stolon.serviceAccountName" . }}
{{- if .Values.image.pullSecrets }}
      imagePullSecrets:
{{ toYaml .Values.image.pullSecrets | indent 8 }}
{{- end }}
      containers:
        - name: {{ .Chart.Name }}
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
          imagePullPolicy: {{ .Values.image.pullPolicy }}
          command:
            - "/bin/bash"
            - "-ec"
            - |
              exec gosu stolon stolon-proxy
          env:
            - name: POD_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
            - name: STPROXY_CLUSTER_NAME
              value: {{ template "stolon.clusterName" . }}
            - name: STPROXY_STORE_BACKEND
              value: {{ .Values.store.backend | quote}}
            {{- if eq .Values.store.backend "kubernetes" }}
            - name: STPROXY_KUBE_RESOURCE_KIND
              value: {{ .Values.store.kubeResourceKind  | quote}}
            {{- else }}
            - name: STPROXY_STORE_ENDPOINTS
              value: {{ .Values.store.endpoints | quote}}
            {{- end }}
            - name: STPROXY_LISTEN_ADDRESS
              value: {{ default "0.0.0.0" .Values.proxy.listenAddress | quote }}
            - name: STPROXY_METRICS_LISTEN_ADDRESS
              value: "0.0.0.0:{{ .Values.ports.metrics.containerPort }}"
            - name: STPROXY_DEBUG
              value: {{ .Values.debug | quote}}
{{- if .Values.proxy.extraEnv }}
{{ toYaml .Values.proxy.extraEnv | indent 12 }}
{{- end }}
          ports:
{{- range $key, $value := .Values.ports }}
            - name: {{ $key }}
{{ toYaml $value | indent 14 }}
{{- end }}
          resources:
{{ toYaml .Values.proxy.resources | indent 12 }}
          readinessProbe:
            tcpSocket:
              port: {{ .Values.ports.stolon.containerPort }}
            initialDelaySeconds: 10
            timeoutSeconds: 5
{{- with .Values.proxy.nodeSelector }}
      nodeSelector:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.proxy.affinity }}
      affinity:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.proxy.tolerations }}
      tolerations:
{{ toYaml . | indent 8 }}
{{- end }}
 # proxy-pdb.yaml
{{- if .Values.proxy.podDisruptionBudget }}
apiVersion: policy/v1beta1
kind: PodDisruptionBudget
metadata:
  name: {{ template "stolon.fullname" . }}-proxy
  labels:
    app: {{ template "stolon.name" . }}
    chart: {{ template "stolon.chart" . }}
    release: {{ .Release.Name }}
    heritage: {{ .Release.Service }}
spec:
  selector:
    matchLabels:
      app: {{ template "stolon.name" . }}
      release: {{ .Release.Name }}
      component: stolon-proxy
{{ toYaml .Values.proxy.podDisruptionBudget | indent 2 }}
{{- end }}
 # proxy-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: {{ template "stolon.fullname" . }}-proxy
  labels:
    app: {{ template "stolon.name" . }}
    chart: {{ template "stolon.chart" . }}
    release: {{ .Release.Name }}
    heritage: {{ .Release.Service }}
  annotations:
{{- with .Values.proxy.service.annotations }}
{{ toYaml . | indent 4 }}
{{- end }}
spec:
{{- if (or (eq .Values.proxy.service.type "ClusterIP") (empty .Values.proxy.service.type)) }}
  type: ClusterIP
  {{- if .Values.proxy.service.clusterIP }}
  clusterIP: {{ .Values.proxy.service.clusterIP }}
  {{end}}
{{- else if eq .Values.proxy.service.type "LoadBalancer" }}
  type: {{ .Values.proxy.service.type }}
  loadBalancerIP: {{ .Values.proxy.service.loadBalancerIP }}
{{- else }}
  type: {{ .Values.proxy.service.type }}
{{- end }}
  ports:
  {{- range $key, $value := .Values.proxy.service.ports }}
    - name: {{ $key }}
{{ toYaml $value | indent 6 }}
{{- end }}
  selector:
    app: {{ template "stolon.name" . }}
    release: {{ .Release.Name }}
    component: stolon-proxy
 # role.yaml
{{- if .Values.rbac.create -}}
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: Role
metadata:
  name: {{ template "stolon.fullname" . }}
  labels:
    app: {{ template "stolon.name" . }}
    chart: {{ template "stolon.chart" . }}
    release: {{ .Release.Name }}
    heritage: {{ .Release.Service }}
rules:
- apiGroups:
    - ""
  resources:
    - pods
    - endpoints
    - configmaps
    - events
  verbs:
    - "*"
{{- end -}}
 # rolebinding.yaml
{{- if .Values.rbac.create -}}
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: RoleBinding
metadata:
  name: {{ template "stolon.fullname" . }}
  labels:
    app: {{ template "stolon.name" . }}
    chart: {{ template "stolon.chart" . }}
    release: {{ .Release.Name }}
    heritage: {{ .Release.Service }}
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: {{ template "stolon.fullname" . }}
subjects:
- kind: ServiceAccount
  name: {{ template "stolon.serviceAccountName" . }}
{{- end -}}
 # secret.yaml
{{ if or (and (empty .Values.superuserSecret.name) (empty .Values.superuserPasswordFile)) (and (empty .Values.replicationSecret.name) (empty .Values.replicationPasswordFile)) }}
apiVersion: v1
kind: Secret
metadata:
  name: {{ template "stolon.fullname" . }}
  labels:
    app: {{ template "stolon.name" . }}
    chart: {{ template "stolon.chart" . }}
    release: {{ .Release.Name }}
    heritage: {{ .Release.Service }}
type: Opaque
data:
{{ if and (empty .Values.superuserSecret.name) (empty .Values.superuserPasswordFile) }}
  pg_su_password: {{ required "A valid .Values.superuserPassword entry is required!" .Values.superuserPassword | b64enc | quote }}
{{ end }}
{{ if and (empty .Values.replicationSecret.name) (empty .Values.replicationPasswordFile) }}
  pg_repl_password: {{ required "A valid .Values.replicationPassword entry is required!" .Values.replicationPassword | b64enc | quote }}
{{ end }}
{{ end }}
 # sentinel-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ template "stolon.fullname" . }}-sentinel
  labels:
    app: {{ template "stolon.name" . }}
    chart: {{ template "stolon.chart" . }}
    release: {{ .Release.Name }}
    heritage: {{ .Release.Service }}
spec:
  replicas: {{ .Values.sentinel.replicaCount }}
  selector:
    matchLabels:
      app: {{ template "stolon.name" . }}
      release: {{ .Release.Name }}
      component: stolon-sentinel
  template:
    metadata:
      labels:
        app: {{ template "stolon.name" . }}
        release: {{ .Release.Name }}
        component: stolon-sentinel
        stolon-cluster: {{ template "stolon.fullname" . }}
      annotations:
        checksum/config: {{ include (print .Template.BasePath "/hooks/update-cluster-spec-job.yaml") . | sha256sum }}
{{- with .Values.sentinel.annotations }}
{{ toYaml . | indent 8 }}
{{- end }}
    spec:
{{- if .Values.sentinel.priorityClassName }}
      priorityClassName: "{{ .Values.sentinel.priorityClassName }}"
{{- end }}
      serviceAccountName: {{ template "stolon.serviceAccountName" . }}
{{- if .Values.image.pullSecrets }}
      imagePullSecrets:
{{ toYaml .Values.image.pullSecrets | indent 8 }}
{{- end }}
      containers:
        - name: {{ .Chart.Name }}
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
          imagePullPolicy: {{ .Values.image.pullPolicy }}
          command:
            - "/bin/bash"
            - "-ec"
            - |
              exec gosu stolon stolon-sentinel
          env:
            - name: POD_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
            - name: STSENTINEL_CLUSTER_NAME
              value: {{ template "stolon.clusterName" . }}
            - name: STSENTINEL_STORE_BACKEND
              value: {{ .Values.store.backend | quote}}
            {{- if eq .Values.store.backend "kubernetes" }}
            - name: STSENTINEL_KUBE_RESOURCE_KIND
              value: {{ .Values.store.kubeResourceKind  | quote}}
            {{- else }}
            - name: STSENTINEL_STORE_ENDPOINTS
              value: {{ .Values.store.endpoints | quote}}
            {{- end }}
            - name: STSENTINEL_METRICS_LISTEN_ADDRESS
              value: "0.0.0.0:{{ .Values.ports.metrics.containerPort }}"
            - name: STSENTINEL_DEBUG
              value: {{ .Values.debug | quote}}
{{- if .Values.sentinel.extraEnv }}
{{ toYaml .Values.sentinel.extraEnv | indent 12 }}
{{- end }}
          ports:
{{- range $key, $value := .Values.ports }}
            - name: {{ $key }}
{{ toYaml $value | indent 14 }}
{{- end }}
          resources:
{{ toYaml .Values.sentinel.resources | indent 12 }}
{{- with .Values.sentinel.nodeSelector }}
      nodeSelector:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.sentinel.affinity }}
      affinity:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.sentinel.tolerations }}
      tolerations:
{{ toYaml . | indent 8 }}
{{- end }}
 # sentinel-pdb.yaml
{{- if .Values.sentinel.podDisruptionBudget }}
apiVersion: policy/v1beta1
kind: PodDisruptionBudget
metadata:
  name: {{ template "stolon.fullname" . }}-sentinel
  labels:
    app: {{ template "stolon.name" . }}
    chart: {{ template "stolon.chart" . }}
    release: {{ .Release.Name }}
    heritage: {{ .Release.Service }}
spec:
  selector:
    matchLabels:
      app: {{ template "stolon.name" . }}
      release: {{ .Release.Name }}
      component: stolon-sentinel
{{ toYaml .Values.sentinel.podDisruptionBudget | indent 2 }}
{{- end }}
 # serviceaccount.yaml
{{- if .Values.serviceAccount.create -}}
apiVersion: v1
kind: ServiceAccount
metadata:
  name: {{ template "stolon.serviceAccountName" . }}
  labels:
    app: {{ template "stolon.name" . }}
    chart: {{ template "stolon.chart" . }}
    release: {{ .Release.Name }}
    heritage: {{ .Release.Service }}
{{- end -}}
 # update-cluster-spec-job.yaml
{{ if .Values.job.autoUpdateClusterSpec }}
apiVersion: batch/v1
kind: Job
metadata:
  name: {{ template "stolon.fullname" . }}-update-cluster-spec
  labels:
    app: {{ template "stolon.name" . }}
    chart: {{ template "stolon.chart" . }}
    release: {{ .Release.Name }}
    heritage: {{ .Release.Service }}
  annotations:
    "helm.sh/hook": post-upgrade
    "helm.sh/hook-delete-policy": before-hook-creation
spec:
  template:
    metadata:
      labels:
        app: {{ template "stolon.fullname" . }}
        release: {{ .Release.Name }}
{{- if .Values.job.annotations }}
      annotations:
{{ toYaml .Values.job.annotations | indent 8 }}
{{- end }}
    spec:
      restartPolicy: OnFailure
      serviceAccountName: {{ template "stolon.serviceAccountName" . }}
  {{- if eq .Values.store.backend "etcdv2" "etcdv3" }}
      initContainers:
        - name: {{ .Chart.Name }}-etcd-wait
          image: "{{ .Values.etcdImage.repository }}:{{ .Values.etcdImage.tag }}"
          imagePullPolicy: {{ .Values.etcdImage.pullPolicy }}
          command: ["sh", "-c", "while ! etcdctl --endpoints {{ .Values.store.endpoints }} cluster-health; do sleep 1 && echo -n .; done"]
  {{- end }}
      containers:
        - name: {{ template "stolon.fullname" . }}-update-cluster-spec
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
          imagePullPolicy: {{ .Values.image.pullPolicy }}
          command: ["/usr/local/bin/stolonctl"]
          args:
            - update
            - --cluster-name={{ template "stolon.clusterName" . }}
            - --store-backend={{ .Values.store.backend }}
            {{- if eq .Values.store.backend "kubernetes" }}
            - --kube-resource-kind={{ .Values.store.kubeResourceKind }}
            {{- else }}
            - --store-endpoints={{ .Values.store.endpoints }}
            {{- end }}
            - -p
            - '{ {{- range $key, $value := .Values.clusterSpec }} {{ $key | quote }}: {{ if typeIs "string" $value }} {{ $value | quote }} {{ else }} {{ $value }} {{ end }}, {{- end }} {{ if .Values.tls.enabled }}"pgParameters": {{- $pgParameters := .Values.pgParameters -}}{{ $all := set $pgParameters "ssl" "on" }}{{ $all := set $all "ssl_cert_file" "/certs/serverCrt.crt" }} {{ $all := set $all "ssl_key_file" "/certs/serverKey.key" }}{{ $all := set $all "ssl_ca_file" "/certs/rootCa.crt" }}{{ toJson $all }} {{ else }}"pgParameters": {{- $pgParameters := .Values.pgParameters -}}{{ $all := set $pgParameters "ssl" "off" }}{{ $all := set $all "ssl_cert_file" nil }} {{ $all := set $all "ssl_key_file" nil }}{{ $all := set $all "ssl_ca_file" nil }}{{ toJson $all }}{{ end}}}'
{{ end }}

# clusterName:
image:
  repository: sorintlab/stolon
  tag: v0.16.0-pg10
  pullPolicy: IfNotPresent
  ## Add secrets manually via kubectl on kubernetes cluster and reference here
  # pullSecrets:
  #   - name: "myKubernetesSecret"

# used by create-cluster-job when store.backend is etcd
etcdImage:
  repository: k8s.gcr.io/etcd-amd64
  tag: 2.3.7
  pullPolicy: IfNotPresent

debug: false

# Enable the creation of a shm volume
shmVolume:
  enabled: false

persistence:
  enabled: true
  ## If defined, storageClassName: <storageClass>
  ## If set to "-", storageClassName: "", which disables dynamic provisioning
  ## If undefined (the default) or set to null, no storageClassName spec is
  ##   set, choosing the default provisioner.  (gp2 on AWS, standard on
  ##   GKE, AWS & OpenStack)
  ##
  storageClassName: ""
  accessModes:
    - ReadWriteOnce
  size: 10Gi

rbac:
  create: true

serviceAccount:
  create: true
  # The name of the ServiceAccount to use. If not set and create is true, a name is generated using the fullname template
  name:

superuserSecret:
  name: ""
  usernameKey: pg_su_username
  passwordKey: pg_su_password

replicationSecret:
  name: ""
  usernameKey: pg_repl_username
  passwordKey: pg_repl_password

superuserPasswordFile:

superuserUsername: "stolon"
## password for the superuser (REQUIRED if superuserSecret and superuserPasswordFile are not set)
superuserPassword:

replicationPasswordFile:

replicationUsername: "repluser"
## password for the replication user (REQUIRED if replicationSecret and replicationPasswordFile are not set)
replicationPassword:

## backend could be one of the following: consul, etcdv2, etcdv3 or kubernetes
store:
  backend: kubernetes
#  endpoints: "http://stolon-consul:8500"
  kubeResourceKind: configmap

pgParameters: {}
  # max_connections: "1000"

ports:
  stolon:
    containerPort: 5432
  metrics:
    containerPort: 8080

serviceMonitor:
  # When set to true then use a ServiceMonitor to collect metrics
  enabled: false
  # Custom labels to use in the ServiceMonitor to be matched with a specific Prometheus
  labels: {}
  # Set the namespace the ServiceMonitor should be deployed to
  # namespace: default
  # Set how frequently Prometheus should scrape
  # interval: 30s
  # Set timeout for scrape
  # scrapeTimeout: 10s

job:
  autoCreateCluster: true
  autoUpdateClusterSpec: true
  annotations: {}

clusterSpec: {}
  # sleepInterval: 1s
  # maxStandbys: 5

## Enable support ssl into postgres, you must specify the certs.
## ref: https://www.postgresql.org/docs/10/ssl-tcp.html
##
tls:
  enabled: false
  rootCa: |-
  serverCrt: |-
  serverKey: |-

  # existingSecret: name-of-existing-secret-to-postgresql

keeper:
  uid_prefix: "keeper"
  replicaCount: 2
  annotations: {}
  resources: {}
  priorityClassName: ""
  fsGroup: ""
  service:
    type: ClusterIP
    annotations: {}
    ports:
      keeper:
        port: 5432
        targetPort: 5432
        protocol: TCP
  nodeSelector: {}
  affinity: {}
  tolerations: []
  volumes: []
  volumeMounts: []
  hooks:
    failKeeper:
      enabled: false
  podDisruptionBudget:
    # minAvailable: 1
    # maxUnavailable: 1
  extraEnv: []
  #  - name: STKEEPER_LOG_LEVEL
  #    value: "info"

proxy:
  replicaCount: 2
  annotations: {}
  resources: {}
  priorityClassName: ""
  service:
    type: ClusterIP
#    loadBalancerIP: ""
    annotations: {}
    ports:
      proxy:
        port: 5432
        targetPort: 5432
        protocol: TCP
  nodeSelector: {}
  affinity: {}
  tolerations: []
  podDisruptionBudget:
    # minAvailable: 1
    # maxUnavailable: 1
  extraEnv: []
  #  - name: STPROXY_LOG_LEVEL
  #    value: "info"
  #  - name: STPROXY_TCP_KEEPALIVE_COUNT
  #    value: "0"
  #  - name: STPROXY_TCP_KEEPALIVE_IDLE
  #    value: "0"
  #  - name: STPROXY_TCP_KEEPALIVE_INTERVAL
  #    value: "0"

sentinel:
  replicaCount: 2
  annotations: {}
  resources: {}
  priorityClassName: ""
  nodeSelector: {}
  affinity: {}
  tolerations: []
  podDisruptionBudget:
    # minAvailable: 1
    # maxUnavailable: 1
  extraEnv: []
  #  - name: STSENTINEL_LOG_LEVEL
  #    value: "info"

## initdb scripts
## Specify dictionary of scripts to be run at first boot, the entry point script is create_script.sh
## i.e. you can use pgsql to run sql script on the cluster.
##
# initdbScripts:
#   create_script.sh: |
#      #!/bin/sh
#      echo "Do something."

## nodePostStart scripts
## Specify dictionary of scripts to be run at first boot, the entry point script is postStartScript.sh
## i.e. you can create tablespace directory here.
##
# nodePostStartScript:
#  postStartScript.sh: |
#    #!/bin/bash
#     echo "Do something."
