Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 29 additions & 3 deletions charts/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,20 @@ spec:
- name: db-migrate
image: "{{ .Values.image.registry }}/{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
command: ["/app/hyperfleet-api", "migrate"]
command:
- /app/hyperfleet-api
- migrate
{{- if and .Values.database.external.enabled .Values.database.external.usePodIdentity }}
- --db-host-file={{ .Values.database.external.secretMountPath }}/db.host
- --db-port-file={{ .Values.database.external.secretMountPath }}/db.port
- --db-name-file={{ .Values.database.external.secretMountPath }}/db.name
- --db-user-file={{ .Values.database.external.secretMountPath }}/db.user
- --db-password-file={{ .Values.database.external.secretMountPath }}/db.password
- --db-sslmode={{ .Values.database.external.sslMode | default "require" }}
{{- end }}
volumeMounts:
- name: secrets
mountPath: /build/secrets
mountPath: {{ if and .Values.database.external.enabled .Values.database.external.usePodIdentity }}{{ .Values.database.external.secretMountPath }}{{ else }}/build/secrets{{ end }}
readOnly: true
{{- end }}
containers:
Expand All @@ -55,6 +65,14 @@ spec:
- --api-server-bindaddress={{ .Values.server.bindAddress | default ":8000" }}
- --health-server-bindaddress={{ .Values.server.healthBindAddress | default ":8080" }}
- --metrics-server-bindaddress={{ .Values.server.metricsBindAddress | default ":9090" }}
{{- if and .Values.database.external.enabled .Values.database.external.usePodIdentity }}
- --db-host-file={{ .Values.database.external.secretMountPath }}/db.host
- --db-port-file={{ .Values.database.external.secretMountPath }}/db.port
- --db-name-file={{ .Values.database.external.secretMountPath }}/db.name
- --db-user-file={{ .Values.database.external.secretMountPath }}/db.user
- --db-password-file={{ .Values.database.external.secretMountPath }}/db.password
- --db-sslmode={{ .Values.database.external.sslMode | default "require" }}
{{- end }}
ports:
- name: http
containerPort: 8000
Expand Down Expand Up @@ -113,7 +131,7 @@ spec:
mountPath: /tmp
{{- if or .Values.database.external.enabled .Values.database.postgresql.enabled }}
- name: secrets
mountPath: /build/secrets
mountPath: {{ if and .Values.database.external.enabled .Values.database.external.usePodIdentity }}{{ .Values.database.external.secretMountPath }}{{ else }}/build/secrets{{ end }}
readOnly: true
{{- end }}
{{- if .Values.extraVolumeMounts }}
Expand All @@ -124,13 +142,21 @@ spec:
emptyDir: {}
{{- if or .Values.database.external.enabled .Values.database.postgresql.enabled }}
- name: secrets
{{- if and .Values.database.external.enabled .Values.database.external.usePodIdentity }}
csi:
driver: secrets-store.csi.k8s.io
readOnly: true
volumeAttributes:
secretProviderClass: {{ ternary (printf "%s-db-secrets" (include "hyperfleet-api.fullname" .)) .Values.database.external.secretProviderClass .Values.database.external.createSecretProviderClass | quote }}
{{- else }}
Comment on lines +145 to +151
Copy link

@coderabbitai coderabbitai bot Mar 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Add a render-time guard for empty secretProviderClass.

At Line 150, if createSecretProviderClass=false and database.external.secretProviderClass is empty, the pod renders with an invalid CSI config and fails at startup.

🔧 Proposed fix
       - name: secrets
       {{- if and .Values.database.external.enabled .Values.database.external.usePodIdentity }}
+        {{- $spcName := ternary (printf "%s-db-secrets" (include "hyperfleet-api.fullname" .)) .Values.database.external.secretProviderClass .Values.database.external.createSecretProviderClass }}
+        {{- if empty $spcName }}
+        {{- fail "database.external.secretProviderClass is required when usePodIdentity=true and createSecretProviderClass=false" }}
+        {{- end }}
         csi:
           driver: secrets-store.csi.k8s.io
           readOnly: true
           volumeAttributes:
