Add DisableChartDigestTracking feature gate

Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
This commit is contained in:
Stefan Prodan 2025-05-08 00:53:15 +03:00
parent b91fd90c75
commit da305300b3
No known key found for this signature in database
GPG Key ID: 3299AEB0E4085BAF
5 changed files with 39 additions and 14 deletions

View File

@ -217,6 +217,9 @@ The controller will automatically perform a Helm upgrade when the `OCIRepository
detects a new digest in the OCI artifact stored in registry, even if the version
inside `Chart.yaml` is unchanged.
**Note:** Disabling the appending of the digest to the chart version can be done
with the `--feature-gates=DisableChartDigestTracking=true` controller flag.
**Warning:** One of `.spec.chart` or `.spec.chartRef` must be set, but not both.
When switching from `.spec.chart` to `.spec.chartRef`, the controller will perform
an Helm upgrade and will garbage collect the old HelmChart object.

View File

@ -94,8 +94,9 @@ type HelmReleaseReconciler struct {
KubeConfigOpts runtimeClient.KubeConfigOptions
APIReader client.Reader
FieldManager string
DefaultServiceAccount string
FieldManager string
DefaultServiceAccount string
DisableChartDigestTracking bool
requeueDependency time.Duration
artifactFetchRetries int
@ -343,7 +344,7 @@ func (r *HelmReleaseReconciler) reconcileRelease(ctx context.Context, patchHelpe
conditions.MarkUnknown(obj, meta.ReadyCondition, meta.ProgressingReason, "reconciliation in progress")
}
ociDigest, err := mutateChartWithSourceRevision(loadedChart, source)
ociDigest, err := r.mutateChartWithSourceRevision(loadedChart, source)
if err != nil {
conditions.MarkFalse(obj, meta.ReadyCondition, "ChartMutateError", "%s", err)
return ctrl.Result{}, err
@ -902,7 +903,7 @@ func getNamespacedName(obj *v2.HelmRelease) (types.NamespacedName, error) {
return namespacedName, nil
}
func mutateChartWithSourceRevision(chart *chart.Chart, source sourcev1.Source) (string, error) {
func (r *HelmReleaseReconciler) mutateChartWithSourceRevision(chart *chart.Chart, source sourcev1.Source) (string, error) {
// If the source is an OCIRepository, we can try to mutate the chart version
// with the artifact revision. The revision is either a <tag>@<digest> or
// just a digest.
@ -957,7 +958,10 @@ func mutateChartWithSourceRevision(chart *chart.Chart, source sourcev1.Source) (
ociDigest = revision
}
chart.Metadata.Version = ver.String()
if !r.DisableChartDigestTracking {
chart.Metadata.Version = ver.String()
}
return ociDigest, nil
}

View File

@ -3926,7 +3926,8 @@ func Test_TryMutateChartWithSourceRevision(t *testing.T) {
},
}
_, err := mutateChartWithSourceRevision(c, s)
r := &HelmReleaseReconciler{}
_, err := r.mutateChartWithSourceRevision(c, s)
if tt.wantErr {
g.Expect(err).To(HaveOccurred())
} else {

View File

@ -58,6 +58,13 @@ const (
// without the need to upgrade the Helm release. But it can be disabled to
// avoid potential abuse of the adoption mechanism.
AdoptLegacyReleases = "AdoptLegacyReleases"
// DisableChartDigestTracking disables the tracking of digest changes
// for Helm OCI charts. When enabled, the controller will not trigger
// a Helm release upgrade if the chart version stays the same, but its
// digest changes. When enabled, the controller will not
// append the digest to the chart version in Chart.yaml.
DisableChartDigestTracking = "DisableChartDigestTracking"
)
var features = map[string]bool{
@ -79,6 +86,9 @@ var features = map[string]bool{
// AdoptLegacyReleases
// opt-out from v0.37
AdoptLegacyReleases: true,
// DisableChartDigestTracking
// opt-in from v1.3.0
DisableChartDigestTracking: false,
}
// FeatureGates contains a list of all supported feature gates and

23
main.go
View File

@ -181,6 +181,12 @@ func main() {
leaderElectionId = leaderelection.GenerateID(leaderElectionId, watchOptions.LabelSelector)
}
disableChartDigestTracking, err := features.Enabled(features.DisableChartDigestTracking)
if err != nil {
setupLog.Error(err, "unable to check feature gate DisableChartDigestTracking")
os.Exit(1)
}
// Set the managedFields owner for resources reconciled from Helm charts.
kube.ManagedFieldsManager = controllerName
@ -269,14 +275,15 @@ func main() {
}
if err = (&controller.HelmReleaseReconciler{
Client: mgr.GetClient(),
APIReader: mgr.GetAPIReader(),
EventRecorder: eventRecorder,
Metrics: metricsH,
GetClusterConfig: ctrl.GetConfig,
ClientOpts: clientOptions,
KubeConfigOpts: kubeConfigOpts,
FieldManager: controllerName,
Client: mgr.GetClient(),
APIReader: mgr.GetAPIReader(),
EventRecorder: eventRecorder,
Metrics: metricsH,
GetClusterConfig: ctrl.GetConfig,
ClientOpts: clientOptions,
KubeConfigOpts: kubeConfigOpts,
FieldManager: controllerName,
DisableChartDigestTracking: disableChartDigestTracking,
}).SetupWithManager(ctx, mgr, controller.HelmReleaseReconcilerOptions{
DependencyRequeueInterval: requeueDependency,
HTTPRetry: httpRetry,