diff --git a/buf.gen.yaml b/buf.gen.yaml new file mode 100644 index 00000000..cacaaf8b --- /dev/null +++ b/buf.gen.yaml @@ -0,0 +1,13 @@ +version: v1 +plugins: + - name: go + out: ./server + opt: paths=source_relative + - name: go-grpc + out: ./server + opt: paths=source_relative + - name: grpc-gateway + out: ./server + opt: paths=source_relative + - name: openapiv2 + out: ./server diff --git a/server/api/adapter.go b/server/api/adapter.go new file mode 100644 index 00000000..21a5adbe --- /dev/null +++ b/server/api/adapter.go @@ -0,0 +1,47 @@ +package api + +import ( + "github.com/odpf/stencil/server/models" + stencilv1 "github.com/odpf/stencil/server/odpf/stencil/v1" + "github.com/odpf/stencil/server/snapshot" +) + +func fromProtoToSnapshot(g *stencilv1.Snapshot) *snapshot.Snapshot { + return &snapshot.Snapshot{ + ID: g.GetId(), + Namespace: g.GetNamespace(), + Name: g.GetName(), + Version: g.GetVersion(), + Latest: g.GetLatest(), + } +} + +func fromSnapshotToProto(g *snapshot.Snapshot) *stencilv1.Snapshot { + return &stencilv1.Snapshot{ + Id: g.ID, + Namespace: g.Namespace, + Name: g.Name, + Version: g.Version, + Latest: g.Latest, + } +} + +func toRulesList(r *stencilv1.Checks) []string { + var rules []string + if r == nil { + return rules + } + for _, rule := range r.Except { + rules = append(rules, rule.String()) + } + return rules +} + +func toFileDownloadRequest(g *stencilv1.DownloadDescriptorRequest) *models.FileDownloadRequest { + return &models.FileDownloadRequest{ + Namespace: g.Namespace, + Name: g.Name, + Version: g.Version, + FullNames: g.GetFullnames(), + } +} diff --git a/server/api/api.go b/server/api/api.go index 714bf4f8..90fe8c79 100644 --- a/server/api/api.go +++ b/server/api/api.go @@ -3,7 +3,9 @@ package api import ( "context" + stencilv1 "github.com/odpf/stencil/server/odpf/stencil/v1" "github.com/odpf/stencil/server/snapshot" + "google.golang.org/grpc/health/grpc_health_v1" ) //StoreService Service Interface for storage and validation @@ -16,14 +18,16 @@ type StoreService interface { // MetadataService Service Interface for metadata store type MetadataService interface { Exists(context.Context, *snapshot.Snapshot) bool - ListNames(context.Context, string) ([]string, error) - ListVersions(context.Context, string, string) ([]string, error) - GetSnapshot(context.Context, string, string, string, bool) (*snapshot.Snapshot, error) + List(context.Context, *snapshot.Snapshot) ([]*snapshot.Snapshot, error) + GetSnapshotByFields(context.Context, string, string, string, bool) (*snapshot.Snapshot, error) + GetSnapshotByID(context.Context, int64) (*snapshot.Snapshot, error) UpdateLatestVersion(context.Context, *snapshot.Snapshot) error } //API holds all handlers type API struct { + stencilv1.UnimplementedStencilServiceServer + grpc_health_v1.UnimplementedHealthServer Store StoreService Metadata MetadataService } diff --git a/server/api/api_test.go b/server/api/api_test.go index e93dead4..74bfe183 100644 --- a/server/api/api_test.go +++ b/server/api/api_test.go @@ -1,15 +1,16 @@ package api_test import ( + "net/http" + "github.com/odpf/stencil/server/config" server2 "github.com/odpf/stencil/server/server" - "github.com/gin-gonic/gin" "github.com/odpf/stencil/server/api" "github.com/odpf/stencil/server/api/mocks" ) -func setup() (*gin.Engine, *mocks.StoreService, *mocks.MetadataService, *api.API) { +func setup() (http.Handler, *mocks.StoreService, *mocks.MetadataService, *api.API) { mockService := &mocks.StoreService{} mockMetadataService := &mocks.MetadataService{} v1 := &api.API{ diff --git a/server/api/download.go b/server/api/download.go index d02e6516..9a794fdf 100644 --- a/server/api/download.go +++ b/server/api/download.go @@ -1,17 +1,21 @@ package api import ( + "context" "fmt" "net/http" "net/url" "github.com/gin-gonic/gin" "github.com/odpf/stencil/server/models" + stencilv1 "github.com/odpf/stencil/server/odpf/stencil/v1" "github.com/odpf/stencil/server/snapshot" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" ) -//Download downloads file -func (a *API) Download(c *gin.Context) { +//HTTPDownload http handler to download requested schema data +func (a *API) HTTPDownload(c *gin.Context) { ctx := c.Request.Context() payload := models.FileDownloadRequest{ FullNames: c.QueryArray("fullnames"), @@ -21,25 +25,44 @@ func (a *API) Download(c *gin.Context) { return } s := payload.ToSnapshot() - st, err := a.Metadata.GetSnapshot(ctx, s.Namespace, s.Name, s.Version, s.Latest) + data, err := a.download(ctx, s, payload.FullNames) + if err != nil { + c.Error(err) + return + } + fileName := payload.Version + c.Header("Content-Disposition", fmt.Sprintf(`attachment; filename="%s"; filename*=UTF-8''%s`, fileName, url.PathEscape(fileName))) + c.Data(http.StatusOK, "application/octet-stream", data) +} + +// DownloadDescriptor grpc handler to download schema data +func (a *API) DownloadDescriptor(ctx context.Context, req *stencilv1.DownloadDescriptorRequest) (*stencilv1.DownloadDescriptorResponse, error) { + payload := toFileDownloadRequest(req) + err := validate.Struct(payload) + if err != nil { + return nil, status.Error(codes.InvalidArgument, err.Error()) + } + s := payload.ToSnapshot() + data, err := a.download(ctx, s, req.Fullnames) + return &stencilv1.DownloadDescriptorResponse{Data: data}, err +} + +func (a *API) download(ctx context.Context, s *snapshot.Snapshot, fullNames []string) ([]byte, error) { + notfoundErr := status.Error(codes.NotFound, "not found") + var data []byte + st, err := a.Metadata.GetSnapshotByFields(ctx, s.Namespace, s.Name, s.Version, s.Latest) if err != nil { if err == snapshot.ErrNotFound { - c.JSON(http.StatusNotFound, gin.H{"message": err.Error()}) - return + return data, notfoundErr } - c.Error(err).SetMeta(models.ErrDownloadFailed) - return + return data, status.Convert(err).Err() } - data, err := a.Store.Get(c.Request.Context(), st, payload.FullNames) + data, err = a.Store.Get(ctx, st, fullNames) if err != nil { - c.Error(err).SetMeta(models.ErrDownloadFailed) - return + return data, status.Convert(err).Err() } if len(data) == 0 { - c.JSON(http.StatusNotFound, gin.H{"message": "not found"}) - return + return data, notfoundErr } - fileName := payload.Version - c.Header("Content-Disposition", fmt.Sprintf(`attachment; filename="%s"; filename*=UTF-8''%s`, fileName, url.PathEscape(fileName))) - c.Data(http.StatusOK, "application/octet-stream", data) + return data, nil } diff --git a/server/api/download_test.go b/server/api/download_test.go index 1a32be8e..09c5acb1 100644 --- a/server/api/download_test.go +++ b/server/api/download_test.go @@ -1,15 +1,19 @@ package api_test import ( + "context" "errors" "fmt" "net/http" "net/http/httptest" "testing" + "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" + stencilv1 "github.com/odpf/stencil/server/odpf/stencil/v1" "github.com/odpf/stencil/server/snapshot" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" + "google.golang.org/grpc/status" ) var downloadFail = errors.New("download fail") @@ -31,11 +35,11 @@ func TestDownload(t *testing.T) { {"should return 200 if download succeeded", "name1", "1.0.1", nil, nil, 200}, {"should be able to download with latest version", "name1", "latest", nil, nil, 200}, } { - t.Run(test.desc, func(t *testing.T) { + t.Run(fmt.Sprintf("http: %s", test.desc), func(t *testing.T) { router, mockService, mockMetadata, _ := setup() fileData := []byte("File contents") - mockMetadata.On("GetSnapshot", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&snapshot.Snapshot{}, test.notFoundErr) + mockMetadata.On("GetSnapshotByFields", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&snapshot.Snapshot{}, test.notFoundErr) mockService.On("Get", mock.Anything, mock.Anything, mock.Anything).Return(fileData, test.downloadErr) w := httptest.NewRecorder() req, _ := http.NewRequest("GET", fmt.Sprintf("/v1/namespaces/namespace/descriptors/%s/versions/%s", test.name, test.version), nil) @@ -49,11 +53,27 @@ func TestDownload(t *testing.T) { assert.Equal(t, expectedHeader, w.Header().Get("Content-Disposition")) } }) + t.Run(fmt.Sprintf("gRPC: %s", test.desc), func(t *testing.T) { + ctx := context.Background() + _, mockService, mockMetadata, a := setup() + + fileData := []byte("File contents") + mockMetadata.On("GetSnapshotByFields", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&snapshot.Snapshot{}, test.notFoundErr) + mockService.On("Get", mock.Anything, mock.Anything, mock.Anything).Return(fileData, test.downloadErr) + req := &stencilv1.DownloadDescriptorRequest{Namespace: "namespace", Name: test.name, Version: test.version} + res, err := a.DownloadDescriptor(ctx, req) + if test.expectedCode != 200 { + e := status.Convert(err) + assert.Equal(t, test.expectedCode, runtime.HTTPStatusFromCode(e.Code())) + } else { + assert.Equal(t, res.Data, []byte("File contents")) + } + }) } t.Run("should return 404 if file content not found", func(t *testing.T) { router, mockService, mockMetadata, _ := setup() fileData := []byte("") - mockMetadata.On("GetSnapshot", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&snapshot.Snapshot{}, nil) + mockMetadata.On("GetSnapshotByFields", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&snapshot.Snapshot{}, nil) mockService.On("Get", mock.Anything, mock.Anything, mock.Anything).Return(fileData, nil) w := httptest.NewRecorder() req, _ := http.NewRequest("GET", "/v1/namespaces/namespace/descriptors/n/versions/latest", nil) diff --git a/server/api/metadata.go b/server/api/metadata.go index 09cadbae..2aa92c85 100644 --- a/server/api/metadata.go +++ b/server/api/metadata.go @@ -1,66 +1,41 @@ package api import ( - "net/http" + "context" - "github.com/gin-gonic/gin" - "github.com/odpf/stencil/server/models" + stencilv1 "github.com/odpf/stencil/server/odpf/stencil/v1" "github.com/odpf/stencil/server/snapshot" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" ) -// ListNames lists descriptor entries -func (a *API) ListNames(c *gin.Context) { - namespace := c.Param("namespace") - result, err := a.Metadata.ListNames(c.Request.Context(), namespace) +// ListSnapshots returns list of snapshots. If filters applied it will return filtered snapshot list +func (a *API) ListSnapshots(ctx context.Context, req *stencilv1.ListSnapshotsRequest) (*stencilv1.ListSnapshotsResponse, error) { + res := &stencilv1.ListSnapshotsResponse{} + list, err := a.Metadata.List(ctx, &snapshot.Snapshot{Namespace: req.Namespace, Name: req.Name, Version: req.Version, Latest: req.Latest}) if err != nil { - c.Error(err).SetMeta(models.ErrUnknown) - return + return res, err } - c.JSON(http.StatusOK, result) -} - -// ListVersions lists version numbers for specific name -func (a *API) ListVersions(c *gin.Context) { - namespace := c.Param("namespace") - name := c.Param("name") - result, err := a.Metadata.ListVersions(c.Request.Context(), namespace, name) - if err != nil { - c.Error(err).SetMeta(models.ErrUnknown) - return + for _, j := range list { + res.Snapshots = append(res.Snapshots, fromSnapshotToProto(j)) } - c.JSON(http.StatusOK, result) + return res, nil } -//GetLatestVersion return latest version number -func (a *API) GetLatestVersion(c *gin.Context) { - namespace := c.Param("namespace") - name := c.Param("name") - snapshot, err := a.Metadata.GetSnapshot(c.Request.Context(), namespace, name, "", true) +// PromoteSnapshot marks specified snapshot as latest +func (a *API) PromoteSnapshot(ctx context.Context, req *stencilv1.PromoteSnapshotRequest) (*stencilv1.PromoteSnapshotResponse, error) { + st, err := a.Metadata.GetSnapshotByID(ctx, req.Id) if err != nil { - c.Error(err).SetMeta(models.ErrGetMetadataFailed) - return - } - c.JSON(http.StatusOK, gin.H{"version": snapshot.Version}) -} - -//UpdateLatestVersion return latest version number -func (a *API) UpdateLatestVersion(c *gin.Context) { - namespace := c.Param("namespace") - payload := &models.MetadataUpdateRequest{ - Namespace: namespace, - } - if err := c.ShouldBind(payload); err != nil { - c.Error(err).SetMeta(models.ErrMissingFormData) - return + if err == snapshot.ErrNotFound { + return nil, status.Error(codes.NotFound, err.Error()) + } + return nil, status.Error(codes.Internal, err.Error()) } - err := a.Metadata.UpdateLatestVersion(c.Request.Context(), &snapshot.Snapshot{ - Namespace: namespace, - Name: payload.Name, - Version: payload.Version, - }) + err = a.Metadata.UpdateLatestVersion(ctx, st) if err != nil { - c.Error(err).SetMeta(models.ErrMetadataUpdateFailed) - return + return nil, err } - c.JSON(http.StatusOK, gin.H{"message": "success"}) + return &stencilv1.PromoteSnapshotResponse{ + Snapshot: fromSnapshotToProto(st), + }, nil } diff --git a/server/api/metadata_test.go b/server/api/metadata_test.go index b76c647b..2af5edcd 100644 --- a/server/api/metadata_test.go +++ b/server/api/metadata_test.go @@ -1,131 +1,130 @@ package api_test import ( - "bytes" + "context" "errors" - "fmt" - "net/http" - "net/http/httptest" "testing" - "github.com/odpf/stencil/server/models" + stencilv1 "github.com/odpf/stencil/server/odpf/stencil/v1" "github.com/odpf/stencil/server/snapshot" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" ) func TestList(t *testing.T) { - for _, test := range []struct { - desc string - err error - values []string - expectedCode int - expectedResp string - }{ - {"should return list", nil, []string{"n1", "n2"}, 200, `["n1", "n2"]`}, - {"should return 404 if path not found", models.ErrNotFound, []string{}, 404, `{"message": "Not found"}`}, - } { - t.Run(test.desc, func(t *testing.T) { - router, _, mockService, _ := setup() - mockService.On("ListNames", mock.Anything, "namespace").Return(test.values, test.err) - - w := httptest.NewRecorder() - req, _ := http.NewRequest("GET", "/v1/namespaces/namespace/descriptors", nil) - router.ServeHTTP(w, req) - - assert.Equal(t, test.expectedCode, w.Code) - assert.JSONEq(t, test.expectedResp, w.Body.String()) - mockService.AssertExpectations(t) - }) - } - -} - -func TestListVersions(t *testing.T) { - for _, test := range []struct { - desc string - err error - values []string - expectedCode int - expectedResp string - }{ - {"should return list", nil, []string{"n1", "n2"}, 200, `["n1", "n2"]`}, - {"should return 404 if path not found", models.ErrNotFound, []string{}, 404, `{"message": "Not found"}`}, - } { - t.Run(test.desc, func(t *testing.T) { - router, _, mockService, _ := setup() - mockService.On("ListVersions", mock.Anything, "namespace", "example").Return(test.values, test.err) - - w := httptest.NewRecorder() - req, _ := http.NewRequest("GET", "/v1/namespaces/namespace/descriptors/example/versions", nil) - router.ServeHTTP(w, req) - - assert.Equal(t, test.expectedCode, w.Code) - assert.JSONEq(t, test.expectedResp, w.Body.String()) - mockService.AssertExpectations(t) - }) - } -} - -func TestGetVersion(t *testing.T) { - for _, test := range []struct { - desc string - name string - latestVersion string - err error - expectedCode int - }{ - {"should return 500 if fetch version fails", "name1", "1.0.1", errors.New("fetch fail"), 500}, - {"should return latest version number", "name1", "1.0.2", nil, 200}, - } { - t.Run(test.desc, func(t *testing.T) { - router, _, mockService, _ := setup() - mockService.On("GetSnapshot", mock.Anything, "namespace", test.name, "", true).Return(&snapshot.Snapshot{Version: test.latestVersion}, test.err) - w := httptest.NewRecorder() - - req, _ := http.NewRequest("GET", fmt.Sprintf("/v1/namespaces/namespace/metadata/%s", test.name), nil) - - router.ServeHTTP(w, req) - - assert.Equal(t, test.expectedCode, w.Code) - if test.expectedCode == 200 { - expectedData := []byte(fmt.Sprintf(`{"version":"%s"}`, test.latestVersion)) - assert.Equal(t, expectedData, w.Body.Bytes()) - } - }) - } + t.Run("should return list", func(t *testing.T) { + ctx := context.Background() + _, _, mockService, v1 := setup() + st := []*snapshot.Snapshot{ + { + Namespace: "t", + Name: "na", + }, + } + req := stencilv1.ListSnapshotsRequest{ + Namespace: "t", + } + mockService.On("List", mock.Anything, &snapshot.Snapshot{Namespace: "t"}).Return(st, nil) + res, err := v1.ListSnapshots(ctx, &req) + assert.Nil(t, err) + assert.Equal(t, "t", res.Snapshots[0].Namespace) + assert.Equal(t, "na", res.Snapshots[0].Name) + }) + + t.Run("should return error if getting a list fails", func(t *testing.T) { + ctx := context.Background() + _, _, mockService, v1 := setup() + req := stencilv1.ListSnapshotsRequest{ + Namespace: "t", + } + err := errors.New("list failed") + mockService.On("List", mock.Anything, &snapshot.Snapshot{Namespace: "t"}).Return(nil, err) + res, err := v1.ListSnapshots(ctx, &req) + assert.NotNil(t, err) + assert.Equal(t, 0, len(res.Snapshots)) + }) } func TestUpdateLatestVersion(t *testing.T) { - for _, test := range []struct { - desc string - name string - version string - err error - expectedCode int - }{ - {"should return 400 if name is missing", "", "1.0.1", nil, 400}, - {"should return 400 if version is missing", "name1", "", nil, 400}, - {"should return 400 if version not follows semantic verioning", "name1", "invalid0.1.0", nil, 400}, - {"should return 500 if store fails", "name1", "1.0.1", errors.New("store fail"), 500}, - {"should return success if update succeeds", "name1", "1.0.2", nil, 200}, - } { - t.Run(test.desc, func(t *testing.T) { - router, _, mockService, _ := setup() - mockService.On("UpdateLatestVersion", mock.Anything, mock.Anything).Return(test.err) - w := httptest.NewRecorder() - - body := bytes.NewReader([]byte(fmt.Sprintf(`{"name": "%s", "version": "%s"}`, test.name, test.version))) - req, _ := http.NewRequest("POST", "/v1/namespaces/namespace/metadata", body) - req.Header.Set("Content-Type", "application/json") - - router.ServeHTTP(w, req) - - assert.Equal(t, test.expectedCode, w.Code) - if test.expectedCode == 200 { - assert.JSONEq(t, `{"message": "success"}`, w.Body.String()) - mockService.AssertExpectations(t) - } - }) - } + t.Run("should update latest tag", func(t *testing.T) { + ctx := context.Background() + _, _, mockService, v1 := setup() + st := &snapshot.Snapshot{ + ID: 1, + Namespace: "t", + Name: "na", + } + req := &stencilv1.PromoteSnapshotRequest{ + Id: 1, + } + mockService.On("GetSnapshotByID", mock.Anything, int64(1)).Return(st, nil) + mockService.On("UpdateLatestVersion", mock.Anything, st).Return(nil) + sp, err := v1.PromoteSnapshot(ctx, req) + res := sp.Snapshot + assert.Nil(t, err) + assert.Equal(t, int64(1), res.Id) + assert.Equal(t, "t", res.Namespace) + assert.Equal(t, "na", res.Name) + }) + t.Run("should return not found err if snapshot not found", func(t *testing.T) { + ctx := context.Background() + _, _, mockService, v1 := setup() + st := &snapshot.Snapshot{ + ID: 1, + Namespace: "t", + Name: "na", + } + req := &stencilv1.PromoteSnapshotRequest{ + Id: 1, + } + mockService.On("GetSnapshotByID", mock.Anything, int64(1)).Return(st, snapshot.ErrNotFound) + mockService.On("UpdateLatestVersion", mock.Anything, st).Return(nil) + _, err := v1.PromoteSnapshot(ctx, req) + assert.NotNil(t, err) + s := status.Convert(err) + assert.Equal(t, codes.NotFound.String(), s.Code().String()) + assert.Equal(t, "not found", s.Message()) + }) + t.Run("should mark as internal error if get snapshot fails", func(t *testing.T) { + ctx := context.Background() + _, _, mockService, v1 := setup() + st := &snapshot.Snapshot{ + ID: 1, + Namespace: "t", + Name: "na", + } + req := &stencilv1.PromoteSnapshotRequest{ + Id: 1, + } + err := errors.New("internal") + mockService.On("GetSnapshotByID", mock.Anything, int64(1)).Return(st, err) + mockService.On("UpdateLatestVersion", mock.Anything, st).Return(nil) + _, err = v1.PromoteSnapshot(ctx, req) + assert.NotNil(t, err) + s := status.Convert(err) + assert.Equal(t, codes.Internal.String(), s.Code().String()) + assert.Equal(t, "internal", s.Message()) + }) + t.Run("should mark as internal error if update snapshot fails", func(t *testing.T) { + ctx := context.Background() + _, _, mockService, v1 := setup() + st := &snapshot.Snapshot{ + ID: 1, + Namespace: "t", + Name: "na", + } + req := &stencilv1.PromoteSnapshotRequest{ + Id: 1, + } + err := errors.New("internal") + mockService.On("GetSnapshotByID", mock.Anything, int64(1)).Return(st, nil) + mockService.On("UpdateLatestVersion", mock.Anything, st).Return(err) + _, err = v1.PromoteSnapshot(ctx, req) + assert.NotNil(t, err) + s := status.Convert(err) + assert.Equal(t, codes.Unknown.String(), s.Code().String()) + assert.Equal(t, "internal", s.Message()) + }) } diff --git a/server/api/mocks/MetadataService.go b/server/api/mocks/MetadataService.go index 9b6fb121..c7e0fb15 100644 --- a/server/api/mocks/MetadataService.go +++ b/server/api/mocks/MetadataService.go @@ -28,8 +28,8 @@ func (_m *MetadataService) Exists(_a0 context.Context, _a1 *snapshot.Snapshot) b return r0 } -// GetSnapshot provides a mock function with given fields: _a0, _a1, _a2, _a3, _a4 -func (_m *MetadataService) GetSnapshot(_a0 context.Context, _a1 string, _a2 string, _a3 string, _a4 bool) (*snapshot.Snapshot, error) { +// GetSnapshotByFields provides a mock function with given fields: _a0, _a1, _a2, _a3, _a4 +func (_m *MetadataService) GetSnapshotByFields(_a0 context.Context, _a1 string, _a2 string, _a3 string, _a4 bool) (*snapshot.Snapshot, error) { ret := _m.Called(_a0, _a1, _a2, _a3, _a4) var r0 *snapshot.Snapshot @@ -51,21 +51,21 @@ func (_m *MetadataService) GetSnapshot(_a0 context.Context, _a1 string, _a2 stri return r0, r1 } -// ListNames provides a mock function with given fields: _a0, _a1 -func (_m *MetadataService) ListNames(_a0 context.Context, _a1 string) ([]string, error) { +// GetSnapshotByID provides a mock function with given fields: _a0, _a1 +func (_m *MetadataService) GetSnapshotByID(_a0 context.Context, _a1 int64) (*snapshot.Snapshot, error) { ret := _m.Called(_a0, _a1) - var r0 []string - if rf, ok := ret.Get(0).(func(context.Context, string) []string); ok { + var r0 *snapshot.Snapshot + if rf, ok := ret.Get(0).(func(context.Context, int64) *snapshot.Snapshot); ok { r0 = rf(_a0, _a1) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).([]string) + r0 = ret.Get(0).(*snapshot.Snapshot) } } var r1 error - if rf, ok := ret.Get(1).(func(context.Context, string) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok { r1 = rf(_a0, _a1) } else { r1 = ret.Error(1) @@ -74,22 +74,22 @@ func (_m *MetadataService) ListNames(_a0 context.Context, _a1 string) ([]string, return r0, r1 } -// ListVersions provides a mock function with given fields: _a0, _a1, _a2 -func (_m *MetadataService) ListVersions(_a0 context.Context, _a1 string, _a2 string) ([]string, error) { - ret := _m.Called(_a0, _a1, _a2) +// List provides a mock function with given fields: _a0, _a1 +func (_m *MetadataService) List(_a0 context.Context, _a1 *snapshot.Snapshot) ([]*snapshot.Snapshot, error) { + ret := _m.Called(_a0, _a1) - var r0 []string - if rf, ok := ret.Get(0).(func(context.Context, string, string) []string); ok { - r0 = rf(_a0, _a1, _a2) + var r0 []*snapshot.Snapshot + if rf, ok := ret.Get(0).(func(context.Context, *snapshot.Snapshot) []*snapshot.Snapshot); ok { + r0 = rf(_a0, _a1) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).([]string) + r0 = ret.Get(0).([]*snapshot.Snapshot) } } var r1 error - if rf, ok := ret.Get(1).(func(context.Context, string, string) error); ok { - r1 = rf(_a0, _a1, _a2) + if rf, ok := ret.Get(1).(func(context.Context, *snapshot.Snapshot) error); ok { + r1 = rf(_a0, _a1) } else { r1 = ret.Error(1) } diff --git a/server/api/noroute.go b/server/api/noroute.go deleted file mode 100644 index e5ccc6b5..00000000 --- a/server/api/noroute.go +++ /dev/null @@ -1,10 +0,0 @@ -package api - -import ( - "github.com/gin-gonic/gin" -) - -//NoRoute default response for no route -func NoRoute(c *gin.Context) { - c.JSON(404, gin.H{"message": "page not found"}) -} diff --git a/server/api/noroute_test.go b/server/api/noroute_test.go deleted file mode 100644 index 152dc9a7..00000000 --- a/server/api/noroute_test.go +++ /dev/null @@ -1,23 +0,0 @@ -package api_test - -import ( - "net/http" - "net/http/httptest" - "testing" - - "github.com/odpf/stencil/server/config" - server2 "github.com/odpf/stencil/server/server" - - "github.com/odpf/stencil/server/api" - "github.com/stretchr/testify/assert" -) - -func TestNoRoute(t *testing.T) { - router := server2.Router(&api.API{}, &config.Config{}) - w := httptest.NewRecorder() - req, _ := http.NewRequest("GET", "/random", nil) - router.ServeHTTP(w, req) - - assert.Equal(t, 404, w.Code) - assert.JSONEq(t, `{"message": "page not found"}`, w.Body.String()) -} diff --git a/server/api/ping.go b/server/api/ping.go index b5fb93e6..da8f179a 100644 --- a/server/api/ping.go +++ b/server/api/ping.go @@ -1,10 +1,18 @@ package api import ( + "context" + "github.com/gin-gonic/gin" + "google.golang.org/grpc/health/grpc_health_v1" ) //Ping handler func Ping(c *gin.Context) { c.JSON(200, gin.H{"message": "pong"}) } + +//Check grpc health check +func (s *API) Check(ctx context.Context, in *grpc_health_v1.HealthCheckRequest) (*grpc_health_v1.HealthCheckResponse, error) { + return &grpc_health_v1.HealthCheckResponse{Status: grpc_health_v1.HealthCheckResponse_SERVING}, nil +} diff --git a/server/api/upload.go b/server/api/upload.go index 0ed98dd7..0190e094 100644 --- a/server/api/upload.go +++ b/server/api/upload.go @@ -1,6 +1,7 @@ package api import ( + "context" "io" "io/ioutil" "mime/multipart" @@ -8,10 +9,14 @@ import ( "github.com/gin-gonic/gin" "github.com/odpf/stencil/server/models" + stencilv1 "github.com/odpf/stencil/server/odpf/stencil/v1" + "github.com/odpf/stencil/server/snapshot" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" ) -//Upload uploads file -func (a *API) Upload(c *gin.Context) { +// HTTPUpload http handler to schema data with metadata information +func (a *API) HTTPUpload(c *gin.Context) { ctx := c.Request.Context() namespace := c.Param("namespace") payload := &models.DescriptorUploadRequest{ @@ -27,25 +32,49 @@ func (a *API) Upload(c *gin.Context) { return } currentSnapshot := payload.ToSnapshot() - if ok := a.Metadata.Exists(ctx, currentSnapshot); ok { - c.JSON(http.StatusConflict, gin.H{"message": "Resource already exist"}) + err = a.upload(ctx, currentSnapshot, data, payload.SkipRules, payload.DryRun) + if err != nil { + c.Error(err) return } - err = a.Store.Validate(ctx, currentSnapshot, data, payload.SkipRules) + c.JSON(http.StatusOK, gin.H{"message": "success", "dryrun": payload.DryRun}) +} + +// UploadDescriptor grpc handler to upload schema data with metadata information +func (a *API) UploadDescriptor(ctx context.Context, req *stencilv1.UploadDescriptorRequest) (*stencilv1.UploadDescriptorResponse, error) { + res := &stencilv1.UploadDescriptorResponse{ + Dryrun: req.Dryrun, + } + s := fromProtoToSnapshot(&stencilv1.Snapshot{Namespace: req.Namespace, Name: req.Name, Version: req.Version, Latest: req.Latest}) + err := validate.StructExcept(s, "ID", "Latest") if err != nil { - c.JSON(http.StatusBadRequest, gin.H{"message": err.Error()}) - return + res.Errors = err.Error() + return res, status.Error(codes.InvalidArgument, err.Error()) } - if payload.DryRun { - c.JSON(http.StatusOK, gin.H{"message": "success", "dryrun": "true"}) - return + if err := a.upload(ctx, s, req.Data, toRulesList(req.Checks), req.Dryrun); err != nil { + res.Errors = err.Error() + return res, err } - err = a.Store.Insert(ctx, currentSnapshot, data) + res.Success = true + return res, nil +} + +func (a *API) upload(ctx context.Context, snapshot *snapshot.Snapshot, data []byte, skipRules []string, dryrun bool) error { + if ok := a.Metadata.Exists(ctx, snapshot); ok { + return status.Error(codes.AlreadyExists, "Resource already exists") + } + err := a.Store.Validate(ctx, snapshot, data, skipRules) if err != nil { - c.Error(err).SetMeta(models.ErrUploadFailed) - return + return status.Error(codes.InvalidArgument, err.Error()) + } + if dryrun { + return nil + } + err = a.Store.Insert(ctx, snapshot, data) + if err != nil { + return status.Error(codes.Internal, err.Error()) } - c.JSON(http.StatusOK, gin.H{"message": "success"}) + return nil } func readDataFromReader(reader io.ReadCloser) ([]byte, error) { diff --git a/server/api/upload_test.go b/server/api/upload_test.go index 480420fe..9ad486af 100644 --- a/server/api/upload_test.go +++ b/server/api/upload_test.go @@ -2,6 +2,7 @@ package api_test import ( "bytes" + "context" "errors" "fmt" "io" @@ -12,9 +13,12 @@ import ( "strconv" "testing" + "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" "github.com/odpf/stencil/server/models" + stencilv1 "github.com/odpf/stencil/server/odpf/stencil/v1" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" + "google.golang.org/grpc/status" ) var ( @@ -64,8 +68,8 @@ func TestUpload(t *testing.T) { {"should return 400 if version is missing", "name1", "", false, nil, nil, 400, formError}, {"should return 400 if version is invalid semantic version", "name1", "invalid", false, nil, nil, 400, formError}, {"should return 400 if backward check fails", "name1", "1.0.1", false, errors.New("validation"), nil, 400, "validation"}, - {"should return 409 if resource already exists", "name1", "1.0.1", true, nil, nil, 409, "Resource already exist"}, - {"should return 500 if insert fails", "name1", "1.0.1", false, nil, errors.New("insert fail"), 500, uploadError}, + {"should return 409 if resource already exists", "name1", "1.0.1", true, nil, nil, 409, "Resource already exists"}, + {"should return 500 if insert fails", "name1", "1.0.1", false, nil, errors.New("insert fail"), 500, "Internal error"}, {"should return 200 if upload succeeded", "name1", "1.0.1", false, nil, nil, 200, success}, } { t.Run(test.desc, func(t *testing.T) { @@ -81,7 +85,33 @@ func TestUpload(t *testing.T) { router.ServeHTTP(w, req) assert.Equal(t, test.expectedCode, w.Code) - assert.JSONEq(t, fmt.Sprintf(`{"message": "%s"}`, test.responseMsg), w.Body.String()) + + if w.Code == 200 { + assert.JSONEq(t, fmt.Sprintf(`{"message": "%s", "dryrun": false}`, test.responseMsg), w.Body.String()) + } else { + assert.JSONEq(t, fmt.Sprintf(`{"message": "%s"}`, test.responseMsg), w.Body.String()) + } + }) + t.Run(fmt.Sprintf("gRPC: %s", test.desc), func(t *testing.T) { + _, mockService, metadata, api := setup() + metadata.On("Exists", mock.Anything, mock.Anything).Return(test.exists) + mockService.On("Validate", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(test.validateErr) + mockService.On("Insert", mock.Anything, mock.Anything, mock.Anything).Return(test.insertErr) + data, err := os.ReadFile("./testdata/test.desc") + assert.Nil(t, err) + req := &stencilv1.UploadDescriptorRequest{ + Namespace: "namespace", Name: test.name, Version: test.version, + Data: data, + } + res, err := api.UploadDescriptor(context.Background(), req) + if test.expectedCode != 200 { + e := status.Convert(err) + assert.Equal(t, test.expectedCode, runtime.HTTPStatusFromCode(e.Code())) + } else { + assert.Equal(t, res.Dryrun, false) + assert.Equal(t, res.Success, true) + assert.Equal(t, res.Errors, "") + } }) } @@ -100,7 +130,7 @@ func TestUpload(t *testing.T) { router.ServeHTTP(w, req) assert.Equal(t, 200, w.Code) - assert.JSONEq(t, `{"message": "success", "dryrun": "true"}`, w.Body.String()) + assert.JSONEq(t, `{"message": "success", "dryrun": true}`, w.Body.String()) mockService.AssertNotCalled(t, "Insert", mock.Anything, mock.Anything, mock.Anything) }) } diff --git a/server/api/validator.go b/server/api/validator.go new file mode 100644 index 00000000..3f27e922 --- /dev/null +++ b/server/api/validator.go @@ -0,0 +1,23 @@ +package api + +import ( + "github.com/blang/semver/v4" + v "github.com/go-playground/validator/v10" +) + +var validate *v.Validate + +func init() { + validate = v.New() + validate.SetTagName("binding") + validate.RegisterValidation("version", func(fl v.FieldLevel) bool { + version, ok := fl.Field().Interface().(string) + if ok { + if _, err := semver.Parse(version); err == nil { + return true + } + return false + } + return false + }) +} diff --git a/server/cmd/upload.go b/server/cmd/upload.go new file mode 100644 index 00000000..79a1fa08 --- /dev/null +++ b/server/cmd/upload.go @@ -0,0 +1,60 @@ +package cmd + +import ( + "context" + "io/ioutil" + "log" + + stencilv1 "github.com/odpf/stencil/server/odpf/stencil/v1" + "github.com/spf13/cobra" + "google.golang.org/grpc" +) + +var host, namespace, name, version, filePath string +var latest bool + +func init() { + uploadCmd := &cobra.Command{ + Use: "upload", + Short: "Upload filedescriptorset file", + Run: upload, + Args: cobra.NoArgs, + } + uploadCmd.Flags().StringVarP(&host, "host", "h", "", "stencil host address eg: localhost:8000") + uploadCmd.MarkFlagRequired("host") + uploadCmd.Flags().StringVarP(&namespace, "namespace", "g", "", "provide namespace/group or entity name") + uploadCmd.MarkFlagRequired("namespace") + uploadCmd.Flags().StringVarP(&name, "name", "n", "", "provide proto repo name") + uploadCmd.MarkFlagRequired("name") + uploadCmd.Flags().StringVarP(&version, "version", "v", "", "provide semantic version compatible value") + uploadCmd.MarkFlagRequired("version") + uploadCmd.Flags().BoolVarP(&latest, "latest", "l", false, "mark as latest version") + uploadCmd.Flags().StringVarP(&filePath, "file", "f", "", "provide path to fully contained file descriptor set file") + uploadCmd.MarkFlagRequired("file") + rootCmd.AddCommand(uploadCmd) +} + +func upload(cmd *cobra.Command, args []string) { + fileData, err := ioutil.ReadFile(filePath) + if err != nil { + log.Fatalln("Unable to read provided file", err) + } + conn, err := grpc.Dial(host, grpc.WithInsecure()) + if err != nil { + log.Fatalln(err) + } + defer conn.Close() + client := stencilv1.NewStencilServiceClient(conn) + ur := &stencilv1.UploadDescriptorRequest{ + Namespace: namespace, + Name: name, + Version: version, + Latest: latest, + Data: fileData, + } + res, err := client.UploadDescriptor(context.Background(), ur) + if err != nil { + log.Fatalln(err) + } + log.Println(res) +} diff --git a/server/config/config.go b/server/config/config.go index cf0a852e..26262393 100644 --- a/server/config/config.go +++ b/server/config/config.go @@ -24,12 +24,19 @@ type DBConfig struct { MigrationsPath string } +//GRPCConfig grpc options +type GRPCConfig struct { + MaxRecvMsgSizeInMB int `default:"10"` + MaxSendMsgSizeInMB int `default:"10"` +} + //Config Server config type Config struct { Port string `default:"8080"` //Timeout represents graceful shutdown period. //Default is 60 seconds. Timeout time.Duration `default:"60s"` + GRPC GRPCConfig NewRelic NewRelicConfig DB DBConfig } diff --git a/server/docs/api.md b/server/docs/api.md index 5d0b0ac0..5ff55b48 100644 --- a/server/docs/api.md +++ b/server/docs/api.md @@ -2,7 +2,7 @@ > Scroll down for code samples, example requests and responses. Select a language for code samples from the tabs above or the mobile navigation menu. -

