{{- $auth := mustMergeOverwrite (mustDeepCopy .Values) .Values.auth -}}
{{- $replicated := gt (int $auth.highAvailability.replicaCount) 1 -}}
{{- $projectedServiceAccountToken := semverCompare ">=1.20.0-0" .Capabilities.KubeVersion.Version }}
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ .Release.Name }}-auth
  namespace: {{ .Release.Namespace }}
  labels:
    {{- include "teleport-cluster.auth.labels" . | nindent 4 }}
    app: {{ .Release.Name }}
{{- if $auth.annotations.deployment }}
  annotations: {{- toYaml $auth.annotations.deployment | nindent 4 }}
{{- end }}
spec:
  replicas: {{ $auth.highAvailability.replicaCount }}
{{- if and $replicated $auth.highAvailability.minReadySeconds }}
  minReadySeconds: {{ $auth.highAvailability.minReadySeconds }}
{{- end }}
  strategy:
{{- if $replicated }}
    # some backends support a maximum amount of auth pods (e.g. DynamoDB),
    # we don't want to exceed this during a rollout.
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 0
      maxUnavailable: 1
{{- else }}
    # using a single replica can be because of a non-replicable storage or when applying upgrade migrations.
    # In those cases, we don't want a rolling update.
    type: Recreate
{{- end }}
  selector:
    matchLabels: {{- include "teleport-cluster.auth.selectorLabels" . | nindent 6 }}
  template:
    metadata:
      annotations:
        # ConfigMap checksum, to recreate the pod on config changes.
        checksum/config: {{ include (print $.Template.BasePath "/auth/config.yaml") . | sha256sum }}
{{- if $auth.annotations.pod }}
  {{- toYaml $auth.annotations.pod | nindent 8 }}
{{- end }}
      labels:
        {{- include "teleport-cluster.auth.labels" . | nindent 8 }}
        app: {{ .Release.Name }}
{{- if eq $auth.chartMode "azure"}}
        azure.workload.identity/use: "true"
{{- end }}
    spec:
{{- if $auth.nodeSelector }}
      nodeSelector: {{- toYaml $auth.nodeSelector | nindent 8 }}
{{- end }}
      affinity:
{{- if $auth.affinity }}
  {{- if $auth.highAvailability.requireAntiAffinity }}
    {{- fail "Cannot use highAvailability.requireAntiAffinity when affinity is also set in chart values - unset one or the other" }}
  {{- end }}
  {{- toYaml $auth.affinity | nindent 8 }}
{{- else }}
        podAntiAffinity:
  {{- if $auth.highAvailability.requireAntiAffinity }}
          requiredDuringSchedulingIgnoredDuringExecution:
            - labelSelector:
                matchExpressions:
                  - key: app.kubernetes.io/instance
                    operator: In
                    values:
                      - {{ .Release.Name }}
                  - key: app.kubernetes.io/component
                    operator: In
                    values:
                      - auth
              topologyKey: "kubernetes.io/hostname"
  {{- else if $replicated }}
          preferredDuringSchedulingIgnoredDuringExecution:
            - weight: 50
              podAffinityTerm:
                labelSelector:
                  matchExpressions:
                    - key: app.kubernetes.io/instance
                      operator: In
                      values:
                        - {{ .Release.Name }}
                    - key: app.kubernetes.io/component
                      operator: In
                      values:
                        - auth
                topologyKey: "kubernetes.io/hostname"
  {{- end }}
{{- end }}
{{- if $auth.tolerations }}
      tolerations: {{- toYaml $auth.tolerations | nindent 6 }}
{{- end }}
{{- if $auth.imagePullSecrets }}
      imagePullSecrets:
  {{- toYaml $auth.imagePullSecrets | nindent 6 }}
{{- end }}
{{- if $auth.initContainers }}
      initContainers:
  {{- range $initContainer := $auth.initContainers }}
    {{- if and (not $initContainer.resources) $auth.resources }}
      {{- $_ := set $initContainer "resources" $auth.resources }}
    {{- end }}
    {{- list $initContainer | toYaml | nindent 8 }}
    {{- /* Note: this will break if the user sets volumeMounts to its initContainer */}}
          volumeMounts:
    {{- if $auth.enterprise }}
          - mountPath: /var/lib/license
            name: "license"
            readOnly: true
    {{- end }}
    {{- if and ($auth.gcp.credentialSecretName) (eq $auth.chartMode "gcp") }}
          - mountPath: /etc/teleport-secrets
            name: "gcp-credentials"
            readOnly: true
    {{- end }}
          - mountPath: /etc/teleport
            name: "config"
            readOnly: true
          - mountPath: /var/lib/teleport
            name: "data"
    {{- if $projectedServiceAccountToken }}
          - mountPath: /var/run/secrets/kubernetes.io/serviceaccount
            name: auth-serviceaccount-token
            readOnly: true
    {{- end }}
    {{- if $auth.extraVolumeMounts }}
      {{- toYaml $auth.extraVolumeMounts | nindent 10 }}
    {{- end }}
  {{- end }}
{{- end }}
      containers:
      - name: "teleport"
        image: '{{ if $auth.enterprise }}{{ $auth.enterpriseImage }}{{ else }}{{ $auth.image }}{{ end }}:{{ include "teleport-cluster.version" . }}'
        imagePullPolicy: {{ $auth.imagePullPolicy }}
        {{- if or $auth.extraEnv $auth.tls.existingCASecretName }}
        env:
        {{- if (gt (len $auth.extraEnv) 0) }}
          {{- toYaml $auth.extraEnv | nindent 8 }}
        {{- end }}
        {{- if $auth.tls.existingCASecretName }}
        - name: SSL_CERT_FILE
          value: /etc/teleport-tls-ca/ca.pem
        {{- end }}
        {{- end }}
        args:
        - "--diag-addr=0.0.0.0:3000"
        {{- if $auth.insecureSkipProxyTLSVerify }}
        - "--insecure"
        {{- end }}
        {{- if $auth.createProxyToken }}
        - "--apply-on-startup=/etc/teleport/apply-on-startup.yaml"
        {{- end }}
        {{- if $auth.extraArgs }}
          {{- toYaml $auth.extraArgs | nindent 8 }}
        {{- end }}
        ports:
        - name: diag
          containerPort: 3000
          protocol: TCP
        - name: auth
          containerPort: 3025
          protocol: TCP
        - name: kube
          containerPort: 3026
          protocol: TCP
        livenessProbe:
          httpGet:
            path: /healthz
            port: diag
          initialDelaySeconds: 5 # wait 5s for agent to start
          periodSeconds: 5 # poll health every 5s
          failureThreshold: 6 # consider agent unhealthy after 30s (6 * 5s)
          timeoutSeconds: {{ .Values.probeTimeoutSeconds }}
        readinessProbe:
          httpGet:
            path: /readyz
            port: diag
          initialDelaySeconds: 5 # wait 5s for agent to register
          periodSeconds: 5 # poll health every 5s
          failureThreshold: 12 # consider agent unhealthy after 60s (12 * 5s)
          timeoutSeconds: {{ .Values.probeTimeoutSeconds }}
        lifecycle:
          # waiting during preStop ensures no new request will hit the Terminating pod
          # on clusters using kube-proxy (kube-proxy syncs the node iptables rules every 30s)
          preStop:
            exec:
              command:
                - teleport
                - wait
                - duration
                - 30s
{{- if $auth.postStart.command }}
          postStart:
            exec:
              command: {{ toYaml $auth.postStart.command | nindent 14 }}
{{- end }}
{{- if $auth.resources }}
        resources:
  {{- toYaml $auth.resources | nindent 10 }}
{{- end }}
{{- if $auth.securityContext }}
        securityContext: {{- toYaml $auth.securityContext | nindent 10 }}
{{- end }}
        volumeMounts:
{{- if $auth.enterprise }}
        - mountPath: /var/lib/license
          name: "license"
          readOnly: true
{{- end }}
{{- if and ($auth.gcp.credentialSecretName) (eq $auth.chartMode "gcp") }}
        - mountPath: /etc/teleport-secrets
          name: "gcp-credentials"
          readOnly: true
{{- end }}
{{- if $auth.tls.existingCASecretName }}
        - mountPath: /etc/teleport-tls-ca
          name: "teleport-tls-ca"
          readOnly: true
{{- end }}
        - mountPath: /etc/teleport
          name: "config"
          readOnly: true
        - mountPath: /var/lib/teleport
          name: "data"
{{- if $projectedServiceAccountToken }}
        - mountPath: /var/run/secrets/kubernetes.io/serviceaccount
          name: auth-serviceaccount-token
          readOnly: true
{{- end }}
{{- if $auth.extraVolumeMounts }}
  {{- toYaml $auth.extraVolumeMounts | nindent 8 }}
{{- end }}
{{- /* Operator uses '.Values' instead of '$auth' as it will likely be moved out of the auth pods */}}
{{- if .Values.operator.enabled }}
      - name: "operator"
        image: '{{ .Values.operator.image }}:{{ include "teleport-cluster.version" . }}'
        imagePullPolicy: {{ .Values.imagePullPolicy }}
        livenessProbe:
          httpGet:
            path: /healthz
            port: 8081
          initialDelaySeconds: 15
          periodSeconds: 20
        readinessProbe:
          httpGet:
            path: /readyz
            port: 8081
          initialDelaySeconds: 5
          periodSeconds: 10
        ports:
          - name: op-metrics
            containerPort: 8080
            protocol: TCP
          - name: op-health
            containerPort: 8081
            protocol: TCP
  {{- if .Values.operator.resources }}
        resources: {{- toYaml .Values.operator.resources | nindent 10 }}
  {{- end }}
        volumeMounts:
        - mountPath: /etc/teleport
          name: "config"
          readOnly: true
        - mountPath: /var/lib/teleport
          name: "data"
  {{- if $projectedServiceAccountToken }}
        - mountPath: /var/run/secrets/kubernetes.io/serviceaccount
          name: auth-serviceaccount-token
          readOnly: true
  {{- end }}
{{ end }}
{{- if $projectedServiceAccountToken }}
      automountServiceAccountToken: false
{{- end }}
      volumes:
{{- if $projectedServiceAccountToken }}
      # This projected token volume mimics the `automountServiceAccountToken`
      # behaviour but defaults to a 1h TTL instead of 1y.
      - name: auth-serviceaccount-token
        projected:
          sources:
            - serviceAccountToken:
                path: token
            - configMap:
                items:
                - key: ca.crt
                  path: ca.crt
                name: kube-root-ca.crt
            - downwardAPI:
                items:
                  - path: "namespace"
                    fieldRef:
                      fieldPath: metadata.namespace
{{- end }}
{{- if $auth.enterprise }}
      - name: license
        secret:
          secretName: "license"
{{- end }}
{{- if and ($auth.gcp.credentialSecretName) (eq $auth.chartMode "gcp") }}
      - name: gcp-credentials
        secret:
          secretName: {{ $auth.gcp.credentialSecretName | quote }}
{{- end }}
{{- if $auth.tls.existingCASecretName }}
      - name: teleport-tls-ca
        secret:
          secretName: {{ $auth.tls.existingCASecretName }}
{{- end }}
      - name: "config"
        configMap:
          name: {{ .Release.Name }}-auth
      - name: "data"
        {{- if and ($auth.persistence.enabled) ( and (not (eq $auth.chartMode "gcp")) (not (eq $auth.chartMode "aws")) (not (eq $auth.chartMode "azure"))) }}
        persistentVolumeClaim:
          claimName: {{ if $auth.persistence.existingClaimName }}{{ $auth.persistence.existingClaimName }}{{ else }}{{ .Release.Name }}{{ end }}
        {{- else }}
        emptyDir: {}
        {{- end }}
{{- if $auth.extraVolumes }}
  {{- toYaml $auth.extraVolumes | nindent 6 }}
{{- end }}
{{- if $auth.priorityClassName }}
      priorityClassName: {{ $auth.priorityClassName }}
{{- end }}
      serviceAccountName: {{ include "teleport-cluster.auth.serviceAccountName" . }}
      terminationGracePeriodSeconds: {{ $auth.terminationGracePeriodSeconds }}
