Skip to content

Commit 4b8a8c8

Browse files
authored
Merge pull request #1322 from k8s-infra-cherrypick-robot/cherry-pick-1261-to-release-1.9
[release-1.9] Filter out GCE operation error codes caused by user errors
2 parents 0d0b9c2 + 6ba9891 commit 4b8a8c8

File tree

2 files changed

+100
-1
lines changed

2 files changed

+100
-1
lines changed

pkg/gce-cloud-provider/compute/gce-compute.go

+27-1
Original file line numberDiff line numberDiff line change
@@ -866,14 +866,40 @@ func (cloud *CloudProvider) WaitForAttach(ctx context.Context, project string, v
866866
}
867867

868868
func wrapOpErr(name string, opErr *computev1.OperationErrorErrors) error {
869+
if opErr == nil {
870+
return nil
871+
}
872+
869873
if opErr.Code == "UNSUPPORTED_OPERATION" {
870874
if diskType := pdDiskTypeUnsupportedRegex.FindStringSubmatch(opErr.Message); diskType != nil {
871875
return &UnsupportedDiskError{
872876
DiskType: diskType[1],
873877
}
874878
}
875879
}
876-
return fmt.Errorf("operation %v failed (%v): %v", name, opErr.Code, opErr.Message)
880+
grpcErrCode := codeForGCEOpError(*opErr)
881+
return status.Errorf(grpcErrCode, "operation %v failed (%v): %v", name, opErr.Code, opErr.Message)
882+
}
883+
884+
// codeForGCEOpError return the grpc error code for the passed in
885+
// gce operation error.
886+
func codeForGCEOpError(err computev1.OperationErrorErrors) codes.Code {
887+
userErrors := map[string]codes.Code{
888+
"RESOURCE_NOT_FOUND": codes.NotFound,
889+
"RESOURCE_ALREADY_EXISTS": codes.AlreadyExists,
890+
"RESOURCE_IN_USE_BY_ANOTHER_RESOURCE": codes.InvalidArgument,
891+
"OPERATION_CANCELED_BY_USER": codes.Aborted,
892+
"QUOTA_EXCEEDED": codes.ResourceExhausted,
893+
"ZONE_RESOURCE_POOL_EXHAUSTED": codes.Unavailable,
894+
"ZONE_RESOURCE_POOL_EXHAUSTED_WITH_DETAILS": codes.Unavailable,
895+
"REGION_QUOTA_EXCEEDED": codes.ResourceExhausted,
896+
"RATE_LIMIT_EXCEEDED": codes.ResourceExhausted,
897+
"INVALID_USAGE": codes.InvalidArgument,
898+
}
899+
if code, ok := userErrors[err.Code]; ok {
900+
return code
901+
}
902+
return codes.Internal
877903
}
878904

879905
func opIsDone(op *computev1.Operation) (bool, error) {

pkg/gce-cloud-provider/compute/gce-compute_test.go

+73
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"testing"
1919

2020
computev1 "google.golang.org/api/compute/v1"
21+
"google.golang.org/grpc/codes"
2122
"sigs.k8s.io/gcp-compute-persistent-disk-csi-driver/pkg/common"
2223
)
2324

@@ -101,3 +102,75 @@ func TestValidateDiskParameters(t *testing.T) {
101102
}
102103
}
103104
}
105+
106+
func TestCodeForGCEOpError(t *testing.T) {
107+
testCases := []struct {
108+
name string
109+
inputErr computev1.OperationErrorErrors
110+
expCode codes.Code
111+
}{
112+
{
113+
name: "RESOURCE_NOT_FOUND error",
114+
inputErr: computev1.OperationErrorErrors{Code: "RESOURCE_NOT_FOUND"},
115+
expCode: codes.NotFound,
116+
},
117+
{
118+
name: "RESOURCE_ALREADY_EXISTS error",
119+
inputErr: computev1.OperationErrorErrors{Code: "RESOURCE_ALREADY_EXISTS"},
120+
expCode: codes.AlreadyExists,
121+
},
122+
{
123+
name: "OPERATION_CANCELED_BY_USER error",
124+
inputErr: computev1.OperationErrorErrors{Code: "OPERATION_CANCELED_BY_USER"},
125+
expCode: codes.Aborted,
126+
},
127+
{
128+
name: "QUOTA_EXCEEDED error",
129+
inputErr: computev1.OperationErrorErrors{Code: "QUOTA_EXCEEDED"},
130+
expCode: codes.ResourceExhausted,
131+
},
132+
{
133+
name: "ZONE_RESOURCE_POOL_EXHAUSTED error",
134+
inputErr: computev1.OperationErrorErrors{Code: "ZONE_RESOURCE_POOL_EXHAUSTED"},
135+
expCode: codes.Unavailable,
136+
},
137+
{
138+
name: "ZONE_RESOURCE_POOL_EXHAUSTED_WITH_DETAILS error",
139+
inputErr: computev1.OperationErrorErrors{Code: "ZONE_RESOURCE_POOL_EXHAUSTED_WITH_DETAILS"},
140+
expCode: codes.Unavailable,
141+
},
142+
{
143+
name: "REGION_QUOTA_EXCEEDED error",
144+
inputErr: computev1.OperationErrorErrors{Code: "REGION_QUOTA_EXCEEDED"},
145+
expCode: codes.ResourceExhausted,
146+
},
147+
{
148+
name: "RATE_LIMIT_EXCEEDED error",
149+
inputErr: computev1.OperationErrorErrors{Code: "RATE_LIMIT_EXCEEDED"},
150+
expCode: codes.ResourceExhausted,
151+
},
152+
{
153+
name: "INVALID_USAGE error",
154+
inputErr: computev1.OperationErrorErrors{Code: "INVALID_USAGE"},
155+
expCode: codes.InvalidArgument,
156+
},
157+
{
158+
name: "RESOURCE_IN_USE_BY_ANOTHER_RESOURCE error",
159+
inputErr: computev1.OperationErrorErrors{Code: "RESOURCE_IN_USE_BY_ANOTHER_RESOURCE"},
160+
expCode: codes.InvalidArgument,
161+
},
162+
{
163+
name: "UNSUPPORTED_OPERATION error",
164+
inputErr: computev1.OperationErrorErrors{Code: "UNSUPPORTED_OPERATION"},
165+
expCode: codes.Internal,
166+
},
167+
}
168+
169+
for _, tc := range testCases {
170+
t.Logf("Running test: %v", tc.name)
171+
errCode := codeForGCEOpError(tc.inputErr)
172+
if errCode != tc.expCode {
173+
t.Errorf("test %v failed: got %v, expected %v", tc.name, errCode, tc.expCode)
174+
}
175+
}
176+
}

0 commit comments

Comments
 (0)