diff --git a/api/v2/helmrelease_types.go b/api/v2/helmrelease_types.go index 50a132bae..08b1379a0 100644 --- a/api/v2/helmrelease_types.go +++ b/api/v2/helmrelease_types.go @@ -933,6 +933,11 @@ type HelmReleaseStatus struct { // +optional ObservedGeneration int64 `json:"observedGeneration,omitempty"` + // ObservedPostRenderersDigest is the digest for the post-renderers of + // the last successful reconciliation attempt. + // +optional + ObservedPostRenderersDigest string `json:"ObservedPostRenderersDigest,omitempty"` + // LastAttemptedGeneration is the last generation the controller attempted // to reconcile. // +optional @@ -1008,11 +1013,6 @@ type HelmReleaseStatus struct { // +optional LastAttemptedConfigDigest string `json:"lastAttemptedConfigDigest,omitempty"` - // LastAttemptedPostRenderersDigest is the digest for the post-renderers of - // the last reconciliation attempt. - // +optional - LastAttemptedPostRenderersDigest string `json:"lastAttemptedPostRenderersDigest,omitempty"` - // LastHandledForceAt holds the value of the most recent force request // value, so a change of the annotation value can be detected. // +optional diff --git a/api/v2beta1/helmrelease_types.go b/api/v2beta1/helmrelease_types.go index 691fa2e4b..b72f1a18b 100644 --- a/api/v2beta1/helmrelease_types.go +++ b/api/v2beta1/helmrelease_types.go @@ -875,6 +875,11 @@ type HelmReleaseStatus struct { // +optional ObservedGeneration int64 `json:"observedGeneration,omitempty"` + // ObservedPostRenderersDigest is the digest for the post-renderers of + // the last successful reconciliation attempt. + // +optional + ObservedPostRenderersDigest string `json:"ObservedPostRenderersDigest,omitempty"` + meta.ReconcileRequestStatus `json:",inline"` // Conditions holds the conditions for the HelmRelease. @@ -950,11 +955,6 @@ type HelmReleaseStatus struct { // +optional LastAttemptedConfigDigest string `json:"lastAttemptedConfigDigest,omitempty"` - // LastAttemptedPostRenderersDigest is the digest for the post-renderers of - // the last reconciliation attempt. - // +optional - LastAttemptedPostRenderersDigest string `json:"lastAttemptedPostRenderersDigest,omitempty"` - // LastAttemptedReleaseAction is the last release action performed for this // HelmRelease. It is used to determine the active remediation strategy. // diff --git a/api/v2beta2/helmrelease_types.go b/api/v2beta2/helmrelease_types.go index 22f88670e..df1fc25b6 100644 --- a/api/v2beta2/helmrelease_types.go +++ b/api/v2beta2/helmrelease_types.go @@ -953,6 +953,11 @@ type HelmReleaseStatus struct { // +optional ObservedGeneration int64 `json:"observedGeneration,omitempty"` + // ObservedPostRenderersDigest is the digest for the post-renderers of + // the last successful reconciliation attempt. + // +optional + ObservedPostRenderersDigest string `json:"ObservedPostRenderersDigest,omitempty"` + // LastAttemptedGeneration is the last generation the controller attempted // to reconcile. // +optional @@ -1034,11 +1039,6 @@ type HelmReleaseStatus struct { // +optional LastAttemptedConfigDigest string `json:"lastAttemptedConfigDigest,omitempty"` - // LastAttemptedPostRenderersDigest is the digest for the post-renderers of - // the last reconciliation attempt. - // +optional - LastAttemptedPostRenderersDigest string `json:"lastAttemptedPostRenderersDigest,omitempty"` - // LastHandledForceAt holds the value of the most recent force request // value, so a change of the annotation value can be detected. // +optional diff --git a/config/crd/bases/helm.toolkit.fluxcd.io_helmreleases.yaml b/config/crd/bases/helm.toolkit.fluxcd.io_helmreleases.yaml index 9ea45d357..25860c95c 100644 --- a/config/crd/bases/helm.toolkit.fluxcd.io_helmreleases.yaml +++ b/config/crd/bases/helm.toolkit.fluxcd.io_helmreleases.yaml @@ -906,6 +906,11 @@ spec: observedGeneration: -1 description: HelmReleaseStatus defines the observed state of a HelmRelease. properties: + ObservedPostRenderersDigest: + description: |- + ObservedPostRenderersDigest is the digest for the post-renderers of + the last successful reconciliation attempt. + type: string conditions: description: Conditions holds the conditions for the HelmRelease. items: @@ -1110,11 +1115,6 @@ spec: to reconcile. format: int64 type: integer - lastAttemptedPostRenderersDigest: - description: |- - LastAttemptedPostRenderersDigest is the digest for the post-renderers of - the last reconciliation attempt. - type: string lastAttemptedReleaseAction: description: |- LastAttemptedReleaseAction is the last release action performed for this @@ -2129,6 +2129,11 @@ spec: observedGeneration: -1 description: HelmReleaseStatus defines the observed state of a HelmRelease. properties: + ObservedPostRenderersDigest: + description: |- + ObservedPostRenderersDigest is the digest for the post-renderers of + the last successful reconciliation attempt. + type: string conditions: description: Conditions holds the conditions for the HelmRelease. items: @@ -2349,11 +2354,6 @@ spec: by v2beta1 HelmReleases. format: int64 type: integer - lastAttemptedPostRenderersDigest: - description: |- - LastAttemptedPostRenderersDigest is the digest for the post-renderers of - the last reconciliation attempt. - type: string lastAttemptedReleaseAction: description: |- LastAttemptedReleaseAction is the last release action performed for this @@ -3427,6 +3427,11 @@ spec: observedGeneration: -1 description: HelmReleaseStatus defines the observed state of a HelmRelease. properties: + ObservedPostRenderersDigest: + description: |- + ObservedPostRenderersDigest is the digest for the post-renderers of + the last successful reconciliation attempt. + type: string conditions: description: Conditions holds the conditions for the HelmRelease. items: @@ -3637,11 +3642,6 @@ spec: to reconcile. format: int64 type: integer - lastAttemptedPostRenderersDigest: - description: |- - LastAttemptedPostRenderersDigest is the digest for the post-renderers of - the last reconciliation attempt. - type: string lastAttemptedReleaseAction: description: |- LastAttemptedReleaseAction is the last release action performed for this diff --git a/docs/api/v2/helm.md b/docs/api/v2/helm.md index 11e6765d4..ec8bd14e9 100644 --- a/docs/api/v2/helm.md +++ b/docs/api/v2/helm.md @@ -1434,6 +1434,19 @@ int64 +ObservedPostRenderersDigest
+ +string + + + +(Optional) +

ObservedPostRenderersDigest is the digest for the post-renderers of +the last successful reconciliation attempt.

+ + + + lastAttemptedGeneration
int64 @@ -1623,19 +1636,6 @@ string -lastAttemptedPostRenderersDigest
- -string - - - -(Optional) -

LastAttemptedPostRenderersDigest is the digest for the post-renderers of -the last reconciliation attempt.

- - - - lastHandledForceAt
string diff --git a/docs/spec/v2/helmreleases.md b/docs/spec/v2/helmreleases.md index 137a22f5b..5104e19de 100644 --- a/docs/spec/v2/helmreleases.md +++ b/docs/spec/v2/helmreleases.md @@ -1666,6 +1666,16 @@ The helm-controller reports an observed generation in the HelmRelease's `.metadata.generation` which resulted in either a [ready state](#ready-helmrelease), or stalled due to error it can not recover from without human intervention. +### Oberved Post Renderers Digest + +The helm-controller reports the digest for the [post renderers](#post-renderers) +it last rendered the Helm chart with in the for a successful Helm install or +upgrade in the `.status.ObervedPostRenderersDigest` field. + +This field is used by the controller to determine if a deployed Helm release +is in sync with the HelmRelease `spec.PostRenderers` configuration and whether +it should trigger a Helm upgrade. + ### Last Attempted Config Digest The helm-controller reports the digest for the [values](#values) it last @@ -1675,15 +1685,6 @@ attempted to perform a Helm install or upgrade with in the The digest is used to determine if the controller should reset the [failure counters](#failure-counters) due to a change in the values. -### Last Attempted Post Renderers Digest - -The helm-controller reports the digest for the [post renderers](#post-renderers) -it last attempted to perform a Helm install or upgrade with in the -`.status.lastAttemptedPostRenderersDigest` field. - -This field is used by the controller to determine if a deployed Helm release -is in sync with the HelmRelease `spec.PostRenderers` configuration and whether -it should trigger a Helm upgrade. ### Last Attempted Revision diff --git a/internal/controller/helmrelease_controller.go b/internal/controller/helmrelease_controller.go index 667500c44..9d0220e7c 100644 --- a/internal/controller/helmrelease_controller.go +++ b/internal/controller/helmrelease_controller.go @@ -393,15 +393,6 @@ func (r *HelmReleaseReconciler) reconcileRelease(ctx context.Context, patchHelpe obj.Status.LastAttemptedRevisionDigest = ociDigest obj.Status.LastAttemptedConfigDigest = chartutil.DigestValues(digest.Canonical, values).String() obj.Status.LastAttemptedValuesChecksum = "" - // Keep track of the post-renderers digest used during the last reconciliation. - // This is used to determine if the post-renderers have changed. - oldPostRenderersDigest := obj.Status.LastAttemptedPostRenderersDigest - // remove stale post-renderers digest - obj.Status.LastAttemptedPostRenderersDigest = "" - if obj.Spec.PostRenderers != nil { - // Update the post-renderers digest if the post-renderers exist. - obj.Status.LastAttemptedPostRenderersDigest = postrender.Digest(digest.Canonical, obj.Spec.PostRenderers).String() - } obj.Status.LastReleaseRevision = 0 // Construct config factory for any further Helm actions. @@ -420,10 +411,9 @@ func (r *HelmReleaseReconciler) reconcileRelease(ctx context.Context, patchHelpe // Off we go! if err = intreconcile.NewAtomicRelease(patchHelper, cfg, r.EventRecorder, r.FieldManager).Reconcile(ctx, &intreconcile.Request{ - Object: obj, - Chart: loadedChart, - Values: values, - PreviousPostrendersDigest: oldPostRenderersDigest, + Object: obj, + Chart: loadedChart, + Values: values, }); err != nil { if errors.Is(err, intreconcile.ErrMustRequeue) { return ctrl.Result{Requeue: true}, nil @@ -658,8 +648,8 @@ func (r *HelmReleaseReconciler) adoptLegacyRelease(ctx context.Context, getter g return nil } -// adoptPostRenderersStatus attempts to set obj.Status.LastAttemptedPostRenderersDigest -// for v1beta1 and v1beta2 HelmReleases. +// adoptPostRenderersStatus attempts to set obj.Status.ObservedPostRenderersDigest +// for v2beta1 and v2beta2 HelmReleases. func (*HelmReleaseReconciler) adoptPostRenderersStatus(obj *v2.HelmRelease) { if obj.GetGeneration() != obj.Status.ObservedGeneration { return @@ -667,8 +657,8 @@ func (*HelmReleaseReconciler) adoptPostRenderersStatus(obj *v2.HelmRelease) { // if we have a reconciled object with PostRenderers not reflected in the // status, we need to update the status. - if obj.Spec.PostRenderers != nil && obj.Status.LastAttemptedPostRenderersDigest == "" { - obj.Status.LastAttemptedPostRenderersDigest = postrender.Digest(digest.Canonical, obj.Spec.PostRenderers).String() + if obj.Spec.PostRenderers != nil && obj.Status.ObservedPostRenderersDigest == "" { + obj.Status.ObservedPostRenderersDigest = postrender.Digest(digest.Canonical, obj.Spec.PostRenderers).String() } } diff --git a/internal/controller/helmrelease_controller_test.go b/internal/controller/helmrelease_controller_test.go index ebde22e79..d998a6ef6 100644 --- a/internal/controller/helmrelease_controller_test.go +++ b/internal/controller/helmrelease_controller_test.go @@ -1269,7 +1269,7 @@ func TestHelmReleaseReconciler_reconcileReleaseFromHelmChartSource(t *testing.T) }, } - obj.Status.LastAttemptedPostRenderersDigest = postrender.Digest(digest.Canonical, obj.Spec.PostRenderers).String() + obj.Status.ObservedPostRenderersDigest = postrender.Digest(digest.Canonical, obj.Spec.PostRenderers).String() obj.Status.LastAttemptedConfigDigest = chartutil.DigestValues(digest.Canonical, chartMock.Values).String() c := fake.NewClientBuilder(). @@ -1304,13 +1304,10 @@ func TestHelmReleaseReconciler_reconcileReleaseFromHelmChartSource(t *testing.T) // Verify attempted values are set. g.Expect(obj.Status.LastAttemptedGeneration).To(Equal(obj.Generation)) - g.Expect(obj.Status.LastAttemptedPostRenderersDigest).To(Equal(postrender.Digest(digest.Canonical, obj.Spec.PostRenderers).String())) + g.Expect(obj.Status.ObservedPostRenderersDigest).To(Equal(postrender.Digest(digest.Canonical, obj.Spec.PostRenderers).String())) // verify upgrade succeeded g.Expect(obj.Status.Conditions).To(conditions.MatchConditions([]metav1.Condition{ - *conditions.TrueCondition(meta.ReconcilingCondition, meta.ProgressingWithRetryReason, "Helm upgrade succeeded for release %s with chart %s", - fmt.Sprintf("%s/%s.v%d", rls.Namespace, rls.Name, rls.Version+1), fmt.Sprintf("%s@%s", chartMock.Name(), - chartMock.Metadata.Version)), *conditions.TrueCondition(meta.ReadyCondition, v2.UpgradeSucceededReason, "Helm upgrade succeeded for release %s with chart %s", fmt.Sprintf("%s/%s.v%d", rls.Namespace, rls.Name, rls.Version+1), fmt.Sprintf("%s@%s", chartMock.Name(), chartMock.Metadata.Version)), diff --git a/internal/reconcile/reconcile.go b/internal/reconcile/reconcile.go index 353dee0ff..6c51dd1cc 100644 --- a/internal/reconcile/reconcile.go +++ b/internal/reconcile/reconcile.go @@ -83,9 +83,6 @@ type Request struct { // Values is the Helm chart values to be used for the installation or // upgrade. Values helmchartutil.Values - // PreviousPostrendersDigest is the digest of the post-renderers that were used - // during the last reconciliation. - PreviousPostrendersDigest string } // ActionReconciler is an interface which defines the methods that a reconciler diff --git a/internal/reconcile/release.go b/internal/reconcile/release.go index 049eaf421..75dc2c3a7 100644 --- a/internal/reconcile/release.go +++ b/internal/reconcile/release.go @@ -28,6 +28,8 @@ import ( v2 "github.com/fluxcd/helm-controller/api/v2" "github.com/fluxcd/helm-controller/internal/action" + "github.com/fluxcd/helm-controller/internal/digest" + "github.com/fluxcd/helm-controller/internal/postrender" "github.com/fluxcd/helm-controller/internal/release" "github.com/fluxcd/helm-controller/internal/storage" ) @@ -137,6 +139,8 @@ func observeRelease(observed observedReleases) storage.ObserveFunc { // tests are not enabled, and excluding it when failures must be ignored. // // If Ready=True, any Stalled condition is removed. +// +// The ObservedPostRenderersDigest is updated if the post-renderers exist. func summarize(req *Request) { var sumConds = []string{v2.RemediatedCondition, v2.ReleasedCondition} if req.Object.GetTest().Enable && !req.Object.GetTest().IgnoreFailures { @@ -186,6 +190,13 @@ func summarize(req *Request) { Message: conds[0].Message, ObservedGeneration: req.Object.Generation, }) + + // remove stale post-renderers digest + req.Object.Status.ObservedPostRenderersDigest = "" + if req.Object.Spec.PostRenderers != nil { + // Update the post-renderers digest if the post-renderers exist. + req.Object.Status.ObservedPostRenderersDigest = postrender.Digest(digest.Canonical, req.Object.Spec.PostRenderers).String() + } } // eventMessageWithLog returns an event message composed out of the given diff --git a/internal/reconcile/state.go b/internal/reconcile/state.go index ea8b2504c..be255d11c 100644 --- a/internal/reconcile/state.go +++ b/internal/reconcile/state.go @@ -27,7 +27,9 @@ import ( ctrl "sigs.k8s.io/controller-runtime" "github.com/fluxcd/helm-controller/internal/action" + "github.com/fluxcd/helm-controller/internal/digest" interrors "github.com/fluxcd/helm-controller/internal/errors" + "github.com/fluxcd/helm-controller/internal/postrender" ) // ReleaseStatus represents the status of a Helm release as determined by @@ -142,7 +144,11 @@ func DetermineReleaseState(ctx context.Context, cfg *action.ConfigFactory, req * } // Verify if postrender digest has changed - if req.PreviousPostrendersDigest != req.Object.Status.LastAttemptedPostRenderersDigest { + var postrenderersDigest string + if req.Object.Spec.PostRenderers != nil { + postrenderersDigest = postrender.Digest(digest.Canonical, req.Object.Spec.PostRenderers).String() + } + if postrenderersDigest != req.Object.Status.ObservedPostRenderersDigest { return ReleaseState{Status: ReleaseStatusOutOfSync, Reason: "postrender digest has changed"}, nil }