{{- if .Values.Secure.Enabled }}
{{- if .Values.Secure.ServiceAccount.Create }}
apiVersion: v1
kind: ServiceAccount
metadata:
  name: {{ template "cockroachdb.serviceAccountName" . }}
  labels:
    heritage: {{ .Release.Service | quote }}
    release: {{ .Release.Name | quote }}
    chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
    component: "{{ .Release.Name }}-{{ .Values.Component }}"
---
{{- end }}
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: Role
metadata:
  name: "{{ printf "%s-%s" .Release.Name .Values.Name | trunc 56 }}"
  labels:
    heritage: {{ .Release.Service | quote }}
    release: {{ .Release.Name | quote }}
    chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
    component: "{{ .Release.Name }}-{{ .Values.Component }}"
rules:
- apiGroups:
  - ""
  resources:
  - secrets
  verbs:
  - create
  - get
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
  name: "{{ printf "%s-%s" .Release.Name .Values.Name | trunc 56 }}"
  labels:
    heritage: {{ .Release.Service | quote }}
    release: {{ .Release.Name | quote }}
    chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
    component: "{{ .Release.Name }}-{{ .Values.Component }}"
rules:
- apiGroups:
  - certificates.k8s.io
  resources:
  - certificatesigningrequests
  verbs:
  - create
  - get
  - watch
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: RoleBinding
metadata:
  name: "{{ printf "%s-%s" .Release.Name .Values.Name | trunc 56 }}"
  labels:
    heritage: {{ .Release.Service | quote }}
    release: {{ .Release.Name | quote }}
    chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
    component: "{{ .Release.Name }}-{{ .Values.Component }}"
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: "{{ printf "%s-%s" .Release.Name .Values.Name | trunc 56 }}"
subjects:
- kind: ServiceAccount
  name: {{ template "cockroachdb.serviceAccountName" . }}
  namespace: {{ .Release.Namespace | quote }}
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: "{{ printf "%s-%s" .Release.Name .Values.Name | trunc 56 }}"
  labels:
    heritage: {{ .Release.Service | quote }}
    release: {{ .Release.Name | quote }}
    chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
    component: "{{ .Release.Name }}-{{ .Values.Component }}"
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: "{{ printf "%s-%s" .Release.Name .Values.Name | trunc 56 }}"
subjects:
- kind: ServiceAccount
  name: {{ template "cockroachdb.serviceAccountName" . }}
  namespace: {{ .Release.Namespace | quote }}
---
{{- end }}
apiVersion: v1
kind: Service
metadata:
  # This service is meant to be used by clients of the database. It exposes a ClusterIP that will
  # automatically load balance connections to the different database pods.
  name: "{{ printf "%s-%s" .Release.Name .Values.Name | trunc 56 }}-public"
  annotations:
{{ toYaml .Values.Service.annotations | indent 4 }}
  labels:
    heritage: {{ .Release.Service | quote }}
    release: {{ .Release.Name | quote }}
    chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
    component: "{{ .Release.Name }}-{{ .Values.Component }}"
spec:
  type: {{ .Values.Service.type }}
  ports:
  # The main port, served by gRPC, serves Postgres-flavor SQL, internode
  # traffic and the cli.
  - port: {{ .Values.ExternalGrpcPort }}
    targetPort: {{ .Values.InternalGrpcPort }}
    name: {{ .Values.ExternalGrpcName }}
  # The secondary port serves the UI as well as health and debug endpoints.
  - port: {{ .Values.ExternalHttpPort }}
    targetPort: {{ .Values.InternalHttpPort }}
    name: {{ .Values.HttpName }}
    {{- if ne .Values.InternalGrpcPort .Values.ExternalGrpcPort }}
  - port: {{ .Values.InternalGrpcPort }}
    targetPort: {{ .Values.InternalGrpcPort }}
    name: {{ .Values.InternalGrpcName }}
    {{- end }}
  selector:
    component: "{{ .Release.Name }}-{{ .Values.Component }}"
