package gcp import ( "errors" "google.golang.org/api/googleapi" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) type Error struct { Err error Message string Code int Verbose string Host string } // Wrap creates a GCPError func Wrap(err error) *Error { if err == nil { return nil } if e, ok := err.(*googleapi.Error); ok { return &Error{ Err: e, Message: e.Message, Code: e.Code, Verbose: e.Error(), Host: e.Header.Get("Host"), } } // wraps grpc errors such as those used in secret manager client if e, ok := status.FromError(err); ok { return &Error{ Err: e.Err(), Message: e.Message(), Code: int(e.Code()), } } return &Error{ Err: err, Message: err.Error(), } } func New(msg string) *Error { return Wrap(errors.New(msg)) } // Error implements the error interface. func (g *Error) Error() string { return g.Message } // Unwrap retrieves the original error. func (g *Error) Unwrap() error { return g.Err } // Extensions additional data about gcp error func (g *Error) Extensions() map[string]interface{} { return map[string]interface{}{ "statusCode": g.Code, //"verbose": g.Verbose, We don't want to expose implementation details "host": g.Host, } } // IgnoreNotFound returns nil if the error is an Error // with Code=404, otherwise it returns the provided error func IgnoreNotFound(err error) error { var gcpErr *Error if !errors.As(err, &gcpErr) { return err } if gcpErr.Code == int(codes.NotFound) { return nil } return err }