From e84bf07a94043be0eb5c12a3b2f0ce72dba07c1d Mon Sep 17 00:00:00 2001 From: MergeCheck Date: Fri, 3 Jul 2026 09:45:22 -0300 Subject: [PATCH 1/2] fix(ddns-updater): align template validation standards --- charts/ddns-updater/templates/NOTES.txt | 113 +++++++++++------- charts/ddns-updater/templates/_helpers.tpl | 11 ++ charts/ddns-updater/templates/ingress.yaml | 4 +- charts/ddns-updater/templates/validate.yaml | 2 + charts/ddns-updater/tests/ingress_test.yaml | 13 ++ .../ddns-updater/tests/validation_test.yaml | 25 ++++ 6 files changed, 126 insertions(+), 42 deletions(-) create mode 100644 charts/ddns-updater/templates/validate.yaml create mode 100644 charts/ddns-updater/tests/validation_test.yaml diff --git a/charts/ddns-updater/templates/NOTES.txt b/charts/ddns-updater/templates/NOTES.txt index 9670aa81e..1c264999a 100644 --- a/charts/ddns-updater/templates/NOTES.txt +++ b/charts/ddns-updater/templates/NOTES.txt @@ -1,58 +1,89 @@ {{/* SPDX-License-Identifier: Apache-2.0 */}} -DDNS Updater has been deployed. +ddns-updater has been deployed. -Release: - Chart: {{ .Chart.Name }} - Version: {{ .Chart.Version }} - AppVersion: {{ .Chart.AppVersion }} - Release: {{ .Release.Name }} - Namespace: {{ .Release.Namespace }} - -Access: - DDNS Updater runs as a background service. The web UI is not exposed outside - the cluster unless ingress is enabled. +1. Installation summary +----------------------- +Chart: {{ .Chart.Name }} +Version: {{ .Chart.Version }} +AppVersion: {{ .Chart.AppVersion }} +Release: {{ .Release.Name }} +Namespace: {{ .Release.Namespace }} +Image: {{ include "ddns-updater.image" . }} +2. Access +--------- +DDNS Updater runs as a background service. The web UI is exposed outside the +cluster only when ingress is enabled. {{- if .Values.ingress.enabled }} {{- range $host := .Values.ingress.hosts }} - Web UI: http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}/ +{{- if $host.host }} +Web UI: http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}/ +{{- else }} +Web UI: hostless ingress is enabled. Use the external address assigned by your ingress controller. +{{- end }} {{- end }} {{- else }} - Port-forward: - kubectl port-forward -n {{ .Release.Namespace }} svc/{{ include "ddns-updater.fullname" . }} 8000:{{ .Values.service.port }} +Port-forward: + + kubectl port-forward -n {{ .Release.Namespace }} svc/{{ include "ddns-updater.fullname" . }} 8000:{{ .Values.service.port }} + +Web UI: - Web UI: - http://localhost:8000/ + http://localhost:8000/ {{- end }} -Configuration: +3. Getting started +------------------ +Check pod status: + + kubectl get pods -l app.kubernetes.io/instance={{ .Release.Name }} -n {{ .Release.Namespace }} + +Follow logs: + + kubectl logs -l app.kubernetes.io/instance={{ .Release.Name }} -n {{ .Release.Namespace }} --all-containers --tail=50 -f + +4. Credentials +-------------- {{- if .Values.config.existingSecret }} - Config source: existing Secret {{ .Values.config.existingSecret }} - Config key: {{ .Values.config.existingSecretKey }} +Config source: existing Secret {{ .Values.config.existingSecret }} +Config key: {{ .Values.config.existingSecretKey }} {{- else }} - Config source: chart-managed Secret {{ include "ddns-updater.configSecretName" . }} - Records: {{ len (.Values.config.settings | default list) }} +Config source: chart-managed Secret {{ include "ddns-updater.configSecretName" . }} +Configured records: {{ len (.Values.config.settings | default list) }} {{- end }} - Data path: /updater/data - Persistence: {{ ternary "enabled" "disabled" .Values.persistence.enabled }} - -Security: - ServiceAccount token automount: {{ .Values.serviceAccount.automountServiceAccountToken }} - Run as non-root: {{ .Values.podSecurityContext.runAsNonRoot }} - Read-only root filesystem: {{ .Values.securityContext.readOnlyRootFilesystem }} - -Next Steps: - 1. Check pod status: - kubectl get pods -l app.kubernetes.io/name=ddns-updater -n {{ .Release.Namespace }} - 2. Follow logs: - kubectl logs -l app.kubernetes.io/name=ddns-updater -n {{ .Release.Namespace }} --all-containers --tail=50 -f - 3. Confirm provider credentials and DNS records in the web UI or logs. - -Troubleshooting: - kubectl describe pod -l app.kubernetes.io/name=ddns-updater -n {{ .Release.Namespace }} - kubectl logs -l app.kubernetes.io/name=ddns-updater -n {{ .Release.Namespace }} --all-containers --tail=100 + +5. Configuration +---------------- +Data path: /updater/data +Persistence: {{ ternary "enabled" "disabled" .Values.persistence.enabled }} +Root URL: {{ .Values.ddns.rootUrl }} +Update period: {{ .Values.ddns.period }} +Public IP fetchers: {{ .Values.ddns.publicIpFetchers }} + +6. Security +----------- +ServiceAccount token automount: {{ .Values.serviceAccount.automountServiceAccountToken }} +Run as non-root: {{ .Values.podSecurityContext.runAsNonRoot }} +Read-only root filesystem: {{ .Values.securityContext.readOnlyRootFilesystem }} + +7. Troubleshooting +------------------ +Describe pod: + + kubectl describe pod -l app.kubernetes.io/instance={{ .Release.Name }} -n {{ .Release.Namespace }} + +Inspect recent logs: + + kubectl logs -l app.kubernetes.io/instance={{ .Release.Name }} -n {{ .Release.Namespace }} --all-containers --tail=100 + +List related resources: + kubectl get all,pvc -l app.kubernetes.io/instance={{ .Release.Name }} -n {{ .Release.Namespace }} -Documentation: - https://helmforge.dev/docs/charts/ddns-updater +8. Resources +------------ +Chart docs: https://helmforge.dev/docs/charts/ddns-updater +Chart source: https://github.com/helmforgedev/charts/tree/main/charts/ddns-updater +Upstream project: https://github.com/qdm12/ddns-updater Happy Helmforging :) diff --git a/charts/ddns-updater/templates/_helpers.tpl b/charts/ddns-updater/templates/_helpers.tpl index cc2e6bbbf..c9bba0e50 100644 --- a/charts/ddns-updater/templates/_helpers.tpl +++ b/charts/ddns-updater/templates/_helpers.tpl @@ -43,6 +43,17 @@ app.kubernetes.io/instance: {{ .Release.Name }} {{- printf "%s:%s" .Values.image.repository .Values.image.tag -}} {{- end -}} +{{- define "ddns-updater.validate" -}} +{{- if and .Values.ingress.enabled (not .Values.ingress.hosts) -}} +{{- fail "ingress.hosts must contain at least one rule when ingress.enabled=true" -}} +{{- end -}} +{{- range $key, $_ := .Values.podLabels -}} +{{- if or (eq $key "app.kubernetes.io/name") (eq $key "app.kubernetes.io/instance") -}} +{{- fail (printf "podLabels must not override selector label %q" $key) -}} +{{- end -}} +{{- end -}} +{{- end -}} + {{/* Config secret name */}} {{- define "ddns-updater.configSecretName" -}} {{- if .Values.config.existingSecret -}} diff --git a/charts/ddns-updater/templates/ingress.yaml b/charts/ddns-updater/templates/ingress.yaml index 2c0032ede..dc75827c4 100644 --- a/charts/ddns-updater/templates/ingress.yaml +++ b/charts/ddns-updater/templates/ingress.yaml @@ -26,7 +26,9 @@ spec: {{- end }} rules: {{- range .Values.ingress.hosts }} - - host: {{ .host | quote }} + - {{- with .host }} + host: {{ . | quote }} + {{- end }} http: paths: {{- range (.paths | default (list (dict "path" "/" "pathType" "Prefix"))) }} diff --git a/charts/ddns-updater/templates/validate.yaml b/charts/ddns-updater/templates/validate.yaml new file mode 100644 index 000000000..5e00daa35 --- /dev/null +++ b/charts/ddns-updater/templates/validate.yaml @@ -0,0 +1,2 @@ +{{/* SPDX-License-Identifier: Apache-2.0 */}} +{{- include "ddns-updater.validate" . -}} diff --git a/charts/ddns-updater/tests/ingress_test.yaml b/charts/ddns-updater/tests/ingress_test.yaml index ac0247777..d52b15ab3 100644 --- a/charts/ddns-updater/tests/ingress_test.yaml +++ b/charts/ddns-updater/tests/ingress_test.yaml @@ -56,3 +56,16 @@ tests: - equal: path: spec.ingressClassName value: nginx + + - it: should support hostless catch-all rules + set: + ingress.enabled: true + ingress.hosts: + - paths: + - path: / + pathType: Prefix + asserts: + - isKind: + of: Ingress + - notExists: + path: spec.rules[0].host diff --git a/charts/ddns-updater/tests/validation_test.yaml b/charts/ddns-updater/tests/validation_test.yaml new file mode 100644 index 000000000..fa41d8943 --- /dev/null +++ b/charts/ddns-updater/tests/validation_test.yaml @@ -0,0 +1,25 @@ +# SPDX-License-Identifier: Apache-2.0 +suite: Validation +templates: + - templates/validate.yaml +tests: + - it: should render no validation manifest by default + asserts: + - hasDocuments: + count: 0 + + - it: should fail when ingress has no rules + set: + ingress.enabled: true + ingress.hosts: [] + asserts: + - failedTemplate: + errorMessage: "ingress.hosts must contain at least one rule when ingress.enabled=true" + + - it: should fail when podLabels override selector labels + set: + podLabels: + app.kubernetes.io/name: custom + asserts: + - failedTemplate: + errorMessage: 'podLabels must not override selector label "app.kubernetes.io/name"' From 62454a9eaececaa887b216c74a1396c219d75f65 Mon Sep 17 00:00:00 2001 From: MergeCheck Date: Sun, 5 Jul 2026 18:56:25 -0300 Subject: [PATCH 2/2] test(ddns-updater): cover selector label validation --- charts/ddns-updater/templates/_helpers.tpl | 6 ++++-- charts/ddns-updater/tests/validation_test.yaml | 8 ++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/charts/ddns-updater/templates/_helpers.tpl b/charts/ddns-updater/templates/_helpers.tpl index c9bba0e50..223371b27 100644 --- a/charts/ddns-updater/templates/_helpers.tpl +++ b/charts/ddns-updater/templates/_helpers.tpl @@ -47,8 +47,10 @@ app.kubernetes.io/instance: {{ .Release.Name }} {{- if and .Values.ingress.enabled (not .Values.ingress.hosts) -}} {{- fail "ingress.hosts must contain at least one rule when ingress.enabled=true" -}} {{- end -}} -{{- range $key, $_ := .Values.podLabels -}} -{{- if or (eq $key "app.kubernetes.io/name") (eq $key "app.kubernetes.io/instance") -}} +{{- $podLabels := .Values.podLabels | default dict -}} +{{- $selectorLabels := include "ddns-updater.selectorLabels" . | fromYaml -}} +{{- range $key, $_ := $selectorLabels -}} +{{- if hasKey $podLabels $key -}} {{- fail (printf "podLabels must not override selector label %q" $key) -}} {{- end -}} {{- end -}} diff --git a/charts/ddns-updater/tests/validation_test.yaml b/charts/ddns-updater/tests/validation_test.yaml index fa41d8943..eadd73143 100644 --- a/charts/ddns-updater/tests/validation_test.yaml +++ b/charts/ddns-updater/tests/validation_test.yaml @@ -23,3 +23,11 @@ tests: asserts: - failedTemplate: errorMessage: 'podLabels must not override selector label "app.kubernetes.io/name"' + + - it: should fail when podLabels override release selector labels + set: + podLabels: + app.kubernetes.io/instance: custom + asserts: + - failedTemplate: + errorMessage: 'podLabels must not override selector label "app.kubernetes.io/instance"'