Skip to content

B #65: Fix Helm 4.0 compatibility for chart installation#66

Open
carloshm91 wants to merge 1 commit intoOpenNebula:masterfrom
carloshm91:fix/helm4-compatibility
Open

B #65: Fix Helm 4.0 compatibility for chart installation#66
carloshm91 wants to merge 1 commit intoOpenNebula:masterfrom
carloshm91:fix/helm4-compatibility

Conversation

@carloshm91
Copy link

Summary

Fixes #65 — Helm chart installation fails with Helm 4.0 due to stricter Server-Side Apply (SSA) validation.

Two issues were found and fixed:

  1. CONTROL_PLANE_HOST renders as YAML null for type: string CRD fields — When CONTROL_PLANE_HOST is empty in values.yaml (the default for non-VIP deployments), the generated chart template produces floatingIP: (bare empty value), which YAML interprets as null. Helm 3 was lenient about this, but Helm 4's SSA rejects it:

    spec.publicNetwork.floatingIP: Invalid value: "null":
      spec.publicNetwork.floatingIP in body must be of type string: "null"
    
  2. remediationStrategy field rejected as undeclared in RKE2ControlPlane CRD schema — The rke2 cluster template included remediationStrategy (with maxRetry and retryPeriod), but this field was introduced in cluster-api-provider-rke2 v0.15.0. This project depends on v0.12.0, where the field does not exist in the CRD. Helm 3 silently ignored it with a warning; Helm 4 SSA rejects unknown fields:

    failed to create typed patch object: .spec.remediationStrategy: field not declared in schema
    

Changes

Makefile (line 196)

-CONTROL_PLANE_HOST := {{ .Values.CONTROL_PLANE_HOST }}
+CONTROL_PLANE_HOST := {{ .Values.CONTROL_PLANE_HOST | default "" | quote }}
  • | default "" converts nil to an empty string explicitly
  • | quote wraps the output in YAML double quotes, ensuring the empty string renders as "" instead of bare empty (which YAML parses as null)

Both are needed because kustomize build strips the original YAML quotes from the source templates during re-serialization (e.g., "${CONTROL_PLANE_HOST}" becomes ${CONTROL_PLANE_HOST}), so envsubst produces an unquoted Helm expression in the final chart template.

kustomize/v1beta1/rke2/cluster-template.yaml

Removed the remediationStrategy block from RKE2ControlPlane spec. This field does not exist in the cluster-api-provider-rke2 v0.12.0 CRD that this project depends on (it was added in v0.15.0). The other RKE2 template variants (rke2-dev, rke2-vip, rke2-e2e) already did not include this field.

api/v1beta1/zz_generated.deepcopy.go and config/crd/bases/infrastructure.cluster.x-k8s.io_oneclusters.yaml

These are auto-generated files regenerated by controller-gen during make build. They were outdated since PR #54 added the ImageDatastoreId *uint pointer field to ONEImage but did not regenerate these artifacts. The changes are:

  • deepcopy: Now properly deep-copies the ImageDatastoreId *uint pointer (allocates a new uint instead of copying the pointer address)
  • CRD: Removes incorrect format: int32 (the Go type is *uint, not *int32) and removes default: 1 (no +kubebuilder:default marker exists in the struct definition)

Validation

Tested with real helm install (not just helm template) against a Kind cluster (Kubernetes v1.35.0) with all CRDs installed (CAPONE, CAPI v1.9.5, RKE2 v0.12.0):

# Helm Version Chart CONTROL_PLANE_HOST Result
1 v3.18.3 capone-kadm empty deployed
2 v4.0.5 capone-kadm empty deployed
3 v3.18.3 capone-kadm 10.2.11.86 deployed
4 v4.0.5 capone-kadm 10.2.11.86 deployed
5 v3.18.3 capone-rke2 empty deployed
6 v4.0.5 capone-rke2 empty deployed
7 v3.18.3 capone-rke2 10.2.11.86 deployed
8 v4.0.5 capone-rke2 10.2.11.86 deployed

All 8 scenarios pass. The floatingIP field is stored as "" (empty string) when unset, and as the provided IP when set — matching the expected behavior for the ONECluster controller.

Helm 4.0 uses Server-Side Apply (SSA) which enforces strict OpenAPI
schema validation. This caused two installation failures:

1. CONTROL_PLANE_HOST null value rejected as non-string
2. remediationStrategy field rejected as undeclared in CRD schema
@jaimecb
Copy link
Contributor

jaimecb commented Feb 20, 2026

Hi, thank you for taking the time to contribute!

I believe we should include // +kubebuilder:default=1 in the ImageDatastoreId field of the ONEImage struct to ensure it remains compatible with existing definitions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CAPONE helm chart compatibility issues with Helm 4.0

2 participants