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

{{/*
Admission operator name
*/}}
{{- define "admission-controller.name" -}}
{{- default .Chart.Name .Values.admissionController.name | 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 "couchbase-operator.fullname" -}}
{{- printf "%s-%s" .Release.Name .Values.couchbaseOperator.name | trunc 63 | trimSuffix "-" -}}
{{- end -}}

{{- define "admission-controller.fullname" -}}
{{- printf "%s-%s" .Release.Name .Values.admissionController.name | trunc 63 | trimSuffix "-" -}}
{{- end -}}

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

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


{{/*
Get kind of rbac role to use based on requested level of access
*/}}
{{- define "couchbase-operator.rbacRole" -}}
{{- if .Values.rbac.clusterRoleAccess -}}
{{- printf "ClusterRole" }}
{{- else -}}
{{- printf "Role" }}
{{- end -}}
{{- end -}}

{{/*
Create the name of the admission-controller service account to use.
This value may be overriden by the serviceAccountName in the controller
*/}}
{{- define "admission-controller.serviceAccountName" -}}
{{- if .Values.rbac.create -}}
    {{- default (include "admission-controller.fullname" .) .Values.rbac.admissionServiceAccountName -}}
{{- else -}}
    {{- default "default" .Values.rbac.admissionServiceAccountName -}}
{{- end -}}
{{- end -}}

{{/*
Create service name for admission service from chart name or apply override.
*/}}
{{- define "admission-controller.service.name" -}}
{{- if .Values.admissionService.create -}}
{{- default (include "admission-controller.fullname" .) .Values.admissionService.name | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- default "default" .Values.admissionService.name -}}
{{- end -}}
{{- end -}}

{{/*
Create service fullname for admission service with namespace as domain.
*/}}
{{- define "admission-controller.service.fullname" -}}
{{- default ( printf "%s.%s.svc" (include "admission-controller.service.name" .) .Release.Namespace ) -}}
{{- end -}}


{{/*
Create secret for admission operator.
*/}}
{{- define "admission-controller.secret.name" -}}
{{- if .Values.admissionSecret.create -}}
  {{- default (include "admission-controller.fullname" .) .Values.admissionSecret.name | trunc 63 | trimSuffix "-" -}}
{{- else -}}
  {{- default "default" .Values.admissionSecret.name -}}
{{- end -}}
{{- end -}}

{{/*
Generate certificates for admission-controller webhooks
*/}}
{{- define "admission-controller.gen-certs" -}}
{{- $expiration := (.Values.admissionCA.expiration | int) -}}
{{- if (or (empty .Values.admissionCA.cert) (empty .Values.admissionCA.key)) -}}
{{- $ca :=  genCA "admission-controller-ca" $expiration -}}
{{- template "admission-controller.gen-client-tls" (dict "RootScope" . "CA" $ca) -}}
{{- else -}}
{{- $ca :=  buildCustomCert (.Values.admissionCA.cert | b64enc) (.Values.admissionCA.key | b64enc) -}}
{{- template "admission-controller.gen-client-tls" (dict "RootScope" . "CA" $ca) -}}
{{- end -}}
{{- end -}}

{{/*
Generate client key and cert from CA
*/}}
{{- define "admission-controller.gen-client-tls" -}}
{{- $altNames := list ( include "admission-controller.service.fullname" .RootScope) -}}
{{- $expiration := (.RootScope.Values.admissionCA.expiration | int) -}}
{{- $cert := genSignedCert ( include "admission-controller.fullname" .RootScope) nil $altNames $expiration .CA -}}
{{- $clientCert := default $cert.Cert .RootScope.Values.admissionSecret.cert | b64enc -}}
{{- $clientKey := default $cert.Key .RootScope.Values.admissionSecret.key | b64enc -}}
caCert: {{ .CA.Cert | b64enc }}
clientCert: {{ $clientCert }}
clientKey: {{ $clientKey }}
{{- end -}}
 # admission-cluster-role-binding.yaml
{{- if and .Values.rbac.create  .Values.deployments.admissionController -}}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: {{ template "admission-controller.fullname" . }}
  labels:
    app.kubernetes.io/name: {{ include "admission-controller.name" . }}
    app.kubernetes.io/instance: {{ .Release.Name }}
    app.kubernetes.io/managed-by: {{ .Release.Service }}
    helm.sh/chart: {{ include "couchbase-operator.chart" . }}
