Skip to content

Commit 5a2d463

Browse files
authored
Merge pull request #1292 from k8s-infra-cherrypick-robot/cherry-pick-1261-to-release-1.10
[release-1.10] Filter out GCE operation error codes caused by user errors
2 parents f9878d8 + 6c1ecb7 commit 5a2d463

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
@@ -859,14 +859,40 @@ func (cloud *CloudProvider) WaitForAttach(ctx context.Context, project string, v
859859
}
860860

861861
func wrapOpErr(name string, opErr *computev1.OperationErrorErrors) error {
862+
if opErr == nil {
863+
return nil
864+
}
865+
862866
if opErr.Code == "UNSUPPORTED_OPERATION" {
863867
if diskType := pdDiskTypeUnsupportedRegex.FindStringSubmatch(opErr.Message); diskType != nil {
864868
return &UnsupportedDiskError{
865869
DiskType: diskType[1],
866870
}
867871
}
868872
}
869-
return fmt.Errorf("operation %v failed (%v): %v", name, opErr.Code, opErr.Message)
873+
grpcErrCode := codeForGCEOpError(*opErr)
874+
return status.Errorf(grpcErrCode, "operation %v failed (%v): %v", name, opErr.Code, opErr.Message)
875+
}
876+
877+
// codeForGCEOpError return the grpc error code for the passed in
878+
// gce operation error.
879+
func codeForGCEOpError(err computev1.OperationErrorErrors) codes.Code {
880+
userErrors := map[string]codes.Code{
881+
"RESOURCE_NOT_FOUND": codes.NotFound,
882+
"RESOURCE_ALREADY_EXISTS": codes.AlreadyExists,
883+
"RESOURCE_IN_USE_BY_ANOTHER_RESOURCE": codes.InvalidArgument,
884+
"OPERATION_CANCELED_BY_USER": codes.Aborted,
885+
"QUOTA_EXCEEDED": codes.ResourceExhausted,
886+
"ZONE_RESOURCE_POOL_EXHAUSTED": codes.Unavailable,
887+
"ZONE_RESOURCE_POOL_EXHAUSTED_WITH_DETAILS": codes.Unavailable,
888+
"REGION_QUOTA_EXCEEDED": codes.ResourceExhausted,
889+
"RATE_LIMIT_EXCEEDED": codes.ResourceExhausted,
890+
"INVALID_USAGE": codes.InvalidArgument,
891+
}
892+
if code, ok := userErrors[err.Code]; ok {
893+
return code
894+
}
895+
return codes.Internal
870896
}
871897

872898
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)