From 04c689d70f3ca2fb6fb54733263cca881ec0c38f Mon Sep 17 00:00:00 2001 From: Christer Edvartsen Date: Fri, 16 Feb 2024 14:57:21 +0100 Subject: [PATCH] handle error that occurs if a team has no state --- .../dependencytrack/reconciler_test.go | 4 +++- internal/reconcilers/dependencytrack/state.go | 15 +++++++++------ .../reconcilers/github/team/reconciler_test.go | 4 +++- internal/reconcilers/github/team/state.go | 16 +++++++++------- .../nais/namespace/reconciler_test.go | 4 +++- internal/reconcilers/nais/namespace/state.go | 15 +++++++++------ 6 files changed, 36 insertions(+), 22 deletions(-) diff --git a/internal/reconcilers/dependencytrack/reconciler_test.go b/internal/reconcilers/dependencytrack/reconciler_test.go index 981b594..3ecfc39 100644 --- a/internal/reconcilers/dependencytrack/reconciler_test.go +++ b/internal/reconcilers/dependencytrack/reconciler_test.go @@ -13,6 +13,8 @@ import ( "github.com/nais/dependencytrack/pkg/client" "github.com/sirupsen/logrus/hooks/test" "github.com/stretchr/testify/mock" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" ) func TestMissingConfig(t *testing.T) { @@ -64,7 +66,7 @@ func TestDependencytrackReconciler_Reconcile(t *testing.T) { apiClient, grpcServers := apiclient.NewMockClient(t) grpcServers.Reconcilers.EXPECT(). State(mock.Anything, &protoapi.GetReconcilerStateRequest{ReconcilerName: "nais:dependencytrack", TeamSlug: teamSlug}). - Return(&protoapi.GetReconcilerStateResponse{}, nil). + Return(nil, status.Error(codes.NotFound, "state not found")). Once() grpcServers.Teams.EXPECT(). Members(mock.Anything, &protoapi.ListTeamMembersRequest{Slug: teamSlug, Limit: 100, Offset: 0}). diff --git a/internal/reconcilers/dependencytrack/state.go b/internal/reconcilers/dependencytrack/state.go index d3f2435..414e24d 100644 --- a/internal/reconcilers/dependencytrack/state.go +++ b/internal/reconcilers/dependencytrack/state.go @@ -6,6 +6,8 @@ import ( "github.com/nais/api/pkg/apiclient" "github.com/nais/api/pkg/protoapi" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" ) type DependencyTrackState struct { @@ -29,19 +31,20 @@ func (r *reconciler) saveState(ctx context.Context, client *apiclient.APIClient, } func (r *reconciler) loadState(ctx context.Context, client *apiclient.APIClient, teamSlug string) (*DependencyTrackState, error) { + st := DependencyTrackState{} resp, err := client.Reconcilers().State(ctx, &protoapi.GetReconcilerStateRequest{ ReconcilerName: reconcilerName, TeamSlug: teamSlug, }) if err != nil { + if e, ok := status.FromError(err); ok && e.Code() == codes.NotFound { + // special case: team does not yet have any state + return &st, nil + } return nil, err - } - - st := DependencyTrackState{} - if resp.State == nil { + } else if resp.State == nil { return &st, nil - } - if err := json.Unmarshal(resp.State.Value, &st); err != nil { + } else if err := json.Unmarshal(resp.State.Value, &st); err != nil { return nil, err } return &st, nil diff --git a/internal/reconcilers/github/team/reconciler_test.go b/internal/reconcilers/github/team/reconciler_test.go index d70465d..4ffe249 100644 --- a/internal/reconcilers/github/team/reconciler_test.go +++ b/internal/reconcilers/github/team/reconciler_test.go @@ -16,6 +16,8 @@ import ( "github.com/shurcooL/githubv4" "github.com/sirupsen/logrus/hooks/test" "github.com/stretchr/testify/mock" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" "k8s.io/utils/ptr" ) @@ -47,7 +49,7 @@ func TestGitHubReconciler_getOrCreateTeam(t *testing.T) { Once() mockServer.Reconcilers.EXPECT(). State(mock.Anything, &protoapi.GetReconcilerStateRequest{ReconcilerName: "github:team", TeamSlug: teamSlug}). - Return(&protoapi.GetReconcilerStateResponse{}, nil). + Return(nil, status.Error(codes.NotFound, "state not found")). Once() mockServer.Teams.EXPECT(). SetTeamExternalReferences(mock.Anything, mock.MatchedBy(func(req *protoapi.SetTeamExternalReferencesRequest) bool { diff --git a/internal/reconcilers/github/team/state.go b/internal/reconcilers/github/team/state.go index e59343e..a17dac2 100644 --- a/internal/reconcilers/github/team/state.go +++ b/internal/reconcilers/github/team/state.go @@ -7,6 +7,8 @@ import ( "github.com/nais/api/pkg/apiclient" "github.com/nais/api/pkg/protoapi" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" ) type GitHubState struct { @@ -66,20 +68,20 @@ func GetTeamRepositories(ctx context.Context, client protoapi.ReconcilersClient, } func getState(ctx context.Context, client protoapi.ReconcilersClient, teamSlug string) (*GitHubState, error) { + st := GitHubState{} resp, err := client.State(ctx, &protoapi.GetReconcilerStateRequest{ ReconcilerName: reconcilerName, TeamSlug: teamSlug, }) if err != nil { + if e, ok := status.FromError(err); ok && e.Code() == codes.NotFound { + // special case: team does not yet have any state + return &st, nil + } return nil, err - } - - st := GitHubState{} - if resp.State == nil { + } else if resp.State == nil { return &st, nil - } - - if err := json.Unmarshal(resp.State.Value, &st); err != nil { + } else if err := json.Unmarshal(resp.State.Value, &st); err != nil { return nil, err } return &st, nil diff --git a/internal/reconcilers/nais/namespace/reconciler_test.go b/internal/reconcilers/nais/namespace/reconciler_test.go index 8d341a8..5bcc2d0 100644 --- a/internal/reconcilers/nais/namespace/reconciler_test.go +++ b/internal/reconcilers/nais/namespace/reconciler_test.go @@ -16,7 +16,9 @@ import ( "github.com/stretchr/testify/mock" "google.golang.org/api/option" "google.golang.org/grpc" + "google.golang.org/grpc/codes" "google.golang.org/grpc/credentials/insecure" + "google.golang.org/grpc/status" "k8s.io/utils/ptr" ) @@ -84,7 +86,7 @@ func TestReconcile(t *testing.T) { apiClient, mockServer := apiclient.NewMockClient(t) mockServer.Reconcilers.EXPECT(). State(mock.Anything, &protoapi.GetReconcilerStateRequest{TeamSlug: teamSlug, ReconcilerName: "nais:namespace"}). - Return(&protoapi.GetReconcilerStateResponse{}, nil). + Return(nil, status.Error(codes.NotFound, "state not found")). Once() mockServer.Reconcilers.EXPECT(). SaveState(mock.Anything, &protoapi.SaveReconcilerStateRequest{Value: []byte("{}"), TeamSlug: teamSlug, ReconcilerName: "nais:namespace"}). diff --git a/internal/reconcilers/nais/namespace/state.go b/internal/reconcilers/nais/namespace/state.go index 4cdae78..a7d1519 100644 --- a/internal/reconcilers/nais/namespace/state.go +++ b/internal/reconcilers/nais/namespace/state.go @@ -6,6 +6,8 @@ import ( "github.com/nais/api/pkg/apiclient" "github.com/nais/api/pkg/protoapi" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" ) // state is a map of namespace names to unix timestamps @@ -26,19 +28,20 @@ func (r *naisNamespaceReconciler) saveState(ctx context.Context, client *apiclie } func (r *naisNamespaceReconciler) loadState(ctx context.Context, client *apiclient.APIClient, teamSlug string) (state, error) { + st := state{} resp, err := client.Reconcilers().State(ctx, &protoapi.GetReconcilerStateRequest{ ReconcilerName: r.Name(), TeamSlug: teamSlug, }) if err != nil { + if e, ok := status.FromError(err); ok && e.Code() == codes.NotFound { + // special case: team does not yet have any state + return st, nil + } return nil, err - } - - st := state{} - if resp.State == nil { + } else if resp.State == nil { return st, nil - } - if err := json.Unmarshal(resp.State.Value, &st); err != nil { + } else if err := json.Unmarshal(resp.State.Value, &st); err != nil { return nil, err } return st, nil