subjects:
- kind: ServiceAccount
  name: {{ template "admission-controller.serviceAccountName" . }}
  namespace: {{ .Release.Namespace }}
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: {{ template "admission-controller.fullname" . }}
{{- end }}
 # admission-cluster-role.yaml
{{- if and .Values.rbac.create .Values.deployments.admissionController -}}
---
apiVersion: rbac.authorization.k8s.io/{{ .Values.rbac.apiVersion }}
kind: ClusterRole
metadata:
  name: {{ template "admission-controller.fullname" . }}
  labels:
    app.kubernetes.io/name: {{ include "admission-controller.name" . }}
    app.kubernetes.io/instance: {{ .Release.Name }}
    app.kubernetes.io/managed-by: {{ .Release.Service }}
    helm.sh/chart: {{ include "couchbase-operator.chart" . }}
rules:
- apiGroups:
  - couchbase.com
  resources:
  - couchbaseclusters
  verbs:
  - get
- apiGroups:
  - ""
  resources:
  - secrets
  verbs:
  - get
- apiGroups:
  - storage.k8s.io
  resources:
  - storageclasses
  verbs:
  - get
{{- end }}
 # admission-deployment.yaml
{{- if .Values.deployments.admissionController }}
{{ $tls := fromYaml ( include "admission-controller.gen-certs" . ) }}
{{- if .Values.admissionSecret.create }}
---
apiVersion: v1
kind: Secret
metadata:
  name: {{ template "admission-controller.secret.name" . }}
  labels:
    app.kubernetes.io/name: {{ include "admission-controller.name" . }}
    app.kubernetes.io/instance: {{ .Release.Name }}
    app.kubernetes.io/managed-by: {{ .Release.Service }}
    helm.sh/chart: {{ include "couchbase-operator.chart" . }}
type: Opaque
data:
  tls-cert-file: {{ $tls.clientCert }}
  tls-private-key-file: {{ $tls.clientKey }}
{{- end }}
---
apiVersion: admissionregistration.k8s.io/v1beta1
kind: ValidatingWebhookConfiguration
metadata:
  name: {{ template "admission-controller.fullname" . }}
webhooks:
- name: {{ include "admission-controller.service.fullname" . }}
  rules:
  - apiGroups:
    - couchbase.com
    apiVersions:
    - v1
    operations:
    - CREATE
    - UPDATE
    resources:
    - couchbaseclusters
  clientConfig:
    service:
      namespace: {{ .Release.Namespace }}
      name: {{ template "admission-controller.service.name" . }}
      path: "/couchbaseclusters/validate"
    caBundle: {{ $tls.caCert }}
---
apiVersion: admissionregistration.k8s.io/v1beta1
kind: MutatingWebhookConfiguration
metadata:
  name: {{ template "admission-controller.fullname" . }}
  labels:
    app.kubernetes.io/name: {{ include "admission-controller.name" . }}
    app.kubernetes.io/instance: {{ .Release.Name }}
    app.kubernetes.io/managed-by: {{ .Release.Service }}
    helm.sh/chart: {{ include "couchbase-operator.chart" . }}
webhooks:
- name: {{ include "admission-controller.service.fullname" . }}
  rules:
  - apiGroups:
    - couchbase.com
    apiVersions:
    - v1
    operations:
    - CREATE
    - UPDATE
    resources:
    - couchbaseclusters
  clientConfig:
    service:
      namespace: {{ .Release.Namespace }}
      name: {{ template "admission-controller.service.name" . }}
      path: "/couchbaseclusters/mutate"
    caBundle: {{ $tls.caCert }}
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ include "admission-controller.fullname" . }}
  labels:
    app.kubernetes.io/name: {{ include "admission-controller.name" . }}
    app.kubernetes.io/instance: {{ .Release.Name }}
    app.kubernetes.io/managed-by: {{ .Release.Service }}
    helm.sh/chart: {{ include "couchbase-operator.chart" . }}
  selector:
    matchLabels:
      app.kubernetes.io/name: {{ include "admission-controller.name" . }}
      app.kubernetes.io/instance: {{ .Release.Name }}
