# helm_charts_mongodb-statefulset.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
  labels:
    app: {{ template "mongodb-replicaset.name" . }}
    chart: {{ template "mongodb-replicaset.chart" . }}
    heritage: {{ .Release.Service }}
    release: {{ .Release.Name }}
{{- if .Values.extraLabels }}
{{ toYaml .Values.extraLabels | indent 4 }}
{{- end }}
{{- if .Values.statefulSetAnnotations }}
  annotations:
{{ toYaml .Values.statefulSetAnnotations | indent 4 }}
{{- end }}
  name: {{ template "mongodb-replicaset.fullname" . }}
  namespace: {{ template "mongodb-replicaset.namespace" . }}
spec:
{{- if .Values.updateStrategy }}
  updateStrategy:
{{ toYaml .Values.updateStrategy | indent 4 }}
{{- end }}
  selector:
    matchLabels:
      app: {{ template "mongodb-replicaset.name" . }}
      release: {{ .Release.Name }}
  serviceName: {{ template "mongodb-replicaset.fullname" . }}
  replicas: {{ .Values.replicas }}
  template:
    metadata:
      labels:
        app: {{ template "mongodb-replicaset.name" . }}
        release: {{ .Release.Name }}
{{- if .Values.extraLabels }}
{{ toYaml .Values.extraLabels | indent 8 }}
{{- end }}
      annotations:
        checksum/config: {{ include (print $.Template.BasePath "/mongodb-mongodb-configmap.yaml") . | sha256sum }}
      {{- if and (.Values.metrics.prometheusServiceDiscovery) (.Values.metrics.enabled) }}
        prometheus.io/scrape: "true"
        prometheus.io/port: {{ .Values.metrics.port | quote }}
        prometheus.io/path: {{ .Values.metrics.path | quote }}
      {{- end }}
      {{- if .Values.podAnnotations }}
{{ toYaml .Values.podAnnotations | indent 8 }}
      {{- end }}
    spec:
    {{- if .Values.priorityClassName }}
      priorityClassName: {{ .Values.priorityClassName }}
    {{- end }}
    {{- if .Values.imagePullSecrets }}
      imagePullSecrets:
      {{- range .Values.imagePullSecrets }}
        - name: {{ . }}
      {{- end}}
    {{- end }}
    {{- if .Values.securityContext.enabled }}
      securityContext:
        runAsUser: {{ .Values.securityContext.runAsUser }}
        fsGroup: {{ .Values.securityContext.fsGroup }}
        runAsNonRoot: {{ .Values.securityContext.runAsNonRoot }}
    {{- end }}
      terminationGracePeriodSeconds: {{ .Values.terminationGracePeriodSeconds }}
      {{- if .Values.serviceAccount }}
      serviceAccountName: {{ .Values.serviceAccount }}
      {{- end }}
      initContainers:
        - name: copy-config
          image: "{{ .Values.copyConfigImage.repository }}:{{ .Values.copyConfigImage.tag }}"
          imagePullPolicy: {{ .Values.copyConfigImage.pullPolicy | quote }}
          command:
            - "sh"
          args:
            - "-c"
            - |
              set -e
              set -x

              cp /configdb-readonly/mongod.conf /data/configdb/mongod.conf

            {{- if .Values.tls.enabled }}
              cp /ca-readonly/tls.key /data/configdb/tls.key
              cp /ca-readonly/tls.crt /data/configdb/tls.crt
            {{- end }}

            {{- if .Values.auth.enabled }}
              cp /keydir-readonly/key.txt /data/configdb/key.txt
              chmod 600 /data/configdb/key.txt
            {{- end }}
          volumeMounts:
            - name: workdir
              mountPath: /work-dir
            - name: config
              mountPath: /configdb-readonly
            - name: configdir
              mountPath: /data/configdb
          {{- if .Values.tls.enabled }}
            - name: ca
              mountPath: /ca-readonly
          {{- end }}
          {{- if .Values.auth.enabled }}
            - name: keydir
              mountPath: /keydir-readonly
          {{- end }}
          resources:
{{ toYaml .Values.init.resources | indent 12 }}
        - name: install
          image: "{{ .Values.installImage.repository }}:{{ .Values.installImage.tag }}"
          args:
            - --work-dir=/work-dir
          imagePullPolicy: "{{ .Values.installImage.pullPolicy }}"
          volumeMounts:
            - name: workdir
              mountPath: /work-dir
          resources:
{{ toYaml .Values.init.resources | indent 12 }}
        - name: bootstrap
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
          command:
            - /work-dir/peer-finder
          args:
            - -on-start=/init/on-start.sh
            - "-service={{ template "mongodb-replicaset.fullname" . }}"
          imagePullPolicy: "{{ .Values.image.pullPolicy }}"
          env:
            - name: POD_NAMESPACE
              valueFrom:
                fieldRef:
                  apiVersion: v1
                  fieldPath: metadata.namespace
            - name: REPLICA_SET
              value: {{ .Values.replicaSetName }}
            - name: TIMEOUT
              value: "{{ .Values.init.timeout }}"
            - name: SKIP_INIT
              value: "{{ .Values.skipInitialization }}"
            - name: TLS_MODE
              value: {{ .Values.tls.mode }}
          {{- if .Values.auth.enabled }}
            - name: AUTH
              value: "true"
            - name: ADMIN_USER
              valueFrom:
                secretKeyRef:
                  name: "{{ template "mongodb-replicaset.adminSecret" . }}"
                  key: user
            - name: ADMIN_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: "{{ template "mongodb-replicaset.adminSecret" . }}"
                  key: password
          {{- if .Values.metrics.enabled }}
            - name: METRICS
              value: "true"
            - name: METRICS_USER
              valueFrom:
                secretKeyRef:
                  name: "{{ template "mongodb-replicaset.metricsSecret" . }}"
                  key: user
            - name: METRICS_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: "{{ template "mongodb-replicaset.metricsSecret" . }}"
                  key: password
          {{- end }}
          {{- end }}
          volumeMounts:
            - name: workdir
              mountPath: /work-dir
            - name: init
              mountPath: /init
            - name: configdir
              mountPath: /data/configdb
            - name: datadir
              mountPath: /data/db
          resources:
{{ toYaml .Values.init.resources | indent 12 }}
      containers:
        - name: {{ template "mongodb-replicaset.name" . }}
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
          imagePullPolicy: "{{ .Values.image.pullPolicy }}"
        {{- if .Values.extraVars }}
          env:
{{ toYaml .Values.extraVars | indent 12 }}
        {{- end }}
          ports:
            - name: mongodb
              containerPort: 27017
          resources:
{{ toYaml .Values.resources | indent 12 }}
          command:
            - mongod
          args:
            - --config=/data/configdb/mongod.conf
            - --dbpath=/data/db
            - --replSet={{ .Values.replicaSetName }}
            - --port=27017
            - --bind_ip=0.0.0.0
          {{- if .Values.auth.enabled }}
            - --auth
            - --keyFile=/data/configdb/key.txt
          {{- end }}
          {{- if .Values.tls.enabled }}
            - --sslMode={{ .Values.tls.mode }}
            - --sslCAFile=/data/configdb/tls.crt
            - --sslPEMKeyFile=/work-dir/mongo.pem
          {{- end }}
          livenessProbe:
            exec:
              command:
                - mongo
              {{- if .Values.tls.enabled }}
                - --ssl
                - --sslCAFile=/data/configdb/tls.crt
                - --sslPEMKeyFile=/work-dir/mongo.pem
              {{- end }}
                - --eval
                - "db.adminCommand('ping')"
            initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds }}
            timeoutSeconds: {{ .Values.livenessProbe.timeoutSeconds }}
            failureThreshold: {{ .Values.livenessProbe.failureThreshold }}
            periodSeconds: {{ .Values.livenessProbe.periodSeconds }}
            successThreshold: {{ .Values.livenessProbe.successThreshold }}
{{- if semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion }}
          startupProbe:
            exec:
              command:
                - mongo
              {{- if .Values.tls.enabled }}
                - --ssl
                - --sslCAFile=/data/configdb/tls.crt
                - --sslPEMKeyFile=/work-dir/mongo.pem
              {{- end }}
                - --eval
                - "db.adminCommand('ping')"
            initialDelaySeconds: {{ .Values.startupProbe.initialDelaySeconds }}
            timeoutSeconds: {{ .Values.startupProbe.timeoutSeconds }}
            failureThreshold: {{ .Values.startupProbe.failureThreshold }}
            periodSeconds: {{ .Values.startupProbe.periodSeconds }}
            successThreshold: {{ .Values.startupProbe.successThreshold }}
{{- end }}
          readinessProbe:
            exec:
              command:
                - mongo
              {{- if .Values.tls.enabled }}
                - --ssl
                - --sslCAFile=/data/configdb/tls.crt
                - --sslPEMKeyFile=/work-dir/mongo.pem
              {{- end }}
                - --eval
                - "db.adminCommand('ping')"
            initialDelaySeconds: {{ .Values.readinessProbe.initialDelaySeconds }}
            timeoutSeconds: {{ .Values.readinessProbe.timeoutSeconds }}
            failureThreshold: {{ .Values.readinessProbe.failureThreshold }}
            periodSeconds: {{ .Values.readinessProbe.periodSeconds }}
            successThreshold: {{ .Values.readinessProbe.successThreshold }}
          volumeMounts:
            - name: datadir
              mountPath: /data/db
            - name: configdir
              mountPath: /data/configdb
            - name: workdir
              mountPath: /work-dir
{{ if .Values.metrics.enabled }}
        - name: metrics
          image: "{{ .Values.metrics.image.repository }}:{{ .Values.metrics.image.tag }}"
          imagePullPolicy: {{ .Values.metrics.image.pullPolicy | quote }}
          command:
            - sh
            - -c
            - >-
              /bin/mongodb_exporter
              --mongodb.uri {{ template "mongodb-replicaset.connection-string" . }}
              --web.telemetry-path={{ .Values.metrics.path }}
              --web.listen-address=:{{ .Values.metrics.port }}
          volumeMounts:
          {{- if and (.Values.tls.enabled) }}
            - name: ca
              mountPath: /ca
              readOnly: true
          {{- end }}
            - name: workdir
              mountPath: /work-dir
              readOnly: true
          env:
          {{- if .Values.auth.enabled }}
            - name: METRICS_USER
              valueFrom:
                secretKeyRef:
                  name: "{{ template "mongodb-replicaset.metricsSecret" . }}"
                  key: user
            - name: METRICS_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: "{{ template "mongodb-replicaset.metricsSecret" . }}"
                  key: password
          {{- end }}
          ports:
            - name: metrics
              containerPort: {{ .Values.metrics.port  }}
          resources:
{{ toYaml .Values.metrics.resources | indent 12 }}
          {{- if .Values.metrics.securityContext.enabled }}
          securityContext:
            runAsUser: {{ .Values.metrics.securityContext.runAsUser }}
          {{- end }}
          livenessProbe:
            exec:
              command:
                - sh
                - -c
                - >-
                  /bin/mongodb_exporter
                  --mongodb.uri {{ template "mongodb-replicaset.connection-string" . }}
                  --test
            initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds }}
            periodSeconds: {{ .Values.livenessProbe.periodSeconds }}
{{- if semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion }}
          startupProbe:
            exec:
              command:
                - sh
                - -c
                - >-
                  /bin/mongodb_exporter
                  --mongodb.uri {{ template "mongodb-replicaset.connection-string" . }}
                  --test
            initialDelaySeconds: {{ .Values.startupProbe.initialDelaySeconds }}
            timeoutSeconds: {{ .Values.startupProbe.timeoutSeconds }}
            failureThreshold: {{ .Values.startupProbe.failureThreshold }}
            periodSeconds: {{ .Values.startupProbe.periodSeconds }}
            successThreshold: {{ .Values.startupProbe.successThreshold }}
{{- end }}
{{ end }}
        {{- if .Values.extraContainers }}
        {{- tpl (toYaml .Values.extraContainers) . | nindent 8 }}
        {{- end }}
   {{- with .Values.nodeSelector }}
      nodeSelector:
{{ toYaml . | indent 8 }}
    {{- end }}
    {{- with .Values.affinity }}
      affinity:
{{ toYaml . | indent 8 }}
    {{- end }}
    {{- with .Values.tolerations }}
      tolerations:
{{ toYaml . | indent 8 }}
    {{- end }}
      volumes:
        - name: config
          configMap:
            name: {{ template "mongodb-replicaset.fullname" . }}-mongodb
        - name: init
          configMap:
            defaultMode: 0755
            name: {{ template "mongodb-replicaset.fullname" . }}-init
        {{- if .Values.tls.enabled }}
        - name: ca
          secret:
            defaultMode: 0400
            secretName: {{ template "mongodb-replicaset.fullname" . }}-ca
        {{- end }}
        {{- if .Values.auth.enabled }}
        - name: keydir
          secret:
            defaultMode: 0400
            secretName: {{ template "mongodb-replicaset.keySecret" . }}
        {{- end }}
        - name: workdir
          emptyDir: {}
        - name: configdir
          emptyDir: {}
{{- if .Values.extraVolumes }}
{{- tpl (toYaml .Values.extraVolumes) . | nindent 8 }}
{{- end }}
{{- if .Values.persistentVolume.enabled }}
  volumeClaimTemplates:
    - metadata:
        name: datadir
        annotations:
        {{- range $key, $value := .Values.persistentVolume.annotations }}
          {{ $key }}: "{{ $value }}"
        {{- end }}
      spec:
        accessModes:
        {{- range .Values.persistentVolume.accessModes }}
          - {{ . | quote }}
        {{- end }}
        resources:
          requests:
            storage: {{ .Values.persistentVolume.size | quote }}
      {{- if .Values.persistentVolume.storageClass }}
      {{- if (eq "-" .Values.persistentVolume.storageClass) }}
        storageClassName: ""
      {{- else }}
        storageClassName: "{{ .Values.persistentVolume.storageClass }}"
      {{- end }}
      {{- end }}
{{- else }}
        - name: datadir
          emptyDir: {}
{{- end }}