From 6311cab2facc317947959cb18d9ba7b6ab85bec6 Mon Sep 17 00:00:00 2001 From: justinsb Date: Tue, 14 Jan 2025 08:03:55 -0500 Subject: [PATCH] delete cluster: avoid logspam on GCE "resource in use" error Similar to what we do on AWS, we avoid printing confusing error messages when there is a dependency we aren't aware of. --- pkg/resources/gce/errors.go | 53 +++++++++++++++++++++++++++++ pkg/resources/ops/delete.go | 3 +- upup/pkg/fi/cloudup/gce/wrappers.go | 8 ++--- 3 files changed, 59 insertions(+), 5 deletions(-) create mode 100644 pkg/resources/gce/errors.go diff --git a/pkg/resources/gce/errors.go b/pkg/resources/gce/errors.go new file mode 100644 index 0000000000000..444224f7594f6 --- /dev/null +++ b/pkg/resources/gce/errors.go @@ -0,0 +1,53 @@ +/* +Copyright 2024 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package gce + +import ( + "errors" + + "google.golang.org/api/googleapi" + "k8s.io/klog/v2" +) + +// AsGoogleAPIError returns a googleapi.Error in the error chain, or false if none is found. +func AsGoogleAPIError(err error) (*googleapi.Error, bool) { + var googleAPIError *googleapi.Error + if errors.As(err, &googleAPIError) { + return googleAPIError, true + } else { + return nil, false + } +} + +// IsDependencyViolation checks if the error is a dependency violation. +func IsDependencyViolation(err error) bool { + apiErr, ok := AsGoogleAPIError(err) + if !ok { + return false + } + + for _, e := range apiErr.Errors { + switch e.Reason { + case "resourceInUseByAnotherResource": + return true + default: + klog.Infof("unexpected gce error code: %+v", e) + } + } + + return false +} diff --git a/pkg/resources/ops/delete.go b/pkg/resources/ops/delete.go index f2680110db3f4..9776e8179bb18 100644 --- a/pkg/resources/ops/delete.go +++ b/pkg/resources/ops/delete.go @@ -24,6 +24,7 @@ import ( "k8s.io/klog/v2" "k8s.io/kops/pkg/resources" awsresources "k8s.io/kops/pkg/resources/aws" + gceresources "k8s.io/kops/pkg/resources/gce" "k8s.io/kops/upup/pkg/fi" ) @@ -128,7 +129,7 @@ func DeleteResources(cloud fi.Cloud, resourceMap map[string]*resources.Resource, } if err != nil { mutex.Lock() - if awsresources.IsDependencyViolation(err) { + if awsresources.IsDependencyViolation(err) || gceresources.IsDependencyViolation(err) { fmt.Printf("%s\tstill has dependencies, will retry\n", human) klog.V(4).Infof("resource %q generated a dependency error: %v", human, err) } else { diff --git a/upup/pkg/fi/cloudup/gce/wrappers.go b/upup/pkg/fi/cloudup/gce/wrappers.go index 80598cb4a9680..b9f9822330cca 100644 --- a/upup/pkg/fi/cloudup/gce/wrappers.go +++ b/upup/pkg/fi/cloudup/gce/wrappers.go @@ -38,7 +38,7 @@ func DeleteInstanceGroupManager(c GCECloud, t *compute.InstanceGroupManager) err klog.Infof("InstanceGroupManager not found, assuming deleted: %q", t.SelfLink) return nil } - return fmt.Errorf("error deleting InstanceGroupManager %s: %v", t.SelfLink, err) + return fmt.Errorf("error deleting InstanceGroupManager %s: %w", t.SelfLink, err) } return c.WaitForOp(op) @@ -58,7 +58,7 @@ func DeleteInstanceTemplate(c GCECloud, selfLink string) error { klog.Infof("instancetemplate not found, assuming deleted: %q", selfLink) return nil } - return fmt.Errorf("error deleting InstanceTemplate %s: %v", selfLink, err) + return fmt.Errorf("error deleting InstanceTemplate %s: %w", selfLink, err) } return c.WaitForOp(op) @@ -78,7 +78,7 @@ func DeleteInstance(c GCECloud, instanceSelfLink string) error { klog.Infof("Instance not found, assuming deleted: %q", instanceSelfLink) return nil } - return fmt.Errorf("error deleting Instance %s: %v", instanceSelfLink, err) + return fmt.Errorf("error deleting Instance %s: %w", instanceSelfLink, err) } return c.WaitForOp(op) @@ -100,7 +100,7 @@ func ListManagedInstances(c GCECloud, igm *compute.InstanceGroupManager) ([]*com instances, err := c.Compute().InstanceGroupManagers().ListManagedInstances(ctx, project, zoneName, igm.Name) if err != nil { - return nil, fmt.Errorf("error listing ManagedInstances in %s: %v", igm.Name, err) + return nil, fmt.Errorf("error listing ManagedInstances in %s: %w", igm.Name, err) } return instances, nil