From 84777e0748d8cfb2549f4a57f48c03e61119d469 Mon Sep 17 00:00:00 2001 From: Yauheni Kaliuta Date: Tue, 9 Apr 2024 11:12:04 +0300 Subject: [PATCH] pkg/deploy: make delete*AndCheck use common code Signed-off-by: Yauheni Kaliuta --- pkg/upgrade/upgrade.go | 128 +++++++++++------------------------------ 1 file changed, 35 insertions(+), 93 deletions(-) diff --git a/pkg/upgrade/upgrade.go b/pkg/upgrade/upgrade.go index 77a85ef3226..849a7e058de 100644 --- a/pkg/upgrade/upgrade.go +++ b/pkg/upgrade/upgrade.go @@ -9,7 +9,6 @@ import ( "github.com/hashicorp/go-multierror" operatorv1 "github.com/openshift/api/operator/v1" - appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" apiextv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" apierrs "k8s.io/apimachinery/pkg/api/errors" @@ -372,7 +371,7 @@ func deleteResources(ctx context.Context, c client.Client, jobs *[]JobSpec) erro return err } -// deleteResourcesWithDone takes array of Jobs and deletes all matching resources. Returns true if any was deleted or error +// deleteResourcesWithDone takes array of Jobs and deletes all matching resources. Returns true if any was deleted or error. func deleteResourcesWithDone(ctx context.Context, c client.Client, jobs *[]JobSpec) (bool, error) { var errors *multierror.Error didWork := false @@ -388,7 +387,7 @@ func deleteResourcesWithDone(ctx context.Context, c client.Client, jobs *[]JobSp return didWork, errors.ErrorOrNil() } -// deleteOneJob takes one Job and deletes all matching resources. Returns true if any was deleted or error +// deleteOneJob takes one Job and deletes all matching resources. Returns true if any was deleted or error. func deleteOneJob(ctx context.Context, c client.Client, job JobSpec) (bool, error) { didWork := false list := &unstructured.UnstructuredList{} @@ -544,106 +543,49 @@ func deleteResource(cli client.Client, namespace string, resourceType string) er } func deleteDeploymentsAndCheck(ctx context.Context, cli client.Client, namespace string) (bool, error) { - // Delete Deployment objects - var multiErr *multierror.Error - deployments := &appsv1.DeploymentList{} - listOpts := &client.ListOptions{ - Namespace: namespace, - } + return deleteAndCheck(ctx, cli, gvkDeployment, namespace) +} - if err := cli.List(ctx, deployments, listOpts); err != nil { - return false, nil //nolint:nilerr - } - // filter deployment which has the new label to limit that we do not overkill other deployment - // this logic can be used even when upgrade from v2.4 to v2.5 without remove it - markedForDeletion := []appsv1.Deployment{} - for _, deployment := range deployments.Items { - deployment := deployment - v2 := false - selectorLabels := deployment.Spec.Selector.MatchLabels - for label := range selectorLabels { - if strings.Contains(label, labels.ODHAppPrefix) { - // this deployment has the new label, this is a v2 to v2 upgrade - // there is no need to recreate it, as labels are matching - v2 = true - continue - } - } - if !v2 { - markedForDeletion = append(markedForDeletion, deployment) - multiErr = multierror.Append(multiErr, cli.Delete(ctx, &deployment)) - } - } +func deleteStatefulsetsAndCheck(ctx context.Context, cli client.Client, namespace string) (bool, error) { + return deleteAndCheck(ctx, cli, gvkStatefulSet, namespace) +} - for _, deployment := range markedForDeletion { - deployment := deployment - if e := cli.Get(ctx, client.ObjectKey{ +func deleteAndCheck(ctx context.Context, cli client.Client, gvk schema.GroupVersionKind, namespace string) (bool, error) { + del := []JobSpec{ + { + Gvk: gvk, Namespace: namespace, - Name: deployment.Name, - }, &deployment); e != nil { - if apierrs.IsNotFound(e) { - // resource has been successfully deleted - continue - } - // unexpected error, report it - multiErr = multierror.Append(multiErr, e) //nolint:staticcheck,wastedassign - } - // resource still exists, wait for it to be deleted - return false, nil - } - - return true, multiErr.ErrorOrNil() -} + Matcher: func(obj *unstructured.Unstructured) (bool, error) { + // remove all the GVK in the namespace _without_ v2 label + selectorLabels, ok, err := unstructured.NestedStringMap(obj.Object, "spec", "selector", "matchLabels") + if err != nil || !ok { + return false, err + } -func deleteStatefulsetsAndCheck(ctx context.Context, cli client.Client, namespace string) (bool, error) { - // Delete statefulset objects - var multiErr *multierror.Error - statefulsets := &appsv1.StatefulSetList{} - listOpts := &client.ListOptions{ - Namespace: namespace, - } + v2 := false + for l := range selectorLabels { + if strings.Contains(l, labels.ODHAppPrefix) { + v2 = true + break + } + } - if err := cli.List(ctx, statefulsets, listOpts); err != nil { - return false, nil //nolint:nilerr + return !v2, nil + }, + }, } - // even only we have one item to delete to avoid nil point still use range - markedForDeletion := []appsv1.StatefulSet{} - for _, statefulset := range statefulsets.Items { - v2 := false - statefulset := statefulset - selectorLabels := statefulset.Spec.Selector.MatchLabels - for label := range selectorLabels { - if strings.Contains(label, labels.ODHAppPrefix) { - v2 = true - continue - } - } - if !v2 { - markedForDeletion = append(markedForDeletion, statefulset) - multiErr = multierror.Append(multiErr, cli.Delete(ctx, &statefulset)) - } - } + // If no error and no work was done means nothing to delete, we are done + // If some work was done, let's try again. If it lists matching resources + // it will do the work again, so we are not done yet, upper level function will call again. - for _, statefulset := range markedForDeletion { - statefulset := statefulset - if e := cli.Get(ctx, client.ObjectKey{ - Namespace: namespace, - Name: statefulset.Name, - }, &statefulset); e != nil { - if apierrs.IsNotFound(e) { - // resource has been successfully deleted - continue - } - // unexpected error, report it - multiErr = multierror.Append(multiErr, e) - } else { - // resource still exists, wait for it to be deleted - return false, nil - } + didWork, err := deleteResourcesWithDone(ctx, cli, &del) + if err != nil || !didWork { + return !didWork, err } - return true, multiErr.ErrorOrNil() + didWork, err = deleteResourcesWithDone(ctx, cli, &del) + return !didWork, err } func RemoveLabel(cli client.Client, objectName string, labelKey string) error {