Skip to content

Commit ccb7071

Browse files
committed
Remove adoption of resources in old API versions
Signed-off-by: Matheus Pimenta <matheuscscp@gmail.com>
1 parent dacd7ea commit ccb7071

File tree

4 files changed

+9
-262
lines changed

4 files changed

+9
-262
lines changed

internal/controller/helmrelease_controller.go

Lines changed: 0 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ import (
2727
"github.com/fluxcd/cli-utils/pkg/kstatus/polling/engine"
2828
celtypes "github.com/google/cel-go/common/types"
2929
chart "helm.sh/helm/v4/pkg/chart/v2"
30-
helmrelease "helm.sh/helm/v4/pkg/release/v1"
3130
corev1 "k8s.io/api/core/v1"
3231
apiequality "k8s.io/apimachinery/pkg/api/equality"
3332
apierrors "k8s.io/apimachinery/pkg/api/errors"
@@ -70,9 +69,7 @@ import (
7069
"github.com/fluxcd/helm-controller/internal/features"
7170
"github.com/fluxcd/helm-controller/internal/kube"
7271
"github.com/fluxcd/helm-controller/internal/loader"
73-
"github.com/fluxcd/helm-controller/internal/postrender"
7472
intreconcile "github.com/fluxcd/helm-controller/internal/reconcile"
75-
"github.com/fluxcd/helm-controller/internal/release"
7673
)
7774

7875
// +kubebuilder:rbac:groups=helm.toolkit.fluxcd.io,resources=helmreleases,verbs=get;list;watch;create;update;patch;delete
@@ -369,19 +366,6 @@ func (r *HelmReleaseReconciler) reconcileRelease(ctx context.Context,
369366
conditions.MarkUnknown(obj, meta.ReadyCondition, meta.ProgressingReason, "reconciliation in progress")
370367
}
371368

372-
// Keep feature flagged code paths separate from the main reconciliation
373-
// logic to ensure easy removal when the feature flag is removed.
374-
if ok, _ := features.Enabled(features.AdoptLegacyReleases); ok {
375-
// Attempt to adopt "legacy" v2beta1 release state on a best-effort basis.
376-
// If this fails, the controller will fall back to performing an upgrade
377-
// to settle on the desired state.
378-
// TODO(hidde): remove this in a future release.
379-
if err := r.adoptLegacyRelease(ctx, getter, statusReader, obj); err != nil {
380-
log.Error(err, "failed to adopt v2beta1 release state")
381-
}
382-
r.adoptPostRenderersStatus(obj)
383-
}
384-
385369
// If the release target configuration has changed, we need to uninstall the
386370
// previous release target first. If we did not do this, the installation would
387371
// fail due to resources already existing.
@@ -681,81 +665,6 @@ func (r *HelmReleaseReconciler) evalReadyExpr(
681665
return celExpr.EvaluateBoolean(ctx, vars)
682666
}
683667

684-
// adoptLegacyRelease attempts to adopt a v2beta1 release into a v2
685-
// release.
686-
// This is done by retrieving the last successful release from the Helm storage
687-
// and converting it to a v2 release snapshot.
688-
// If the v2beta1 release has already been adopted, this function is a no-op.
689-
func (r *HelmReleaseReconciler) adoptLegacyRelease(ctx context.Context,
690-
getter genericclioptions.RESTClientGetter, statusReader engine.StatusReader, obj *v2.HelmRelease) error {
691-
692-
if obj.Status.LastReleaseRevision < 1 || len(obj.Status.History) > 0 {
693-
return nil
694-
}
695-
696-
var (
697-
log = ctrl.LoggerFrom(ctx).V(logger.DebugLevel)
698-
storageNamespace = obj.GetStorageNamespace()
699-
releaseNamespace = obj.GetReleaseNamespace()
700-
releaseName = obj.GetReleaseName()
701-
version = obj.Status.LastReleaseRevision
702-
)
703-
704-
log.Info("adopting %s/%s.v%d release from v2beta1 state", releaseNamespace, releaseName, version)
705-
706-
// Construct config factory for current release.
707-
cfg, err := action.NewConfigFactory(getter,
708-
action.WithStorage(action.DefaultStorageDriver, storageNamespace),
709-
action.WithStorageLog(action.NewTraceLogger(ctx)),
710-
action.WithStatusReader(statusReader),
711-
)
712-
if err != nil {
713-
return err
714-
}
715-
716-
// Get the last successful release based on the observation for the v2beta1
717-
// object.
718-
rls, err := cfg.NewStorage().Get(releaseName, version)
719-
if err != nil {
720-
return err
721-
}
722-
723-
// Convert it to a v2 release snapshot.
724-
rlsTyped, ok := rls.(*helmrelease.Release)
725-
if !ok {
726-
return fmt.Errorf("only the Chart API v2 is supported")
727-
}
728-
snap := release.ObservedToSnapshot(release.ObserveRelease(rlsTyped))
729-
730-
// If tests are enabled, include them as well.
731-
if obj.GetTest().Enable {
732-
snap.SetTestHooks(release.TestHooksFromRelease(rlsTyped))
733-
}
734-
735-
// Adopt it as the current release in the history.
736-
obj.Status.History = append(obj.Status.History, snap)
737-
obj.Status.StorageNamespace = storageNamespace
738-
739-
// Erase the last release revision from the status.
740-
obj.Status.LastReleaseRevision = 0
741-
742-
return nil
743-
}
744-
745-
// adoptPostRenderersStatus attempts to set obj.Status.ObservedPostRenderersDigest
746-
// for v2beta1 and v2beta2 HelmReleases.
747-
func (*HelmReleaseReconciler) adoptPostRenderersStatus(obj *v2.HelmRelease) {
748-
if obj.GetGeneration() != obj.Status.ObservedGeneration {
749-
return
750-
}
751-
752-
// if we have a reconciled object with PostRenderers not reflected in the
753-
// status, we need to update the status.
754-
if obj.Spec.PostRenderers != nil && obj.Status.ObservedPostRenderersDigest == "" {
755-
obj.Status.ObservedPostRenderersDigest = postrender.Digest(digest.Canonical, obj.Spec.PostRenderers).String()
756-
}
757-
}
758-
759668
func (r *HelmReleaseReconciler) buildRESTClientGetter(ctx context.Context, obj *v2.HelmRelease) (genericclioptions.RESTClientGetter, error) {
760669
opts := []kube.Option{
761670
kube.WithNamespace(obj.GetReleaseNamespace()),

internal/controller/helmrelease_controller_test.go

Lines changed: 0 additions & 169 deletions
Original file line numberDiff line numberDiff line change
@@ -3300,175 +3300,6 @@ dep.metadata.generation == dep.status.observedGeneration
33003300
}
33013301
}
33023302

3303-
func TestHelmReleaseReconciler_adoptLegacyRelease(t *testing.T) {
3304-
tests := []struct {
3305-
name string
3306-
releases func(namespace string) []*helmrelease.Release
3307-
spec func(spec *v2.HelmReleaseSpec)
3308-
status v2.HelmReleaseStatus
3309-
expectHistory func(releases []*helmrelease.Release) v2.Snapshots
3310-
expectLastReleaseRevision int
3311-
wantErr bool
3312-
}{
3313-
{
3314-
name: "adopts last release revision",
3315-
releases: func(namespace string) []*helmrelease.Release {
3316-
return []*helmrelease.Release{
3317-
testutil.BuildRelease(&helmrelease.MockReleaseOptions{
3318-
Name: "orphaned",
3319-
Namespace: namespace,
3320-
Version: 6,
3321-
Chart: testutil.BuildChart(),
3322-
Status: helmreleasecommon.StatusDeployed,
3323-
}, testutil.ReleaseWithTestHook()),
3324-
}
3325-
},
3326-
spec: func(spec *v2.HelmReleaseSpec) {
3327-
spec.ReleaseName = "orphaned"
3328-
},
3329-
status: v2.HelmReleaseStatus{
3330-
LastReleaseRevision: 6,
3331-
},
3332-
expectHistory: func(releases []*helmrelease.Release) v2.Snapshots {
3333-
return v2.Snapshots{
3334-
release.ObservedToSnapshot(release.ObserveRelease(releases[0])),
3335-
}
3336-
},
3337-
expectLastReleaseRevision: 0,
3338-
},
3339-
{
3340-
name: "includes test hooks if enabled",
3341-
releases: func(namespace string) []*helmrelease.Release {
3342-
return []*helmrelease.Release{
3343-
testutil.BuildRelease(&helmrelease.MockReleaseOptions{
3344-
Name: "orphaned-with-hooks",
3345-
Namespace: namespace,
3346-
Version: 3,
3347-
Chart: testutil.BuildChart(testutil.ChartWithTestHook()),
3348-
Status: helmreleasecommon.StatusDeployed,
3349-
}, testutil.ReleaseWithTestHook()),
3350-
}
3351-
},
3352-
spec: func(spec *v2.HelmReleaseSpec) {
3353-
spec.ReleaseName = "orphaned-with-hooks"
3354-
spec.Test = &v2.Test{
3355-
Enable: true,
3356-
}
3357-
},
3358-
status: v2.HelmReleaseStatus{
3359-
LastReleaseRevision: 3,
3360-
},
3361-
expectHistory: func(releases []*helmrelease.Release) v2.Snapshots {
3362-
snap := release.ObservedToSnapshot(release.ObserveRelease(releases[0]))
3363-
snap.SetTestHooks(release.TestHooksFromRelease(releases[0]))
3364-
3365-
return v2.Snapshots{
3366-
snap,
3367-
}
3368-
},
3369-
expectLastReleaseRevision: 0,
3370-
},
3371-
{
3372-
name: "non-existing release",
3373-
spec: func(spec *v2.HelmReleaseSpec) {
3374-
spec.ReleaseName = "non-existing"
3375-
},
3376-
status: v2.HelmReleaseStatus{
3377-
LastReleaseRevision: 2,
3378-
},
3379-
expectLastReleaseRevision: 2,
3380-
wantErr: true,
3381-
},
3382-
{
3383-
name: "without last release revision",
3384-
status: v2.HelmReleaseStatus{
3385-
LastReleaseRevision: 0,
3386-
},
3387-
expectHistory: func(releases []*helmrelease.Release) v2.Snapshots {
3388-
return nil
3389-
},
3390-
expectLastReleaseRevision: 0,
3391-
},
3392-
{
3393-
name: "with existing history",
3394-
status: v2.HelmReleaseStatus{
3395-
History: v2.Snapshots{
3396-
{
3397-
Name: "something",
3398-
},
3399-
},
3400-
LastReleaseRevision: 5,
3401-
},
3402-
expectHistory: func(releases []*helmrelease.Release) v2.Snapshots {
3403-
return v2.Snapshots{
3404-
{
3405-
Name: "something",
3406-
},
3407-
}
3408-
},
3409-
expectLastReleaseRevision: 5,
3410-
},
3411-
}
3412-
3413-
for _, tt := range tests {
3414-
t.Run(tt.name, func(t *testing.T) {
3415-
g := NewWithT(t)
3416-
3417-
// Create a test namespace for storing the Helm release mock.
3418-
ns, err := testEnv.CreateNamespace(context.TODO(), "adopt-release")
3419-
g.Expect(err).ToNot(HaveOccurred())
3420-
t.Cleanup(func() {
3421-
_ = testEnv.Delete(context.TODO(), ns)
3422-
})
3423-
3424-
// Mock a HelmRelease object.
3425-
obj := &v2.HelmRelease{
3426-
Spec: v2.HelmReleaseSpec{
3427-
StorageNamespace: ns.Name,
3428-
},
3429-
Status: tt.status,
3430-
}
3431-
if tt.spec != nil {
3432-
tt.spec(&obj.Spec)
3433-
}
3434-
3435-
r := &HelmReleaseReconciler{
3436-
Client: testEnv.Client,
3437-
APIReader: testEnv.Client,
3438-
GetClusterConfig: GetTestClusterConfig,
3439-
}
3440-
3441-
// Store the Helm release mock in the test namespace.
3442-
getter, err := r.buildRESTClientGetter(context.TODO(), obj)
3443-
g.Expect(err).ToNot(HaveOccurred())
3444-
3445-
cfg, err := action.NewConfigFactory(getter, action.WithStorage(helmdriver.SecretsDriverName, obj.GetStorageNamespace()))
3446-
g.Expect(err).ToNot(HaveOccurred())
3447-
3448-
var releases []*helmrelease.Release
3449-
if tt.releases != nil {
3450-
releases = tt.releases(ns.Name)
3451-
}
3452-
store := helmstorage.Init(cfg.Driver)
3453-
for _, rls := range releases {
3454-
g.Expect(store.Create(rls)).To(Succeed())
3455-
}
3456-
3457-
// Adopt the Helm release mock.
3458-
err = r.adoptLegacyRelease(context.TODO(), getter, nil, obj)
3459-
g.Expect(err != nil).To(Equal(tt.wantErr), "unexpected error: %s", err)
3460-
3461-
// Verify the Helm release mock has been adopted.
3462-
var expectHistory v2.Snapshots
3463-
if tt.expectHistory != nil {
3464-
expectHistory = tt.expectHistory(releases)
3465-
}
3466-
g.Expect(obj.Status.History).To(Equal(expectHistory))
3467-
g.Expect(obj.Status.LastReleaseRevision).To(Equal(tt.expectLastReleaseRevision))
3468-
})
3469-
}
3470-
}
3471-
34723303
func TestHelmReleaseReconciler_buildRESTClientGetter(t *testing.T) {
34733304
const (
34743305
namespace = "some-namespace"

internal/features/features.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ const (
6161
// This is enabled by default to support an upgrade path from v2beta1 to v2
6262
// without the need to upgrade the Helm release. But it can be disabled to
6363
// avoid potential abuse of the adoption mechanism.
64+
//
65+
// Ignored from v1.5.0, prints a warning if set.
6466
AdoptLegacyReleases = "AdoptLegacyReleases"
6567

6668
// DisableChartDigestTracking disables the tracking of digest changes
@@ -100,8 +102,8 @@ var features = map[string]bool{
100102
// opt-in from v0.31
101103
OOMWatch: false,
102104
// AdoptLegacyReleases
103-
// opt-out from v0.37
104-
AdoptLegacyReleases: true,
105+
// ignored, prints warning from v1.5.0
106+
AdoptLegacyReleases: false,
105107
// DisableChartDigestTracking
106108
// opt-in from v1.3.0
107109
DisableChartDigestTracking: false,

main.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,11 @@ func main() {
237237
os.Exit(1)
238238
}
239239

240+
if ok, _ := features.Enabled(features.AdoptLegacyReleases); ok {
241+
setupLog.Info("warning: the 'AdoptLegacyReleases' feature gate is ignored and has no effect since v1.5.0, " +
242+
"adoption of HelmRelease resources in legacy API versions is no longer supported")
243+
}
244+
240245
// Set the managedFields owner for resources reconciled from Helm charts.
241246
kube.ManagedFieldsManager = controllerName
242247

0 commit comments

Comments
 (0)