Default

+

health

## ping @@ -30,9 +30,7 @@ curl -X GET /ping This operation does not require authentication -

descriptors

- -Manage descriptors +

StencilService

## post__v1_namespaces_{namespace}_descriptors @@ -88,232 +86,248 @@ file: string |Status|Meaning|Description|Schema| |---|---|---|---| -|200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|Success response|None| -|409|[Conflict](https://tools.ietf.org/html/rfc7231#section-6.5.8)|Conflict|None| +|200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|Success response if operation succeded|None| +|400|[Bad Request](https://tools.ietf.org/html/rfc7231#section-6.5.1)|Validation error response when user payload has missing required fields or currently being uploaded file is not backward compatible with previously uploaded file|None| +|409|[Conflict](https://tools.ietf.org/html/rfc7231#section-6.5.8)|conflict error reponse if namespace, name and version combination already present|None| +|500|[Internal Server Error](https://tools.ietf.org/html/rfc7231#section-6.6.1)|Unexpected internal error reponse|None| -## get__v1_namespaces_{namespace}_descriptors +## get__v1_namespaces_{namespace}_descriptors_{name}_versions_{version} > Code samples ```shell # You can also use wget -curl -X GET /v1/namespaces/{namespace}/descriptors \ - -H 'Accept: application/json' +curl -X GET /v1/namespaces/{namespace}/descriptors/{name}/versions/{version} ``` -`GET /v1/namespaces/{namespace}/descriptors` +`GET /v1/namespaces/{namespace}/descriptors/{name}/versions/{version}` -*list all available descriptor names under one namespace* +*download specified descriptor file* -