---
apiVersion: v1
kind: Service
metadata:
  # This service only exists to create DNS entries for each pod in the stateful
  # set such that they can resolve each other's IP addresses. It does not
  # create a load-balanced ClusterIP and should not be used directly by clients
  # in most circumstances.
  name: "{{ printf "%s-%s" .Release.Name .Values.Name | trunc 56 }}"
  labels:
    heritage: {{ .Release.Service | quote }}
    release: {{ .Release.Name | quote }}
    chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
    component: "{{ .Release.Name }}-{{ .Values.Component }}"
  annotations:
    # Use this annotation in addition to the actual field below because the
    # annotation will stop being respected soon but the field is broken in
    # some versions of Kubernetes:
    # https://github.com/kubernetes/kubernetes/issues/58662
    service.alpha.kubernetes.io/tolerate-unready-endpoints: "true"
    # Enable automatic monitoring of all instances when Prometheus is running in the cluster.
    prometheus.io/scrape: "true"
    prometheus.io/path: "_status/vars"
    prometheus.io/port: "{{ .Values.ExternalHttpPort }}"
spec:
  ports:
  - port: {{ .Values.ExternalGrpcPort }}
    targetPort: {{ .Values.InternalGrpcPort }}
    name: {{ .Values.ExternalGrpcName }}
  # The secondary port serves the UI as well as health and debug endpoints.
  - port: {{ .Values.ExternalHttpPort }}
    targetPort: {{ .Values.InternalHttpPort }}
    name: {{ .Values.HttpName }}
    {{- if ne .Values.InternalGrpcPort .Values.ExternalGrpcPort }}
  - port: {{ .Values.InternalGrpcPort }}
    targetPort: {{ .Values.InternalGrpcPort }}
    name: {{ .Values.InternalGrpcName }}
    {{- end }}
  # We want all pods in the StatefulSet to have their addresses published for
  # the sake of the other CockroachDB pods even before they're ready, since they
  # have to be able to talk to each other in order to become ready.
  publishNotReadyAddresses: true
  clusterIP: None
  selector:
    component: "{{ .Release.Name }}-{{ .Values.Component }}"
---
apiVersion: policy/v1beta1
kind: PodDisruptionBudget
metadata:
  name: "{{ printf "%s-%s" .Release.Name .Values.Name | trunc 56 }}-budget"
  labels:
    heritage: {{ .Release.Service | quote }}
    release: {{ .Release.Name | quote }}
    chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
    component: "{{ .Release.Name }}-{{ .Values.Component }}"
spec:
  selector:
    matchLabels:
      component: "{{ .Release.Name }}-{{ .Values.Component }}"
  maxUnavailable: {{ .Values.MaxUnavailable }}
---
apiVersion: apps/v1beta1
kind: StatefulSet
metadata:
  name: "{{ printf "%s-%s" .Release.Name .Values.Name | trunc 56 }}"
