From 8c56ccc5b09ff0cf49a9e9ef4805ae2d06d6eaff Mon Sep 17 00:00:00 2001 From: Philip Laine Date: Mon, 7 Nov 2022 13:32:08 +0100 Subject: [PATCH 1/2] Aggregate errors in uninstall functions Signed-off-by: Philip Laine --- pkg/uninstall/uninstall.go | 39 ++++++++++++++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/pkg/uninstall/uninstall.go b/pkg/uninstall/uninstall.go index ee3f678c43..49b64c0c88 100644 --- a/pkg/uninstall/uninstall.go +++ b/pkg/uninstall/uninstall.go @@ -35,10 +35,12 @@ import ( kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta2" notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1" sourcev1 "github.com/fluxcd/source-controller/api/v1beta2" + "github.com/hashicorp/go-multierror" ) // Components removes all Kubernetes components that are part of Flux excluding the CRDs and namespace. -func Components(ctx context.Context, logger log.Logger, kubeClient client.Client, namespace string, dryRun bool) { +func Components(ctx context.Context, logger log.Logger, kubeClient client.Client, namespace string, dryRun bool) error { + var aggregateErr error opts, dryRunStr := getDeleteOptions(dryRun) selector := client.MatchingLabels{manifestgen.PartOfLabelKey: manifestgen.PartOfLabelValue} { @@ -47,6 +49,7 @@ func Components(ctx context.Context, logger log.Logger, kubeClient client.Client for _, r := range list.Items { if err := kubeClient.Delete(ctx, &r, opts); err != nil { logger.Failuref("Deployment/%s/%s deletion failed: %s", r.Namespace, r.Name, err.Error()) + aggregateErr = multierror.Append(aggregateErr, err) } else { logger.Successf("Deployment/%s/%s deleted %s", r.Namespace, r.Name, dryRunStr) } @@ -59,6 +62,7 @@ func Components(ctx context.Context, logger log.Logger, kubeClient client.Client for _, r := range list.Items { if err := kubeClient.Delete(ctx, &r, opts); err != nil { logger.Failuref("Service/%s/%s deletion failed: %s", r.Namespace, r.Name, err.Error()) + aggregateErr = multierror.Append(aggregateErr, err) } else { logger.Successf("Service/%s/%s deleted %s", r.Namespace, r.Name, dryRunStr) } @@ -71,6 +75,7 @@ func Components(ctx context.Context, logger log.Logger, kubeClient client.Client for _, r := range list.Items { if err := kubeClient.Delete(ctx, &r, opts); err != nil { logger.Failuref("NetworkPolicy/%s/%s deletion failed: %s", r.Namespace, r.Name, err.Error()) + aggregateErr = multierror.Append(aggregateErr, err) } else { logger.Successf("NetworkPolicy/%s/%s deleted %s", r.Namespace, r.Name, dryRunStr) } @@ -83,6 +88,7 @@ func Components(ctx context.Context, logger log.Logger, kubeClient client.Client for _, r := range list.Items { if err := kubeClient.Delete(ctx, &r, opts); err != nil { logger.Failuref("ServiceAccount/%s/%s deletion failed: %s", r.Namespace, r.Name, err.Error()) + aggregateErr = multierror.Append(aggregateErr, err) } else { logger.Successf("ServiceAccount/%s/%s deleted %s", r.Namespace, r.Name, dryRunStr) } @@ -95,6 +101,7 @@ func Components(ctx context.Context, logger log.Logger, kubeClient client.Client for _, r := range list.Items { if err := kubeClient.Delete(ctx, &r, opts); err != nil { logger.Failuref("ClusterRole/%s deletion failed: %s", r.Name, err.Error()) + aggregateErr = multierror.Append(aggregateErr, err) } else { logger.Successf("ClusterRole/%s deleted %s", r.Name, dryRunStr) } @@ -107,16 +114,20 @@ func Components(ctx context.Context, logger log.Logger, kubeClient client.Client for _, r := range list.Items { if err := kubeClient.Delete(ctx, &r, opts); err != nil { logger.Failuref("ClusterRoleBinding/%s deletion failed: %s", r.Name, err.Error()) + aggregateErr = multierror.Append(aggregateErr, err) } else { logger.Successf("ClusterRoleBinding/%s deleted %s", r.Name, dryRunStr) } } } } + + return aggregateErr } // Finalizers removes all finalizes on Kubernetes components that have been added by a Flux controller. -func Finalizers(ctx context.Context, logger log.Logger, kubeClient client.Client, dryRun bool) { +func Finalizers(ctx context.Context, logger log.Logger, kubeClient client.Client, dryRun bool) error { + var aggregateErr error opts, dryRunStr := getUpdateOptions(dryRun) { var list sourcev1.GitRepositoryList @@ -125,6 +136,7 @@ func Finalizers(ctx context.Context, logger log.Logger, kubeClient client.Client r.Finalizers = []string{} if err := kubeClient.Update(ctx, &r, opts); err != nil { logger.Failuref("%s/%s/%s removing finalizers failed: %s", r.Kind, r.Namespace, r.Name, err.Error()) + aggregateErr = multierror.Append(aggregateErr, err) } else { logger.Successf("%s/%s/%s finalizers deleted %s", r.Kind, r.Namespace, r.Name, dryRunStr) } @@ -138,6 +150,7 @@ func Finalizers(ctx context.Context, logger log.Logger, kubeClient client.Client r.Finalizers = []string{} if err := kubeClient.Update(ctx, &r, opts); err != nil { logger.Failuref("%s/%s/%s removing finalizers failed: %s", r.Kind, r.Namespace, r.Name, err.Error()) + aggregateErr = multierror.Append(aggregateErr, err) } else { logger.Successf("%s/%s/%s finalizers deleted %s", r.Kind, r.Namespace, r.Name, dryRunStr) } @@ -151,6 +164,7 @@ func Finalizers(ctx context.Context, logger log.Logger, kubeClient client.Client r.Finalizers = []string{} if err := kubeClient.Update(ctx, &r, opts); err != nil { logger.Failuref("%s/%s/%s removing finalizers failed: %s", r.Kind, r.Namespace, r.Name, err.Error()) + aggregateErr = multierror.Append(aggregateErr, err) } else { logger.Successf("%s/%s/%s finalizers deleted %s", r.Kind, r.Namespace, r.Name, dryRunStr) } @@ -164,6 +178,7 @@ func Finalizers(ctx context.Context, logger log.Logger, kubeClient client.Client r.Finalizers = []string{} if err := kubeClient.Update(ctx, &r, opts); err != nil { logger.Failuref("%s/%s/%s removing finalizers failed: %s", r.Kind, r.Namespace, r.Name, err.Error()) + aggregateErr = multierror.Append(aggregateErr, err) } else { logger.Successf("%s/%s/%s finalizers deleted %s", r.Kind, r.Namespace, r.Name, dryRunStr) } @@ -177,6 +192,7 @@ func Finalizers(ctx context.Context, logger log.Logger, kubeClient client.Client r.Finalizers = []string{} if err := kubeClient.Update(ctx, &r, opts); err != nil { logger.Failuref("%s/%s/%s removing finalizers failed: %s", r.Kind, r.Namespace, r.Name, err.Error()) + aggregateErr = multierror.Append(aggregateErr, err) } else { logger.Successf("%s/%s/%s finalizers deleted %s", r.Kind, r.Namespace, r.Name, dryRunStr) } @@ -190,6 +206,7 @@ func Finalizers(ctx context.Context, logger log.Logger, kubeClient client.Client r.Finalizers = []string{} if err := kubeClient.Update(ctx, &r, opts); err != nil { logger.Failuref("%s/%s/%s removing finalizers failed: %s", r.Kind, r.Namespace, r.Name, err.Error()) + aggregateErr = multierror.Append(aggregateErr, err) } else { logger.Successf("%s/%s/%s finalizers deleted %s", r.Kind, r.Namespace, r.Name, dryRunStr) } @@ -203,6 +220,7 @@ func Finalizers(ctx context.Context, logger log.Logger, kubeClient client.Client r.Finalizers = []string{} if err := kubeClient.Update(ctx, &r, opts); err != nil { logger.Failuref("%s/%s/%s removing finalizers failed: %s", r.Kind, r.Namespace, r.Name, err.Error()) + aggregateErr = multierror.Append(aggregateErr, err) } else { logger.Successf("%s/%s/%s finalizers deleted %s", r.Kind, r.Namespace, r.Name, dryRunStr) } @@ -216,6 +234,7 @@ func Finalizers(ctx context.Context, logger log.Logger, kubeClient client.Client r.Finalizers = []string{} if err := kubeClient.Update(ctx, &r, opts); err != nil { logger.Failuref("%s/%s/%s removing finalizers failed: %s", r.Kind, r.Namespace, r.Name, err.Error()) + aggregateErr = multierror.Append(aggregateErr, err) } else { logger.Successf("%s/%s/%s finalizers deleted %s", r.Kind, r.Namespace, r.Name, dryRunStr) } @@ -229,6 +248,7 @@ func Finalizers(ctx context.Context, logger log.Logger, kubeClient client.Client r.Finalizers = []string{} if err := kubeClient.Update(ctx, &r, opts); err != nil { logger.Failuref("%s/%s/%s removing finalizers failed: %s", r.Kind, r.Namespace, r.Name, err.Error()) + aggregateErr = multierror.Append(aggregateErr, err) } else { logger.Successf("%s/%s/%s finalizers deleted %s", r.Kind, r.Namespace, r.Name, dryRunStr) } @@ -242,6 +262,7 @@ func Finalizers(ctx context.Context, logger log.Logger, kubeClient client.Client r.Finalizers = []string{} if err := kubeClient.Update(ctx, &r, opts); err != nil { logger.Failuref("%s/%s/%s removing finalizers failed: %s", r.Kind, r.Namespace, r.Name, err.Error()) + aggregateErr = multierror.Append(aggregateErr, err) } else { logger.Successf("%s/%s/%s finalizers deleted %s", r.Kind, r.Namespace, r.Name, dryRunStr) } @@ -255,6 +276,7 @@ func Finalizers(ctx context.Context, logger log.Logger, kubeClient client.Client r.Finalizers = []string{} if err := kubeClient.Update(ctx, &r, opts); err != nil { logger.Failuref("%s/%s/%s removing finalizers failed: %s", r.Kind, r.Namespace, r.Name, err.Error()) + aggregateErr = multierror.Append(aggregateErr, err) } else { logger.Successf("%s/%s/%s finalizers deleted %s", r.Kind, r.Namespace, r.Name, dryRunStr) } @@ -268,6 +290,7 @@ func Finalizers(ctx context.Context, logger log.Logger, kubeClient client.Client r.Finalizers = []string{} if err := kubeClient.Update(ctx, &r, opts); err != nil { logger.Failuref("%s/%s/%s removing finalizers failed: %s", r.Kind, r.Namespace, r.Name, err.Error()) + aggregateErr = multierror.Append(aggregateErr, err) } else { logger.Successf("%s/%s/%s finalizers deleted %s", r.Kind, r.Namespace, r.Name, dryRunStr) } @@ -281,16 +304,19 @@ func Finalizers(ctx context.Context, logger log.Logger, kubeClient client.Client r.Finalizers = []string{} if err := kubeClient.Update(ctx, &r, opts); err != nil { logger.Failuref("%s/%s/%s removing finalizers failed: %s", r.Kind, r.Namespace, r.Name, err.Error()) + aggregateErr = multierror.Append(aggregateErr, err) } else { logger.Successf("%s/%s/%s finalizers deleted %s", r.Kind, r.Namespace, r.Name, dryRunStr) } } } } + return aggregateErr } // CustomResourceDefinitions removes all Kubernetes CRDs that are a part of Flux. -func CustomResourceDefinitions(ctx context.Context, logger log.Logger, kubeClient client.Client, dryRun bool) { +func CustomResourceDefinitions(ctx context.Context, logger log.Logger, kubeClient client.Client, dryRun bool) error { + var aggregateErr error opts, dryRunStr := getDeleteOptions(dryRun) selector := client.MatchingLabels{manifestgen.PartOfLabelKey: manifestgen.PartOfLabelValue} { @@ -299,23 +325,28 @@ func CustomResourceDefinitions(ctx context.Context, logger log.Logger, kubeClien for _, r := range list.Items { if err := kubeClient.Delete(ctx, &r, opts); err != nil { logger.Failuref("CustomResourceDefinition/%s deletion failed: %s", r.Name, err.Error()) + aggregateErr = multierror.Append(aggregateErr, err) } else { logger.Successf("CustomResourceDefinition/%s deleted %s", r.Name, dryRunStr) } } } } + return aggregateErr } // Namespace removes the namespace Flux is installed in. -func Namespace(ctx context.Context, logger log.Logger, kubeClient client.Client, namespace string, dryRun bool) { +func Namespace(ctx context.Context, logger log.Logger, kubeClient client.Client, namespace string, dryRun bool) error { + var aggregateErr error opts, dryRunStr := getDeleteOptions(dryRun) ns := corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: namespace}} if err := kubeClient.Delete(ctx, &ns, opts); err != nil { logger.Failuref("Namespace/%s deletion failed: %s", namespace, err.Error()) + aggregateErr = multierror.Append(aggregateErr, err) } else { logger.Successf("Namespace/%s deleted %s", namespace, dryRunStr) } + return aggregateErr } func getDeleteOptions(dryRun bool) (*client.DeleteOptions, string) { From b004fbfc417fa53243ff02db7c2e18feeda93f8e Mon Sep 17 00:00:00 2001 From: Hidde Beydals Date: Tue, 22 Nov 2022 13:09:41 +0000 Subject: [PATCH 2/2] Use k8s.io/apimachinery/pkg for error aggregation Signed-off-by: Hidde Beydals --- go.mod | 2 +- internal/build/diff.go | 18 +++++++----- pkg/uninstall/uninstall.go | 60 +++++++++++++++++++------------------- 3 files changed, 41 insertions(+), 39 deletions(-) diff --git a/go.mod b/go.mod index 5cb03eb07b..6d68a82d8e 100644 --- a/go.mod +++ b/go.mod @@ -30,7 +30,6 @@ require ( github.com/gonvenience/ytbx v1.4.4 github.com/google/go-cmp v0.5.9 github.com/google/go-containerregistry v0.12.1 - github.com/hashicorp/go-multierror v1.1.1 github.com/homeport/dyff v1.5.6 github.com/lucasb-eyer/go-colorful v1.2.0 github.com/manifoldco/promptui v0.9.0 @@ -141,6 +140,7 @@ require ( github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect + github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/go-retryablehttp v0.7.1 // indirect github.com/hashicorp/golang-lru v0.5.4 // indirect github.com/imdario/mergo v0.3.13 // indirect diff --git a/internal/build/diff.go b/internal/build/diff.go index b955989c92..9709f1deae 100644 --- a/internal/build/diff.go +++ b/internal/build/diff.go @@ -27,20 +27,22 @@ import ( "sort" "strings" - "github.com/fluxcd/flux2/pkg/printers" - kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta2" - "github.com/fluxcd/pkg/ssa" "github.com/gonvenience/bunt" "github.com/gonvenience/ytbx" "github.com/google/go-cmp/cmp" - "github.com/hashicorp/go-multierror" "github.com/homeport/dyff/pkg/dyff" "github.com/lucasb-eyer/go-colorful" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/util/errors" "sigs.k8s.io/cli-utils/pkg/kstatus/polling" "sigs.k8s.io/cli-utils/pkg/object" "sigs.k8s.io/yaml" + + "github.com/fluxcd/pkg/ssa" + + "github.com/fluxcd/flux2/pkg/printers" + kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta2" ) func (b *Builder) Manager() (*ssa.ResourceManager, error) { @@ -85,7 +87,7 @@ func (b *Builder) Diff() (string, bool, error) { } } - var diffErrs error + var diffErrs []error // create an inventory of objects to be reconciled newInventory := newInventory() for _, obj := range objects { @@ -97,7 +99,7 @@ func (b *Builder) Diff() (string, bool, error) { change, liveObject, mergedObject, err := resourceManager.Diff(ctx, obj, diffOptions) if err != nil { // gather errors and continue, as we want to see all the diffs - diffErrs = multierror.Append(diffErrs, err) + diffErrs = append(diffErrs, err) continue } @@ -135,7 +137,7 @@ func (b *Builder) Diff() (string, bool, error) { b.spinner.Message("processing inventory") } - if b.kustomization.Spec.Prune && diffErrs == nil { + if b.kustomization.Spec.Prune && len(diffErrs) == 0 { oldStatus := b.kustomization.Status.DeepCopy() if oldStatus.Inventory != nil { diffObjects, err := diffInventory(oldStatus.Inventory, newInventory) @@ -155,7 +157,7 @@ func (b *Builder) Diff() (string, bool, error) { } } - return output.String(), createdOrDrifted, diffErrs + return output.String(), createdOrDrifted, errors.Reduce(errors.Flatten(errors.NewAggregate(diffErrs))) } func writeYamls(liveObject, mergedObject *unstructured.Unstructured) (string, string, string, error) { diff --git a/pkg/uninstall/uninstall.go b/pkg/uninstall/uninstall.go index 49b64c0c88..07f6ed492b 100644 --- a/pkg/uninstall/uninstall.go +++ b/pkg/uninstall/uninstall.go @@ -25,6 +25,7 @@ import ( rbacv1 "k8s.io/api/rbac/v1" apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/errors" "sigs.k8s.io/controller-runtime/pkg/client" "github.com/fluxcd/flux2/pkg/log" @@ -35,12 +36,11 @@ import ( kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta2" notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1" sourcev1 "github.com/fluxcd/source-controller/api/v1beta2" - "github.com/hashicorp/go-multierror" ) // Components removes all Kubernetes components that are part of Flux excluding the CRDs and namespace. func Components(ctx context.Context, logger log.Logger, kubeClient client.Client, namespace string, dryRun bool) error { - var aggregateErr error + var aggregateErr []error opts, dryRunStr := getDeleteOptions(dryRun) selector := client.MatchingLabels{manifestgen.PartOfLabelKey: manifestgen.PartOfLabelValue} { @@ -49,7 +49,7 @@ func Components(ctx context.Context, logger log.Logger, kubeClient client.Client for _, r := range list.Items { if err := kubeClient.Delete(ctx, &r, opts); err != nil { logger.Failuref("Deployment/%s/%s deletion failed: %s", r.Namespace, r.Name, err.Error()) - aggregateErr = multierror.Append(aggregateErr, err) + aggregateErr = append(aggregateErr, err) } else { logger.Successf("Deployment/%s/%s deleted %s", r.Namespace, r.Name, dryRunStr) } @@ -62,7 +62,7 @@ func Components(ctx context.Context, logger log.Logger, kubeClient client.Client for _, r := range list.Items { if err := kubeClient.Delete(ctx, &r, opts); err != nil { logger.Failuref("Service/%s/%s deletion failed: %s", r.Namespace, r.Name, err.Error()) - aggregateErr = multierror.Append(aggregateErr, err) + aggregateErr = append(aggregateErr, err) } else { logger.Successf("Service/%s/%s deleted %s", r.Namespace, r.Name, dryRunStr) } @@ -75,7 +75,7 @@ func Components(ctx context.Context, logger log.Logger, kubeClient client.Client for _, r := range list.Items { if err := kubeClient.Delete(ctx, &r, opts); err != nil { logger.Failuref("NetworkPolicy/%s/%s deletion failed: %s", r.Namespace, r.Name, err.Error()) - aggregateErr = multierror.Append(aggregateErr, err) + aggregateErr = append(aggregateErr, err) } else { logger.Successf("NetworkPolicy/%s/%s deleted %s", r.Namespace, r.Name, dryRunStr) } @@ -88,7 +88,7 @@ func Components(ctx context.Context, logger log.Logger, kubeClient client.Client for _, r := range list.Items { if err := kubeClient.Delete(ctx, &r, opts); err != nil { logger.Failuref("ServiceAccount/%s/%s deletion failed: %s", r.Namespace, r.Name, err.Error()) - aggregateErr = multierror.Append(aggregateErr, err) + aggregateErr = append(aggregateErr, err) } else { logger.Successf("ServiceAccount/%s/%s deleted %s", r.Namespace, r.Name, dryRunStr) } @@ -101,7 +101,7 @@ func Components(ctx context.Context, logger log.Logger, kubeClient client.Client for _, r := range list.Items { if err := kubeClient.Delete(ctx, &r, opts); err != nil { logger.Failuref("ClusterRole/%s deletion failed: %s", r.Name, err.Error()) - aggregateErr = multierror.Append(aggregateErr, err) + aggregateErr = append(aggregateErr, err) } else { logger.Successf("ClusterRole/%s deleted %s", r.Name, dryRunStr) } @@ -114,7 +114,7 @@ func Components(ctx context.Context, logger log.Logger, kubeClient client.Client for _, r := range list.Items { if err := kubeClient.Delete(ctx, &r, opts); err != nil { logger.Failuref("ClusterRoleBinding/%s deletion failed: %s", r.Name, err.Error()) - aggregateErr = multierror.Append(aggregateErr, err) + aggregateErr = append(aggregateErr, err) } else { logger.Successf("ClusterRoleBinding/%s deleted %s", r.Name, dryRunStr) } @@ -122,12 +122,12 @@ func Components(ctx context.Context, logger log.Logger, kubeClient client.Client } } - return aggregateErr + return errors.Reduce(errors.Flatten(errors.NewAggregate(aggregateErr))) } // Finalizers removes all finalizes on Kubernetes components that have been added by a Flux controller. func Finalizers(ctx context.Context, logger log.Logger, kubeClient client.Client, dryRun bool) error { - var aggregateErr error + var aggregateErr []error opts, dryRunStr := getUpdateOptions(dryRun) { var list sourcev1.GitRepositoryList @@ -136,7 +136,7 @@ func Finalizers(ctx context.Context, logger log.Logger, kubeClient client.Client r.Finalizers = []string{} if err := kubeClient.Update(ctx, &r, opts); err != nil { logger.Failuref("%s/%s/%s removing finalizers failed: %s", r.Kind, r.Namespace, r.Name, err.Error()) - aggregateErr = multierror.Append(aggregateErr, err) + aggregateErr = append(aggregateErr, err) } else { logger.Successf("%s/%s/%s finalizers deleted %s", r.Kind, r.Namespace, r.Name, dryRunStr) } @@ -150,7 +150,7 @@ func Finalizers(ctx context.Context, logger log.Logger, kubeClient client.Client r.Finalizers = []string{} if err := kubeClient.Update(ctx, &r, opts); err != nil { logger.Failuref("%s/%s/%s removing finalizers failed: %s", r.Kind, r.Namespace, r.Name, err.Error()) - aggregateErr = multierror.Append(aggregateErr, err) + aggregateErr = append(aggregateErr, err) } else { logger.Successf("%s/%s/%s finalizers deleted %s", r.Kind, r.Namespace, r.Name, dryRunStr) } @@ -164,7 +164,7 @@ func Finalizers(ctx context.Context, logger log.Logger, kubeClient client.Client r.Finalizers = []string{} if err := kubeClient.Update(ctx, &r, opts); err != nil { logger.Failuref("%s/%s/%s removing finalizers failed: %s", r.Kind, r.Namespace, r.Name, err.Error()) - aggregateErr = multierror.Append(aggregateErr, err) + aggregateErr = append(aggregateErr, err) } else { logger.Successf("%s/%s/%s finalizers deleted %s", r.Kind, r.Namespace, r.Name, dryRunStr) } @@ -178,7 +178,7 @@ func Finalizers(ctx context.Context, logger log.Logger, kubeClient client.Client r.Finalizers = []string{} if err := kubeClient.Update(ctx, &r, opts); err != nil { logger.Failuref("%s/%s/%s removing finalizers failed: %s", r.Kind, r.Namespace, r.Name, err.Error()) - aggregateErr = multierror.Append(aggregateErr, err) + aggregateErr = append(aggregateErr, err) } else { logger.Successf("%s/%s/%s finalizers deleted %s", r.Kind, r.Namespace, r.Name, dryRunStr) } @@ -192,7 +192,7 @@ func Finalizers(ctx context.Context, logger log.Logger, kubeClient client.Client r.Finalizers = []string{} if err := kubeClient.Update(ctx, &r, opts); err != nil { logger.Failuref("%s/%s/%s removing finalizers failed: %s", r.Kind, r.Namespace, r.Name, err.Error()) - aggregateErr = multierror.Append(aggregateErr, err) + aggregateErr = append(aggregateErr, err) } else { logger.Successf("%s/%s/%s finalizers deleted %s", r.Kind, r.Namespace, r.Name, dryRunStr) } @@ -206,7 +206,7 @@ func Finalizers(ctx context.Context, logger log.Logger, kubeClient client.Client r.Finalizers = []string{} if err := kubeClient.Update(ctx, &r, opts); err != nil { logger.Failuref("%s/%s/%s removing finalizers failed: %s", r.Kind, r.Namespace, r.Name, err.Error()) - aggregateErr = multierror.Append(aggregateErr, err) + aggregateErr = append(aggregateErr, err) } else { logger.Successf("%s/%s/%s finalizers deleted %s", r.Kind, r.Namespace, r.Name, dryRunStr) } @@ -220,7 +220,7 @@ func Finalizers(ctx context.Context, logger log.Logger, kubeClient client.Client r.Finalizers = []string{} if err := kubeClient.Update(ctx, &r, opts); err != nil { logger.Failuref("%s/%s/%s removing finalizers failed: %s", r.Kind, r.Namespace, r.Name, err.Error()) - aggregateErr = multierror.Append(aggregateErr, err) + aggregateErr = append(aggregateErr, err) } else { logger.Successf("%s/%s/%s finalizers deleted %s", r.Kind, r.Namespace, r.Name, dryRunStr) } @@ -234,7 +234,7 @@ func Finalizers(ctx context.Context, logger log.Logger, kubeClient client.Client r.Finalizers = []string{} if err := kubeClient.Update(ctx, &r, opts); err != nil { logger.Failuref("%s/%s/%s removing finalizers failed: %s", r.Kind, r.Namespace, r.Name, err.Error()) - aggregateErr = multierror.Append(aggregateErr, err) + aggregateErr = append(aggregateErr, err) } else { logger.Successf("%s/%s/%s finalizers deleted %s", r.Kind, r.Namespace, r.Name, dryRunStr) } @@ -248,7 +248,7 @@ func Finalizers(ctx context.Context, logger log.Logger, kubeClient client.Client r.Finalizers = []string{} if err := kubeClient.Update(ctx, &r, opts); err != nil { logger.Failuref("%s/%s/%s removing finalizers failed: %s", r.Kind, r.Namespace, r.Name, err.Error()) - aggregateErr = multierror.Append(aggregateErr, err) + aggregateErr = append(aggregateErr, err) } else { logger.Successf("%s/%s/%s finalizers deleted %s", r.Kind, r.Namespace, r.Name, dryRunStr) } @@ -262,7 +262,7 @@ func Finalizers(ctx context.Context, logger log.Logger, kubeClient client.Client r.Finalizers = []string{} if err := kubeClient.Update(ctx, &r, opts); err != nil { logger.Failuref("%s/%s/%s removing finalizers failed: %s", r.Kind, r.Namespace, r.Name, err.Error()) - aggregateErr = multierror.Append(aggregateErr, err) + aggregateErr = append(aggregateErr, err) } else { logger.Successf("%s/%s/%s finalizers deleted %s", r.Kind, r.Namespace, r.Name, dryRunStr) } @@ -276,7 +276,7 @@ func Finalizers(ctx context.Context, logger log.Logger, kubeClient client.Client r.Finalizers = []string{} if err := kubeClient.Update(ctx, &r, opts); err != nil { logger.Failuref("%s/%s/%s removing finalizers failed: %s", r.Kind, r.Namespace, r.Name, err.Error()) - aggregateErr = multierror.Append(aggregateErr, err) + aggregateErr = append(aggregateErr, err) } else { logger.Successf("%s/%s/%s finalizers deleted %s", r.Kind, r.Namespace, r.Name, dryRunStr) } @@ -290,7 +290,7 @@ func Finalizers(ctx context.Context, logger log.Logger, kubeClient client.Client r.Finalizers = []string{} if err := kubeClient.Update(ctx, &r, opts); err != nil { logger.Failuref("%s/%s/%s removing finalizers failed: %s", r.Kind, r.Namespace, r.Name, err.Error()) - aggregateErr = multierror.Append(aggregateErr, err) + aggregateErr = append(aggregateErr, err) } else { logger.Successf("%s/%s/%s finalizers deleted %s", r.Kind, r.Namespace, r.Name, dryRunStr) } @@ -304,19 +304,19 @@ func Finalizers(ctx context.Context, logger log.Logger, kubeClient client.Client r.Finalizers = []string{} if err := kubeClient.Update(ctx, &r, opts); err != nil { logger.Failuref("%s/%s/%s removing finalizers failed: %s", r.Kind, r.Namespace, r.Name, err.Error()) - aggregateErr = multierror.Append(aggregateErr, err) + aggregateErr = append(aggregateErr, err) } else { logger.Successf("%s/%s/%s finalizers deleted %s", r.Kind, r.Namespace, r.Name, dryRunStr) } } } } - return aggregateErr + return errors.Reduce(errors.Flatten(errors.NewAggregate(aggregateErr))) } // CustomResourceDefinitions removes all Kubernetes CRDs that are a part of Flux. func CustomResourceDefinitions(ctx context.Context, logger log.Logger, kubeClient client.Client, dryRun bool) error { - var aggregateErr error + var aggregateErr []error opts, dryRunStr := getDeleteOptions(dryRun) selector := client.MatchingLabels{manifestgen.PartOfLabelKey: manifestgen.PartOfLabelValue} { @@ -325,28 +325,28 @@ func CustomResourceDefinitions(ctx context.Context, logger log.Logger, kubeClien for _, r := range list.Items { if err := kubeClient.Delete(ctx, &r, opts); err != nil { logger.Failuref("CustomResourceDefinition/%s deletion failed: %s", r.Name, err.Error()) - aggregateErr = multierror.Append(aggregateErr, err) + aggregateErr = append(aggregateErr, err) } else { logger.Successf("CustomResourceDefinition/%s deleted %s", r.Name, dryRunStr) } } } } - return aggregateErr + return errors.Reduce(errors.Flatten(errors.NewAggregate(aggregateErr))) } // Namespace removes the namespace Flux is installed in. func Namespace(ctx context.Context, logger log.Logger, kubeClient client.Client, namespace string, dryRun bool) error { - var aggregateErr error + var aggregateErr []error opts, dryRunStr := getDeleteOptions(dryRun) ns := corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: namespace}} if err := kubeClient.Delete(ctx, &ns, opts); err != nil { logger.Failuref("Namespace/%s deletion failed: %s", namespace, err.Error()) - aggregateErr = multierror.Append(aggregateErr, err) + aggregateErr = append(aggregateErr, err) } else { logger.Successf("Namespace/%s deleted %s", namespace, dryRunStr) } - return aggregateErr + return errors.Reduce(errors.Flatten(errors.NewAggregate(aggregateErr))) } func getDeleteOptions(dryRun bool) (*client.DeleteOptions, string) {