# ArgoCD Hook Jobs for Phase 2 releases # Replaces helmfile presync/postsync hooks with K8s Job manifests --- # ── CloudNativePG — PreSync: Create CNPG Cluster CR ────────────────────────── apiVersion: batch/v1 kind: Job metadata: name: cnpg-cluster-setup namespace: ddb annotations: argocd.argoproj.io/hook: PreSync argocd.argoproj.io/hook-delete-policy: HookSucceeded spec: backoffLimit: 1 template: spec: serviceAccountName: cnpg-setup restartPolicy: Never containers: - name: setup image: bitnami/kubectl:latest command: - /bin/sh - -c - | set -e echo "Creating CNPG Cluster CR..." # Wait for operator to be ready kubectl rollout status deploy/cloudnative-pg -n ddb --timeout=120s 2>/dev/null || true # Apply CNPG Cluster CR (from existing helmfile hook) kubectl apply -f - <<'EOF' apiVersion: postgresql.cnpg.io/v1 kind: Cluster metadata: name: ddb-cluster namespace: ddb spec: instances: 3 imageName: ghcr.io/cloudnative-pg/postgresql:16.2 bootstrap: initdb: database: postgres owner: postgres postInitApplicationSQL: - "CREATE EXTENSION IF NOT EXISTS vector;" storage: size: 10Gi storageClass: longhorn postgresql: parameters: max_parallel_workers_per_gather: "4" max_parallel_workers: "4" shared_buffers: "256MB" wal_sender_timeout: "900" wal_receiver_timeout: "900" podTemplateSpec: spec: affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 podAffinityTerm: labelSelector: matchExpressions: - key: cnpg.io/cluster operator: In values: - ddb-cluster topologyKey: kubernetes.io/hostname containers: - name: postgres livenessProbe: httpGet: port: 8000 path: /healthz initialDelaySeconds: 0 timeoutSeconds: 60 periodSeconds: 10 failureThreshold: 3 readinessProbe: httpGet: port: 8000 path: /readyz initialDelaySeconds: 0 timeoutSeconds: 60 periodSeconds: 10 failureThreshold: 3 startupProbe: httpGet: port: 8000 path: /healthz initialDelaySeconds: 0 timeoutSeconds: 60 periodSeconds: 10 failureThreshold: 360 EOF echo "✓ CNPG Cluster CR applied" --- # ── CloudNativePG — PostSync: Wait for cluster, init-users, migrations ────── apiVersion: batch/v1 kind: Job metadata: name: cnpg-init-complete namespace: ddb annotations: argocd.argoproj.io/hook: PostSync argocd.argoproj.io/hook-delete-policy: HookSucceeded spec: backoffLimit: 1 template: spec: serviceAccountName: cnpg-setup restartPolicy: Never containers: - name: init image: bitnami/kubectl:latest command: - /bin/sh - -c - | set -e echo "Waiting for CNPG cluster to be Ready..." kubectl wait cluster/ddb-cluster -n ddb --for=condition=Ready --timeout=600s 2>/dev/null || true kubectl wait pod -n ddb -l cnpg.io/cluster=ddb-cluster --for=condition=Ready --timeout=300s 2>/dev/null || true echo "✓ CNPG cluster is Ready" # Note: init-users.sh and migrations require access to .env secrets # TODO: migrate to SOPS-based secret injection echo "Database initialization requires Vault/Secret integration (placeholder)" --- # ── Prometheus — PostSync: Apply alerts and CRDs ────────────────────────────── apiVersion: batch/v1 kind: Job metadata: name: prometheus-alerts-apply namespace: monitoring annotations: argocd.argoproj.io/hook: PostSync argocd.argoproj.io/hook-delete-policy: HookSucceeded spec: backoffLimit: 1 template: spec: serviceAccountName: prometheus-setup restartPolicy: Never containers: - name: apply-alerts image: bitnami/kubectl:latest command: - /bin/sh - -c - | set -e echo "Waiting for Prometheus operator..." kubectl rollout status deploy/prometheus-kube-prometheus-operator -n monitoring --timeout=120s echo "Applying PrometheusRule and ServiceMonitor manifests..." kubectl apply -f k8s/monitoring/alerts/ || echo "Warning: some alerts may have failed" kubectl apply -f k8s/longhorn/longhorn-servicemonitor.yaml || echo "Warning: Longhorn ServiceMonitor failed" echo "✓ Alerts applied" --- # ── Forgejo-Runner — PreSync: Generate runner token ────────────────────────── apiVersion: batch/v1 kind: Job metadata: name: forgejo-runner-token-gen namespace: cicd annotations: argocd.argoproj.io/hook: PreSync argocd.argoproj.io/hook-delete-policy: HookSucceeded spec: backoffLimit: 1 template: spec: serviceAccountName: forgejo-setup restartPolicy: Never containers: - name: token-gen image: bitnami/kubectl:latest command: - /bin/sh - -c - | set -e echo "Waiting for Forgejo to be ready..." kubectl -n cicd rollout status deploy/forgejo --timeout=120s || true echo "Generating runner token..." TOKEN=$(kubectl -n cicd exec deploy/forgejo -c gitea -- \ forgejo actions generate-runner-token 2>/dev/null | tr -d '\r\n') || TOKEN="placeholder" if [ -z "$TOKEN" ] || [ "$TOKEN" = "placeholder" ]; then echo "Warning: Could not generate token, using placeholder" TOKEN="placeholder-token-$(date +%s)" fi kubectl -n cicd create secret generic runner-token \ --from-literal=token="$TOKEN" \ --dry-run=client -o yaml | kubectl apply -f - echo "✓ Runner token stored" --- # ── RBAC for Hook Jobs ────────────────────────────────────────────────────── apiVersion: v1 kind: ServiceAccount metadata: name: cnpg-setup namespace: ddb --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: cnpg-setup rules: - apiGroups: ["postgresql.cnpg.io"] resources: ["clusters"] verbs: ["get", "list", "create", "apply", "patch"] - apiGroups: [""] resources: ["pods"] verbs: ["list", "get", "wait"] - apiGroups: ["apps"] resources: ["deployments"] verbs: ["list", "get"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: cnpg-setup roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: cnpg-setup subjects: - kind: ServiceAccount name: cnpg-setup namespace: ddb --- apiVersion: v1 kind: ServiceAccount metadata: name: prometheus-setup namespace: monitoring --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: prometheus-setup rules: - apiGroups: ["monitoring.coreos.com"] resources: ["prometheusrules", "servicemonitors"] verbs: ["get", "list", "create", "apply", "patch"] - apiGroups: ["apps"] resources: ["deployments"] verbs: ["list", "get"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: prometheus-setup roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: prometheus-setup subjects: - kind: ServiceAccount name: prometheus-setup namespace: monitoring --- apiVersion: v1 kind: ServiceAccount metadata: name: forgejo-setup namespace: cicd --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: forgejo-setup rules: - apiGroups: [""] resources: ["secrets"] verbs: ["get", "list", "create", "apply", "patch"] - apiGroups: ["apps"] resources: ["deployments"] verbs: ["list", "get"] - apiGroups: [""] resources: ["pods", "pods/exec"] verbs: ["list", "get", "create"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: forgejo-setup roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: forgejo-setup subjects: - kind: ServiceAccount name: forgejo-setup namespace: cicd