apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ include "zddc-server.fullname" . }}
  labels:
    {{- include "zddc-server.labels" . | nindent 4 }}
spec:
  replicas: {{ .Values.replicaCount }}
  # Dev: always re-pull the build image and re-clone source, so a kubectl
  # rollout restart picks up new commits on the tracked ref.
  strategy:
    type: Recreate
  selector:
    matchLabels:
      {{- include "zddc-server.selectorLabels" . | nindent 6 }}
  template:
    metadata:
      labels:
        {{- include "zddc-server.selectorLabels" . | nindent 8 }}
      annotations:
        # Forces pod recreation on every helm upgrade, ensuring the init
        # container re-clones the tracked ref. Useful in dev where you
        # want `helm upgrade` to pick up new main HEAD without changing
        # values.
        zddc.varasys.io/build-time: {{ now | quote }}
    spec:
      {{- with .Values.imagePullSecrets }}
      imagePullSecrets:
        {{- toYaml . | nindent 8 }}
      {{- end }}
      volumes:
        - name: zddc-bin
          emptyDir: {}
        # Production data volume — mounted READ-ONLY so the dev pod
        # cannot corrupt prod even with a bug. Becomes the lowerdir of
        # the OverlayFS mount below.
        - name: data-readonly
          persistentVolumeClaim:
            claimName: {{ .Values.data.pvcName }}
            readOnly: true
        # Writable scratch for OverlayFS upperdir + workdir. emptyDir
        # is ephemeral by default — dev tweaks evaporate on pod restart,
        # which is usually right for a dev replica. Replace with a
        # small PVC if persistence across restarts matters.
        - name: overlay-scratch
          emptyDir: {}
        # The composed read-write view zddc-server reads from. Populated
        # by the setup-overlay init container; passed through to the main
        # container as ZDDC_ROOT.
        - name: data
          emptyDir: {}
      initContainers:
        # OverlayFS sandwich:
        #   lowerdir = /mnt/data-readonly  (prod data, RO)
        #   upperdir = /mnt/overlay-scratch/upper
        #   workdir  = /mnt/overlay-scratch/work
        #   merged   = /mnt/data           (what main container sees)
        #
        # Why this exists: dev runs against the same on-disk dataset as
        # prod, but its writes (anything zddc-server writes — index
        # state, form submissions during testing, .zddc edits via the
        # admin page, etc.) MUST NOT mutate prod data. OverlayFS solves
        # this at the filesystem layer: prod data is RO, dev's writes
        # land in upperdir, the dev container sees the merged view. No
        # zddc-server code change required.
        #
        # Requires CAP_SYS_ADMIN (the overlay mount syscall is
        # privileged). Stays scoped to this one init container; the main
        # container runs without elevated privs.
        - name: setup-overlay
          image: {{ printf "%s:%s" .Values.runtimeImage.repository .Values.runtimeImage.tag | quote }}
          securityContext:
            privileged: true
          command: ["/bin/sh", "-c"]
          args:
            - |
              set -eu
              mkdir -p /mnt/overlay-scratch/upper /mnt/overlay-scratch/work
              mount -t overlay overlay \
                -o lowerdir=/mnt/data-readonly,upperdir=/mnt/overlay-scratch/upper,workdir=/mnt/overlay-scratch/work \
                /mnt/data
              echo "OverlayFS mounted: /mnt/data-readonly (RO) + /mnt/overlay-scratch (RW) -> /mnt/data"
              ls -la /mnt/data | head -10
          volumeMounts:
            - name: data-readonly
              mountPath: /mnt/data-readonly
              readOnly: true
            - name: overlay-scratch
              mountPath: /mnt/overlay-scratch
            - name: data
              mountPath: /mnt/data
              mountPropagation: Bidirectional
        - name: build-zddc-server
          image: {{ printf "%s:%s" .Values.buildImage.repository .Values.buildImage.tag | quote }}
          imagePullPolicy: Always
          command: ["/bin/sh", "-c"]
          args:
            - |
              set -eu
              apk add --no-cache git
              git clone --depth 1 --branch "$GIT_REF" "$GIT_REPO" /workspace
              cd /workspace/zddc
              CGO_ENABLED=0 GOOS=linux GOARCH=amd64 \
                go build -trimpath \
                  -ldflags="-s -w -X main.version=$GIT_REF" \
                  -o /out/zddc-server \
                  ./cmd/zddc-server
              echo "built /out/zddc-server from $GIT_REF ($(git -C /workspace rev-parse --short HEAD))"
          env:
            - name: GIT_REPO
              value: {{ .Values.zddc.gitRepo | quote }}
            - name: GIT_REF
              value: {{ .Values.zddc.gitRef | quote }}
          volumeMounts:
            - name: zddc-bin
              mountPath: /out
          resources:
            requests:
              cpu: 100m
              memory: 128Mi
            limits:
              cpu: 1000m
              memory: 512Mi
      containers:
        - name: zddc-server
          image: {{ printf "%s:%s" .Values.runtimeImage.repository .Values.runtimeImage.tag | quote }}
          imagePullPolicy: IfNotPresent
          command: ["/zddc/zddc-server"]
          ports:
            - name: http
              containerPort: 8080
              protocol: TCP
          env:
            - name: ZDDC_ROOT
              value: {{ .Values.zddc.env.rootPath | quote }}
            - name: ZDDC_ADDR
              value: {{ .Values.zddc.env.addr | quote }}
            - name: ZDDC_TLS_CERT
              value: "none"
            - name: ZDDC_INSECURE_DIRECT
              value: "1"
            - name: ZDDC_EMAIL_HEADER
              value: {{ .Values.zddc.env.emailHeader | quote }}
            - name: ZDDC_CORS_ORIGIN
              value: {{ .Values.zddc.env.corsOrigin | quote }}
            - name: ZDDC_LOG_LEVEL
              value: {{ .Values.zddc.env.logLevel | quote }}
            - name: ZDDC_INDEX_PATH
              value: {{ .Values.zddc.env.indexPath | quote }}
            {{- if .Values.zddc.env.noAuth }}
            - name: ZDDC_NO_AUTH
              value: "1"
            {{- end }}
          volumeMounts:
            - name: zddc-bin
              mountPath: /zddc
            - name: data
              mountPath: {{ .Values.zddc.env.rootPath }}
              {{- with .Values.data.subPath }}
              subPath: {{ . | quote }}
              {{- end }}
          resources:
            {{- toYaml .Values.resources | nindent 12 }}
          # Tighter probe cadence than prod — fail fast in dev so issues
          # surface immediately during testing.
          livenessProbe:
            httpGet:
              path: /
              port: http
            initialDelaySeconds: 3
            periodSeconds: 10
            timeoutSeconds: 3
          readinessProbe:
            httpGet:
              path: /
              port: http
            initialDelaySeconds: 1
            periodSeconds: 5
            timeoutSeconds: 2