spec:
  replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/name: {{ template "admission-controller.name" . }}
  template:
    metadata:
      labels:
        app.kubernetes.io/name: {{ template "admission-controller.name" . }}
      annotations:
        checksum/config: {{ printf "%s%s" $tls.clientCert $tls.clientKey | sha256sum }}
    spec:
      imagePullSecrets:
  {{- range .Values.admissionController.imagePullSecrets }}
      - name: "{{ . }}"
  {{- end }}
      containers:
      - name: {{ .Chart.Name }}
        image: "{{ .Values.admissionController.image.repository }}:{{ .Values.admissionController.image.tag }}"
        imagePullPolicy: {{ .Values.admissionController.imagePullPolicy }}

        command:
        - couchbase-operator-admission
        args:
          - "--logtostderr"
          - "--stderrthreshold"
          - "0"
          - "-v"
          - {{if .Values.admissionController.verboseLogging }} "1" {{else}} "0" {{end}}
          - "--tls-cert-file"
          - "/var/run/secrets/couchbase.com/couchbase-operator-admission/tls-cert-file"
          - "--tls-private-key-file"
          - "/var/run/secrets/couchbase.com/couchbase-operator-admission/tls-private-key-file"
        ports:
        - name: https
          containerPort: {{ .Values.admissionService.port }}
        volumeMounts:
        - name: couchbase-operator-admission
          mountPath: "/var/run/secrets/couchbase.com/couchbase-operator-admission"
          readOnly: true
      volumes:
      - name: couchbase-operator-admission
        secret:
          secretName: {{ template "admission-controller.secret.name" . }}
      serviceAccountName:  {{ template "admission-controller.serviceAccountName" . }}
{{- end }}
 # admission-service-account.yaml
{{- if and .Values.rbac.create  .Values.deployments.admissionController -}}
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: {{ template "admission-controller.serviceAccountName" . }}
  labels:
    app.kubernetes.io/name: {{ include "admission-controller.name" . }}
    app.kubernetes.io/instance: {{ .Release.Name }}
    app.kubernetes.io/managed-by: {{ .Release.Service }}
    helm.sh/chart: {{ include "couchbase-operator.chart" . }}
{{- end }}
 # admission-service.yaml
{{- if and .Values.admissionService.create .Values.deployments.admissionController }}
---
apiVersion: v1
kind: Service
metadata:
  name: {{ template "admission-controller.service.name" . }}
  labels:
    app.kubernetes.io/name: {{ include "admission-controller.name" . }}
    app.kubernetes.io/instance: {{ .Release.Name }}
    app.kubernetes.io/managed-by: {{ .Release.Service }}
    helm.sh/chart: {{ include "couchbase-operator.chart" . }}
spec:
  selector:
    app.kubernetes.io/name : {{ template "admission-controller.name" . }}
  ports:
  - protocol: TCP
    port: {{ .Values.admissionService.port }}
    targetPort: {{ .Values.admissionService.targetPort }}
{{- end }}
 # couchbase-cluster-role-binding.yaml
{{- if and .Values.rbac.create  .Values.deployments.couchbaseOperator -}}
---
kind: {{ printf "%sBinding" (include "couchbase-operator.rbacRole" .) }}
apiVersion: rbac.authorization.k8s.io/{{ required "A valid .Values.rbac.apiVersion entry required!" .Values.rbac.apiVersion }}
metadata:
  name: {{ template "couchbase-operator.fullname" . }}
  labels:
    app.kubernetes.io/name: {{ include "couchbase-operator.name" . }}
    app.kubernetes.io/instance: {{ .Release.Name }}
    app.kubernetes.io/managed-by: {{ .Release.Service }}
    helm.sh/chart: {{ include "couchbase-operator.chart" . }}
subjects:
- kind: ServiceAccount
  name: {{ template "couchbase-operator.serviceAccountName" . }}
  namespace: {{ .Release.Namespace }}
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: {{ template "couchbase-operator.rbacRole" . }}
  name: {{ template "couchbase-operator.fullname" . }}
{{- end }}
 # couchbase-cluster-role.yaml
{{- if and .Values.rbac.create .Values.rbac.clusterRoleAccess -}}
---
apiVersion: rbac.authorization.k8s.io/{{ .Values.rbac.apiVersion }}
kind: ClusterRole
metadata:
  name: {{ template "couchbase-operator.fullname" . }}
  labels:
    app.kubernetes.io/name: {{ include "couchbase-operator.name" . }}
    app.kubernetes.io/instance: {{ .Release.Name }}
    app.kubernetes.io/managed-by: {{ .Release.Service }}
    helm.sh/chart: {{ include "couchbase-operator.chart" . }}
