diff --git a/pkg/common/utils.go b/pkg/common/utils.go index 26ecb5a8d..191bf9bfc 100644 --- a/pkg/common/utils.go +++ b/pkg/common/utils.go @@ -70,6 +70,9 @@ const ( // Full or partial URL of the machine type resource, in the format: // zones/zone/machineTypes/machine-type machineTypePattern = "zones/[^/]+/machineTypes/([^/]+)$" + + // User-caused quota exceeded messages + stockoutError = "QUOTA_EXCEEDED" ) var ( @@ -340,6 +343,9 @@ func CodeForError(err error) *codes.Code { if code := isContextError(err); code != nil { return code } + if code := isStockoutError(err); code != nil { + return code + } internalErrorCode := codes.Internal // Upwrap the error @@ -361,6 +367,19 @@ func CodeForError(err error) *codes.Code { return &internalErrorCode } +// isStockout returns a pointer to the grpc error code ResourceExhausted +// if the passed in error contains the "ZONE_RESOURCE_POOL_EXHAUSTED" +func isStockoutError(err error) *codes.Code { + if err == nil { + return nil + } + + if strings.Contains(err.Error(), stockoutError) { + return errCodePtr(codes.ResourceExhausted) + } + return nil +} + // isContextError returns a pointer to the grpc error code DeadlineExceeded // if the passed in error contains the "context deadline exceeded" string and returns // the grpc error code Canceled if the error contains the "context canceled" string. diff --git a/pkg/common/utils_test.go b/pkg/common/utils_test.go index 0fbb5a0b0..b3bdf2eca 100644 --- a/pkg/common/utils_test.go +++ b/pkg/common/utils_test.go @@ -1001,6 +1001,11 @@ func TestCodeForError(t *testing.T) { inputErr: context.DeadlineExceeded, expCode: errCodePtr(codes.DeadlineExceeded), }, + { + name: "user-caused stockout error", + inputErr: fmt.Errorf("csi.v1.Controller/CreateVolume returned with error: rpc error: code = Internal desc = CreateVolume failed to create single zonal disk test-pvc: failed to insert zonal disk: unknown Insert disk operation error: operation CreateDisk failed (QUOTA_EXCEEDED): Quota 'SSD_TOTAL_GB' exceeded. Limit: 100.00 in region us-central1."), + expCode: errCodePtr(codes.ResourceExhausted), + }, { name: "status error with Aborted error code", inputErr: status.Error(codes.Aborted, "aborted error"),