@@ -26,6 +26,7 @@ import (
26
26
"time"
27
27
28
28
"github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta"
29
+ "github.com/googleapis/gax-go/v2/apierror"
29
30
"golang.org/x/time/rate"
30
31
"google.golang.org/api/googleapi"
31
32
"google.golang.org/grpc/codes"
@@ -423,7 +424,6 @@ func CodeForError(sourceError error) codes.Code {
423
424
if sourceError == nil {
424
425
return codes .Internal
425
426
}
426
-
427
427
if code , err := isUserMultiAttachError (sourceError ); err == nil {
428
428
return code
429
429
}
@@ -433,12 +433,7 @@ func CodeForError(sourceError error) codes.Code {
433
433
if code , err := isContextError (sourceError ); err == nil {
434
434
return code
435
435
}
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 {
442
437
return code
443
438
}
444
439
@@ -479,12 +474,49 @@ func existingErrorCode(err error) (codes.Code, error) {
479
474
if err == nil {
480
475
return codes .Unknown , fmt .Errorf ("null error" )
481
476
}
482
- if status , ok := status .FromError (err ); ok {
483
- return status .Code (), nil
477
+ var tmpError * TemporaryError
478
+ // This explicitly checks our error is a temporary error before extracting its
479
+ // status, as there can be other errors that can qualify as statusable
480
+ // while not necessarily being temporary.
481
+ if errors .As (err , & tmpError ) {
482
+ if status , ok := status .FromError (err ); ok {
483
+ return status .Code (), nil
484
+ }
485
+ }
486
+ // We want to make sure we catch other temporary error types that are statusable.
487
+ // (eg. grpc-go/internal/status/status.go Error struct that wraps a status)
488
+ var googleErr * googleapi.Error
489
+ if ! errors .As (err , & googleErr ) {
490
+ if status , ok := status .FromError (err ); ok {
491
+ return status .Code (), nil
492
+ }
484
493
}
494
+
485
495
return codes .Unknown , fmt .Errorf ("no existing error code for %w" , err )
486
496
}
487
497
498
+ func isAPIError (err error ) (codes.Code , error ) {
499
+ var googleErr * googleapi.Error
500
+ if ! errors .As (err , & googleErr ) {
501
+ return codes .Unknown , fmt .Errorf ("error %w is not a googleapi.Error" , err )
502
+ }
503
+ var sourceCode int
504
+ var apiErr * apierror.APIError
505
+ if errors .As (googleErr .Unwrap (), & apiErr ) {
506
+ // When googleapi.Err is used as a wrapper, we return the error code of the wrapped contents.
507
+ sourceCode = apiErr .HTTPCode ()
508
+ } else {
509
+ // Rely on error code in googleapi.Err when it is our primary error.
510
+ sourceCode = googleErr .Code
511
+ }
512
+ // Map API error code to user error code.
513
+ if code , ok := userErrorCodeMap [sourceCode ]; ok {
514
+ return code , nil
515
+ }
516
+
517
+ return codes .Unknown , fmt .Errorf ("googleapi.Error %w does not map to any known errors" , err )
518
+ }
519
+
488
520
func LoggedError (msg string , err error ) error {
489
521
klog .Errorf (msg + "%v" , err .Error ())
490
522
return status .Errorf (CodeForError (err ), msg + "%v" , err .Error ())
0 commit comments