From da47b70e2cc2fd2124b554c8151bdb45beee4a52 Mon Sep 17 00:00:00 2001 From: Ivan Okhotnikov Date: Tue, 14 Jul 2026 12:02:23 +0300 Subject: [PATCH] fix(fluxcd): omit empty distribution.artifact in FluxInstance The flux-instance template rendered spec.distribution.artifact unconditionally, unlike the sibling optional fields (artifactPullSecret, imagePullSecret, variant). The umbrella default is empty to use the operator's embedded manifests (the air-gapped default from #964), but an empty value renders as YAML null. In the flux-operator v0.50.0 CRD the field is optional yet typed 'string' with pattern ^oci://.*$ and is not nullable, so the rendered null (like an empty string) fails schema validation and the API rejects the FluxInstance. Guest Kubernetes clusters with the fluxcd addon enabled could therefore never install it: the sub-release looped install/uninstall, the parent kubernetes release stayed InProgress, and the cluster never reached Ready. Guard the field so an empty value is omitted (the operator falls back to its embedded manifests, preserving the air-gapped default) while a non-empty artifact still renders. The template lives in the vendored subchart, so the change is carried as a patch applied by 'make update'. Signed-off-by: Ivan Okhotnikov --- packages/system/fluxcd/Makefile | 3 ++- .../flux-instance/templates/instance.yaml | 2 ++ .../patches/guard-distribution-artifact.diff | 22 +++++++++++++++++++ 3 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 packages/system/fluxcd/patches/guard-distribution-artifact.diff diff --git a/packages/system/fluxcd/Makefile b/packages/system/fluxcd/Makefile index 9aa32fe9b..c398a1b7e 100644 --- a/packages/system/fluxcd/Makefile +++ b/packages/system/fluxcd/Makefile @@ -8,4 +8,5 @@ apply-locally: update: rm -rf charts - helm pull oci://ghcr.io/controlplaneio-fluxcd/charts/flux-instance --untar --untardir charts + helm pull oci://ghcr.io/controlplaneio-fluxcd/charts/flux-instance --version 0.50.0 --untar --untardir charts + patch --no-backup-if-mismatch -p1 < patches/guard-distribution-artifact.diff diff --git a/packages/system/fluxcd/charts/flux-instance/templates/instance.yaml b/packages/system/fluxcd/charts/flux-instance/templates/instance.yaml index f1f58309e..5217c24d9 100644 --- a/packages/system/fluxcd/charts/flux-instance/templates/instance.yaml +++ b/packages/system/fluxcd/charts/flux-instance/templates/instance.yaml @@ -16,7 +16,9 @@ spec: distribution: version: {{ .Values.instance.distribution.version | quote }} registry: {{ .Values.instance.distribution.registry }} + {{- if .Values.instance.distribution.artifact }} artifact: {{ .Values.instance.distribution.artifact }} + {{- end }} {{- if .Values.instance.distribution.artifactPullSecret }} artifactPullSecret: {{ .Values.instance.distribution.artifactPullSecret }} {{- end }} diff --git a/packages/system/fluxcd/patches/guard-distribution-artifact.diff b/packages/system/fluxcd/patches/guard-distribution-artifact.diff new file mode 100644 index 000000000..57348afe5 --- /dev/null +++ b/packages/system/fluxcd/patches/guard-distribution-artifact.diff @@ -0,0 +1,22 @@ +# Upstream bug: flux-instance's instance.yaml renders spec.distribution.artifact +# unconditionally, unlike the sibling optional fields (artifactPullSecret, +# imagePullSecret, variant). The umbrella's empty default then renders as +# `artifact: null`, which the FluxInstance CRD rejects (type: string, +# pattern ^oci://.*$, and the field is optional). Guard it like its siblings. +# +# Chart source: https://github.com/controlplaneio-fluxcd/charts (flux-instance) +# Not yet reported upstream; drop this hunk once upstream guards the field. +diff --git a/charts/flux-instance/templates/instance.yaml b/charts/flux-instance/templates/instance.yaml +index f1f58309e..5217c24d9 100644 +--- a/charts/flux-instance/templates/instance.yaml ++++ b/charts/flux-instance/templates/instance.yaml +@@ -16,7 +16,9 @@ spec: + distribution: + version: {{ .Values.instance.distribution.version | quote }} + registry: {{ .Values.instance.distribution.registry }} ++ {{- if .Values.instance.distribution.artifact }} + artifact: {{ .Values.instance.distribution.artifact }} ++ {{- end }} + {{- if .Values.instance.distribution.artifactPullSecret }} + artifactPullSecret: {{ .Values.instance.distribution.artifactPullSecret }} + {{- end }}