apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: {{ include "keydb.fullname" . }}
  {{- if .Values.annotations }}
  annotations:
    {{- toYaml .Values.annotations | nindent 4 }}
  {{- end }}
  labels:
    {{- include "keydb.labels" . | nindent 4 }}
spec:
  replicas: {{ .Values.nodes }}
  serviceName: {{ include "keydb.fullname" . }}-headless
  selector:
    matchLabels:
      {{- include "keydb.selectorLabels" . | nindent 6 }}
  template:
    metadata:
      annotations:
        checksum/secret-utils: {{ include (print $.Template.BasePath "/secret-utils.yaml") . | sha256sum }}
        {{- if .Values.exporter.enabled }}
        prometheus.io/scrape: "true"
        prometheus.io/path: "{{ .Values.exporter.scrapePath }}"
        prometheus.io/port: "{{ .Values.exporter.port }}"
        {{- end }}
        {{- if .Values.podAnnotations }}
        {{- toYaml .Values.podAnnotations | nindent 8 }}
        {{- end }}
      labels:
        {{- include "keydb.labels" . | nindent 8 }}
    spec:
      affinity:
        {{- include "common.tplvalues.render" (dict "value" .Values.affinity "context" $) | nindent 8 }}
      {{- if .Values.extraInitContainers }}
      initContainers:
      {{- toYaml .Values.extraInitContainers | nindent 6 }}
      {{- end }}
      containers:
      - name: keydb
        {{- if .Values.image }}
        image: {{ .Values.image }}
        {{- else }}
        image: {{ .Values.imageRepository }}:{{ .Values.imageTag }}
        {{- end }}
        imagePullPolicy: {{ .Values.imagePullPolicy }}
        command:
        - /utils/server.sh
        env:
        - name: REDIS_PORT
          value: {{ .Values.internalPort | quote }}
        {{- if .Values.existingSecret }}
        - name: REDIS_PASSWORD
          valueFrom:
            secretKeyRef:
              name: {{ .Values.existingSecret }}
              key: {{ .Values.existingSecretPasswordKey }}
        {{- else if .Values.password }}
        - name: REDIS_PASSWORD
          value: "{{ .Values.password }}"
        {{- end }}
        ports:
        - name: {{ .Values.internalPortName }}
          containerPort: {{ .Values.internalPort | int }}
          protocol: TCP
        {{- if .Values.livenessProbe.enabled }}
        livenessProbe:
        {{- if .Values.livenessProbe.custom }}
          {{- toYaml .Values.livenessProbe.custom | nindent 10 }}
        {{- else }}
          initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds }}
          periodSeconds: {{ .Values.livenessProbe.periodSeconds }}
          # One second longer than command timeout should prevent generation of zombie processes.
          timeoutSeconds: {{ add1 .Values.livenessProbe.timeoutSeconds }}
          successThreshold: {{ .Values.livenessProbe.successThreshold }}
          failureThreshold: {{ .Values.livenessProbe.failureThreshold }}
          exec:
            command:
              - sh
              - -c
              - /health/ping_liveness_local.sh {{ .Values.livenessProbe.timeoutSeconds }}
        {{- end }}
        {{- end }}
        {{- if .Values.readinessProbe.enabled }}
        readinessProbe:
        {{- if .Values.readinessProbe.custom }}
          {{- toYaml .Values.readinessProbe.custom | nindent 10 }}
        {{- else }}
          initialDelaySeconds: {{ .Values.readinessProbe.initialDelaySeconds }}
          periodSeconds: {{ .Values.readinessProbe.periodSeconds }}
          # One second longer than command timeout should prevent generation of zombie processes.
          timeoutSeconds: {{ add1 .Values.readinessProbe.timeoutSeconds }}
          successThreshold: {{ .Values.readinessProbe.successThreshold }}
          failureThreshold: {{ .Values.readinessProbe.failureThreshold }}
          exec:
            command:
              - sh
              - -c
              - /health/ping_readiness_local.sh {{ .Values.readinessProbe.timeoutSeconds }}
        {{- end }}
        {{- end }}
        {{- if .Values.startupProbe.enabled }}
        startupProbe:
        {{- if .Values.startupProbe.custom }}
          {{- toYaml .Values.startupProbe.custom | nindent 10 }}
        {{- else }}
          periodSeconds: {{ .Values.startupProbe.periodSeconds }}
          # One second longer than command timeout should prevent generation of zombie processes.
          timeoutSeconds: {{ add1 .Values.startupProbe.timeoutSeconds }}
          failureThreshold: {{ .Values.startupProbe.failureThreshold }}
          exec:
            command:
              - sh
              - -c
              - /health/ping_readiness_local.sh {{ .Values.startupProbe.timeoutSeconds }}
        {{- end }}
        {{- end }}
        {{- if .Values.lifecycle }}
        lifecycle:
          {{- toYaml .Values.lifecycle | nindent 10 }}
        {{- end }}
        resources:
          {{- toYaml .Values.resources | nindent 10 }}
        securityContext:
          {{- toYaml .Values.keydb.securityContext | nindent 10 }}
        volumeMounts:
        - name: health
          mountPath: /health
        - name: keydb-data
          mountPath: /data
        - name: utils
          mountPath: /utils
          readOnly: true
      {{- if .Values.exporter.enabled }}
      - name: redis-exporter
        {{- if .Values.exporter.image }}
        image: {{ .Values.exporter.image }}
        {{- else }}
        image: {{ .Values.exporter.imageRepository }}:{{ .Values.exporter.imageTag }}
        {{- end }}
        imagePullPolicy: {{ .Values.exporter.pullPolicy }}
        args:
        {{- range $item := .Values.exporter.extraArgs }}
        {{- range $key, $value := $item }}
        {{- if kindIs "invalid" $value }}
        - --{{ $key }}
        {{- else if kindIs "slice" $value }}
        - --{{ $key }}
        {{- range $value }}
        - {{ . | quote }}
        {{- end }}
        {{- else }}
        - --{{ $key }}
        - {{ $value | quote }}
        {{- end }}
        {{- end }}
        {{- end }}
        env:
        - name: REDIS_EXPORTER_WEB_LISTEN_ADDRESS
          value: "0.0.0.0:{{ .Values.exporter.port }}"
        - name: REDIS_EXPORTER_WEB_TELEMETRY_PATH
          value: {{ .Values.exporter.scrapePath | quote }}
        - name: REDIS_ADDR
          value: "redis://localhost:{{ .Values.internalPort }}"
        {{- if .Values.existingSecret }}
        - name: REDIS_PASSWORD
          valueFrom:
            secretKeyRef:
              name: {{ .Values.existingSecret }}
              key: {{ .Values.existingSecretPasswordKey }}
        {{- else if .Values.password }}
        - name: REDIS_PASSWORD
          value: "{{ .Values.password }}"
        {{- end }}
        {{- if .Values.exporter.livenessProbe }}
        livenessProbe:
          {{- toYaml .Values.exporter.livenessProbe | nindent 10 }}
        {{- end }}
        {{- if .Values.exporter.readinessProbe }}
        readinessProbe:
          {{- toYaml .Values.exporter.readinessProbe | nindent 10 }}
        {{- end }}
        {{- if .Values.exporter.startupProbe }}
        startupProbe:
          {{- toYaml .Values.exporter.startupProbe | nindent 10 }}
        {{- end }}
        resources:
          {{- toYaml .Values.exporter.resources | nindent 10 }}
        securityContext:
          {{- toYaml .Values.exporter.securityContext | nindent 10 }}
        ports:
        - name: {{ .Values.exporter.portName | quote }}
          containerPort: {{ .Values.exporter.port }}
          protocol: TCP
      {{- end }}
      {{- if .Values.scripts.enabled }}
      - name: scripts
        {{- if .Values.image }}
        image: {{ .Values.image }}
        {{- else }}
        image: {{ .Values.imageRepository }}:{{ .Values.imageTag }}
        {{- end }}
        imagePullPolicy: {{ .Values.imagePullPolicy }}
        command:
        - /health/scripts_local.sh
        env:
        - name: REDIS_PORT
          value: {{ .Values.internalPort | quote }}
        {{- if .Values.existingSecret }}
        - name: REDIS_PASSWORD
          valueFrom:
            secretKeyRef:
              name: {{ .Values.existingSecret }}
              key: {{ .Values.existingSecretPasswordKey }}
        {{- else if .Values.password }}
        - name: REDIS_PASSWORD
          value: "{{ .Values.password }}"
        {{- end }}
        resources:
          {{- toYaml .Values.scripts.resources | nindent 10 }}
        securityContext:
          {{- toYaml .Values.scripts.securityContext | nindent 10 }}
        volumeMounts:
        - name: health
          mountPath: /health
        - name: keydb-data
          mountPath: /data
      {{- end }}
      {{- if .Values.extraContainers }}
      {{- toYaml .Values.extraContainers | nindent 6 }}
      {{- end }}
      imagePullSecrets:
        {{- toYaml .Values.imagePullSecrets | nindent 8 }}
      securityContext:
        {{- toYaml .Values.securityContext | nindent 8 }}
      {{- if .Values.serviceAccount.enabled }}
      serviceAccountName: {{ include "keydb.serviceAccountName" . | quote }}
      {{- end }}
      {{- if .Values.tolerations }}
      tolerations:
        {{- toYaml .Values.tolerations | nindent 8 }}
      {{- end }}
      {{- if .Values.nodeSelector }}
      nodeSelector:
        {{- toYaml .Values.nodeSelector | nindent 8 }}
      {{- end }}
      {{- if .Values.topologySpreadConstraints }}
      topologySpreadConstraints:
        {{- range .Values.topologySpreadConstraints }}
        - labelSelector:
            matchLabels:
              {{- include "keydb.selectorLabels" $ | nindent 14 }}
          topologyKey: {{ default "topology.kubernetes.io/zone" .topologyKey }}
          maxSkew: {{ .maxSkew }}
          {{- if .minDomains }}
          minDomains: {{ .minDomains }}
          {{- end }}
          whenUnsatisfiable: {{ default "DoNotSchedule" .whenUnsatisfiable }}
          {{- if .nodeAffinityPolicy }}
          nodeAffinityPolicy: {{ .nodeAffinityPolicy }}
          {{- end }}
          {{- if .nodeTaintsPolicy }}
          nodeTaintsPolicy: {{ .nodeTaintsPolicy }}
          {{- end }}
        {{- end }}
      {{- end }}
      volumes:
      - name: health
        configMap:
          name: {{ include "keydb.fullname" . }}-health
          defaultMode: 0755
      - name: utils
        secret:
          secretName: {{ include "keydb.fullname" . }}-utils
          defaultMode: 0755
          items:
          - key: server.sh
            path: server.sh
      {{- if not .Values.persistentVolume.enabled }}
      - name: keydb-data
        emptyDir: {{- toYaml .Values.persistentVolume.emptyDir | nindent 10 }}
      {{- end }}
      {{- if .Values.extraVolumes }}
      {{- toYaml .Values.extraVolumes | nindent 6 }}
      {{- end }}
  {{- if .Values.persistentVolume.enabled }}
  volumeClaimTemplates:
  - metadata:
      name: keydb-data
      annotations:
      {{- if .Values.persistentVolume.annotations }}
        {{- toYaml .Values.persistentVolume.annotations | nindent 8 }}
      {{- end }}
      labels:
    spec:
      accessModes:
        {{- toYaml .Values.persistentVolume.accessModes | nindent 8 }}
      resources:
        requests:
          storage: {{ .Values.persistentVolume.size }}
      {{- if .Values.persistentVolume.storageClass }}
      {{- if (eq "-" .Values.persistentVolume.storageClass) }}
      storageClassName: ""
      {{ else }}
      storageClassName: {{ .Values.persistentVolume.storageClass }}
      {{- end }}
      {{- end }}
      {{- if .Values.persistentVolume.selector }}
      selector:
        {{- toYaml .Values.persistentVolume.selector | nindent 8 }}
      {{- end }}
  {{- end }}
