{{/*
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/}}

{{/*
The controller reconciling the Database/User/Grant/Connection custom
resources. Kept separate from mariadb-controller, which elects the galera
primary: that one has to keep working while the database is unreachable,
which is exactly when this one is retrying, and it must not be handed
administrative database credentials or a client certificate.
*/}}

{{- if .Values.manifests.deployment_db_controller }}
{{- $envAll := . }}

{{- $serviceAccountName := "mariadb-db-controller" }}
{{ tuple $envAll "db_controller" $serviceAccountName | include "helm-toolkit.snippets.kubernetes_pod_rbac_serviceaccount" }}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: {{ $envAll.Release.Name }}-{{ $serviceAccountName }}
  namespace: {{ $envAll.Release.Namespace }}
rules:
  - apiGroups:
      - mariadb.osh.openstack.org
    resources:
      - databases
      - users
      - grants
      - connections
    verbs:
      - get
      - list
      - watch
      - update
      - patch
  - apiGroups:
      - mariadb.osh.openstack.org
    resources:
      - databases/status
      - users/status
      - grants/status
      - connections/status
    verbs:
      - get
      - update
      - patch
  - apiGroups:
      - ""
    resources:
      - secrets
    verbs:
      - get
      - list
      - watch
      - create
      - update
      - patch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: {{ $envAll.Release.Name }}-{{ $serviceAccountName }}
  namespace: {{ $envAll.Release.Namespace }}
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: {{ $envAll.Release.Name }}-{{ $serviceAccountName }}
subjects:
  - kind: ServiceAccount
    name: {{ $serviceAccountName }}
    namespace: {{ $envAll.Release.Namespace }}
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mariadb-db-controller
  annotations:
    {{ tuple $envAll | include "helm-toolkit.snippets.release_uuid" }}
  labels:
{{ tuple $envAll "mariadb" "db-controller" | include "helm-toolkit.snippets.kubernetes_metadata_labels" | indent 4 }}
spec:
  replicas: {{ .Values.pod.replicas.db_controller }}
  selector:
    matchLabels:
{{ tuple $envAll "mariadb" "db-controller" | include "helm-toolkit.snippets.kubernetes_metadata_labels" | indent 6 }}
  {{/*
  Recreate rather than the chart-wide rolling update: with max_surge two
  reconcilers would briefly run at once. Everything they do is idempotent so
  an overlap is survivable, but it produces confusing churn on the secrets
  they both patch.
  */}}
  strategy:
    type: Recreate
  revisionHistoryLimit: {{ .Values.pod.lifecycle.upgrades.deployments.revision_history }}
  template:
    metadata:
      labels:
{{ tuple $envAll "mariadb" "db-controller" | include "helm-toolkit.snippets.kubernetes_metadata_labels" | indent 8 }}
      annotations:
{{ tuple $envAll | include "helm-toolkit.snippets.release_uuid" | indent 8 }}
        configmap-bin-hash: {{ tuple "configmap-bin.yaml" . | include "helm-toolkit.utils.hash" }}
    spec:
      serviceAccountName: {{ $serviceAccountName }}
{{ dict "envAll" $envAll "application" "db_controller" | include "helm-toolkit.snippets.kubernetes_pod_security_context" | indent 6 }}
      affinity:
{{ tuple $envAll "mariadb" "db-controller" | include "helm-toolkit.snippets.kubernetes_pod_anti_affinity" | indent 8 }}
{{ if $envAll.Values.pod.tolerations.mariadb.enabled }}
{{ tuple $envAll "mariadb" | include "helm-toolkit.snippets.kubernetes_tolerations" | indent 6 }}
{{ end }}
      nodeSelector:
        {{ .Values.labels.db_controller.node_selector_key }}: {{ .Values.labels.db_controller.node_selector_value }}
      initContainers:
{{ tuple $envAll "db_controller" list | include "helm-toolkit.snippets.kubernetes_entrypoint_init_container" | indent 8 }}
      containers:
        - name: db-controller
{{ tuple $envAll "mariadb_db_controller" | include "helm-toolkit.snippets.image" | indent 10 }}
{{ dict "envAll" $envAll "application" "db_controller" "container" "db_controller" | include "helm-toolkit.snippets.kubernetes_container_security_context" | indent 10 }}
{{ tuple $envAll $envAll.Values.pod.resources.db_controller | include "helm-toolkit.snippets.kubernetes_resources" | indent 10 }}
          command:
            - /tmp/mariadb_db_controller.py
          env:
{{ include "helm-toolkit.utils.to_k8s_env_vars" .Values.pod.env.mariadb_db_controller | indent 12 }}
            - name: MARIADB_DB_CONTROLLER_NAMESPACE
              value: {{ $envAll.Release.Namespace }}
            - name: MARIADB_DB_CONTROLLER_CLUSTER_DOMAIN
              value: {{ $envAll.Values.endpoints.cluster_domain_suffix }}
            {{/*
            The elected primary service, so that writes always land on the
            node the galera controller currently points at.
            */}}
            - name: MARIADB_HOST
              value: {{ tuple "oslo_db" "internal" $envAll | include "helm-toolkit.endpoints.endpoint_host_lookup" }}
            - name: MARIADB_PORT
              value: {{ tuple "oslo_db" "internal" "mysql" $envAll | include "helm-toolkit.endpoints.endpoint_port_lookup" | quote }}
            - name: MARIADB_USER
              value: {{ $envAll.Values.endpoints.oslo_db.auth.admin.username | quote }}
            - name: MARIADB_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: mariadb-dbadmin-password
                  key: MYSQL_DBADMIN_PASSWORD
            {{/*
            The name this controller answers for. A custom resource pointing
            at a different cluster is left untouched, so this controller and
            the upstream mariadb-operator can coexist in one namespace.
            */}}
            - name: MARIADB_REF_NAME
              value: {{ tuple "oslo_db" "internal" $envAll | include "helm-toolkit.endpoints.hostname_short_endpoint_lookup" }}
{{- if $envAll.Values.manifests.certificates }}
            - name: MARIADB_X509
              value: "REQUIRE X509"
{{- end }}
          volumeMounts:
            - name: pod-tmp
              mountPath: /tmp
            - name: mariadb-bin
              mountPath: /tmp/mariadb_db_controller.py
              subPath: mariadb_db_controller.py
              readOnly: true
            {{/*
            Carries the ssl-ca, ssl-key and ssl-cert settings when the chart
            is deployed with TLS, which pymysql picks up from
            read_default_file, so mutual TLS needs no extra wiring.
            */}}
            - name: mariadb-secrets
              mountPath: /etc/mysql/admin_user.cnf
              subPath: admin_user.cnf
              readOnly: true
{{- dict "enabled" $envAll.Values.manifests.certificates "name" $envAll.Values.secrets.tls.oslo_db.server.internal "path" "/etc/mysql/certs" | include "helm-toolkit.snippets.tls_volume_mount" | indent 12 }}
      volumes:
        - name: pod-tmp
          emptyDir: {}
        - name: mariadb-bin
          configMap:
            name: mariadb-bin
            defaultMode: 0555
        - name: mariadb-secrets
          secret:
            secretName: mariadb-secrets
            defaultMode: 0444
{{- dict "enabled" $envAll.Values.manifests.certificates "name" $envAll.Values.secrets.tls.oslo_db.server.internal | include "helm-toolkit.snippets.tls_volume" | indent 8 }}
{{- end }}