-            secretProviderClass: {{ ternary (printf "%s-db-secrets" (include "hyperfleet-api.fullname" .)) .Values.database.external.secretProviderClass .Values.database.external.createSecretProviderClass | quote }}
+            secretProviderClass: {{ $spcName | quote }}
       {{- else }}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@charts/templates/deployment.yaml` around lines 145 - 151, The CSI
volumeAttributes currently always renders a secretProviderClass even when
.Values.database.external.createSecretProviderClass is false and
.Values.database.external.secretProviderClass is empty; update the template
around the csi block to conditionally render the secretProviderClass key only
when the computed value is non-empty (check
.Values.database.external.createSecretProviderClass OR
.Values.database.external.secretProviderClass) so the CSI config is omitted if
no provider class is provided; locate the ternary expression that builds the
name (uses include "hyperfleet-api.fullname",
.Values.database.external.secretProviderClass,
.Values.database.external.createSecretProviderClass) and wrap or gate the
secretProviderClass output with an if that ensures the rendered string is not
empty.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will add

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cdoan1, sounds good! The proposed fix above adds the $spcName variable and the {{- if empty $spcName }} guard to fail early at render time, so it should be straightforward to drop in. Feel free to ping me once it's in and I'll take another look. 👍


🧠 Learnings used
Learnt from: rafabene
Repo: openshift-hyperfleet/hyperfleet-api PR: 43
File: charts/templates/servicemonitor.yaml:1-1
Timestamp: 2026-02-02T18:38:24.725Z
Learning: In the openshift-hyperfleet/hyperfleet-api repo, Helm template files under charts/templates/ use Go template syntax (e.g., {{ .Values.xxx }}). Do not lint or flag yamllint errors for these files, as standard YAML linters do not understand Helm Go templates. If you must lint, configure yamllint to skip these files or use a Helm-aware linter.

secret:
{{- if .Values.database.external.enabled }}
secretName: {{ .Values.database.external.secretName }}
{{- else }}
secretName: {{ include "hyperfleet-api.fullname" . }}-db-secrets
{{- end }}
{{- end }}
{{- end }}
{{- if .Values.extraVolumes }}
{{- toYaml .Values.extraVolumes | nindent 6 }}
{{- end }}
Expand Down
28 changes: 28 additions & 0 deletions charts/templates/secretproviderclass.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{{- if and .Values.database.external.enabled .Values.database.external.usePodIdentity .Values.database.external.createSecretProviderClass }}
apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
name: {{ include "hyperfleet-api.fullname" . }}-db-secrets
namespace: {{ .Release.Namespace }}
labels:
{{- include "hyperfleet-api.labels" . | nindent 4 }}
spec:
provider: aws
parameters:
usePodIdentity: "true"
region: {{ .Values.database.external.aws.region | quote }}
objects: |
- objectName: {{ .Values.database.external.aws.secretName | quote }}
objectType: "secretsmanager"
Comment on lines +13 to +16
Copy link

@coderabbitai coderabbitai bot Mar 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Fail fast when AWS SecretProviderClass inputs are empty.

At Line 13 and Line 15, empty region or objectName can render successfully but fail later at pod mount/runtime. Guard these with required so misconfiguration is caught during template rendering.

🔧 Proposed fix
 {{- if and .Values.database.external.enabled .Values.database.external.usePodIdentity .Values.database.external.createSecretProviderClass }}
+{{- $awsRegion := required "database.external.aws.region is required when createSecretProviderClass=true" .Values.database.external.aws.region }}
+{{- $awsSecretName := required "database.external.aws.secretName is required when createSecretProviderClass=true" .Values.database.external.aws.secretName }}
 apiVersion: secrets-store.csi.x-k8s.io/v1
 kind: SecretProviderClass
 metadata:
@@
 spec:
   provider: aws
   parameters:
     usePodIdentity: "true"
-    region: {{ .Values.database.external.aws.region | quote }}
+    region: {{ $awsRegion | quote }}
     objects: |
-      - objectName: {{ .Values.database.external.aws.secretName | quote }}
+      - objectName: {{ $awsSecretName | quote }}
         objectType: "secretsmanager"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
region: {{ .Values.database.external.aws.region | quote }}
objects: |
- objectName: {{ .Values.database.external.aws.secretName | quote }}
objectType: "secretsmanager"
{{- if and .Values.database.external.enabled .Values.database.external.usePodIdentity .Values.database.external.createSecretProviderClass }}
{{- $awsRegion := required "database.external.aws.region is required when createSecretProviderClass=true" .Values.database.external.aws.region }}
{{- $awsSecretName := required "database.external.aws.secretName is required when createSecretProviderClass=true" .Values.database.external.aws.secretName }}
apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
name: {{ .Values.database.external.secretProviderClassName }}
spec:
provider: aws
parameters:
usePodIdentity: "true"
region: {{ $awsRegion | quote }}
objects: |
- objectName: {{ $awsSecretName | quote }}
objectType: "secretsmanager"
{{- end }}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@charts/templates/secretproviderclass.yaml` around lines 13 - 16, The
SecretProviderClass template currently renders potentially empty values for
region and objectName which defers failure to runtime; update the template to
validate and fail fast by wrapping .Values.database.external.aws.region and
.Values.database.external.aws.secretName with the Helm required function (e.g.,
required "aws.region is required" .Values.database.external.aws.region) so
template rendering fails when those inputs are empty; ensure the required checks
are applied where region and objectName are inserted in the SecretProviderClass
objects block to prevent creating a pod-mount-time error.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will add

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cdoan1, sounds good! Here's a quick recap of the proposed change for reference when you implement it:

{{- if and .Values.database.external.enabled .Values.database.external.usePodIdentity .Values.database.external.createSecretProviderClass }}
{{- $awsRegion := required "database.external.aws.region is required when createSecretProviderClass=true" .Values.database.external.aws.region }}
{{- $awsSecretName := required "database.external.aws.secretName is required when createSecretProviderClass=true" .Values.database.external.aws.secretName }}
apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
  name: {{ include "hyperfleet-api.fullname" . }}-db-secrets
  namespace: {{ .Release.Namespace }}
  labels:
    {{- include "hyperfleet-api.labels" . | nindent 4 }}
spec:
  provider: aws
  parameters:
    usePodIdentity: "true"
    region: {{ $awsRegion | quote }}
    objects: |
      - objectName: {{ $awsSecretName | quote }}
        objectType: "secretsmanager"

Using required ensures helm template / helm install fails immediately with a clear error message if either value is missing, rather than silently producing a broken SecretProviderClass that only fails at pod mount time.


🧠 Learnings used
Learnt from: rafabene
Repo: openshift-hyperfleet/hyperfleet-api PR: 43
File: charts/templates/servicemonitor.yaml:1-1
Timestamp: 2026-02-02T18:38:24.725Z
Learning: In the openshift-hyperfleet/hyperfleet-api repo, Helm template files under charts/templates/ use Go template syntax (e.g., {{ .Values.xxx }}). Do not lint or flag yamllint errors for these files, as standard YAML linters do not understand Helm Go templates. If you must lint, configure yamllint to skip these files or use a Helm-aware linter.

jmesPath:
- path: "username"
objectAlias: "db.user"
- path: "password"
objectAlias: "db.password"
- path: "host"
objectAlias: "db.host"
- path: "port"
objectAlias: "db.port"
- path: "database"
objectAlias: "db.name"
{{- end }}
32 changes: 22 additions & 10 deletions charts/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,21 @@ database:
enabled: false
# Name of existing secret with db.host, db.port, db.name, db.user, db.password keys
secretName: ""
# Use AWS Pod Identity / Secrets Store CSI driver for DB credentials (no Kubernetes Secret)
usePodIdentity: false
# Mount path for CSI secrets-store volume (when usePodIdentity is true)
secretMountPath: /mnt/secrets-store
# Name of SecretProviderClass for CSI secrets-store driver (required when usePodIdentity is true and createSecretProviderClass is false)
secretProviderClass: ""
# Create a SecretProviderClass from the chart (uses database.external.aws when true)
createSecretProviderClass: false
# AWS Secrets Manager config when createSecretProviderClass is true
aws:
region: ""
# Secrets Manager secret name or ARN (objectName in SecretProviderClass)
secretName: "hyperfleet/db-credentials"
# PostgreSQL SSL mode: disable | require | verify-ca | verify-full
sslMode: require

# Built-in PostgreSQL for development/testing
postgresql:
Expand Down Expand Up @@ -126,15 +141,12 @@ auth:

# Adapter configuration (REQUIRED)
# Configure which adapters must be ready for resources to be marked as "Ready"
# Both cluster and nodepool adapters MUST be specified - the application will not start without them
# Empty arrays [] are valid if you want no adapters required for the Ready state
# Both cluster and nodepool MUST be specified (empty arrays [] are valid)
adapters:
# Required adapters for cluster "Ready" state (REQUIRED)
# Example: ["validation", "dns", "pullsecret", "hypershift"]
# cluster: []
# Required adapters for nodepool "Ready" state (REQUIRED)
# Example: ["validation", "hypershift"]
# nodepool: []
# Required adapters for cluster "Ready" state. Example: ["validation", "dns", "pullsecret", "hypershift"]
cluster: []
# Required adapters for nodepool "Ready" state. Example: ["validation", "hypershift"]
nodepool: []

# ServiceMonitor for Prometheus Operator
# Enables automatic metrics discovery in clusters with Prometheus Operator
Expand All @@ -155,8 +167,8 @@ serviceMonitor:
# Additional environment variables
# You can override adapters by setting HYPERFLEET_*_ADAPTERS here
env: []
# - name: GLOG_V
# value: "10"
# - name: GLOG_V
# value: "10"

# Volume mounts for additional configs
extraVolumeMounts: []
Expand Down