Parameters

+

Parameters

|Name|In|Type|Required|Description| |---|---|---|---|---| |namespace|path|string|true|none| +|name|path|string|true|none| +|version|path|string|true|none| +|fullnames|query|array[string]|false|Proto fullnames| -> Example responses - -> 200 Response - -```json -[ - "string" -] -``` - -

Responses

+

Responses

|Status|Meaning|Description|Schema| |---|---|---|---| -|200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|returns list of descriptor names|Inline| - -

Response Schema

+|200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|download response|None| -## get__v1_namespaces_{namespace}_descriptors_{name}_versions +## StencilService_ListSnapshots + + > Code samples ```shell # You can also use wget -curl -X GET /v1/namespaces/{namespace}/descriptors/{name}/versions \ +curl -X GET /v1/snapshots \ -H 'Accept: application/json' ``` -`GET /v1/namespaces/{namespace}/descriptors/{name}/versions` - -*list all available versions for specified descriptor* +`GET /v1/snapshots` -

Parameters

+

Parameters

|Name|In|Type|Required|Description| |---|---|---|---|---| -|namespace|path|string|true|none| -|name|path|string|true|none| +|namespace|query|string|false|none| +|name|query|string|false|none| +|version|query|string|false|none| +|latest|query|boolean|false|none| > Example responses > 200 Response ```json -[ - "string" -] +{ + "snapshots": [ + { + "id": "string", + "namespace": "string", + "name": "string", + "version": "string", + "latest": true + } + ] +} ``` -

Responses

+

Responses

|Status|Meaning|Description|Schema| |---|---|---|---| -|200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|returns list of versions|Inline| - -

Response Schema