spec:
  serviceName: "{{ printf "%s-%s" .Release.Name .Values.Name | trunc 56 }}"
  replicas: {{ default 3 .Values.Replicas }}
  template:
    metadata:
      labels:
        heritage: {{ .Release.Service | quote }}
        release: {{ .Release.Name | quote }}
        chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
        component: "{{ .Release.Name }}-{{ .Values.Component }}"
    spec:
{{- if .Values.Secure.Enabled }}
      serviceAccountName: {{ template "cockroachdb.serviceAccountName" . }}
      initContainers:
      # The init-certs container sends a certificate signing request to the
      # kubernetes cluster.
      # You can see pending requests using: kubectl get csr
      # CSRs can be approved using:         kubectl certificate approve <csr name>
      #
      # All addresses used to contact a node must be specified in the --addresses arg.
      #
      # In addition to the node certificate and key, the init-certs entrypoint will symlink
      # the cluster CA to the certs directory.
      - name: init-certs
        image: "{{ .Values.Secure.RequestCertsImage }}:{{ .Values.Secure.RequestCertsImageTag }}"
        imagePullPolicy: "{{ .Values.ImagePullPolicy }}"
        command:
        - "/bin/ash"
        - "-ecx"
        - "/request-cert -namespace=${POD_NAMESPACE} -certs-dir=/cockroach-certs -type=node -addresses=localhost,127.0.0.1,$(hostname -f),$(hostname -f|cut -f 1-2 -d '.'),{{ printf "%s-%s" .Release.Name .Values.Name | trunc 56 }}-public,{{ printf "%s-%s" .Release.Name .Values.Name | trunc 56 }}-public.$(hostname -f|cut -f 3- -d '.') -symlink-ca-from=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt"
        env:
        - name: POD_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
        volumeMounts:
        - name: certs
          mountPath: /cockroach-certs
{{- end }}
      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 100
            podAffinityTerm:
              labelSelector:
                matchExpressions:
                - key: component
                  operator: In
                  values:
                  - "{{ .Release.Name }}-{{ .Values.Component }}"
              topologyKey: kubernetes.io/hostname
      {{- if .Values.NodeSelector }}
      nodeSelector:
{{ toYaml .Values.NodeSelector | indent 8 }}
      {{- end }}
{{- if .Values.Tolerations }}
      tolerations:
{{ toYaml .Values.Tolerations | indent 8 }}
{{- end }}
      containers:
      - name: "{{ printf "%s-%s" .Release.Name .Values.Name | trunc 56 }}"
        image: "{{ .Values.Image }}:{{ .Values.ImageTag }}"
        imagePullPolicy: "{{ .Values.ImagePullPolicy }}"
        ports:
        - containerPort: {{ .Values.InternalGrpcPort }}
          name: grpc
        - containerPort: {{ .Values.InternalHttpPort }}
          name: http
        livenessProbe:
          httpGet:
            path: "/health"
            port: http
{{- if .Values.Secure.Enabled }}
            scheme: HTTPS
{{- end }}
          initialDelaySeconds: 30
          periodSeconds: 5
        readinessProbe:
          httpGet:
            path: "/health?ready=1"
            port: http
{{- if .Values.Secure.Enabled }}
            scheme: HTTPS
{{- end }}
          initialDelaySeconds: 10
          periodSeconds: 5
          failureThreshold: 2
        resources:
{{ toYaml .Values.Resources | indent 10 }}
        env:
        - name: STATEFULSET_NAME
          value: "{{ printf "%s-%s" .Release.Name .Values.Name | trunc 56 }}"
        - name: COCKROACH_CHANNEL
          value: kubernetes-helm
        volumeMounts:
        - name: datadir
          mountPath: /cockroach/cockroach-data
{{- if .Values.Secure.Enabled }}
        - name: certs
          mountPath: /cockroach/cockroach-certs
{{- end }}
        command:
          - "/bin/bash"
          - "-ecx"
            # The use of qualified `hostname -f` is crucial:
            # Other nodes aren't able to look up the unqualified hostname.
          - "exec /cockroach/cockroach start --logtostderr {{ if .Values.Secure.Enabled }}--certs-dir /cockroach/cockroach-certs{{ else }}--insecure{{ end }} --advertise-host $(hostname -f) --http-host 0.0.0.0 --http-port {{ .Values.InternalHttpPort }} --port {{ .Values.InternalGrpcPort }} --cache {{ .Values.CacheSize }} --max-sql-memory {{ .Values.MaxSQLMemory }} --join ${STATEFULSET_NAME}-0.${STATEFULSET_NAME}:{{ .Values.InternalGrpcPort }},${STATEFULSET_NAME}-1.${STATEFULSET_NAME}:{{ .Values.InternalGrpcPort }},${STATEFULSET_NAME}-2.${STATEFULSET_NAME}:{{ .Values.InternalGrpcPort }}"
      # No pre-stop hook is required, a SIGTERM plus some time is all that's
      # needed for graceful shutdown of a node.
      terminationGracePeriodSeconds: 60
      volumes:
      - name: datadir
        persistentVolumeClaim:
          claimName: datadir
{{- if .Values.Secure.Enabled }}
      - name: certs
        emptyDir: {}
{{- end }}
  podManagementPolicy: {{ .Values.PodManagementPolicy }}
  updateStrategy:
{{ toYaml .Values.UpdateStrategy | indent 4 }}
  volumeClaimTemplates:
  - metadata:
      name: datadir
    spec:
      accessModes:
        - "ReadWriteOnce"
{{- if .Values.StorageClass }}
{{- if (eq "-" .Values.StorageClass) }}
      storageClassName: ""
{{- else }}
      storageClassName: "{{ .Values.StorageClass }}"
{{- end }}
{{- end }}
      resources:
        requests:
          storage: "{{ .Values.Storage }}"
