github.com/argoproj/argo-cd/v3@v3.2.1/util/grpc/errors_test.go (about)

     1  package grpc
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"testing"
     7  
     8  	"google.golang.org/grpc/codes"
     9  	"google.golang.org/grpc/status"
    10  	apierrors "k8s.io/apimachinery/pkg/api/errors"
    11  	"k8s.io/apimachinery/pkg/runtime/schema"
    12  
    13  	"github.com/stretchr/testify/assert"
    14  	"github.com/stretchr/testify/require"
    15  )
    16  
    17  func Test_gitErrToGRPC(t *testing.T) {
    18  	var ok bool
    19  	require.NoError(t, gitErrToGRPC(nil))
    20  
    21  	defaultErrorMsg := "default error"
    22  	defaultError := gitErrToGRPC(errors.New(defaultErrorMsg))
    23  	_, ok = defaultError.(interface{ GRPCStatus() *status.Status })
    24  	assert.False(t, ok)
    25  	assert.Equal(t, defaultError.Error(), defaultErrorMsg)
    26  
    27  	grpcErrorMsg := "grpc error"
    28  	grpcError := gitErrToGRPC(status.Error(codes.Unknown, grpcErrorMsg))
    29  	se, ok := grpcError.(interface{ GRPCStatus() *status.Status })
    30  	assert.True(t, ok)
    31  	assert.Equal(t, codes.Unknown, se.GRPCStatus().Code())
    32  	assert.Equal(t, se.GRPCStatus().Message(), grpcErrorMsg)
    33  
    34  	notFoundMsg := "repository not found"
    35  	notFound := gitErrToGRPC(status.Error(codes.NotFound, notFoundMsg))
    36  	se1, ok := notFound.(interface{ GRPCStatus() *status.Status })
    37  	assert.True(t, ok)
    38  	assert.Equal(t, codes.NotFound, se1.GRPCStatus().Code())
    39  	assert.Equal(t, se1.GRPCStatus().Message(), notFoundMsg)
    40  }
    41  
    42  func Test_kubeErrToGRPC(t *testing.T) {
    43  	type testCase struct {
    44  		name               string
    45  		givenErrFn         func() error
    46  		expectedErrFn      func() error
    47  		expectedGRPCStatus *status.Status
    48  	}
    49  	newForbiddenError := func() error {
    50  		gr := schema.GroupResource{
    51  			Group:    "apps",
    52  			Resource: "Deployment",
    53  		}
    54  		return apierrors.NewForbidden(gr, "some-app", errors.New("authentication error"))
    55  	}
    56  	newUnauthorizedError := func() error {
    57  		return apierrors.NewUnauthorized("unauthenticated")
    58  	}
    59  	cases := []*testCase{
    60  		{
    61  			name: "will return standard error if not grpc status",
    62  			givenErrFn: func() error {
    63  				return errors.New("standard error")
    64  			},
    65  			expectedErrFn: func() error {
    66  				return errors.New("standard error")
    67  			},
    68  			expectedGRPCStatus: nil,
    69  		},
    70  		{
    71  			name: "will return wrapped status if nested in err",
    72  			givenErrFn: func() error {
    73  				grpcStatus := status.New(codes.NotFound, "Not found")
    74  				return fmt.Errorf("wrapped status: %w", grpcStatus.Err())
    75  			},
    76  			expectedErrFn: func() error {
    77  				grpcStatus := status.New(codes.NotFound, "Not found")
    78  				return grpcStatus.Err()
    79  			},
    80  			expectedGRPCStatus: status.New(codes.NotFound, "Not found"),
    81  		},
    82  		{
    83  			name: "will return permission denied if apierrors.IsForbidden",
    84  			givenErrFn: func() error {
    85  				return newForbiddenError()
    86  			},
    87  			expectedErrFn: func() error {
    88  				err := newForbiddenError()
    89  				grpcStatus := status.New(codes.PermissionDenied, err.Error())
    90  				return grpcStatus.Err()
    91  			},
    92  			expectedGRPCStatus: status.New(codes.PermissionDenied, newForbiddenError().Error()),
    93  		},
    94  		{
    95  			name: "will return unauthenticated if apierrors.IsUnauthorized",
    96  			givenErrFn: func() error {
    97  				return newUnauthorizedError()
    98  			},
    99  			expectedErrFn: func() error {
   100  				err := newUnauthorizedError()
   101  				grpcStatus := status.New(codes.Unauthenticated, err.Error())
   102  				return grpcStatus.Err()
   103  			},
   104  			expectedGRPCStatus: status.New(codes.Unauthenticated, newUnauthorizedError().Error()),
   105  		},
   106  		{
   107  			name: "will return Unavailable if apierrors.IsServerTimeout",
   108  			givenErrFn: func() error {
   109  				return apierrors.NewServerTimeout(schema.GroupResource{}, "update", 1)
   110  			},
   111  			expectedErrFn: func() error {
   112  				err := apierrors.NewServerTimeout(schema.GroupResource{}, "update", 1)
   113  				grpcStatus := status.New(codes.Unavailable, err.Error())
   114  				return grpcStatus.Err()
   115  			},
   116  			expectedGRPCStatus: status.New(codes.Unavailable, apierrors.NewServerTimeout(schema.GroupResource{}, "update", 1).Error()),
   117  		},
   118  		{
   119  			name: "will return Aborted if apierrors.IsConflict",
   120  			givenErrFn: func() error {
   121  				return apierrors.NewConflict(schema.GroupResource{}, "foo", errors.New("foo"))
   122  			},
   123  			expectedErrFn: func() error {
   124  				err := apierrors.NewConflict(schema.GroupResource{}, "foo", errors.New("foo"))
   125  				grpcStatus := status.New(codes.Aborted, err.Error())
   126  				return grpcStatus.Err()
   127  			},
   128  			expectedGRPCStatus: status.New(codes.Aborted, apierrors.NewConflict(schema.GroupResource{}, "foo", errors.New("foo")).Error()),
   129  		},
   130  		{
   131  			name: "will return ResourceExhausted if apierrors.IsTooManyRequests",
   132  			givenErrFn: func() error {
   133  				return apierrors.NewTooManyRequests("foo", 1)
   134  			},
   135  			expectedErrFn: func() error {
   136  				err := apierrors.NewTooManyRequests("foo", 1)
   137  				grpcStatus := status.New(codes.ResourceExhausted, err.Error())
   138  				return grpcStatus.Err()
   139  			},
   140  			expectedGRPCStatus: status.New(codes.ResourceExhausted, apierrors.NewTooManyRequests("foo", 1).Error()),
   141  		},
   142  	}
   143  	for _, c := range cases {
   144  		c := c
   145  		t.Run(c.name, func(t *testing.T) {
   146  			// when
   147  			err := kubeErrToGRPC(c.givenErrFn())
   148  
   149  			// then
   150  			assert.Equal(t, c.expectedErrFn(), err, "error comparison mismatch")
   151  			grpcStatus := UnwrapGRPCStatus(err)
   152  			assert.Equal(t, c.expectedGRPCStatus, grpcStatus, "grpc status mismatch")
   153  		})
   154  	}
   155  }