+|200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|A successful response.|[v1ListSnapshotsResponse](#schemav1listsnapshotsresponse)| +|default|Default|An unexpected error response.|[rpcStatus](#schemarpcstatus)| -## get__v1_namespaces_{namespace}_descriptors_{name}_versions_{version} +## StencilService_PromoteSnapshot + + > Code samples ```shell # You can also use wget -curl -X GET /v1/namespaces/{namespace}/descriptors/{name}/versions/{version} +curl -X PATCH /v1/snapshots/{id}/promote \ + -H 'Accept: application/json' ``` -`GET /v1/namespaces/{namespace}/descriptors/{name}/versions/{version}` +`PATCH /v1/snapshots/{id}/promote` -*download specified descriptor file* +*PromoteSnapshot promotes particular snapshot version as latest* -

Parameters

+

Parameters

|Name|In|Type|Required|Description| |---|---|---|---|---| -|namespace|path|string|true|none| -|name|path|string|true|none| -|version|path|string|true|none| -|fullnames|query|array[string]|false|Proto fullnames| - -

Responses

- -|Status|Meaning|Description|Schema| -|---|---|---|---| -|200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|download response|None| - - - -

metadata

- -manage latest versions for uploaded descriptor files +|id|path|string(int64)|true|none| -## post__v1_namespaces_{namespace}_metadata - -> Code samples - -```shell -# You can also use wget -curl -X POST /v1/namespaces/{namespace}/metadata \ - -H 'Content-Type: application/json' - -``` - -`POST /v1/namespaces/{namespace}/metadata` - -*update metadata* +> Example responses -> Body parameter +> 200 Response ```json { - "name": "string", - "version": "string" + "snapshot": { + "id": "string", + "namespace": "string", + "name": "string", + "version": "string", + "latest": true + } } ``` -

Parameters

- -|Name|In|Type|Required|Description| -|---|---|---|---|---| -|namespace|path|string|true|none| -|body|body|[MetadataPayload](#schemametadatapayload)|true|specify name and version in payload| - -

Responses

+

Responses

|Status|Meaning|Description|Schema| |---|---|---|---| -|200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|Success response|None| +|200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|A successful response.|[v1PromoteSnapshotResponse](#schemav1promotesnapshotresponse)| +|default|Default|An unexpected error response.|[rpcStatus](#schemarpcstatus)| -## get__v1_namespaces_{namespace}_metadata_{name} +# Schemas -> Code samples +

protobufAny

+ + + + + -```shell -# You can also use wget -curl -X GET /v1/namespaces/{namespace}/metadata/{name} \ - -H 'Accept: application/json' +```json +{ + "typeUrl": "string", + "value": "string" +} ``` -`GET /v1/namespaces/{namespace}/metadata/{name}` - -*get latest version for specified descriptor* - -

Parameters

+### Properties -|Name|In|Type|Required|Description| +|Name|Type|Required|Restrictions|Description| |---|---|---|---|---| -|namespace|path|string|true|none| -|name|path|string|true|none| - -> Example responses +|typeUrl|string|false|none|none| +|value|string(byte)|false|none|none| -> 200 Response +

rpcStatus

+ + + + + ```json { - "version": "string" + "code": 0, + "message": "string", + "details": [ + { + "typeUrl": "string", + "value": "string" + } + ] } + ``` -

Responses

+### Properties -|Status|Meaning|Description|Schema| -|---|---|---|---| -|200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|Success response|[MetadataResponse](#schemametadataresponse)| +|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|code|integer(int32)|false|none|none| +|message|string|false|none|none| +|details|[[protobufAny](#schemaprotobufany)]|false|none|none| - +

v1ListSnapshotsResponse

+ + + + + -# Schemas +```json +{ + "snapshots": [ + { + "id": "string", + "namespace": "string", + "name": "string", + "version": "string", + "latest": true + } + ] +} + +``` + +### Properties -

MetadataResponse

+|Name|Type|Required|Restrictions|Description| +|---|---|---|---|---| +|snapshots|[[v1Snapshot](#schemav1snapshot)]|false|none|none| + +

v1PromoteSnapshotResponse

- - - - + + + + ```json { - "version": "string" + "snapshot": { + "id": "string", + "namespace": "string", + "name": "string", + "version": "string", + "latest": true + } } ``` @@ -322,19 +336,22 @@ This operation does not require authentication |Name|Type|Required|Restrictions|Description| |---|---|---|---|---| -|version|string|false|none|none| +|snapshot|[v1Snapshot](#schemav1snapshot)|false|none|none| -

MetadataPayload

+

v1Snapshot

- - - - + + + + ```json { + "id": "string", + "namespace": "string", "name": "string", - "version": "string" + "version": "string", + "latest": true } ``` @@ -343,9 +360,9 @@ This operation does not require authentication |Name|Type|Required|Restrictions|Description| |---|---|---|---|---| +|id|string(int64)|false|none|none| +|namespace|string|true|none|none| |name|string|false|none|none| |version|string|false|none|none| - - - +|latest|boolean|false|none|none| diff --git a/server/go.mod b/server/go.mod index e22fa6b0..6d528379 100644 --- a/server/go.mod +++ b/server/go.mod @@ -8,16 +8,24 @@ require ( github.com/gin-gonic/gin v1.7.4 github.com/go-playground/validator/v10 v10.4.1 github.com/golang-migrate/migrate/v4 v4.14.1 + github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 + github.com/grpc-ecosystem/grpc-gateway/v2 v2.5.0 github.com/jackc/pgx/v4 v4.13.0 github.com/jeremywohl/flatten v1.0.1 github.com/mcuadros/go-defaults v1.2.0 github.com/mitchellh/mapstructure v1.4.1 github.com/newrelic/go-agent/v3 v3.12.0 github.com/newrelic/go-agent/v3/integrations/nrgin v1.1.0 + github.com/newrelic/go-agent/v3/integrations/nrgrpc v1.3.1 github.com/spf13/cobra v1.2.1 github.com/spf13/viper v1.8.1 github.com/stretchr/testify v1.7.0 go.uber.org/multierr v1.6.0 go.uber.org/zap v1.19.0 - google.golang.org/protobuf v1.26.0 + golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d + golang.org/x/sys v0.0.0-20210819072135-bce67f096156 // indirect + golang.org/x/text v0.3.7 // indirect + google.golang.org/genproto v0.0.0-20210818220304-27ea9cc85d9f + google.golang.org/grpc v1.40.0 + google.golang.org/protobuf v1.27.1 ) diff --git a/server/go.sum b/server/go.sum index f9dbbd4d..b4573c16 100644 --- a/server/go.sum +++ b/server/go.sum @@ -48,6 +48,7 @@ github.com/ClickHouse/clickhouse-go v1.3.12/go.mod h1:EaI/sW7Azgz9UATzd5ZdZHRUhH github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5 h1:ygIc8M6trr62pF5DucadTWGdEB4mEyvzi0e2nbcmcyA= github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/apache/arrow/go/arrow v0.0.0-20200601151325-b2287a20f230/go.mod h1:QNYViu/X0HXDHw7m3KXzWSVXIbfUvJqBFe6Gj8/pYA0= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= @@ -65,6 +66,7 @@ github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2y github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= github.com/cenkalti/backoff/v4 v4.0.2/go.mod h1:eEew/i+1Q6OrCDZh3WiXYv3+nJwBASZ8Bog/87DQnVg= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= @@ -73,6 +75,7 @@ github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58/go.mod h1:EOBUe0h github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= github.com/cockroachdb/cockroach-go v0.0.0-20190925194419-606b3d062051 h1:eApuUG8W2EtBVwxqLlY2wgoqDYOg3WvIHGvW4fUbbow= @@ -112,6 +115,7 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= @@ -131,7 +135,9 @@ github.com/gin-gonic/gin v1.7.4/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjX github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= @@ -158,6 +164,8 @@ github.com/golang-migrate/migrate/v4 v4.14.1 h1:qmRd/rNGjM1r3Ve5gHd5ZplytrD02UcI github.com/golang-migrate/migrate/v4 v4.14.1/go.mod h1:l7Ks0Au6fYHuUIxUhQ0rcVX1uLlJg54C/VvW7tvxSz0= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/glog v0.0.0-20210429001901-424d2337a529 h1:2voWjNECnrZRbfwXxHB1/j8wa6xdKn85B5NzgVL/pTU= +github.com/golang/glog v0.0.0-20210429001901-424d2337a529/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -203,8 +211,9 @@ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -234,7 +243,12 @@ github.com/gorilla/handlers v1.4.2/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/ github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= +github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= +github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.5.0 h1:ajue7SzQMywqRjg2fK7dcpc0QhFGpTR2plWfV4EZWR4= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.5.0/go.mod h1:r1hZAcvfFXuYmcKyCJI9wlyOPIZUJl6FCB8Cpca/NLE= github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= @@ -363,6 +377,7 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxv github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= @@ -426,6 +441,8 @@ github.com/newrelic/go-agent/v3 v3.12.0 h1:tcDo0Q8qRWAJqb9uykfmM8pxGSbv0HqSS3q1+ github.com/newrelic/go-agent/v3 v3.12.0/go.mod h1:1A1dssWBwzB7UemzRU6ZVaGDsI+cEn5/bNxI0wiYlIc= github.com/newrelic/go-agent/v3/integrations/nrgin v1.1.0 h1:lbxcXUImLm7FEvjwDll3jnZ3P+AyZo9gN5UVNg6NYNM= github.com/newrelic/go-agent/v3/integrations/nrgin v1.1.0/go.mod h1:CYFq0517T2EwtONPFd+7qFsrpSR0nydqQf22N284nok= +github.com/newrelic/go-agent/v3/integrations/nrgrpc v1.3.1 h1:/ar1Omo9luapTJYWXt86oQGBpWwpWF92x+UuYU9v/7o= +github.com/newrelic/go-agent/v3/integrations/nrgrpc v1.3.1/go.mod h1:2q0u6qkNJ4ClDt920A4r+NpcO370lFze1NF4OPJjAks= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -436,6 +453,7 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8 github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI= github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pelletier/go-toml v1.9.3 h1:zeC5b1GviRUyKYd6OJPvBU/mcVDVoL1OhT17FCt5dSQ= github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= @@ -476,6 +494,7 @@ github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIK github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/snowflakedb/glog v0.0.0-20180824191149-f5055e6f21ce/go.mod h1:EB/w24pR5VKI60ecFnKqXzxX3dOorz1rnVicQTQrGM0= github.com/snowflakedb/gosnowflake v1.3.5/go.mod h1:13Ky+lxzIm3VqNDZJdyvu9MCGy+WgRdYFdXp96UcLZU= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY= github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng= @@ -529,6 +548,7 @@ go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= @@ -646,8 +666,9 @@ golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 h1:4nGaVu0QrbjT/AK2PRLuQfQuh6DJve+pELhqTdAj3x0= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d h1:LO7XpTYMwTqxjLcGWPijK3vRXg1aWdlNOVOHRq45d7c= +golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/oauth2 v0.0.0-20180227000427-d7d64896b5ff/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -662,6 +683,7 @@ golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210615190721-d04028783cf1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -727,9 +749,11 @@ golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210819072135-bce67f096156 h1:f7XLk/QXGE6IM4HjJ4ttFFlPSwJ65A1apfDd+mmViR0= +golang.org/x/sys v0.0.0-20210819072135-bce67f096156/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -739,8 +763,9 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -806,8 +831,10 @@ golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.1.2 h1:kRBLX7v7Af8W7Gdbbc908OJcdgtK8bOz9Uaj8/F1ACA= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.5 h1:ouewzE6p+/VEB31YYnTbEJdi8pFqKp4P4n85vwo3DHA= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -867,6 +894,7 @@ google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfG google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= @@ -890,8 +918,10 @@ google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c h1:wtujag7C+4D6KMoulW9YauvK2lgdvCMS260jsqqBXr0= google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210617175327-b9e0b3197ced/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= +google.golang.org/genproto v0.0.0-20210818220304-27ea9cc85d9f h1:enWPderunHptc5pzJkSYGx0olpF8goXzG0rY3kL0eSg= +google.golang.org/genproto v0.0.0-20210818220304-27ea9cc85d9f/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -912,8 +942,9 @@ google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA5 google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.38.0 h1:/9BgsAsa5nWe26HqOlvlgJnqBuktYOLCgjCPqsa56W0= google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.40.0 h1:AGJ0Ih4mHjSeibYkFGh1dD9KJ/eOtZ93I6hoHhukQ5Q= +google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -925,8 +956,9 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= diff --git a/server/logger/logger.go b/server/logger/logger.go new file mode 100644 index 00000000..8b013f72 --- /dev/null +++ b/server/logger/logger.go @@ -0,0 +1,18 @@ +package logger + +import ( + "log" + + "go.uber.org/zap" +) + +// Logger zap logger instance +var Logger *zap.Logger + +func init() { + l, err := zap.NewProduction() + if err != nil { + log.Fatalln(err) + } + Logger = l +} diff --git a/server/main.go b/server/main.go index 799edfbd..9c491fbb 100644 --- a/server/main.go +++ b/server/main.go @@ -1,6 +1,8 @@ package main -import "github.com/odpf/stencil/server/cmd" +import ( + "github.com/odpf/stencil/server/cmd" +) func main() { cmd.Execute() diff --git a/server/models/descriptor.go b/server/models/descriptor.go index 1aa396d0..592cdae8 100644 --- a/server/models/descriptor.go +++ b/server/models/descriptor.go @@ -9,7 +9,7 @@ import ( type FileDownloadRequest struct { Namespace string `uri:"namespace" binding:"required"` Name string `uri:"name" binding:"required"` - Version string `uri:"version" binding:"required,versionWithLatest"` + Version string `uri:"version" binding:"required,version|eq=latest"` FullNames []string } @@ -46,18 +46,3 @@ func (d *DescriptorUploadRequest) ToSnapshot() *snapshot.Snapshot { Latest: d.Latest, } } - -type GetMetadataRequest struct { - Namespace string `uri:"namespace" binding:"required"` - Name string `uri:"name" binding:"required"` -} - -type MetadataUpdateRequest struct { - Namespace string - Name string `json:"name" binding:"required"` - Version string `json:"version" binding:"required,version"` -} - -type MetadataFile struct { - Version string `json:"version"` -} diff --git a/server/models/error.go b/server/models/error.go index 2b82b27c..b497e640 100644 --- a/server/models/error.go +++ b/server/models/error.go @@ -86,6 +86,9 @@ func (a *apiErr) Error() string { if err == nil { err = errors.New("") } + if a.code >= 500 { + return a.message + } return fmt.Sprintf("Err: %s, Message: %s", err.Error(), a.Message()) } diff --git a/server/odpf/stencil/v1/stencil.pb.go b/server/odpf/stencil/v1/stencil.pb.go new file mode 100644 index 00000000..a3fc78e2 --- /dev/null +++ b/server/odpf/stencil/v1/stencil.pb.go @@ -0,0 +1,1021 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.27.1 +// protoc v3.17.3 +// source: odpf/stencil/v1/stencil.proto + +package stencilv1 + +import ( + _ "github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options" + _ "google.golang.org/genproto/googleapis/api/annotations" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + _ "google.golang.org/protobuf/types/descriptorpb" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type Rule int32 + +const ( + Rule_UNKNOWN Rule = 0 + Rule_FILE_NO_BREAKING_CHANGE Rule = 1 + Rule_MESSAGE_NO_DELETE Rule = 2 + Rule_FIELD_NO_BREAKING_CHANGE Rule = 3 + Rule_ENUM_NO_BREAKING_CHANGE Rule = 4 +) + +// Enum value maps for Rule. +var ( + Rule_name = map[int32]string{ + 0: "UNKNOWN", + 1: "FILE_NO_BREAKING_CHANGE", + 2: "MESSAGE_NO_DELETE", + 3: "FIELD_NO_BREAKING_CHANGE", + 4: "ENUM_NO_BREAKING_CHANGE", + } + Rule_value = map[string]int32{ + "UNKNOWN": 0, + "FILE_NO_BREAKING_CHANGE": 1, + "MESSAGE_NO_DELETE": 2, + "FIELD_NO_BREAKING_CHANGE": 3, + "ENUM_NO_BREAKING_CHANGE": 4, + } +) + +func (x Rule) Enum() *Rule { + p := new(Rule) + *p = x + return p +} + +func (x Rule) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (Rule) Descriptor() protoreflect.EnumDescriptor { + return file_odpf_stencil_v1_stencil_proto_enumTypes[0].Descriptor() +} + +func (Rule) Type() protoreflect.EnumType { + return &file_odpf_stencil_v1_stencil_proto_enumTypes[0] +} + +func (x Rule) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use Rule.Descriptor instead. +func (Rule) EnumDescriptor() ([]byte, []int) { + return file_odpf_stencil_v1_stencil_proto_rawDescGZIP(), []int{0} +} + +type Snapshot struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` + Namespace string `protobuf:"bytes,2,opt,name=namespace,proto3" json:"namespace,omitempty"` + Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"` + Version string `protobuf:"bytes,4,opt,name=version,proto3" json:"version,omitempty"` + Latest bool `protobuf:"varint,5,opt,name=latest,proto3" json:"latest,omitempty"` +} + +func (x *Snapshot) Reset() { + *x = Snapshot{} + if protoimpl.UnsafeEnabled { + mi := &file_odpf_stencil_v1_stencil_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Snapshot) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Snapshot) ProtoMessage() {} + +func (x *Snapshot) ProtoReflect() protoreflect.Message { + mi := &file_odpf_stencil_v1_stencil_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Snapshot.ProtoReflect.Descriptor instead. +func (*Snapshot) Descriptor() ([]byte, []int) { + return file_odpf_stencil_v1_stencil_proto_rawDescGZIP(), []int{0} +} + +func (x *Snapshot) GetId() int64 { + if x != nil { + return x.Id + } + return 0 +} + +func (x *Snapshot) GetNamespace() string { + if x != nil { + return x.Namespace + } + return "" +} + +func (x *Snapshot) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *Snapshot) GetVersion() string { + if x != nil { + return x.Version + } + return "" +} + +func (x *Snapshot) GetLatest() bool { + if x != nil { + return x.Latest + } + return false +} + +type DownloadDescriptorRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Namespace string `protobuf:"bytes,1,opt,name=namespace,proto3" json:"namespace,omitempty"` + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` + Version string `protobuf:"bytes,3,opt,name=version,proto3" json:"version,omitempty"` + Fullnames []string `protobuf:"bytes,4,rep,name=fullnames,proto3" json:"fullnames,omitempty"` +} + +func (x *DownloadDescriptorRequest) Reset() { + *x = DownloadDescriptorRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_odpf_stencil_v1_stencil_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DownloadDescriptorRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DownloadDescriptorRequest) ProtoMessage() {} + +func (x *DownloadDescriptorRequest) ProtoReflect() protoreflect.Message { + mi := &file_odpf_stencil_v1_stencil_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DownloadDescriptorRequest.ProtoReflect.Descriptor instead. +func (*DownloadDescriptorRequest) Descriptor() ([]byte, []int) { + return file_odpf_stencil_v1_stencil_proto_rawDescGZIP(), []int{1} +} + +func (x *DownloadDescriptorRequest) GetNamespace() string { + if x != nil { + return x.Namespace + } + return "" +} + +func (x *DownloadDescriptorRequest) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *DownloadDescriptorRequest) GetVersion() string { + if x != nil { + return x.Version + } + return "" +} + +func (x *DownloadDescriptorRequest) GetFullnames() []string { + if x != nil { + return x.Fullnames + } + return nil +} + +type DownloadDescriptorResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Data []byte `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"` +} + +func (x *DownloadDescriptorResponse) Reset() { + *x = DownloadDescriptorResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_odpf_stencil_v1_stencil_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DownloadDescriptorResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DownloadDescriptorResponse) ProtoMessage() {} + +func (x *DownloadDescriptorResponse) ProtoReflect() protoreflect.Message { + mi := &file_odpf_stencil_v1_stencil_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DownloadDescriptorResponse.ProtoReflect.Descriptor instead. +func (*DownloadDescriptorResponse) Descriptor() ([]byte, []int) { + return file_odpf_stencil_v1_stencil_proto_rawDescGZIP(), []int{2} +} + +func (x *DownloadDescriptorResponse) GetData() []byte { + if x != nil { + return x.Data + } + return nil +} + +type UploadDescriptorRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Namespace string `protobuf:"bytes,1,opt,name=namespace,proto3" json:"namespace,omitempty"` + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` + Version string `protobuf:"bytes,3,opt,name=version,proto3" json:"version,omitempty"` + Data []byte `protobuf:"bytes,4,opt,name=data,proto3" json:"data,omitempty"` + Latest bool `protobuf:"varint,5,opt,name=latest,proto3" json:"latest,omitempty"` + Dryrun bool `protobuf:"varint,6,opt,name=dryrun,proto3" json:"dryrun,omitempty"` + Checks *Checks `protobuf:"bytes,7,opt,name=checks,proto3" json:"checks,omitempty"` +} + +func (x *UploadDescriptorRequest) Reset() { + *x = UploadDescriptorRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_odpf_stencil_v1_stencil_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *UploadDescriptorRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UploadDescriptorRequest) ProtoMessage() {} + +func (x *UploadDescriptorRequest) ProtoReflect() protoreflect.Message { + mi := &file_odpf_stencil_v1_stencil_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UploadDescriptorRequest.ProtoReflect.Descriptor instead. +func (*UploadDescriptorRequest) Descriptor() ([]byte, []int) { + return file_odpf_stencil_v1_stencil_proto_rawDescGZIP(), []int{3} +} + +func (x *UploadDescriptorRequest) GetNamespace() string { + if x != nil { + return x.Namespace + } + return "" +} + +func (x *UploadDescriptorRequest) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *UploadDescriptorRequest) GetVersion() string { + if x != nil { + return x.Version + } + return "" +} + +func (x *UploadDescriptorRequest) GetData() []byte { + if x != nil { + return x.Data + } + return nil +} + +func (x *UploadDescriptorRequest) GetLatest() bool { + if x != nil { + return x.Latest + } + return false +} + +func (x *UploadDescriptorRequest) GetDryrun() bool { + if x != nil { + return x.Dryrun + } + return false +} + +func (x *UploadDescriptorRequest) GetChecks() *Checks { + if x != nil { + return x.Checks + } + return nil +} + +type Checks struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Except []Rule `protobuf:"varint,2,rep,packed,name=except,proto3,enum=odpf.stencil.v1.Rule" json:"except,omitempty"` +} + +func (x *Checks) Reset() { + *x = Checks{} + if protoimpl.UnsafeEnabled { + mi := &file_odpf_stencil_v1_stencil_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Checks) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Checks) ProtoMessage() {} + +func (x *Checks) ProtoReflect() protoreflect.Message { + mi := &file_odpf_stencil_v1_stencil_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Checks.ProtoReflect.Descriptor instead. +func (*Checks) Descriptor() ([]byte, []int) { + return file_odpf_stencil_v1_stencil_proto_rawDescGZIP(), []int{4} +} + +func (x *Checks) GetExcept() []Rule { + if x != nil { + return x.Except + } + return nil +} + +type UploadDescriptorResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"` + Dryrun bool `protobuf:"varint,2,opt,name=dryrun,proto3" json:"dryrun,omitempty"` + Errors string `protobuf:"bytes,3,opt,name=errors,proto3" json:"errors,omitempty"` +} + +func (x *UploadDescriptorResponse) Reset() { + *x = UploadDescriptorResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_odpf_stencil_v1_stencil_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *UploadDescriptorResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UploadDescriptorResponse) ProtoMessage() {} + +func (x *UploadDescriptorResponse) ProtoReflect() protoreflect.Message { + mi := &file_odpf_stencil_v1_stencil_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UploadDescriptorResponse.ProtoReflect.Descriptor instead. +func (*UploadDescriptorResponse) Descriptor() ([]byte, []int) { + return file_odpf_stencil_v1_stencil_proto_rawDescGZIP(), []int{5} +} + +func (x *UploadDescriptorResponse) GetSuccess() bool { + if x != nil { + return x.Success + } + return false +} + +func (x *UploadDescriptorResponse) GetDryrun() bool { + if x != nil { + return x.Dryrun + } + return false +} + +func (x *UploadDescriptorResponse) GetErrors() string { + if x != nil { + return x.Errors + } + return "" +} + +type ListSnapshotsResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Snapshots []*Snapshot `protobuf:"bytes,1,rep,name=snapshots,proto3" json:"snapshots,omitempty"` +} + +func (x *ListSnapshotsResponse) Reset() { + *x = ListSnapshotsResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_odpf_stencil_v1_stencil_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListSnapshotsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListSnapshotsResponse) ProtoMessage() {} + +func (x *ListSnapshotsResponse) ProtoReflect() protoreflect.Message { + mi := &file_odpf_stencil_v1_stencil_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListSnapshotsResponse.ProtoReflect.Descriptor instead. +func (*ListSnapshotsResponse) Descriptor() ([]byte, []int) { + return file_odpf_stencil_v1_stencil_proto_rawDescGZIP(), []int{6} +} + +func (x *ListSnapshotsResponse) GetSnapshots() []*Snapshot { + if x != nil { + return x.Snapshots + } + return nil +} + +type ListSnapshotsRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Namespace string `protobuf:"bytes,1,opt,name=namespace,proto3" json:"namespace,omitempty"` + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` + Version string `protobuf:"bytes,3,opt,name=version,proto3" json:"version,omitempty"` + Latest bool `protobuf:"varint,4,opt,name=latest,proto3" json:"latest,omitempty"` +} + +func (x *ListSnapshotsRequest) Reset() { + *x = ListSnapshotsRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_odpf_stencil_v1_stencil_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListSnapshotsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListSnapshotsRequest) ProtoMessage() {} + +func (x *ListSnapshotsRequest) ProtoReflect() protoreflect.Message { + mi := &file_odpf_stencil_v1_stencil_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListSnapshotsRequest.ProtoReflect.Descriptor instead. +func (*ListSnapshotsRequest) Descriptor() ([]byte, []int) { + return file_odpf_stencil_v1_stencil_proto_rawDescGZIP(), []int{7} +} + +func (x *ListSnapshotsRequest) GetNamespace() string { + if x != nil { + return x.Namespace + } + return "" +} + +func (x *ListSnapshotsRequest) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *ListSnapshotsRequest) GetVersion() string { + if x != nil { + return x.Version + } + return "" +} + +func (x *ListSnapshotsRequest) GetLatest() bool { + if x != nil { + return x.Latest + } + return false +} + +type PromoteSnapshotRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` +} + +func (x *PromoteSnapshotRequest) Reset() { + *x = PromoteSnapshotRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_odpf_stencil_v1_stencil_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PromoteSnapshotRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PromoteSnapshotRequest) ProtoMessage() {} + +func (x *PromoteSnapshotRequest) ProtoReflect() protoreflect.Message { + mi := &file_odpf_stencil_v1_stencil_proto_msgTypes[8] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PromoteSnapshotRequest.ProtoReflect.Descriptor instead. +func (*PromoteSnapshotRequest) Descriptor() ([]byte, []int) { + return file_odpf_stencil_v1_stencil_proto_rawDescGZIP(), []int{8} +} + +func (x *PromoteSnapshotRequest) GetId() int64 { + if x != nil { + return x.Id + } + return 0 +} + +type PromoteSnapshotResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Snapshot *Snapshot `protobuf:"bytes,1,opt,name=snapshot,proto3" json:"snapshot,omitempty"` +} + +func (x *PromoteSnapshotResponse) Reset() { + *x = PromoteSnapshotResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_odpf_stencil_v1_stencil_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PromoteSnapshotResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PromoteSnapshotResponse) ProtoMessage() {} + +func (x *PromoteSnapshotResponse) ProtoReflect() protoreflect.Message { + mi := &file_odpf_stencil_v1_stencil_proto_msgTypes[9] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PromoteSnapshotResponse.ProtoReflect.Descriptor instead. +func (*PromoteSnapshotResponse) Descriptor() ([]byte, []int) { + return file_odpf_stencil_v1_stencil_proto_rawDescGZIP(), []int{9} +} + +func (x *PromoteSnapshotResponse) GetSnapshot() *Snapshot { + if x != nil { + return x.Snapshot + } + return nil +} + +var File_odpf_stencil_v1_stencil_proto protoreflect.FileDescriptor + +var file_odpf_stencil_v1_stencil_proto_rawDesc = []byte{ + 0x0a, 0x1d, 0x6f, 0x64, 0x70, 0x66, 0x2f, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x69, 0x6c, 0x2f, 0x76, + 0x31, 0x2f, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x69, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, + 0x0f, 0x6f, 0x64, 0x70, 0x66, 0x2e, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x69, 0x6c, 0x2e, 0x76, 0x31, + 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x6e, 0x6e, + 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x66, 0x69, 0x65, 0x6c, 0x64, + 0x5f, 0x62, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, + 0x20, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x2d, 0x67, 0x65, 0x6e, 0x2d, 0x6f, 0x70, + 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, + 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x22, 0x84, 0x01, 0x0a, 0x08, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x12, 0x0e, + 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, 0x69, 0x64, 0x12, 0x22, + 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x42, 0x04, 0xe2, 0x41, 0x01, 0x02, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, + 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x12, 0x16, 0x0a, 0x06, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x06, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x22, 0x97, 0x01, 0x0a, 0x19, 0x44, 0x6f, 0x77, + 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x22, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, + 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x04, 0xe2, 0x41, 0x01, 0x02, 0x52, + 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x18, 0x0a, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x04, 0xe2, 0x41, 0x01, 0x02, 0x52, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1e, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x04, 0xe2, 0x41, 0x01, 0x02, 0x52, 0x07, 0x76, 0x65, 0x72, + 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x66, 0x75, 0x6c, 0x6c, 0x6e, 0x61, 0x6d, 0x65, + 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x66, 0x75, 0x6c, 0x6c, 0x6e, 0x61, 0x6d, + 0x65, 0x73, 0x22, 0x30, 0x0a, 0x1a, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x44, 0x65, + 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, + 0x64, 0x61, 0x74, 0x61, 0x22, 0xf2, 0x01, 0x0a, 0x17, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x44, + 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x22, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x42, 0x04, 0xe2, 0x41, 0x01, 0x02, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, + 0x70, 0x61, 0x63, 0x65, 0x12, 0x18, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x42, 0x04, 0xe2, 0x41, 0x01, 0x02, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1e, + 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, + 0x04, 0xe2, 0x41, 0x01, 0x02, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x18, + 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x04, 0xe2, 0x41, + 0x01, 0x02, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x16, 0x0a, 0x06, 0x6c, 0x61, 0x74, 0x65, + 0x73, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, + 0x12, 0x16, 0x0a, 0x06, 0x64, 0x72, 0x79, 0x72, 0x75, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x06, 0x64, 0x72, 0x79, 0x72, 0x75, 0x6e, 0x12, 0x2f, 0x0a, 0x06, 0x63, 0x68, 0x65, 0x63, + 0x6b, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6f, 0x64, 0x70, 0x66, 0x2e, + 0x73, 0x74, 0x65, 0x6e, 0x63, 0x69, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, + 0x73, 0x52, 0x06, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x22, 0x37, 0x0a, 0x06, 0x43, 0x68, 0x65, + 0x63, 0x6b, 0x73, 0x12, 0x2d, 0x0a, 0x06, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x18, 0x02, 0x20, + 0x03, 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x6f, 0x64, 0x70, 0x66, 0x2e, 0x73, 0x74, 0x65, 0x6e, 0x63, + 0x69, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x06, 0x65, 0x78, 0x63, 0x65, + 0x70, 0x74, 0x22, 0x64, 0x0a, 0x18, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x44, 0x65, 0x73, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, + 0x0a, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x72, 0x79, 0x72, + 0x75, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x64, 0x72, 0x79, 0x72, 0x75, 0x6e, + 0x12, 0x16, 0x0a, 0x06, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x06, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x22, 0x50, 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, + 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x37, 0x0a, 0x09, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x73, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x6f, 0x64, 0x70, 0x66, 0x2e, 0x73, 0x74, 0x65, 0x6e, + 0x63, 0x69, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, + 0x09, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x73, 0x22, 0x7a, 0x0a, 0x14, 0x4c, 0x69, + 0x73, 0x74, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, + 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x16, + 0x0a, 0x06, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, + 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x22, 0x28, 0x0a, 0x16, 0x50, 0x72, 0x6f, 0x6d, 0x6f, 0x74, + 0x65, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, 0x69, 0x64, + 0x22, 0x50, 0x0a, 0x17, 0x50, 0x72, 0x6f, 0x6d, 0x6f, 0x74, 0x65, 0x53, 0x6e, 0x61, 0x70, 0x73, + 0x68, 0x6f, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x35, 0x0a, 0x08, 0x73, + 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, + 0x6f, 0x64, 0x70, 0x66, 0x2e, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x69, 0x6c, 0x2e, 0x76, 0x31, 0x2e, + 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x08, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, + 0x6f, 0x74, 0x2a, 0x82, 0x01, 0x0a, 0x04, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x55, + 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x1b, 0x0a, 0x17, 0x46, 0x49, 0x4c, 0x45, + 0x5f, 0x4e, 0x4f, 0x5f, 0x42, 0x52, 0x45, 0x41, 0x4b, 0x49, 0x4e, 0x47, 0x5f, 0x43, 0x48, 0x41, + 0x4e, 0x47, 0x45, 0x10, 0x01, 0x12, 0x15, 0x0a, 0x11, 0x4d, 0x45, 0x53, 0x53, 0x41, 0x47, 0x45, + 0x5f, 0x4e, 0x4f, 0x5f, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x10, 0x02, 0x12, 0x1c, 0x0a, 0x18, + 0x46, 0x49, 0x45, 0x4c, 0x44, 0x5f, 0x4e, 0x4f, 0x5f, 0x42, 0x52, 0x45, 0x41, 0x4b, 0x49, 0x4e, + 0x47, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x10, 0x03, 0x12, 0x1b, 0x0a, 0x17, 0x45, 0x4e, + 0x55, 0x4d, 0x5f, 0x4e, 0x4f, 0x5f, 0x42, 0x52, 0x45, 0x41, 0x4b, 0x49, 0x4e, 0x47, 0x5f, 0x43, + 0x48, 0x41, 0x4e, 0x47, 0x45, 0x10, 0x04, 0x32, 0xb7, 0x04, 0x0a, 0x0e, 0x53, 0x74, 0x65, 0x6e, + 0x63, 0x69, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x93, 0x01, 0x0a, 0x10, 0x55, + 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x12, + 0x28, 0x2e, 0x6f, 0x64, 0x70, 0x66, 0x2e, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x69, 0x6c, 0x2e, 0x76, + 0x31, 0x2e, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x6f, 0x64, 0x70, 0x66, + 0x2e, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x69, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x6c, 0x6f, + 0x61, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2a, 0x92, 0x41, 0x27, 0x32, 0x13, 0x6d, 0x75, 0x6c, 0x74, 0x69, + 0x70, 0x61, 0x72, 0x74, 0x2f, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x64, 0x61, 0x74, 0x61, 0x3a, 0x10, + 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6a, 0x73, 0x6f, 0x6e, + 0x12, 0x8c, 0x01, 0x0a, 0x12, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x44, 0x65, 0x73, + 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x12, 0x2a, 0x2e, 0x6f, 0x64, 0x70, 0x66, 0x2e, 0x73, + 0x74, 0x65, 0x6e, 0x63, 0x69, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, + 0x61, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x6f, 0x64, 0x70, 0x66, 0x2e, 0x73, 0x74, 0x65, 0x6e, 0x63, + 0x69, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x44, 0x65, + 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x1d, 0x92, 0x41, 0x1a, 0x3a, 0x18, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x2f, 0x6f, 0x63, 0x74, 0x65, 0x74, 0x2d, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, + 0x75, 0x0a, 0x0d, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x73, + 0x12, 0x25, 0x2e, 0x6f, 0x64, 0x70, 0x66, 0x2e, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x69, 0x6c, 0x2e, + 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x6f, 0x64, 0x70, 0x66, 0x2e, 0x73, + 0x74, 0x65, 0x6e, 0x63, 0x69, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x6e, + 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x15, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0f, 0x12, 0x0d, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x6e, 0x61, + 0x70, 0x73, 0x68, 0x6f, 0x74, 0x73, 0x12, 0x88, 0x01, 0x0a, 0x0f, 0x50, 0x72, 0x6f, 0x6d, 0x6f, + 0x74, 0x65, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x12, 0x27, 0x2e, 0x6f, 0x64, 0x70, + 0x66, 0x2e, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x69, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, + 0x6d, 0x6f, 0x74, 0x65, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x6f, 0x64, 0x70, 0x66, 0x2e, 0x73, 0x74, 0x65, 0x6e, 0x63, + 0x69, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x6d, 0x6f, 0x74, 0x65, 0x53, 0x6e, 0x61, + 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x22, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x1c, 0x32, 0x1a, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x6e, 0x61, 0x70, 0x73, + 0x68, 0x6f, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x2f, 0x70, 0x72, 0x6f, 0x6d, 0x6f, 0x74, + 0x65, 0x42, 0x3c, 0x5a, 0x2b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, + 0x6f, 0x64, 0x70, 0x66, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x6e, 0x2f, 0x73, 0x74, 0x65, 0x6e, + 0x63, 0x69, 0x6c, 0x2f, 0x76, 0x31, 0x3b, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x69, 0x6c, 0x76, 0x31, + 0x92, 0x41, 0x0c, 0x12, 0x07, 0x32, 0x05, 0x30, 0x2e, 0x31, 0x2e, 0x34, 0x2a, 0x01, 0x01, 0x62, + 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_odpf_stencil_v1_stencil_proto_rawDescOnce sync.Once + file_odpf_stencil_v1_stencil_proto_rawDescData = file_odpf_stencil_v1_stencil_proto_rawDesc +) + +func file_odpf_stencil_v1_stencil_proto_rawDescGZIP() []byte { + file_odpf_stencil_v1_stencil_proto_rawDescOnce.Do(func() { + file_odpf_stencil_v1_stencil_proto_rawDescData = protoimpl.X.CompressGZIP(file_odpf_stencil_v1_stencil_proto_rawDescData) + }) + return file_odpf_stencil_v1_stencil_proto_rawDescData +} + +var file_odpf_stencil_v1_stencil_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_odpf_stencil_v1_stencil_proto_msgTypes = make([]protoimpl.MessageInfo, 10) +var file_odpf_stencil_v1_stencil_proto_goTypes = []interface{}{ + (Rule)(0), // 0: odpf.stencil.v1.Rule + (*Snapshot)(nil), // 1: odpf.stencil.v1.Snapshot + (*DownloadDescriptorRequest)(nil), // 2: odpf.stencil.v1.DownloadDescriptorRequest + (*DownloadDescriptorResponse)(nil), // 3: odpf.stencil.v1.DownloadDescriptorResponse + (*UploadDescriptorRequest)(nil), // 4: odpf.stencil.v1.UploadDescriptorRequest + (*Checks)(nil), // 5: odpf.stencil.v1.Checks + (*UploadDescriptorResponse)(nil), // 6: odpf.stencil.v1.UploadDescriptorResponse + (*ListSnapshotsResponse)(nil), // 7: odpf.stencil.v1.ListSnapshotsResponse + (*ListSnapshotsRequest)(nil), // 8: odpf.stencil.v1.ListSnapshotsRequest + (*PromoteSnapshotRequest)(nil), // 9: odpf.stencil.v1.PromoteSnapshotRequest + (*PromoteSnapshotResponse)(nil), // 10: odpf.stencil.v1.PromoteSnapshotResponse +} +var file_odpf_stencil_v1_stencil_proto_depIdxs = []int32{ + 5, // 0: odpf.stencil.v1.UploadDescriptorRequest.checks:type_name -> odpf.stencil.v1.Checks + 0, // 1: odpf.stencil.v1.Checks.except:type_name -> odpf.stencil.v1.Rule + 1, // 2: odpf.stencil.v1.ListSnapshotsResponse.snapshots:type_name -> odpf.stencil.v1.Snapshot + 1, // 3: odpf.stencil.v1.PromoteSnapshotResponse.snapshot:type_name -> odpf.stencil.v1.Snapshot + 4, // 4: odpf.stencil.v1.StencilService.UploadDescriptor:input_type -> odpf.stencil.v1.UploadDescriptorRequest + 2, // 5: odpf.stencil.v1.StencilService.DownloadDescriptor:input_type -> odpf.stencil.v1.DownloadDescriptorRequest + 8, // 6: odpf.stencil.v1.StencilService.ListSnapshots:input_type -> odpf.stencil.v1.ListSnapshotsRequest + 9, // 7: odpf.stencil.v1.StencilService.PromoteSnapshot:input_type -> odpf.stencil.v1.PromoteSnapshotRequest + 6, // 8: odpf.stencil.v1.StencilService.UploadDescriptor:output_type -> odpf.stencil.v1.UploadDescriptorResponse + 3, // 9: odpf.stencil.v1.StencilService.DownloadDescriptor:output_type -> odpf.stencil.v1.DownloadDescriptorResponse + 7, // 10: odpf.stencil.v1.StencilService.ListSnapshots:output_type -> odpf.stencil.v1.ListSnapshotsResponse + 10, // 11: odpf.stencil.v1.StencilService.PromoteSnapshot:output_type -> odpf.stencil.v1.PromoteSnapshotResponse + 8, // [8:12] is the sub-list for method output_type + 4, // [4:8] is the sub-list for method input_type + 4, // [4:4] is the sub-list for extension type_name + 4, // [4:4] is the sub-list for extension extendee + 0, // [0:4] is the sub-list for field type_name +} + +func init() { file_odpf_stencil_v1_stencil_proto_init() } +func file_odpf_stencil_v1_stencil_proto_init() { + if File_odpf_stencil_v1_stencil_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_odpf_stencil_v1_stencil_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Snapshot); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_odpf_stencil_v1_stencil_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DownloadDescriptorRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_odpf_stencil_v1_stencil_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DownloadDescriptorResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_odpf_stencil_v1_stencil_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*UploadDescriptorRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_odpf_stencil_v1_stencil_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Checks); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_odpf_stencil_v1_stencil_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*UploadDescriptorResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_odpf_stencil_v1_stencil_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListSnapshotsResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_odpf_stencil_v1_stencil_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListSnapshotsRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_odpf_stencil_v1_stencil_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PromoteSnapshotRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_odpf_stencil_v1_stencil_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PromoteSnapshotResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_odpf_stencil_v1_stencil_proto_rawDesc, + NumEnums: 1, + NumMessages: 10, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_odpf_stencil_v1_stencil_proto_goTypes, + DependencyIndexes: file_odpf_stencil_v1_stencil_proto_depIdxs, + EnumInfos: file_odpf_stencil_v1_stencil_proto_enumTypes, + MessageInfos: file_odpf_stencil_v1_stencil_proto_msgTypes, + }.Build() + File_odpf_stencil_v1_stencil_proto = out.File + file_odpf_stencil_v1_stencil_proto_rawDesc = nil + file_odpf_stencil_v1_stencil_proto_goTypes = nil + file_odpf_stencil_v1_stencil_proto_depIdxs = nil +} diff --git a/server/odpf/stencil/v1/stencil.pb.gw.go b/server/odpf/stencil/v1/stencil.pb.gw.go new file mode 100644 index 00000000..5116dd6b --- /dev/null +++ b/server/odpf/stencil/v1/stencil.pb.gw.go @@ -0,0 +1,268 @@ +// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT. +// source: odpf/stencil/v1/stencil.proto + +/* +Package stencilv1 is a reverse proxy. + +It translates gRPC into RESTful JSON APIs. +*/ +package stencilv1 + +import ( + "context" + "io" + "net/http" + + "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" + "github.com/grpc-ecosystem/grpc-gateway/v2/utilities" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/grpclog" + "google.golang.org/grpc/metadata" + "google.golang.org/grpc/status" + "google.golang.org/protobuf/proto" +) + +// Suppress "imported and not used" errors +var _ codes.Code +var _ io.Reader +var _ status.Status +var _ = runtime.String +var _ = utilities.NewDoubleArray +var _ = metadata.Join + +var ( + filter_StencilService_ListSnapshots_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} +) + +func request_StencilService_ListSnapshots_0(ctx context.Context, marshaler runtime.Marshaler, client StencilServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq ListSnapshotsRequest + var metadata runtime.ServerMetadata + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_StencilService_ListSnapshots_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.ListSnapshots(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_StencilService_ListSnapshots_0(ctx context.Context, marshaler runtime.Marshaler, server StencilServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq ListSnapshotsRequest + var metadata runtime.ServerMetadata + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_StencilService_ListSnapshots_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.ListSnapshots(ctx, &protoReq) + return msg, metadata, err + +} + +func request_StencilService_PromoteSnapshot_0(ctx context.Context, marshaler runtime.Marshaler, client StencilServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq PromoteSnapshotRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id") + } + + protoReq.Id, err = runtime.Int64(val) + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err) + } + + msg, err := client.PromoteSnapshot(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_StencilService_PromoteSnapshot_0(ctx context.Context, marshaler runtime.Marshaler, server StencilServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq PromoteSnapshotRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id") + } + + protoReq.Id, err = runtime.Int64(val) + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err) + } + + msg, err := server.PromoteSnapshot(ctx, &protoReq) + return msg, metadata, err + +} + +// RegisterStencilServiceHandlerServer registers the http handlers for service StencilService to "mux". +// UnaryRPC :call StencilServiceServer directly. +// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. +// Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterStencilServiceHandlerFromEndpoint instead. +func RegisterStencilServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, server StencilServiceServer) error { + + mux.Handle("GET", pattern_StencilService_ListSnapshots_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/odpf.stencil.v1.StencilService/ListSnapshots", runtime.WithHTTPPathPattern("/v1/snapshots")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_StencilService_ListSnapshots_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_StencilService_ListSnapshots_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("PATCH", pattern_StencilService_PromoteSnapshot_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/odpf.stencil.v1.StencilService/PromoteSnapshot", runtime.WithHTTPPathPattern("/v1/snapshots/{id}/promote")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_StencilService_PromoteSnapshot_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_StencilService_PromoteSnapshot_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + +// RegisterStencilServiceHandlerFromEndpoint is same as RegisterStencilServiceHandler but +// automatically dials to "endpoint" and closes the connection when "ctx" gets done. +func RegisterStencilServiceHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { + conn, err := grpc.Dial(endpoint, opts...) + if err != nil { + return err + } + defer func() { + if err != nil { + if cerr := conn.Close(); cerr != nil { + grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + } + return + } + go func() { + <-ctx.Done() + if cerr := conn.Close(); cerr != nil { + grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + } + }() + }() + + return RegisterStencilServiceHandler(ctx, mux, conn) +} + +// RegisterStencilServiceHandler registers the http handlers for service StencilService to "mux". +// The handlers forward requests to the grpc endpoint over "conn". +func RegisterStencilServiceHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error { + return RegisterStencilServiceHandlerClient(ctx, mux, NewStencilServiceClient(conn)) +} + +// RegisterStencilServiceHandlerClient registers the http handlers for service StencilService +// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "StencilServiceClient". +// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "StencilServiceClient" +// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in +// "StencilServiceClient" to call the correct interceptors. +func RegisterStencilServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, client StencilServiceClient) error { + + mux.Handle("GET", pattern_StencilService_ListSnapshots_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/odpf.stencil.v1.StencilService/ListSnapshots", runtime.WithHTTPPathPattern("/v1/snapshots")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_StencilService_ListSnapshots_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_StencilService_ListSnapshots_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("PATCH", pattern_StencilService_PromoteSnapshot_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/odpf.stencil.v1.StencilService/PromoteSnapshot", runtime.WithHTTPPathPattern("/v1/snapshots/{id}/promote")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_StencilService_PromoteSnapshot_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_StencilService_PromoteSnapshot_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + +var ( + pattern_StencilService_ListSnapshots_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "snapshots"}, "")) + + pattern_StencilService_PromoteSnapshot_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2, 2, 3}, []string{"v1", "snapshots", "id", "promote"}, "")) +) + +var ( + forward_StencilService_ListSnapshots_0 = runtime.ForwardResponseMessage + + forward_StencilService_PromoteSnapshot_0 = runtime.ForwardResponseMessage +) diff --git a/server/odpf/stencil/v1/stencil_grpc.pb.go b/server/odpf/stencil/v1/stencil_grpc.pb.go new file mode 100644 index 00000000..33fe5c55 --- /dev/null +++ b/server/odpf/stencil/v1/stencil_grpc.pb.go @@ -0,0 +1,211 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. + +package stencilv1 + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 + +// StencilServiceClient is the client API for StencilService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type StencilServiceClient interface { + UploadDescriptor(ctx context.Context, in *UploadDescriptorRequest, opts ...grpc.CallOption) (*UploadDescriptorResponse, error) + DownloadDescriptor(ctx context.Context, in *DownloadDescriptorRequest, opts ...grpc.CallOption) (*DownloadDescriptorResponse, error) + ListSnapshots(ctx context.Context, in *ListSnapshotsRequest, opts ...grpc.CallOption) (*ListSnapshotsResponse, error) + // PromoteSnapshot promotes particular snapshot version as latest + PromoteSnapshot(ctx context.Context, in *PromoteSnapshotRequest, opts ...grpc.CallOption) (*PromoteSnapshotResponse, error) +} + +type stencilServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewStencilServiceClient(cc grpc.ClientConnInterface) StencilServiceClient { + return &stencilServiceClient{cc} +} + +func (c *stencilServiceClient) UploadDescriptor(ctx context.Context, in *UploadDescriptorRequest, opts ...grpc.CallOption) (*UploadDescriptorResponse, error) { + out := new(UploadDescriptorResponse) + err := c.cc.Invoke(ctx, "/odpf.stencil.v1.StencilService/UploadDescriptor", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *stencilServiceClient) DownloadDescriptor(ctx context.Context, in *DownloadDescriptorRequest, opts ...grpc.CallOption) (*DownloadDescriptorResponse, error) { + out := new(DownloadDescriptorResponse) + err := c.cc.Invoke(ctx, "/odpf.stencil.v1.StencilService/DownloadDescriptor", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *stencilServiceClient) ListSnapshots(ctx context.Context, in *ListSnapshotsRequest, opts ...grpc.CallOption) (*ListSnapshotsResponse, error) { + out := new(ListSnapshotsResponse) + err := c.cc.Invoke(ctx, "/odpf.stencil.v1.StencilService/ListSnapshots", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *stencilServiceClient) PromoteSnapshot(ctx context.Context, in *PromoteSnapshotRequest, opts ...grpc.CallOption) (*PromoteSnapshotResponse, error) { + out := new(PromoteSnapshotResponse) + err := c.cc.Invoke(ctx, "/odpf.stencil.v1.StencilService/PromoteSnapshot", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// StencilServiceServer is the server API for StencilService service. +// All implementations must embed UnimplementedStencilServiceServer +// for forward compatibility +type StencilServiceServer interface { + UploadDescriptor(context.Context, *UploadDescriptorRequest) (*UploadDescriptorResponse, error) + DownloadDescriptor(context.Context, *DownloadDescriptorRequest) (*DownloadDescriptorResponse, error) + ListSnapshots(context.Context, *ListSnapshotsRequest) (*ListSnapshotsResponse, error) + // PromoteSnapshot promotes particular snapshot version as latest + PromoteSnapshot(context.Context, *PromoteSnapshotRequest) (*PromoteSnapshotResponse, error) + mustEmbedUnimplementedStencilServiceServer() +} + +// UnimplementedStencilServiceServer must be embedded to have forward compatible implementations. +type UnimplementedStencilServiceServer struct { +} + +func (UnimplementedStencilServiceServer) UploadDescriptor(context.Context, *UploadDescriptorRequest) (*UploadDescriptorResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method UploadDescriptor not implemented") +} +func (UnimplementedStencilServiceServer) DownloadDescriptor(context.Context, *DownloadDescriptorRequest) (*DownloadDescriptorResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method DownloadDescriptor not implemented") +} +func (UnimplementedStencilServiceServer) ListSnapshots(context.Context, *ListSnapshotsRequest) (*ListSnapshotsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ListSnapshots not implemented") +} +func (UnimplementedStencilServiceServer) PromoteSnapshot(context.Context, *PromoteSnapshotRequest) (*PromoteSnapshotResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method PromoteSnapshot not implemented") +} +func (UnimplementedStencilServiceServer) mustEmbedUnimplementedStencilServiceServer() {} + +// UnsafeStencilServiceServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to StencilServiceServer will +// result in compilation errors. +type UnsafeStencilServiceServer interface { + mustEmbedUnimplementedStencilServiceServer() +} + +func RegisterStencilServiceServer(s grpc.ServiceRegistrar, srv StencilServiceServer) { + s.RegisterService(&StencilService_ServiceDesc, srv) +} + +func _StencilService_UploadDescriptor_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(UploadDescriptorRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(StencilServiceServer).UploadDescriptor(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/odpf.stencil.v1.StencilService/UploadDescriptor", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(StencilServiceServer).UploadDescriptor(ctx, req.(*UploadDescriptorRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _StencilService_DownloadDescriptor_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DownloadDescriptorRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(StencilServiceServer).DownloadDescriptor(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/odpf.stencil.v1.StencilService/DownloadDescriptor", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(StencilServiceServer).DownloadDescriptor(ctx, req.(*DownloadDescriptorRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _StencilService_ListSnapshots_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ListSnapshotsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(StencilServiceServer).ListSnapshots(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/odpf.stencil.v1.StencilService/ListSnapshots", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(StencilServiceServer).ListSnapshots(ctx, req.(*ListSnapshotsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _StencilService_PromoteSnapshot_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(PromoteSnapshotRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(StencilServiceServer).PromoteSnapshot(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/odpf.stencil.v1.StencilService/PromoteSnapshot", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(StencilServiceServer).PromoteSnapshot(ctx, req.(*PromoteSnapshotRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// StencilService_ServiceDesc is the grpc.ServiceDesc for StencilService service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var StencilService_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "odpf.stencil.v1.StencilService", + HandlerType: (*StencilServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "UploadDescriptor", + Handler: _StencilService_UploadDescriptor_Handler, + }, + { + MethodName: "DownloadDescriptor", + Handler: _StencilService_DownloadDescriptor_Handler, + }, + { + MethodName: "ListSnapshots", + Handler: _StencilService_ListSnapshots_Handler, + }, + { + MethodName: "PromoteSnapshot", + Handler: _StencilService_PromoteSnapshot_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "odpf/stencil/v1/stencil.proto", +} diff --git a/server/proto/service.go b/server/proto/service.go index 9138d1c8..358cab4a 100644 --- a/server/proto/service.go +++ b/server/proto/service.go @@ -15,11 +15,11 @@ type Service struct { // Validate checks if current data is backward compatible against previous stable data func (s *Service) Validate(ctx context.Context, cs *snapshot.Snapshot, data []byte, rulesToSkip []string) error { var err error - prevSt, err := s.snapshotRepo.GetSnapshot(ctx, cs.Namespace, cs.Name, "", true) + prevSt, err := s.snapshotRepo.GetSnapshotByFields(ctx, cs.Namespace, cs.Name, "", true) if err == snapshot.ErrNotFound { return nil } - // no need to handle error here. Since without snapshot data won't exist. + // no need to handle error here. Since without snapshot, data won't exist. // If snapshot exist and data is nil, then validation still passes as it's treated as completely new prevData, _ := s.Get(ctx, prevSt, []string{}) return Compare(data, prevData, rulesToSkip) diff --git a/server/server/graceful.go b/server/server/graceful.go index 4cc9fb00..b7220c23 100644 --- a/server/server/graceful.go +++ b/server/server/graceful.go @@ -10,11 +10,10 @@ import ( "os/signal" "syscall" - "github.com/gin-gonic/gin" "github.com/odpf/stencil/server/config" ) -func runWithGracefulShutdown(config *config.Config, router *gin.Engine, cleanUp func()) { +func runWithGracefulShutdown(config *config.Config, router http.Handler, cleanUp func()) { srv := &http.Server{ Addr: fmt.Sprintf(":%s", config.Port), Handler: router, diff --git a/server/server/middleware.go b/server/server/middleware.go index 2f6514fd..5fd8d2e7 100644 --- a/server/server/middleware.go +++ b/server/server/middleware.go @@ -5,8 +5,11 @@ import ( "time" "github.com/gin-gonic/gin" + "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" + "github.com/newrelic/go-agent/v3/integrations/nrgin" "github.com/odpf/stencil/server/config" "github.com/odpf/stencil/server/models" + "google.golang.org/grpc/status" ) func errorHandle() gin.HandlerFunc { @@ -16,6 +19,15 @@ func errorHandle() gin.HandlerFunc { if ginErr == nil { return } + if err, ok := status.FromError(ginErr.Err); ok { + code := runtime.HTTPStatusFromCode(err.Code()) + msg := err.Message() + if code >= 500 { + msg = "Internal error" + } + c.AbortWithStatusJSON(code, gin.H{"message": msg}) + return + } if err, ok := ginErr.Err.(models.APIError); ok { c.AbortWithStatusJSON(err.Code(), gin.H{"message": err.Message()}) return @@ -37,7 +49,7 @@ func getLogger() gin.HandlerFunc { } func addMiddleware(router *gin.Engine, config *config.Config) { - router.Use(getNewRelicMiddleware(config)) + router.Use(nrgin.Middleware(getNewRelic(config))) router.Use(gin.Recovery()) router.Use(getLogger()) router.Use(errorHandle()) diff --git a/server/server/newrelic.go b/server/server/newrelic.go index 9244d5dc..12fcc97b 100644 --- a/server/server/newrelic.go +++ b/server/server/newrelic.go @@ -3,13 +3,11 @@ package server import ( "log" - "github.com/gin-gonic/gin" - "github.com/newrelic/go-agent/v3/integrations/nrgin" "github.com/newrelic/go-agent/v3/newrelic" "github.com/odpf/stencil/server/config" ) -func getNewRelicMiddleware(config *config.Config) gin.HandlerFunc { +func getNewRelic(config *config.Config) *newrelic.Application { newRelicConfig := config.NewRelic app, err := newrelic.NewApplication( newrelic.ConfigAppName(newRelicConfig.AppName), @@ -19,5 +17,5 @@ func getNewRelicMiddleware(config *config.Config) gin.HandlerFunc { if err != nil { log.Fatal(err) } - return nrgin.Middleware(app) + return app } diff --git a/server/server/routes.go b/server/server/routes.go index de02d6d4..34002b1c 100644 --- a/server/server/routes.go +++ b/server/server/routes.go @@ -1,18 +1,25 @@ package server import ( + "net/http" + "github.com/gin-gonic/gin" + "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" "github.com/odpf/stencil/server/api" ) -func registerRoutes(router *gin.Engine, handlers *api.API) { +func proxyToGin(e *gin.Engine) func(http.ResponseWriter, *http.Request, map[string]string) { + return func(rw http.ResponseWriter, r *http.Request, m map[string]string) { + e.ServeHTTP(rw, r) + } +} + +func registerRoutes(router *gin.Engine, mux *runtime.ServeMux, handlers *api.API) { apiV1 := router.Group("/v1/namespaces/:namespace") - router.NoRoute(api.NoRoute) router.GET("/ping", api.Ping) - apiV1.POST("/descriptors", handlers.Upload) - apiV1.GET("/descriptors", handlers.ListNames) - apiV1.GET("/descriptors/:name/versions", handlers.ListVersions) - apiV1.GET("/descriptors/:name/versions/:version", handlers.Download) - apiV1.GET("/metadata/:name", handlers.GetLatestVersion) - apiV1.POST("/metadata", handlers.UpdateLatestVersion) + apiV1.POST("/descriptors", handlers.HTTPUpload) + apiV1.GET("/descriptors/:name/versions/:version", handlers.HTTPDownload) + mux.HandlePath("GET", "/ping", proxyToGin(router)) + mux.HandlePath("GET", "/v1/namespaces/{namespace}/descriptors/{name}/versions/{version}", proxyToGin(router)) + mux.HandlePath("POST", "/v1/namespaces/{namespace}/descriptors", proxyToGin(router)) } diff --git a/server/server/server.go b/server/server/server.go index 924e63d6..e3d492ed 100644 --- a/server/server/server.go +++ b/server/server/server.go @@ -1,38 +1,100 @@ package server import ( + "context" + "fmt" + "log" + "net/http" + "strings" + "github.com/gin-gonic/gin" + "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" + "github.com/newrelic/go-agent/v3/integrations/nrgrpc" + + grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware" + grpc_zap "github.com/grpc-ecosystem/go-grpc-middleware/logging/zap" + grpc_recovery "github.com/grpc-ecosystem/go-grpc-middleware/recovery" + grpc_ctxtags "github.com/grpc-ecosystem/go-grpc-middleware/tags" "github.com/odpf/stencil/server/api" "github.com/odpf/stencil/server/config" + "github.com/odpf/stencil/server/logger" + stencilv1 "github.com/odpf/stencil/server/odpf/stencil/v1" "github.com/odpf/stencil/server/proto" "github.com/odpf/stencil/server/snapshot" "github.com/odpf/stencil/server/store" + "golang.org/x/net/http2" + "golang.org/x/net/http2/h2c" + "google.golang.org/grpc" + "google.golang.org/grpc/health/grpc_health_v1" ) // Router returns server router -func Router(api *api.API, config *config.Config) *gin.Engine { +func Router(api *api.API, config *config.Config) *runtime.ServeMux { + gwmux := runtime.NewServeMux() router := gin.New() addMiddleware(router, config) registerCustomValidations(router) - registerRoutes(router, api) - return router + registerRoutes(router, gwmux, api) + return gwmux } // Start Entry point to start the server func Start() { + ctx := context.Background() config := config.LoadConfig() db := store.NewDBStore(config) stRepo := snapshot.NewSnapshotRepository(db) - stSvc := snapshot.NewSnapshotService(stRepo) protoRepo := proto.NewProtoRepository(db) protoService := proto.NewService(protoRepo, stRepo) api := &api.API{ Store: protoService, - Metadata: stSvc, + Metadata: stRepo, + } + port := fmt.Sprintf(":%s", config.Port) + nr := getNewRelic(config) + mux := Router(api, config) + + // init grpc server + opts := []grpc.ServerOption{ + grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer( + grpc_recovery.UnaryServerInterceptor(), + grpc_ctxtags.UnaryServerInterceptor(), + nrgrpc.UnaryServerInterceptor(nr), + grpc_zap.UnaryServerInterceptor(logger.Logger))), + grpc.MaxRecvMsgSize(config.GRPC.MaxRecvMsgSizeInMB << 20), + grpc.MaxSendMsgSize(config.GRPC.MaxSendMsgSizeInMB << 20), } - router := Router(api, config) + // Create a gRPC server object + s := grpc.NewServer(opts...) + stencilv1.RegisterStencilServiceServer(s, api) + grpc_health_v1.RegisterHealthServer(s, api) + conn, err := grpc.DialContext( + context.Background(), + port, + grpc.WithInsecure(), + ) + if err != nil { + log.Fatalln("Failed to dial server:", err) + } + + stencilv1.RegisterStencilServiceHandler(ctx, mux, conn) - runWithGracefulShutdown(config, router, func() { - db.Pool.Close() + runWithGracefulShutdown(config, grpcHandlerFunc(s, mux), func() { + conn.Close() + s.GracefulStop() + db.Close() }) } + +// grpcHandlerFunc returns an http.Handler that delegates to grpcServer on incoming gRPC +// connections or otherHandler otherwise. +func grpcHandlerFunc(grpcServer *grpc.Server, otherHandler http.Handler) http.Handler { + return h2c.NewHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + // This is a partial recreation of gRPC's internal checks https://github.com/grpc/grpc-go/pull/514/files#diff-95e9a25b738459a2d3030e1e6fa2a718R61 + if r.ProtoMajor == 2 && strings.Contains(r.Header.Get("Content-Type"), "application/grpc") { + grpcServer.ServeHTTP(w, r) + } else { + otherHandler.ServeHTTP(w, r) + } + }), &http2.Server{}) +} diff --git a/server/server/validation.go b/server/server/validation.go index 5cb2612b..f3cc13ee 100644 --- a/server/server/validation.go +++ b/server/server/validation.go @@ -19,21 +19,8 @@ func ValidateVersion(fl validator.FieldLevel) bool { return false } -//ValidateVersionWithLatest validates if value is equal to latest or valid semantic version -func ValidateVersionWithLatest(fl validator.FieldLevel) bool { - version, ok := fl.Field().Interface().(string) - if ok { - if _, err := semver.Parse(version); err == nil { - return true - } - return version == "latest" - } - return false -} - func registerCustomValidations(e *gin.Engine) { if v, ok := binding.Validator.Engine().(*validator.Validate); ok { v.RegisterValidation("version", ValidateVersion) - v.RegisterValidation("versionWithLatest", ValidateVersionWithLatest) } } diff --git a/server/snapshot/model.go b/server/snapshot/model.go index c2008f5e..1b775a2a 100644 --- a/server/snapshot/model.go +++ b/server/snapshot/model.go @@ -1,6 +1,8 @@ package snapshot -import "errors" +import ( + "errors" +) var ( //ErrNotFound used when snapshot is not found @@ -9,9 +11,9 @@ var ( // Snapshot represents specific version of protodescriptorset type Snapshot struct { - ID int64 - Namespace string - Name string - Version string - Latest bool + ID int64 `binding:"required"` + Namespace string `binding:"required"` + Name string `binding:"required"` + Version string `binding:"required,version"` + Latest bool `binding:"required"` } diff --git a/server/snapshot/repository.go b/server/snapshot/repository.go index f9a1696f..24e9412b 100644 --- a/server/snapshot/repository.go +++ b/server/snapshot/repository.go @@ -2,6 +2,7 @@ package snapshot import ( "context" + "fmt" "strings" "github.com/georgysavva/scany/pgxscan" @@ -34,29 +35,39 @@ type Repository struct { db *store.DB } -// ListNames returns names -func (r *Repository) ListNames(ctx context.Context, namespace string) ([]string, error) { - var names []string - err := pgxscan.Select(ctx, r.db, &names, `SELECT DISTINCT(name) from snapshots where namespace=$1`, namespace) - return names, err -} - -// ListVersions returns versions -func (r *Repository) ListVersions(ctx context.Context, namespace string, name string) ([]string, error) { - var names []string - err := pgxscan.Select(ctx, r.db, &names, `SELECT version from snapshots where namespace=$1 and name=$2`, namespace, name) - return names, err -} - -// Exists checks if mentioned version is present or not -func (r *Repository) Exists(ctx context.Context, snapshot *Snapshot) bool { - var count int64 - err := r.db.QueryRow(ctx, `SELECT count(id) from snapshots where namespace=$1 and name=$2 and version=$3`, - snapshot.Namespace, snapshot.Name, snapshot.Version).Scan(&count) - if err != nil { - return false +// List returns list of snapshots +func (r *Repository) List(ctx context.Context, queryFields *Snapshot) ([]*Snapshot, error) { + var snapshots []*Snapshot + var query strings.Builder + var args []interface{} + var conditions []string + query.WriteString(`SELECT * from snapshots`) + if queryFields.Latest { + conditions = append(conditions, "latest=true") + } + if queryFields.Namespace != "" { + conditions = append(conditions, fmt.Sprintf("namespace=$%d", len(args)+1)) + args = append(args, queryFields.Namespace) + } + if queryFields.Name != "" { + conditions = append(conditions, fmt.Sprintf("name=$%d", len(args)+1)) + args = append(args, queryFields.Name) + } + if queryFields.Version != "" { + conditions = append(conditions, fmt.Sprintf("version=$%d", len(args)+1)) + args = append(args, queryFields.Version) + } + if queryFields.ID != 0 { + conditions = append(conditions, fmt.Sprintf("id=$%d", len(args)+1)) + args = append(args, queryFields.ID) + } + if len(conditions) > 0 { + condition := strings.Join(conditions, " AND ") + query.WriteString(fmt.Sprintf(` WHERE %s`, condition)) } - return count != 0 + + err := pgxscan.Select(ctx, r.db, &snapshots, query.String(), args...) + return snapshots, err } // UpdateLatestVersion returns latest version number @@ -72,25 +83,26 @@ func (r *Repository) UpdateLatestVersion(ctx context.Context, snapshot *Snapshot return err } _, err = t.Exec(ctx, `UPDATE snapshots set latest=true where id=$1`, snapshot.ID) - return err + if err != nil { + return err + } + snapshot.Latest = true + return nil }) } -// GetSnapshot returns full snapshot data -func (r *Repository) GetSnapshot(ctx context.Context, namespace, name, version string, latest bool) (*Snapshot, error) { +// GetSnapshotByFields returns full snapshot data +func (r *Repository) GetSnapshotByFields(ctx context.Context, namespace, name, version string, latest bool) (*Snapshot, error) { snapshot := &Snapshot{ Namespace: namespace, Name: name, } var query strings.Builder var args []interface{} - query.WriteString(`SELECT id, version, latest from snapshots where namespace=$1 and name=$2`) - args = append(args, namespace, name) - if latest { - query.WriteString(` and latest=true`) - } + query.WriteString(`SELECT id, version, latest from snapshots where namespace=$1 and name=$2 and latest=$3`) + args = append(args, namespace, name, latest) if version != "" { - query.WriteString(` and version=$3`) + query.WriteString(` and version=$4`) args = append(args, version) } err := r.db.QueryRow(ctx, query.String(), args...).Scan(&snapshot.ID, &snapshot.Version, &snapshot.Latest) @@ -100,6 +112,22 @@ func (r *Repository) GetSnapshot(ctx context.Context, namespace, name, version s return snapshot, err } +// GetSnapshotByID get snapshot by ID +func (r *Repository) GetSnapshotByID(ctx context.Context, id int64) (*Snapshot, error) { + var s Snapshot + err := r.db.QueryRow(ctx, `SELECT * FROM snapshots where id=$1`, id).Scan(&s.ID, &s.Namespace, &s.Name, &s.Version, &s.Latest) + if err == pgx.ErrNoRows { + return &s, ErrNotFound + } + return &s, err +} + +// Exists checks if snapshot exits in DB or not +func (r *Repository) Exists(ctx context.Context, st *Snapshot) bool { + l, err := r.List(ctx, st) + return err == nil && len(l) > 0 +} + // Create inserts snapshot data func (r *Repository) Create(ctx context.Context, snapshot *Snapshot) error { return r.db.QueryRow(ctx, snapshotInsertQuery, snapshot.Namespace, snapshot.Name, snapshot.Version).Scan(&snapshot.ID) diff --git a/server/snapshot/service.go b/server/snapshot/service.go deleted file mode 100644 index ffb2e521..00000000 --- a/server/snapshot/service.go +++ /dev/null @@ -1,44 +0,0 @@ -package snapshot - -import ( - "context" -) - -// Service handles snapshot CRUD operations -type Service struct { - repo *Repository -} - -// ListNames returns list of available proto descriptorset names under specified namespace -func (s *Service) ListNames(ctx context.Context, namespace string) ([]string, error) { - return s.repo.ListNames(ctx, namespace) -} - -// ListVersions returns list of available versions -func (s *Service) ListVersions(ctx context.Context, namespace, name string) ([]string, error) { - return s.repo.ListVersions(ctx, namespace, name) -} - -// GetSnapshot returns latest version number -func (s *Service) GetSnapshot(ctx context.Context, namespace, name, version string, latest bool) (*Snapshot, error) { - return s.repo.GetSnapshot(ctx, namespace, name, version, latest) -} - -// UpdateLatestVersion updates latest version number for snapshot -func (s *Service) UpdateLatestVersion(ctx context.Context, st *Snapshot) error { - snapshotWithID, err := s.repo.GetSnapshot(ctx, st.Namespace, st.Name, st.Version, st.Latest) - if err != nil { - return err - } - return s.repo.UpdateLatestVersion(ctx, snapshotWithID) -} - -// Exists check if snapshot exists or not -func (s *Service) Exists(ctx context.Context, snapshot *Snapshot) bool { - return s.repo.Exists(ctx, snapshot) -} - -// NewSnapshotService creates new instance of proto service -func NewSnapshotService(r *Repository) *Service { - return &Service{r} -} diff --git a/server/store/db.go b/server/store/db.go index c9b709d1..2b49c91f 100644 --- a/server/store/db.go +++ b/server/store/db.go @@ -4,11 +4,10 @@ import ( "context" "log" - "github.com/jackc/pgx/v4" "github.com/jackc/pgx/v4/log/zapadapter" "github.com/jackc/pgx/v4/pgxpool" "github.com/odpf/stencil/server/config" - "go.uber.org/zap" + "github.com/odpf/stencil/server/logger" ) // DB db instance @@ -19,12 +18,7 @@ type DB struct { // NewDBStore create DB store func NewDBStore(dbConfig *config.Config) *DB { cc, _ := pgxpool.ParseConfig(dbConfig.DB.ConnectionString) - logger, err := zap.NewProduction() - if err != nil { - log.Fatal(err) - } - cc.ConnConfig.Logger = zapadapter.NewLogger(logger) - cc.ConnConfig.LogLevel = pgx.LogLevelInfo + cc.ConnConfig.Logger = zapadapter.NewLogger(logger.Logger) pgxPool, err := pgxpool.ConnectConfig(context.Background(), cc) if err != nil { diff --git a/server/swagger.yml b/server/swagger.yml index c817b6dd..2eb01804 100644 --- a/server/swagger.yml +++ b/server/swagger.yml @@ -1,6 +1,6 @@ info: title: Stencil server - version: 0.1.0 + version: 0.1.4 produces: - application/json consumes: @@ -9,6 +9,8 @@ paths: /ping: get: summary: service health check + tags: + - health operationId: ping responses: "200": @@ -21,7 +23,7 @@ paths: produces: - "application/json" tags: - - descriptors + - StencilService parameters: - name: "namespace" in: "path" @@ -65,51 +67,18 @@ paths: type: "file" responses: "200": - description: "Success response" + description: "Success response if operation succeded" + "400": + description: "Validation error response when user payload has missing required fields or currently being uploaded file is not backward compatible with previously uploaded file" "409": - description: "Conflict" - get: - summary: list all available descriptor names under one namespace - tags: - - descriptors - parameters: - - name: "namespace" - in: "path" - required: true - type: "string" - responses: - "200": - description: "returns list of descriptor names" - schema: - type: "array" - items: - type: string - /v1/namespaces/{namespace}/descriptors/{name}/versions: - get: - summary: list all available versions for specified descriptor - tags: - - descriptors - parameters: - - name: "namespace" - in: "path" - required: true - type: "string" - - name: "name" - in: "path" - required: true - type: "string" - responses: - "200": - description: "returns list of versions" - schema: - type: "array" - items: - type: string + description: "conflict error reponse if namespace, name and version combination already present" + "500": + description: "Unexpected internal error reponse" /v1/namespaces/{namespace}/descriptors/{name}/versions/{version}: get: summary: download specified descriptor file tags: - - descriptors + - StencilService produces: - application/octet-stream parameters: @@ -135,63 +104,109 @@ paths: responses: "200": description: "download response" - /v1/namespaces/{namespace}/metadata: - post: - summary: update metadata - tags: - - metadata - parameters: - - name: "namespace" - in: "path" - required: true - type: "string" - - name: "body" - in: "body" - description: "specify name and version in payload" - required: true - schema: - $ref: "#/definitions/MetadataPayload" - responses: - "200": - description: "Success response" - /v1/namespaces/{namespace}/metadata/{name}: + /v1/snapshots: get: - summary: get latest version for specified descriptor - tags: - - metadata + operationId: StencilService_ListSnapshots + responses: + '200': + description: A successful response. + schema: + $ref: '#/definitions/v1ListSnapshotsResponse' + default: + description: An unexpected error response. + schema: + $ref: '#/definitions/rpcStatus' parameters: - - name: "namespace" - in: "path" - required: true - type: "string" - - name: "name" - in: "path" - required: true - type: "string" + - name: namespace + in: query + required: false + type: string + - name: name + in: query + required: false + type: string + - name: version + in: query + required: false + type: string + - name: latest + in: query + required: false + type: boolean + tags: + - StencilService + /v1/snapshots/{id}/promote: + patch: + summary: PromoteSnapshot promotes particular snapshot version as latest + operationId: StencilService_PromoteSnapshot responses: - "200": - description: "Success response" + '200': + description: A successful response. schema: - $ref: "#/definitions/MetadataResponse" - -tags: - - name: "descriptors" - description: "Manage descriptors" - - name: "metadata" - description: "manage latest versions for uploaded descriptor files" + $ref: '#/definitions/v1PromoteSnapshotResponse' + default: + description: An unexpected error response. + schema: + $ref: '#/definitions/rpcStatus' + parameters: + - name: id + in: path + required: true + type: string + format: int64 + tags: + - StencilService definitions: - MetadataResponse: + protobufAny: + type: object properties: - version: + typeUrl: + type: string + value: type: string + format: byte + rpcStatus: type: object - MetadataPayload: properties: + code: + type: integer + format: int32 + message: + type: string + details: + type: array + items: + $ref: '#/definitions/protobufAny' + v1ListSnapshotsResponse: + type: object + properties: + snapshots: + type: array + items: + $ref: '#/definitions/v1Snapshot' + v1PromoteSnapshotResponse: + type: object + properties: + snapshot: + $ref: '#/definitions/v1Snapshot' + v1Snapshot: + type: object + properties: + id: + type: string + format: int64 + namespace: + type: string + required: + - namespace name: type: string version: type: string - type: object + latest: + type: boolean + required: + - namespace schemes: - http swagger: "2.0"