rules:
- apiGroups:
  - couchbase.com
  resources:
  - couchbaseclusters
  verbs:
  - get
  - list
  - watch
  - update
- apiGroups:
  - apiextensions.k8s.io
  resources:
  - customresourcedefinitions
  verbs:
  - get
  - create
- apiGroups:
  - ""
  resources:
  - pods
  - services
  - endpoints
  - persistentvolumeclaims
  verbs:
  - get
  - list
  - watch
  - create
  - update
  - delete
- apiGroups:
  - ""
  resources:
  - pods/exec
  verbs:
  - create
- apiGroups:
  - ""
  resources:
  - events
  verbs:
  - create
  - patch
- apiGroups:
  - ""
  resources:
  - secrets
  verbs:
  - get
- apiGroups:
  - policy
  resources:
  - poddisruptionbudgets
  verbs:
  - get
  - create
  - delete
{{- end }}
 # couchbase-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ include "couchbase-operator.fullname" . }}
  labels:
    app.kubernetes.io/name: {{ include "couchbase-operator.name" . }}
    app.kubernetes.io/instance: {{ .Release.Name }}
    app.kubernetes.io/managed-by: {{ .Release.Service }}
    helm.sh/chart: {{ include "couchbase-operator.chart" . }}
  selector:
    matchLabels:
      app.kubernetes.io/name: {{ include "couchbase-operator.name" . }}
      app.kubernetes.io/instance: {{ .Release.Name }}
spec:
  replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/name: {{ template "couchbase-operator.name" . }}
  template:
    metadata:
      labels:
        app.kubernetes.io/name: {{ template "couchbase-operator.name" . }}
    spec:
      serviceAccountName: {{ template "couchbase-operator.serviceAccountName" . }}
      imagePullSecrets:
  {{- range .Values.couchbaseOperator.imagePullSecrets }}
      - name: "{{ . }}"
  {{- end }}
      containers:
      - name: {{ .Chart.Name }}
        image: "{{ .Values.couchbaseOperator.image.repository }}:{{ .Values.couchbaseOperator.image.tag }}"
        imagePullPolicy: {{ .Values.couchbaseOperator.imagePullPolicy}}
        command:
        - couchbase-operator
  {{- range $key, $value := .Values.couchbaseOperator.commandArgs }}
        - "--{{ $key }}={{ $value }}"
  {{- end }}
        env:
        - name: MY_POD_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
        - name: MY_POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        ports:
          - name: readiness-port
            containerPort: {{ .Values.couchbaseOperator.readinessProbe.port}}
        readinessProbe:
          httpGet:
            path: /readyz
            port: readiness-port
          initialDelaySeconds: {{ .Values.couchbaseOperator.readinessProbe.initialDelaySeconds }}
          periodSeconds: {{ .Values.couchbaseOperator.readinessProbe.periodSeconds }}
          timeoutSeconds: {{ .Values.couchbaseOperator.readinessProbe.timeoutSeconds }}
          failureThreshold: {{ .Values.couchbaseOperator.readinessProbe.failureThreshold }}
        resources:
{{ toYaml .Values.couchbaseOperator.resources | indent 12 }}
    {{- with .Values.couchbaseOperator.nodeSelector }}
      nodeSelector:
{{ toYaml . | indent 8 }}
    {{- end }}
    {{- with .Values.couchbaseOperator.affinity }}
      affinity:
{{ toYaml . | indent 8 }}
    {{- end }}
    {{- with .Values.couchbaseOperator.tolerations }}
      tolerations:
{{ toYaml . | indent 8 }}
    {{- end }}
 # couchbase-role-template.yaml
{{- if and .Values.rbac.create (not .Values.rbac.clusterRoleAccess) -}}
---
apiVersion: rbac.authorization.k8s.io/{{ .Values.rbac.apiVersion }}
kind: Role
metadata:
  name: {{ template "couchbase-operator.fullname" . }}
  labels:
    app.kubernetes.io/name: {{ include "couchbase-operator.name" . }}
    app.kubernetes.io/instance: {{ .Release.Name }}
    app.kubernetes.io/managed-by: {{ .Release.Service }}
    helm.sh/chart: {{ include "couchbase-operator.chart" . }}
