apiVersion: v1
kind: ServiceAccount
metadata:
  name: {{ envOr "KODEX_INTERNAL_REGISTRY_SERVICE" "" }}-gc
  namespace: {{ envOr "KODEX_PRODUCTION_NAMESPACE" "" }}
  labels:
    app.kubernetes.io/name: kodex-registry-gc
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: {{ envOr "KODEX_INTERNAL_REGISTRY_SERVICE" "" }}-gc
  namespace: {{ envOr "KODEX_PRODUCTION_NAMESPACE" "" }}
  labels:
    app.kubernetes.io/name: kodex-registry-gc
rules:
  - apiGroups: ["apps"]
    resources:
      - deployments
      - deployments/scale
    verbs:
      - get
      - list
      - watch
      - patch
      - update
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: {{ envOr "KODEX_INTERNAL_REGISTRY_SERVICE" "" }}-gc
  namespace: {{ envOr "KODEX_PRODUCTION_NAMESPACE" "" }}
  labels:
    app.kubernetes.io/name: kodex-registry-gc
subjects:
  - kind: ServiceAccount
    name: {{ envOr "KODEX_INTERNAL_REGISTRY_SERVICE" "" }}-gc
    namespace: {{ envOr "KODEX_PRODUCTION_NAMESPACE" "" }}
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: {{ envOr "KODEX_INTERNAL_REGISTRY_SERVICE" "" }}-gc
---
apiVersion: batch/v1
kind: CronJob
metadata:
  name: {{ envOr "KODEX_INTERNAL_REGISTRY_SERVICE" "" }}-gc
  namespace: {{ envOr "KODEX_PRODUCTION_NAMESPACE" "" }}
  labels:
    app.kubernetes.io/name: kodex-registry-gc
spec:
  # UTC by default: every day at 03:17.
  schedule: "17 3 * * *"
  concurrencyPolicy: Forbid
  suspend: false
  successfulJobsHistoryLimit: 2
  failedJobsHistoryLimit: 3
  jobTemplate:
    spec:
      backoffLimit: 0
      ttlSecondsAfterFinished: 86400
      activeDeadlineSeconds: 7200
      template:
        metadata:
          labels:
            app.kubernetes.io/name: kodex-registry-gc
        spec:
          serviceAccountName: {{ envOr "KODEX_INTERNAL_REGISTRY_SERVICE" "" }}-gc
          restartPolicy: Never
          volumes:
            - name: registry-data
              persistentVolumeClaim:
                claimName: {{ envOr "KODEX_INTERNAL_REGISTRY_SERVICE" "" }}-data
            - name: tools
              emptyDir: {}
          initContainers:
            - name: copy-kubectl
              image: {{ envOr "KODEX_KUBECTL_IMAGE" "127.0.0.1:5000/kodex/mirror/alpine-k8s:1.32.2" }}
              imagePullPolicy: IfNotPresent
              command:
                - sh
                - -ec
                - |
                  set -eu
                  candidate="$(command -v kubectl || true)"
                  [ -n "$candidate" ] && [ -x "$candidate" ] || {
                    echo "kubectl binary not found in image" >&2
                    exit 1
                  }
                  cp "$candidate" /tools/kubectl
                  chmod +x /tools/kubectl
                  exit 0
              volumeMounts:
                - name: tools
                  mountPath: /tools
          containers:
            - name: gc
              image: {{ envOr "KODEX_REGISTRY_IMAGE" "registry:2" }}
              imagePullPolicy: IfNotPresent
              command:
                - sh
                - -ec
                - |
                  set -eu

                  REGISTRY_DEPLOYMENT='{{ envOr "KODEX_INTERNAL_REGISTRY_SERVICE" "" }}'
                  TARGET_NAMESPACE='{{ envOr "KODEX_PRODUCTION_NAMESPACE" "" }}'
                  TARGET_REPLICAS='1'
                  ROLLOUT_TIMEOUT='15m'
                  KUBECTL_BIN='/tools/kubectl'

                  if [ ! -x "$KUBECTL_BIN" ]; then
                    echo "kubectl binary is missing at $KUBECTL_BIN" >&2
                    exit 1
                  fi

                  restore_registry() {
                    "$KUBECTL_BIN" -n "$TARGET_NAMESPACE" scale deployment "$REGISTRY_DEPLOYMENT" --replicas="$TARGET_REPLICAS" >/dev/null 2>&1 || true
                  }

                  trap restore_registry EXIT

                  echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] scale registry down"
                  "$KUBECTL_BIN" -n "$TARGET_NAMESPACE" scale deployment "$REGISTRY_DEPLOYMENT" --replicas=0
                  "$KUBECTL_BIN" -n "$TARGET_NAMESPACE" rollout status deployment "$REGISTRY_DEPLOYMENT" --timeout="$ROLLOUT_TIMEOUT"

                  echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] run registry garbage-collect"
                  registry garbage-collect --delete-untagged /etc/docker/registry/config.yml

                  echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] scale registry up"
                  "$KUBECTL_BIN" -n "$TARGET_NAMESPACE" scale deployment "$REGISTRY_DEPLOYMENT" --replicas="$TARGET_REPLICAS"
                  "$KUBECTL_BIN" -n "$TARGET_NAMESPACE" rollout status deployment "$REGISTRY_DEPLOYMENT" --timeout="$ROLLOUT_TIMEOUT"

                  trap - EXIT
              volumeMounts:
                - name: registry-data
                  mountPath: /var/lib/registry
                - name: tools
                  mountPath: /tools
