Skip to content
Merged
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
43 changes: 43 additions & 0 deletions charts/dolibarr/templates/_helpers.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -262,3 +262,46 @@ true
{{- end -}}
{{- end -}}
{{- end -}}

{{- define "dolibarr.validate" -}}
{{- $_ := include "dolibarr.databaseMode" . -}}
{{- if .Values.backup.enabled -}}
{{- $_ := include "dolibarr.backupEnabled" . -}}
{{- end -}}
{{- if and .Values.ingress.enabled (not .Values.ingress.hosts) -}}
{{- fail "ingress.hosts must contain at least one rule when ingress.enabled=true" -}}
{{- end -}}
{{- if .Values.gateway.enabled -}}
{{- if not .Values.gateway.parentRefs -}}
{{- fail "gateway.enabled requires gateway.parentRefs to be populated to create a valid HTTPRoute." -}}
{{- end -}}
{{- range .Values.gateway.parentRefs -}}
{{- if not .name -}}
{{- fail "Each gateway.parentRefs entry must define a 'name' field" -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{- if .Values.externalSecrets.enabled -}}
{{- if not .Values.admin.existingSecret -}}
{{- fail "externalSecrets.enabled requires admin.existingSecret to be set to prevent credential drift between the chart-managed Secret and the ExternalSecret." -}}
{{- end -}}
{{- if not .Values.externalSecrets.data -}}
{{- fail "externalSecrets.data must not be empty when externalSecrets.enabled=true" -}}
{{- end -}}
{{- $passKey := .Values.admin.existingSecretPasswordKey | default "admin-password" -}}
{{- $hasPass := false -}}
{{- range .Values.externalSecrets.data -}}
{{- if eq .secretKey $passKey }}{{ $hasPass = true }}{{ end -}}
{{- end -}}
{{- if not $hasPass -}}
{{- fail (printf "externalSecrets.data must include a mapping for key '%s' (admin password)" $passKey) -}}
{{- end -}}
{{- end -}}
{{- $podLabels := .Values.podLabels | default dict -}}
{{- if hasKey $podLabels "app.kubernetes.io/name" -}}
{{- fail "podLabels must not override selector label app.kubernetes.io/name" -}}
{{- end -}}
{{- if hasKey $podLabels "app.kubernetes.io/instance" -}}
{{- fail "podLabels must not override selector label app.kubernetes.io/instance" -}}
{{- end -}}
{{- end -}}
2 changes: 2 additions & 0 deletions charts/dolibarr/templates/validate.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
{{/* SPDX-License-Identifier: Apache-2.0 */}}
{{- include "dolibarr.validate" . -}}
113 changes: 113 additions & 0 deletions charts/dolibarr/tests/validation_test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
# SPDX-License-Identifier: Apache-2.0
suite: Validation
templates:
- templates/validate.yaml
tests:
- it: should reject ingress without rules
set:
ingress.enabled: true
ingress.hosts: []
asserts:
- failedTemplate:
errorMessage: "ingress.hosts must contain at least one rule when ingress.enabled=true"

- it: should reject gateway without parentRefs
set:
gateway.enabled: true
gateway.parentRefs: []
asserts:
- failedTemplate:
errorMessage: "gateway.enabled requires gateway.parentRefs to be populated to create a valid HTTPRoute."

- it: should reject gateway parentRefs entry missing name
set:
gateway.enabled: true
gateway.parentRefs:
- namespace: default
asserts:
- failedTemplate:
errorMessage: "Each gateway.parentRefs entry must define a 'name' field"

- it: should reject reserved selector label overrides
set:
podLabels:
app.kubernetes.io/name: custom
asserts:
- failedTemplate:
errorMessage: "podLabels must not override selector label app.kubernetes.io/name"

- it: should reject reserved instance selector label overrides
set:
podLabels:
app.kubernetes.io/instance: custom
asserts:
- failedTemplate:
errorMessage: "podLabels must not override selector label app.kubernetes.io/instance"

- it: should allow null pod labels
set:
podLabels: null
asserts:
- notFailedTemplate: {}

- it: should reject missing backup settings
set:
backup.enabled: true
backup.s3.bucket: dolibarr-backups
asserts:
- failedTemplate:
errorMessage: "backup.enabled requires backup.s3.endpoint, backup.s3.bucket, and either backup.s3.existingSecret or both backup.s3.accessKey and backup.s3.secretKey"

- it: should reject external secrets without an existing admin secret
set:
externalSecrets.enabled: true
externalSecrets.data:
- secretKey: admin-password
remoteRef:
key: dolibarr/admin
asserts:
- failedTemplate:
errorMessage: "externalSecrets.enabled requires admin.existingSecret to be set to prevent credential drift between the chart-managed Secret and the ExternalSecret."

- it: should reject external secrets without data
set:
admin.existingSecret: dolibarr-admin
externalSecrets.enabled: true
externalSecrets.data: []
asserts:
- failedTemplate:
errorMessage: "externalSecrets.data must not be empty when externalSecrets.enabled=true"

- it: should reject external secrets missing admin password mapping
set:
admin.existingSecret: dolibarr-admin
externalSecrets.enabled: true
externalSecrets.data:
- secretKey: some-other-key
remoteRef:
key: dolibarr/other
asserts:
- failedTemplate:
errorMessage: "externalSecrets.data must include a mapping for key 'admin-password' (admin password)"

- it: should allow ingress gateway and external secrets together
set:
admin.existingSecret: dolibarr-admin
ingress.enabled: true
ingress.hosts:
- host: dolibarr.example.com
paths:
- path: /
pathType: Prefix
gateway.enabled: true
gateway.parentRefs:
- name: shared-gateway
namespace: default
externalSecrets.enabled: true
externalSecrets.secretStoreRef.name: fake-store
externalSecrets.data:
- secretKey: admin-password
remoteRef:
key: dolibarr/admin-password
asserts:
- notFailedTemplate: {}