rules:
- apiGroups:
  - couchbase.com
  resources:
  - couchbaseclusters
  verbs:
  - get
  - list
  - watch
  - update
- apiGroups:
  - ""
  resources:
  - pods
  - services
  - endpoints
  - persistentvolumeclaims
  verbs:
  - get
  - list
  - watch
  - create
  - update
  - delete
- apiGroups:
  - ""
  resources:
  - pods/exec
  verbs:
  - create
- apiGroups:
  - ""
  resources:
  - events
  verbs:
  - create
  - patch
- apiGroups:
  - ""
  resources:
  - secrets
  verbs:
  - get
- apiGroups:
  - policy
  resources:
  - poddisruptionbudgets
  verbs:
  - get
  - create
  - delete
{{- end }}
 # couchbase-service-account.yaml
{{- if .Values.rbac.create -}}
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: {{ template "couchbase-operator.serviceAccountName" . }}
  labels:
    app.kubernetes.io/name: {{ include "couchbase-operator.name" . }}
    app.kubernetes.io/instance: {{ .Release.Name }}
    app.kubernetes.io/managed-by: {{ .Release.Service }}
    helm.sh/chart: {{ include "couchbase-operator.chart" . }}
{{- end }}

# Default values for couchbase-operator chart.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.

# Install Default RBAC roles and bindings
rbac:
  create: true
  apiVersion: v1beta1
  # grant cluster-wide access to service accounts
  clusterRoleAccess: true
  # name of couchbase service account
  couchbaseServiceAccountName:
  # name of admission service account
  admissionServiceAccountName:


# Select what to deploy
deployments:
  # couchbaseOperator is the couchbase-operator deployment
  couchbaseOperator: true
  # admissionController enforces validation
  admissionController: true

# couchbaseOperator is the controller for couchbase cluster
couchbaseOperator:
  # name of the couchbase operator
  name: "couchbase-operator"
  # image config
  image:
    repository: couchbase/operator
    tag: 1.2.2
  imagePullPolicy: IfNotPresent
  # imagePullSecrets is an optional list of references to secrets  to use for pulling images
  imagePullSecrets: []
  # additional command arguments will be translated to `--key=value`
  commandArgs:
    # Set to false if you are installing the CRD manually
    create-crd: true
  # readinessProbe marks pod as ready when readiness port (8080) responds
  readinessProbe:
    # initialDelaySeconds is a delay before readiness probe is initiated
    initialDelaySeconds: 3
    # periodSeconds decides how often to perform the probe
    periodSeconds: 3
    # failureThreshold sets Pod status to failure when threshold is reached
    failureThreshold: 19
    # port exposed to check readiness
    port: 8080
  # resources of couchbase-operator
  resources:
    cpu: 100m
    memory: 128Mi
  # nodeSelector for couchbase-operator pod assignment
  # Ref: https://kubernetes.io/docs/user-guide/node-selection/
  nodeSelector: {}
  # tolerations of pod match nodes with corresponding taints
  tolerations: []


# admissionController is the controller for couchbase admission controller
# name is derived from chart
admissionController:
  name: "couchbase-admission-controller"
  image:
    repository: couchbase/admission-controller
    tag: 1.2.2
  imagePullPolicy: IfNotPresent
  # imagePullSecrets is an optional list of references to secrets  to use for pulling images
  imagePullSecrets: []
  verboseLogging: true

# admissionService exposes validation to cluster. This service
# is over https and certs are auto-generated based on serviceName.
# Use nameOverride when manually creating service, or disable altogether.
admissionService:
  # create determines if service is created
  create: true
  # name of the service (auto-generated)
  name:
  # port service exposes
  port: 443
  targetPort: 8443

# admissionCA can be used to override the Certs that will be used
# to sign the keys used by the admsission operator.
admissionCA:
  # disable if manually creating certs
  # provide cert and key via --set-file
  create: true
  # A base64 encoded PEM format certificate
  cert:
  # A base64 encoded PEM format private key
  key:
  # Expiry time of CA in days for generated certs
  expiration: 365

# secret with client certs mounted within the admission controller.
admissionSecret:
  create: true
  # name of the secret (auto-generated)
  name:
  # PEM format certificate (auto-generated)
  # override via --set-file
  cert:
  # PEM format certificate (auto-generated)
  # override via --set-file
  key:
