apiVersion: apps/v1beta1
kind: StatefulSet
metadata:
  name: {{ template "fullname" . }}
  labels:
    app: {{ template "fullname" . }}
    chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
    release: "{{ .Release.Name }}"
    heritage: "{{ .Release.Service }}"
spec:
  serviceName: {{ template "fullname" . }}
  replicas: {{ .Values.mysqlha.replicaCount }}
  template:
    metadata:
      labels:
        app: {{ template "fullname" . }}
    spec:
      initContainers:
      - name: clone-mysql
        image: {{ .Values.xtraBackupImage }}
        command:
          - bash
          - "-c"
          - |
            set -ex
            # Skip the clone on master (ordinal index 0).
            [[ `hostname` =~ -([0-9]+)$ ]] || exit 1
            ordinal=${BASH_REMATCH[1]}
            [[ $ordinal -eq 0 ]] && exit 0

            # If data already exists, delete and proceed to clone.
            [[ -d /var/lib/mysql/mysql ]] && rm -fr /var/lib/mysql/*

            # Clone data from previous peer.
            ncat --recv-only {{ template "fullname" . }}-$(($ordinal-1)).{{ template "fullname" . }} 3307 | xbstream -x -C /var/lib/mysql
            # Prepare the backup.
            xtrabackup --prepare --user=${MYSQL_REPLICATION_USER} --password=${MYSQL_REPLICATION_PASSWORD} --target-dir=/var/lib/mysql
        env:
        - name: MYSQL_REPLICATION_USER
          value: {{ .Values.mysqlha.mysqlReplicationUser }}
        - name: MYSQL_REPLICATION_PASSWORD
          valueFrom:
            secretKeyRef:
              name: {{ template "fullname" . }}
              key: mysql-replication-password
        volumeMounts:
        - name: data
          mountPath: /var/lib/mysql
          subPath: mysql
        - name: conf
          mountPath: /etc/mysql/conf.d
      - name: init-mysql
        image: {{ .Values.mysqlImage }}
        command:
          - bash
          - "-c"
          - |
            set -ex
            # Generate mysql server-id from pod ordinal index.
            [[ `hostname` =~ -([0-9]+)$ ]] || exit 1
            ordinal=${BASH_REMATCH[1]}
            # Copy server-id.conf adding offset to avoid reserved server-id=0 value.
            cat /mnt/config-map/server-id.cnf | sed s/@@SERVER_ID@@/$((100 + $ordinal))/g > /mnt/conf.d/server-id.cnf
            # Copy appropriate conf.d files from config-map to config mount.
            if [[ $ordinal -eq 0 ]]; then
              cp /mnt/config-map/master.cnf /mnt/conf.d/
            else
              cp /mnt/config-map/slave.cnf /mnt/conf.d/
            fi
            # Copy replication user script
            if [[ $ordinal -eq 0 ]]; then
              cp /mnt/config-map/create-replication-user.sql /mnt/scripts/create-replication-user.sql
            fi
        volumeMounts:
          - name: conf
            mountPath: /mnt/conf.d
          - name: config-map
            mountPath: /mnt/config-map
          - name: scripts
            mountPath: /mnt/scripts
      containers:
      - name: mysql
        image: {{ .Values.mysqlImage }}
        env:
        - name: MYSQL_DATABASE
          value: {{ default "" .Values.mysqlha.mysqlDatabase | quote }}
        - name: MYSQL_ROOT_PASSWORD
          valueFrom:
            secretKeyRef:
              name: {{ template "fullname" . }}
              key: mysql-root-password
        - name: MYSQL_REPLICATION_USER
          value: {{ .Values.mysqlha.mysqlReplicationUser }}
        - name: MYSQL_REPLICATION_PASSWORD
          valueFrom:
            secretKeyRef:
              name: {{ template "fullname" . }}
              key: mysql-replication-password
        {{ if .Values.mysqlha.mysqlUser }}
        - name: MYSQL_USER
          value: {{ .Values.mysqlha.mysqlUser | quote }}
        - name: MYSQL_PASSWORD
          valueFrom:
            secretKeyRef:
              name: {{ template "fullname" . }}
              key: mysql-password
        {{ end }}
        ports:
        - name: mysql
          containerPort: 3306
        volumeMounts:
        - name: data
          mountPath: /var/lib/mysql
          subPath: mysql
        - name: conf
          mountPath: /etc/mysql/conf.d
        resources:
          requests:
            cpu: {{ .Values.resources.requests.cpu }}
            memory: {{ .Values.resources.requests.memory }}
        livenessProbe:
          exec:
            command:
            - /bin/sh
            - "-c"
            - mysqladmin ping -h 127.0.0.1 -u root -p${MYSQL_ROOT_PASSWORD}
          initialDelaySeconds: 30
          timeoutSeconds: 5
        readinessProbe:
          exec:
            # Check we can execute queries over TCP (skip-networking is off).
            command:
            - /bin/sh
            - "-c"
            - MYSQL_PWD="${MYSQL_ROOT_PASSWORD}"
            - mysql -h 127.0.0.1 -u root -e "SELECT 1"
          initialDelaySeconds: 10
          timeoutSeconds: 1
      - name: xtrabackup
        image: {{ .Values.xtraBackupImage }}
        env:
        - name: MYSQL_PWD
          valueFrom:
            secretKeyRef:
              name: {{ template "fullname" . }}
              key: mysql-root-password
        - name: MYSQL_REPLICATION_USER
          value: {{ .Values.mysqlha.mysqlReplicationUser }}
        - name: MYSQL_REPLICATION_PASSWORD
          valueFrom:
            secretKeyRef:
              name: {{ template "fullname" . }}
              key: mysql-replication-password
        ports:
        - name: xtrabackup
          containerPort: 3307
        command:
        - bash
        - "-c"
        - |
          set -ex

          echo "Waiting for mysqld to be ready (accepting connections)"
          until mysql -h 127.0.0.1 -e "SELECT 1"; do sleep 1; done

          # Create replication user
          cd /mnt/scripts
          if [[ -f create-replication-user.sql  ]]; then
            cp create-replication-user.sql create-replication-user.orig.sql
            cat create-replication-user.sql \
              | sed s/@@REPLICATION_USER@@/"${MYSQL_REPLICATION_USER}"/g \
              | sed s/@@REPLICATION_PASSWORD@@/"${MYSQL_REPLICATION_PASSWORD}"/g \
              | tee create-replication-user.sql
            mysql -h 127.0.0.1 --verbose < create-replication-user.sql
          fi

          cd /var/lib/mysql
          # Determine binlog position of cloned data, if any.
          if [[ -f xtrabackup_slave_info ]]; then
            # XtraBackup already generated a partial "CHANGE MASTER TO" query
            # because we're cloning from an existing slave.
            cp xtrabackup_slave_info change_master_to.sql.in
          elif [[ -f xtrabackup_binlog_info ]]; then
            # We're cloning directly from master. Parse binlog position.
            [[ $(cat xtrabackup_binlog_info) =~ ^(.*?)[[:space:]]+(.*?)$ ]] || exit 1
            echo "CHANGE MASTER TO MASTER_LOG_FILE='${BASH_REMATCH[1]}',\
                  MASTER_LOG_POS=${BASH_REMATCH[2]}" > change_master_to.sql.in
          fi

          # Check if we need to complete a clone by starting replication.
          if [[ -f change_master_to.sql.in ]]; then

            # In case of container restart, attempt this at-most-once.
            cp change_master_to.sql.in change_master_to.sql.orig
            mysql -h 127.0.0.1 --verbose<<EOF
            STOP SLAVE IO_THREAD;
            $(<change_master_to.sql.orig),
            MASTER_HOST='{{ template "fullname" . }}-0.{{ template "fullname" . }}',
            MASTER_USER='${MYSQL_REPLICATION_USER}',
            MASTER_PASSWORD='${MYSQL_REPLICATION_PASSWORD}',
            MASTER_CONNECT_RETRY=10;
            START SLAVE;
          EOF
          fi

          # Start a server to send backups when requested by peers.
          exec ncat --listen --keep-open --send-only --max-conns=1 3307 -c \
            "xtrabackup --backup --slave-info --stream=xbstream --host=127.0.0.1 --user=${MYSQL_REPLICATION_USER} --password=${MYSQL_REPLICATION_PASSWORD}"
        volumeMounts:
        - name: data
          mountPath: /var/lib/mysql
          subPath: mysql
        - name: conf
          mountPath: /etc/mysql/conf.d
        - name: scripts
          mountPath: /mnt/scripts
        resources:
          requests:
            cpu: 100m
            memory: 100Mi
      volumes:
      - name: conf
        emptyDir: {}
      - name: config-map
        configMap:
          name: {{ template "fullname" . }}
      - name: scripts
        emptyDir: {}
{{- if .Values.persistence.enabled }}
  volumeClaimTemplates:
  - metadata:
      name: data
      annotations:
      {{- range $key, $value := .Values.persistence.annotations }}
        {{ $key }}: {{ $value }}
      {{- end }}
    spec:
      accessModes:
      {{- range .Values.persistence.accessModes }}
      - {{ . | quote }}
      {{- end }}
      resources:
        requests:
          storage: {{ .Values.persistence.size | quote }}
      {{- if .Values.persistence.storageClass }}
      {{- if (eq "-" .Values.persistence.storageClass) }}
      storageClassName: ""
      {{- else }}
      storageClassName: "{{ .Values.persistence.storageClass }}"
      {{- end }}
      {{- end }}
{{- else }}
      - name: data
        emptyDir: {}
{{- end }}
