diff --git a/deploy/helm/codex-lb/templates/_helpers.tpl b/deploy/helm/codex-lb/templates/_helpers.tpl index 4b61fd84..e70b568d 100644 --- a/deploy/helm/codex-lb/templates/_helpers.tpl +++ b/deploy/helm/codex-lb/templates/_helpers.tpl @@ -139,3 +139,13 @@ Image string — resolves registry/repository:tag with optional digest override {{- printf "%s/%s:%s" $registry $repository $tag }} {{- end }} {{- end }} + +{{/* +Merged nodeSelector: global.nodeSelector + local nodeSelector (local wins). +*/}} +{{- define "codex-lb.nodeSelector" -}} +{{- $merged := mustMerge (.Values.nodeSelector | default dict) (.Values.global.nodeSelector | default dict) -}} +{{- if $merged }} +{{- toYaml $merged }} +{{- end }} +{{- end -}} diff --git a/deploy/helm/codex-lb/templates/deployment.yaml b/deploy/helm/codex-lb/templates/deployment.yaml index defca0a3..99eaefb4 100644 --- a/deploy/helm/codex-lb/templates/deployment.yaml +++ b/deploy/helm/codex-lb/templates/deployment.yaml @@ -89,10 +89,10 @@ spec: topologySpreadConstraints: {{- toYaml . | nindent 8 }} {{- end }} - {{- with .Values.nodeSelector }} - nodeSelector: - {{- toYaml . | nindent 8 }} - {{- end }} + {{- with (include "codex-lb.nodeSelector" .) }} + nodeSelector: + {{- . | nindent 8 }} + {{- end }} {{- with .Values.tolerations }} tolerations: {{- toYaml . | nindent 8 }} diff --git a/deploy/helm/codex-lb/templates/hooks/db-init-job.yaml b/deploy/helm/codex-lb/templates/hooks/db-init-job.yaml new file mode 100644 index 00000000..38bdb2e0 --- /dev/null +++ b/deploy/helm/codex-lb/templates/hooks/db-init-job.yaml @@ -0,0 +1,57 @@ +{{- if and .Values.dbInit.enabled (not .Values.postgresql.enabled) }} +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ printf "%s-db-init" (include "codex-lb.fullname" . | trunc 52 | trimSuffix "-") }} + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "codex-lb.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": pre-install + "helm.sh/hook-weight": "-10" + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded +spec: + template: + spec: + restartPolicy: OnFailure + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: db-init + image: {{ printf "%s/bitnami/postgresql:16" (.Values.global.imageRegistry | default "docker.io") }} + command: ["sh", "-ec"] + args: + - | + PGPASSWORD="$ADMIN_PASSWORD" psql \ + -h "$DB_HOST" -p "$DB_PORT" -U "$ADMIN_USER" -d postgres <<'SQL' + {{- range .Values.dbInit.databases }} + DO $$ BEGIN + IF NOT EXISTS (SELECT FROM pg_roles WHERE rolname = '{{ .user }}') THEN + CREATE ROLE {{ .user }} WITH LOGIN PASSWORD '{{ .password }}'; + END IF; + END $$; + SELECT format('CREATE DATABASE %I OWNER %I', '{{ .name }}', '{{ .user }}') + WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = '{{ .name }}')\gexec + GRANT ALL PRIVILEGES ON DATABASE {{ .name }} TO {{ .user }}; + {{- end }} + SQL + env: + - name: DB_HOST + value: {{ .Values.dbInit.host | quote }} + - name: DB_PORT + value: {{ .Values.dbInit.port | default "5432" | quote }} + - name: ADMIN_USER + value: {{ .Values.dbInit.adminUser | quote }} + - name: ADMIN_PASSWORD + {{- if .Values.dbInit.adminPasswordSecret }} + valueFrom: + secretKeyRef: + name: {{ .Values.dbInit.adminPasswordSecret.name }} + key: {{ .Values.dbInit.adminPasswordSecret.key }} + {{- else }} + value: {{ .Values.dbInit.adminPassword | quote }} + {{- end }} + backoffLimit: 3 +{{- end }} diff --git a/deploy/helm/codex-lb/templates/hooks/migration-job.yaml b/deploy/helm/codex-lb/templates/hooks/migration-job.yaml index 55e2daf4..097bfbc0 100644 --- a/deploy/helm/codex-lb/templates/hooks/migration-job.yaml +++ b/deploy/helm/codex-lb/templates/hooks/migration-job.yaml @@ -35,8 +35,12 @@ spec: {{- range $pullSecrets }} - name: {{ . }} {{- end }} - {{- end }} - {{- if .Values.postgresql.enabled }} + {{- end }} + {{- with (include "codex-lb.nodeSelector" .) }} + nodeSelector: + {{- . | nindent 8 }} + {{- end }} + {{- if .Values.postgresql.enabled }} initContainers: - name: wait-for-db image: postgres:16-alpine diff --git a/deploy/helm/codex-lb/templates/tests/test-connection.yaml b/deploy/helm/codex-lb/templates/tests/test-connection.yaml index 68396259..cc5e2ad5 100644 --- a/deploy/helm/codex-lb/templates/tests/test-connection.yaml +++ b/deploy/helm/codex-lb/templates/tests/test-connection.yaml @@ -15,6 +15,10 @@ spec: runAsUser: 1000 seccompProfile: type: RuntimeDefault + {{- with (include "codex-lb.nodeSelector" .) }} + nodeSelector: + {{- . | nindent 4 }} + {{- end }} containers: - name: test-connection image: busybox:1.37 diff --git a/deploy/helm/codex-lb/values.yaml b/deploy/helm/codex-lb/values.yaml index e7537e1e..193de8a6 100644 --- a/deploy/helm/codex-lb/values.yaml +++ b/deploy/helm/codex-lb/values.yaml @@ -6,6 +6,8 @@ global: imagePullSecrets: [] # @param global.storageClass Global storage class for PVCs storageClass: "" + # @param global.nodeSelector Node selector labels applied to ALL pods (deployment, jobs, tests) + nodeSelector: {} # @section Common parameters # @param nameOverride Override the chart name @@ -295,6 +297,13 @@ metrics: port: 9090 serviceMonitor: # @param metrics.serviceMonitor.enabled Create a ServiceMonitor for Prometheus Operator + # Defaults to false because it requires the Prometheus Operator CRDs to be installed. + # Enable this when running kube-prometheus-stack or standalone Prometheus Operator. + # Without ServiceMonitor, configure prometheus.io annotations for scraping: + # commonAnnotations: + # prometheus.io/scrape: "true" + # prometheus.io/port: "9090" + # prometheus.io/path: "/metrics" enabled: false # @param metrics.serviceMonitor.interval Metrics scrape interval interval: 30s @@ -306,6 +315,8 @@ metrics: relabelings: [] prometheusRule: # @param metrics.prometheusRule.enabled Create PrometheusRule for alerting + # Requires Prometheus Operator. Includes alerts for: high error rate, circuit breaker open, + # all accounts exhausted, high request latency. See templates/prometheusrule.yaml for details. enabled: false # @param metrics.prometheusRule.additionalLabels Additional labels for PrometheusRule additionalLabels: {} @@ -355,6 +366,28 @@ externalDatabase: # @param externalDatabase.existingSecret Secret containing external DB credentials existingSecret: "" +# @section Database initialization parameters +dbInit: + # @param dbInit.enabled Enable pre-install Job to create databases/users on external PostgreSQL + enabled: false + # @param dbInit.host External PostgreSQL host + host: "" + # @param dbInit.port External PostgreSQL port + port: "5432" + # @param dbInit.adminUser Admin username for creating databases/users + adminUser: "adminuser" + # @param dbInit.adminPassword Admin password (use adminPasswordSecret for production) + adminPassword: "" + # @param dbInit.adminPasswordSecret Reference to existing Secret for admin password + adminPasswordSecret: {} + # name: pg-admin-secret + # key: password + # @param dbInit.databases List of databases and users to create + databases: + - name: codexlb + user: codexlb + password: changeme + # @section Migration parameters migration: # @param migration.enabled Run database migration Job on install/upgrade