Skip to content

Commit 9c6fea5

Browse files
committed
Properly unwrap gce-compute error code.
1 parent 586f6c8 commit 9c6fea5

File tree

3 files changed

+78
-10
lines changed

3 files changed

+78
-10
lines changed

pkg/common/utils.go

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
"time"
2727

2828
"github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta"
29+
"github.com/googleapis/gax-go/v2/apierror"
2930
"golang.org/x/time/rate"
3031
"google.golang.org/api/googleapi"
3132
"google.golang.org/grpc/codes"
@@ -423,7 +424,6 @@ func CodeForError(sourceError error) codes.Code {
423424
if sourceError == nil {
424425
return codes.Internal
425426
}
426-
427427
if code, err := isUserMultiAttachError(sourceError); err == nil {
428428
return code
429429
}
@@ -433,15 +433,9 @@ func CodeForError(sourceError error) codes.Code {
433433
if code, err := isContextError(sourceError); err == nil {
434434
return code
435435
}
436-
437-
var apiErr *googleapi.Error
438-
if !errors.As(sourceError, &apiErr) {
439-
return codes.Internal
440-
}
441-
if code, ok := userErrorCodeMap[apiErr.Code]; ok {
436+
if code, err := isAPIError(sourceError); err == nil {
442437
return code
443438
}
444-
445439
return codes.Internal
446440
}
447441

@@ -479,12 +473,43 @@ func existingErrorCode(err error) (codes.Code, error) {
479473
if err == nil {
480474
return codes.Unknown, fmt.Errorf("null error")
481475
}
482-
if status, ok := status.FromError(err); ok {
483-
return status.Code(), nil
476+
var tmpError *TemporaryError
477+
if errors.As(err, &tmpError) {
478+
if status, ok := status.FromError(err); ok {
479+
return status.Code(), nil
480+
}
481+
}
482+
var googleErr *googleapi.Error
483+
if !errors.As(err, &googleErr) {
484+
if status, ok := status.FromError(err); ok {
485+
return status.Code(), nil
486+
}
484487
}
488+
485489
return codes.Unknown, fmt.Errorf("no existing error code for %w", err)
486490
}
487491

492+
func isAPIError(err error) (codes.Code, error) {
493+
var googleErr *googleapi.Error
494+
if errors.As(err, &googleErr) {
495+
var sourceCode int
496+
var apiErr *apierror.APIError
497+
if errors.As(googleErr.Unwrap(), &apiErr) {
498+
sourceCode = apiErr.HTTPCode()
499+
} else {
500+
sourceCode = googleErr.Code
501+
}
502+
// Map API error code to user error code.
503+
if code, ok := userErrorCodeMap[sourceCode]; ok {
504+
return code, nil
505+
}
506+
507+
return codes.Unknown, fmt.Errorf("googleapi.Error %w does not map to any known errors", err)
508+
}
509+
510+
return codes.Unknown, fmt.Errorf("error %w is not a googleapi.Error", err)
511+
}
512+
488513
func LoggedError(msg string, err error) error {
489514
klog.Errorf(msg+"%v", err.Error())
490515
return status.Errorf(CodeForError(err), msg+"%v", err.Error())

pkg/common/utils_test.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626

2727
"github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta"
2828
"github.com/google/go-cmp/cmp"
29+
"github.com/googleapis/gax-go/v2/apierror"
2930
"google.golang.org/api/googleapi"
3031
"google.golang.org/grpc/codes"
3132
"google.golang.org/grpc/status"
@@ -1205,6 +1206,13 @@ func TestParseMachineType(t *testing.T) {
12051206
}
12061207

12071208
func TestCodeForError(t *testing.T) {
1209+
getAPIWrappedError := func(err *googleapi.Error) *googleapi.Error {
1210+
apierr, _ := apierror.ParseError(err, false)
1211+
wrappedError := &googleapi.Error{}
1212+
wrappedError.Wrap(apierr)
1213+
1214+
return wrappedError
1215+
}
12081216
testCases := []struct {
12091217
name string
12101218
inputErr error
@@ -1220,6 +1228,14 @@ func TestCodeForError(t *testing.T) {
12201228
inputErr: &googleapi.Error{Code: http.StatusBadRequest, Message: "User error with bad request"},
12211229
expCode: codes.InvalidArgument,
12221230
},
1231+
{
1232+
name: "googleapi.Error that wraps apierror.APIError, that wraps googleapi.Error",
1233+
inputErr: getAPIWrappedError(&googleapi.Error{
1234+
Code: 403,
1235+
Message: "Some permission error",
1236+
}),
1237+
expCode: codes.PermissionDenied,
1238+
},
12231239
{
12241240
name: "googleapi.Error but not a user error",
12251241
inputErr: &googleapi.Error{Code: http.StatusInternalServerError, Message: "Internal error"},

test/e2e/tests/single_zone_e2e_test.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ const (
5050
defaultRepdSizeGb int64 = 200
5151
defaultMwSizeGb int64 = 200
5252
defaultVolumeLimit int64 = 127
53+
invalidSizeGb int64 = 66000
5354
readyState = "READY"
5455
standardDiskType = "pd-standard"
5556
ssdDiskType = "pd-ssd"
@@ -269,6 +270,32 @@ var _ = Describe("GCE PD CSI Driver", func() {
269270
}
270271
})
271272

273+
It("Should fail to create disk when disk size exceeds limit", func() {
274+
Expect(testContexts).ToNot(BeEmpty())
275+
testContext := getRandomTestContext()
276+
277+
zones := []string{"us-central1-c", "us-central1-b", "us-central1-a"}
278+
279+
for _, zone := range zones {
280+
volName := testNamePrefix + string(uuid.NewUUID())
281+
topReq := &csi.TopologyRequirement{
282+
Requisite: []*csi.Topology{
283+
{
284+
Segments: map[string]string{common.TopologyKeyZone: zone},
285+
},
286+
},
287+
}
288+
volume, err := testContext.Client.CreateVolume(volName, nil, invalidSizeGb, topReq, nil)
289+
Expect(err).ToNot(BeNil(), "Failed to fetch error from create volume.")
290+
Expect(err.Error()).To(ContainSubstring("InvalidArgument"), "Failed to verify error code matches InvalidArgument.")
291+
defer func() {
292+
if volume != nil {
293+
testContext.Client.DeleteVolume(volume.VolumeId)
294+
}
295+
}()
296+
}
297+
})
298+
272299
DescribeTable("Should complete entire disk lifecycle with underspecified volume ID",
273300
func(diskType string) {
274301
testContext := getRandomTestContext()

0 commit comments

Comments
 (0)