apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ include "zddc-server.fullname" . }}
  labels:
    {{- include "zddc-server.labels" . | nindent 4 }}
spec:
  replicas: {{ .Values.replicaCount }}
  selector:
    matchLabels:
      {{- include "zddc-server.selectorLabels" . | nindent 6 }}
  template:
    metadata:
      labels:
        {{- include "zddc-server.selectorLabels" . | nindent 8 }}
    spec:
      {{- with .Values.imagePullSecrets }}
      imagePullSecrets:
        {{- toYaml . | nindent 8 }}
      {{- end }}
      volumes:
        - name: zddc-bin
          emptyDir: {}
        - name: data
          persistentVolumeClaim:
            claimName: {{ .Values.data.pvcName }}
      initContainers:
        # Build zddc-server from the pinned git ref. The static binary
        # lands in the shared zddc-bin volume that the main container
        # mounts. No image pull from a custom registry — the build
        # image is golang upstream + the runtime image is alpine.
        - name: build-zddc-server
          image: {{ printf "%s:%s" .Values.buildImage.repository .Values.buildImage.tag | quote }}
          imagePullPolicy: IfNotPresent
          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"
          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: 200m
              memory: 256Mi
            limits:
              cpu: 1000m
              memory: 512Mi
      containers:
        - name: zddc-server
          image: {{ printf "%s:%s" .Values.runtimeImage.repository .Values.runtimeImage.tag | quote }}
          imagePullPolicy: IfNotPresent
          # zddc-cgroup-init prepares cgroup v2 subtree_control then
          # exec's zddc-server. Required because cgroup v2 forbids
          # processes in a cgroup that has child cgroups; the per-
          # conversion wrapper (zddc-sandbox-exec) creates child
          # cgroups for resource caps, so the init script has to
          # move zddc-server itself out of the root cgroup first.
          # See zddc/runtime/zddc-cgroup-init in the source repo.
          command: ["/usr/local/libexec/zddc-cgroup-init", "/zddc/zddc-server"]
          # The conversion sandbox (bwrap, invoked per-call by
          # /usr/local/bin/{pandoc,chromium-browser}) needs to create
          # user + mount namespaces inside the container. Pod Security
          # Standards default policies forbid this; the chart sets the
          # minimum securityContext that lets bwrap function. If your
          # cluster's admission controller rejects these settings, you
          # have two choices: ask the platform team to allow this pod,
          # or accept that /.convert serves 503 (the rest of zddc-
          # server still works fine without conversion).
          securityContext:
            capabilities:
              add: ["SYS_ADMIN"]
              # cap-add SYS_ADMIN alone isn't enough — see the
              # zddc/runtime/zddc-sandbox-exec docstring for the full
              # set of LSM relaxations required. K8s 1.30+ supports
              # specifying seccompProfile + appArmorProfile fields;
              # if your cluster is older, you'll need annotations:
              #   container.apparmor.security.beta.kubernetes.io/zddc-server: unconfined
            seccompProfile:
              type: Unconfined
            appArmorProfile:
              type: Unconfined
          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 }}
          livenessProbe:
            httpGet:
              path: /
              port: http
            initialDelaySeconds: 5
            periodSeconds: 30
            timeoutSeconds: 5
          readinessProbe:
            httpGet:
              path: /
              port: http
            initialDelaySeconds: 2
            periodSeconds: 10
            timeoutSeconds: 3
