diff --git a/pkg/gce-cloud-provider/compute/gce.go b/pkg/gce-cloud-provider/compute/gce.go index f3beb5269..8fe92d728 100644 --- a/pkg/gce-cloud-provider/compute/gce.go +++ b/pkg/gce-cloud-provider/compute/gce.go @@ -16,6 +16,7 @@ package gcecloudprovider import ( "context" + "errors" "fmt" "net/http" "os" @@ -240,8 +241,8 @@ func getProjectAndZone(config *ConfigFile) (string, string, error) { // isGCEError returns true if given error is a googleapi.Error with given // reason (e.g. "resourceInUseByAnotherResource") func IsGCEError(err error, reason string) bool { - apiErr, ok := err.(*googleapi.Error) - if !ok { + var apiErr *googleapi.Error + if !errors.As(err, &apiErr) { return false } diff --git a/pkg/gce-cloud-provider/compute/gce_test.go b/pkg/gce-cloud-provider/compute/gce_test.go new file mode 100644 index 000000000..5bb2aed89 --- /dev/null +++ b/pkg/gce-cloud-provider/compute/gce_test.go @@ -0,0 +1,86 @@ +/* +Copyright 2023 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 gcecloudprovider + +import ( + "errors" + "fmt" + "net/http" + "testing" + + "google.golang.org/api/googleapi" +) + +func TestIsGCEError(t *testing.T) { + testCases := []struct { + name string + inputErr error + reason string + expIsGCEError bool + }{ + { + name: "Not googleapi.Error", + inputErr: errors.New("I am not a googleapi.Error"), + reason: "notFound", + expIsGCEError: false, + }, + { + name: "googleapi.Error not found error", + inputErr: &googleapi.Error{ + Code: http.StatusNotFound, + Errors: []googleapi.ErrorItem{ + { + Reason: "notFound", + }, + }, + Message: "Not found", + }, + reason: "notFound", + expIsGCEError: true, + }, + { + name: "wrapped googleapi.Error", + inputErr: fmt.Errorf("encountered not found: %w", &googleapi.Error{ + Code: http.StatusNotFound, + Errors: []googleapi.ErrorItem{ + { + Reason: "notFound", + }, + }, + Message: "Not found", + }, + ), + reason: "notFound", + expIsGCEError: true, + }, + { + name: "nil error", + inputErr: nil, + reason: "notFound", + expIsGCEError: false, + }, + } + + for _, tc := range testCases { + t.Logf("Running test: %v", tc.name) + isGCEError := IsGCEError(tc.inputErr, tc.reason) + if tc.expIsGCEError != isGCEError { + t.Fatalf("Got isGCEError '%t', expected '%t'", isGCEError, tc.expIsGCEError) + } + } +} diff --git a/test/remote/instance.go b/test/remote/instance.go index b6aec1532..bb012870b 100644 --- a/test/remote/instance.go +++ b/test/remote/instance.go @@ -388,8 +388,8 @@ func generateMetadataWithPublicKey(pubKeyFile string) (*compute.Metadata, error) // isGCEError returns true if given error is a googleapi.Error with given // reason (e.g. "resourceInUseByAnotherResource") func isGCEError(err error, reason string) bool { - apiErr, ok := err.(*googleapi.Error) - if !ok { + var apiErr *googleapi.Error + if !errors.As(err, &apiErr) { return false }