commit
5797324cfc
|
@ -219,12 +219,12 @@ func (c *Client) CreateDashboard(ctx context.Context, d *platform.Dashboard) err
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *Client) createViewIfNotExists(ctx context.Context, tx *bolt.Tx, cell *platform.Cell, opts platform.AddDashboardCellOptions) error {
|
||||
func (c *Client) createViewIfNotExists(ctx context.Context, tx *bolt.Tx, cell *platform.Cell, opts platform.AddDashboardCellOptions) *platform.Error {
|
||||
if opts.UsingView.Valid() {
|
||||
// Creates a hard copy of a view
|
||||
v, err := c.findViewByID(ctx, tx, opts.UsingView)
|
||||
if err != nil {
|
||||
return err
|
||||
v, pe := c.findViewByID(ctx, tx, opts.UsingView)
|
||||
if pe != nil {
|
||||
return pe
|
||||
}
|
||||
view, err := c.copyView(ctx, tx, v.ID)
|
||||
if err != nil {
|
||||
|
|
144
bolt/view.go
144
bolt/view.go
|
@ -27,43 +27,49 @@ func (c *Client) FindViewByID(ctx context.Context, id platform.ID) (*platform.Vi
|
|||
err := c.db.View(func(tx *bolt.Tx) error {
|
||||
dash, err := c.findViewByID(ctx, tx, id)
|
||||
if err != nil {
|
||||
return err
|
||||
return &platform.Error{
|
||||
Err: err,
|
||||
Op: getOp(platform.OpFindViewByID),
|
||||
}
|
||||
}
|
||||
d = dash
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return d, nil
|
||||
return d, err
|
||||
}
|
||||
|
||||
func (c *Client) findViewByID(ctx context.Context, tx *bolt.Tx, id platform.ID) (*platform.View, error) {
|
||||
func (c *Client) findViewByID(ctx context.Context, tx *bolt.Tx, id platform.ID) (*platform.View, *platform.Error) {
|
||||
var d platform.View
|
||||
|
||||
encodedID, err := id.Encode()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, &platform.Error{
|
||||
Err: err,
|
||||
}
|
||||
}
|
||||
|
||||
v := tx.Bucket(viewBucket).Get(encodedID)
|
||||
if len(v) == 0 {
|
||||
return nil, platform.ErrViewNotFound
|
||||
return nil, &platform.Error{
|
||||
Code: platform.ENotFound,
|
||||
Msg: platform.ErrViewNotFound,
|
||||
}
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(v, &d); err != nil {
|
||||
return nil, err
|
||||
return nil, &platform.Error{
|
||||
Err: err,
|
||||
}
|
||||
}
|
||||
|
||||
return &d, nil
|
||||
}
|
||||
|
||||
func (c *Client) copyView(ctx context.Context, tx *bolt.Tx, id platform.ID) (*platform.View, error) {
|
||||
v, err := c.findViewByID(ctx, tx, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
func (c *Client) copyView(ctx context.Context, tx *bolt.Tx, id platform.ID) (*platform.View, *platform.Error) {
|
||||
v, pe := c.findViewByID(ctx, tx, id)
|
||||
if pe != nil {
|
||||
return nil, pe
|
||||
}
|
||||
|
||||
view := &platform.View{
|
||||
|
@ -73,8 +79,8 @@ func (c *Client) copyView(ctx context.Context, tx *bolt.Tx, id platform.ID) (*pl
|
|||
Properties: v.Properties,
|
||||
}
|
||||
|
||||
if err := c.createView(ctx, tx, view); err != nil {
|
||||
return nil, err
|
||||
if pe := c.createView(ctx, tx, view); pe != nil {
|
||||
return nil, pe
|
||||
}
|
||||
|
||||
return view, nil
|
||||
|
@ -99,11 +105,16 @@ func (c *Client) FindView(ctx context.Context, filter platform.ViewFilter) (*pla
|
|||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, &platform.Error{
|
||||
Err: err,
|
||||
}
|
||||
}
|
||||
|
||||
if d == nil {
|
||||
return nil, platform.ErrViewNotFound
|
||||
return nil, &platform.Error{
|
||||
Code: platform.ENotFound,
|
||||
Msg: platform.ErrViewNotFound,
|
||||
}
|
||||
}
|
||||
|
||||
return d, nil
|
||||
|
@ -132,30 +143,36 @@ func filterViewsFn(filter platform.ViewFilter) func(v *platform.View) bool {
|
|||
|
||||
// FindViews retrives all views that match an arbitrary view filter.
|
||||
func (c *Client) FindViews(ctx context.Context, filter platform.ViewFilter) ([]*platform.View, int, error) {
|
||||
ds := []*platform.View{}
|
||||
op := getOp(platform.OpFindViews)
|
||||
if filter.ID != nil {
|
||||
d, err := c.FindViewByID(ctx, *filter.ID)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
if err != nil && platform.ErrorCode(err) != platform.ENotFound {
|
||||
return nil, 0, &platform.Error{
|
||||
Err: err,
|
||||
Op: op,
|
||||
}
|
||||
}
|
||||
if d != nil {
|
||||
ds = append(ds, d)
|
||||
}
|
||||
|
||||
return []*platform.View{d}, 1, nil
|
||||
return ds, 1, nil
|
||||
}
|
||||
|
||||
ds := []*platform.View{}
|
||||
err := c.db.View(func(tx *bolt.Tx) error {
|
||||
dashs, err := c.findViews(ctx, tx, filter)
|
||||
if err != nil {
|
||||
return err
|
||||
return &platform.Error{
|
||||
Err: err,
|
||||
Op: op,
|
||||
}
|
||||
}
|
||||
ds = dashs
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
return ds, len(ds), nil
|
||||
return ds, len(ds), err
|
||||
}
|
||||
|
||||
func (c *Client) findViews(ctx context.Context, tx *bolt.Tx, filter platform.ViewFilter) ([]*platform.View, error) {
|
||||
|
@ -179,11 +196,17 @@ func (c *Client) findViews(ctx context.Context, tx *bolt.Tx, filter platform.Vie
|
|||
// CreateView creates a platform view and sets d.ID.
|
||||
func (c *Client) CreateView(ctx context.Context, d *platform.View) error {
|
||||
return c.db.Update(func(tx *bolt.Tx) error {
|
||||
return c.createView(ctx, tx, d)
|
||||
if pe := c.createView(ctx, tx, d); pe != nil {
|
||||
return &platform.Error{
|
||||
Op: getOp(platform.OpCreateView),
|
||||
Err: pe,
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (c *Client) createView(ctx context.Context, tx *bolt.Tx, d *platform.View) error {
|
||||
func (c *Client) createView(ctx context.Context, tx *bolt.Tx, d *platform.View) *platform.Error {
|
||||
d.ID = c.IDGenerator.ID()
|
||||
return c.putView(ctx, tx, d)
|
||||
}
|
||||
|
@ -191,21 +214,30 @@ func (c *Client) createView(ctx context.Context, tx *bolt.Tx, d *platform.View)
|
|||
// PutView will put a view without setting an ID.
|
||||
func (c *Client) PutView(ctx context.Context, d *platform.View) error {
|
||||
return c.db.Update(func(tx *bolt.Tx) error {
|
||||
return c.putView(ctx, tx, d)
|
||||
if pe := c.putView(ctx, tx, d); pe != nil {
|
||||
return pe
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (c *Client) putView(ctx context.Context, tx *bolt.Tx, d *platform.View) error {
|
||||
func (c *Client) putView(ctx context.Context, tx *bolt.Tx, d *platform.View) *platform.Error {
|
||||
v, err := json.Marshal(d)
|
||||
if err != nil {
|
||||
return err
|
||||
return &platform.Error{
|
||||
Err: err,
|
||||
}
|
||||
}
|
||||
encodedID, err := d.ID.Encode()
|
||||
if err != nil {
|
||||
return err
|
||||
return &platform.Error{
|
||||
Err: err,
|
||||
}
|
||||
}
|
||||
if err := tx.Bucket(viewBucket).Put(encodedID, v); err != nil {
|
||||
return err
|
||||
return &platform.Error{
|
||||
Err: err,
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -230,9 +262,12 @@ func (c *Client) forEachView(ctx context.Context, tx *bolt.Tx, fn func(*platform
|
|||
func (c *Client) UpdateView(ctx context.Context, id platform.ID, upd platform.ViewUpdate) (*platform.View, error) {
|
||||
var d *platform.View
|
||||
err := c.db.Update(func(tx *bolt.Tx) error {
|
||||
dash, err := c.updateView(ctx, tx, id, upd)
|
||||
if err != nil {
|
||||
return err
|
||||
dash, pe := c.updateView(ctx, tx, id, upd)
|
||||
if pe != nil {
|
||||
return &platform.Error{
|
||||
Err: pe,
|
||||
Op: getOp(platform.OpUpdateView),
|
||||
}
|
||||
}
|
||||
d = dash
|
||||
return nil
|
||||
|
@ -265,24 +300,39 @@ func (c *Client) updateView(ctx context.Context, tx *bolt.Tx, id platform.ID, up
|
|||
// DeleteView deletes a view and prunes it from the index.
|
||||
func (c *Client) DeleteView(ctx context.Context, id platform.ID) error {
|
||||
return c.db.Update(func(tx *bolt.Tx) error {
|
||||
return c.deleteView(ctx, tx, id)
|
||||
if pe := c.deleteView(ctx, tx, id); pe != nil {
|
||||
return &platform.Error{
|
||||
Err: pe,
|
||||
Op: getOp(platform.OpDeleteView),
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (c *Client) deleteView(ctx context.Context, tx *bolt.Tx, id platform.ID) error {
|
||||
_, err := c.findViewByID(ctx, tx, id)
|
||||
if err != nil {
|
||||
return err
|
||||
func (c *Client) deleteView(ctx context.Context, tx *bolt.Tx, id platform.ID) *platform.Error {
|
||||
_, pe := c.findViewByID(ctx, tx, id)
|
||||
if pe != nil {
|
||||
return pe
|
||||
}
|
||||
encodedID, err := id.Encode()
|
||||
if err != nil {
|
||||
return err
|
||||
return &platform.Error{
|
||||
Err: err,
|
||||
}
|
||||
}
|
||||
if err := tx.Bucket(viewBucket).Delete(encodedID); err != nil {
|
||||
return err
|
||||
return &platform.Error{
|
||||
Err: err,
|
||||
}
|
||||
}
|
||||
return c.deleteUserResourceMappings(ctx, tx, platform.UserResourceMappingFilter{
|
||||
if err := c.deleteUserResourceMappings(ctx, tx, platform.UserResourceMappingFilter{
|
||||
ResourceID: id,
|
||||
ResourceType: platform.ViewResourceType,
|
||||
})
|
||||
}); err != nil {
|
||||
return &platform.Error{
|
||||
Err: err,
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -5,10 +5,11 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/influxdata/platform"
|
||||
"github.com/influxdata/platform/bolt"
|
||||
platformtesting "github.com/influxdata/platform/testing"
|
||||
)
|
||||
|
||||
func initViewService(f platformtesting.ViewFields, t *testing.T) (platform.ViewService, func()) {
|
||||
func initViewService(f platformtesting.ViewFields, t *testing.T) (platform.ViewService, string, func()) {
|
||||
c, closeFn, err := NewTestClient()
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create new bolt client: %v", err)
|
||||
|
@ -20,7 +21,7 @@ func initViewService(f platformtesting.ViewFields, t *testing.T) (platform.ViewS
|
|||
t.Fatalf("failed to populate cells")
|
||||
}
|
||||
}
|
||||
return c, func() {
|
||||
return c, bolt.OpPrefix, func() {
|
||||
defer closeFn()
|
||||
for _, b := range f.Views {
|
||||
if err := c.DeleteView(ctx, b.ID); err != nil {
|
||||
|
|
|
@ -129,9 +129,6 @@ func (h *TelegrafHandler) handleGetTelegrafs(w http.ResponseWriter, r *http.Requ
|
|||
}
|
||||
tcs, _, err := h.TelegrafService.FindTelegrafConfigs(ctx, *filter)
|
||||
if err != nil {
|
||||
if err == platform.ErrViewNotFound {
|
||||
err = errors.New(err.Error(), errors.NotFound)
|
||||
}
|
||||
EncodeError(ctx, err, w)
|
||||
return
|
||||
}
|
||||
|
@ -150,9 +147,6 @@ func (h *TelegrafHandler) handleGetTelegraf(w http.ResponseWriter, r *http.Reque
|
|||
}
|
||||
tc, err := h.TelegrafService.FindTelegrafConfigByID(ctx, id)
|
||||
if err != nil {
|
||||
if err == platform.ErrViewNotFound {
|
||||
err = errors.New(err.Error(), errors.NotFound)
|
||||
}
|
||||
EncodeError(ctx, err, w)
|
||||
return
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@ import (
|
|||
"net/http"
|
||||
|
||||
"github.com/influxdata/platform"
|
||||
"github.com/influxdata/platform/kit/errors"
|
||||
"github.com/julienschmidt/httprouter"
|
||||
)
|
||||
|
||||
|
@ -106,7 +105,7 @@ func (h *ViewHandler) handleGetViews(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
views, _, err := h.ViewService.FindViews(ctx, req.filter)
|
||||
if err != nil {
|
||||
EncodeError(ctx, errors.InternalErrorf("Error loading views: %v", err), w)
|
||||
EncodeError(ctx, err, w)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -164,7 +163,7 @@ func (h *ViewHandler) handlePostViews(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
if err := h.ViewService.CreateView(ctx, req.View); err != nil {
|
||||
EncodeError(ctx, errors.InternalErrorf("Error loading views: %v", err), w)
|
||||
EncodeError(ctx, err, w)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -200,9 +199,6 @@ func (h *ViewHandler) handleGetView(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
view, err := h.ViewService.FindViewByID(ctx, req.ViewID)
|
||||
if err != nil {
|
||||
if err == platform.ErrViewNotFound {
|
||||
err = errors.New(err.Error(), errors.NotFound)
|
||||
}
|
||||
EncodeError(ctx, err, w)
|
||||
return
|
||||
}
|
||||
|
@ -221,7 +217,10 @@ func decodeGetViewRequest(ctx context.Context, r *http.Request) (*getViewRequest
|
|||
params := httprouter.ParamsFromContext(ctx)
|
||||
id := params.ByName("id")
|
||||
if id == "" {
|
||||
return nil, errors.InvalidDataf("url missing id")
|
||||
return nil, &platform.Error{
|
||||
Code: platform.EInvalid,
|
||||
Msg: "url missing id",
|
||||
}
|
||||
}
|
||||
|
||||
var i platform.ID
|
||||
|
@ -245,9 +244,6 @@ func (h *ViewHandler) handleDeleteView(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
if err := h.ViewService.DeleteView(ctx, req.ViewID); err != nil {
|
||||
if err == platform.ErrViewNotFound {
|
||||
err = errors.New(err.Error(), errors.NotFound)
|
||||
}
|
||||
EncodeError(ctx, err, w)
|
||||
return
|
||||
}
|
||||
|
@ -263,7 +259,10 @@ func decodeDeleteViewRequest(ctx context.Context, r *http.Request) (*deleteViewR
|
|||
params := httprouter.ParamsFromContext(ctx)
|
||||
id := params.ByName("id")
|
||||
if id == "" {
|
||||
return nil, errors.InvalidDataf("url missing id")
|
||||
return nil, &platform.Error{
|
||||
Code: platform.EInvalid,
|
||||
Msg: "url missing id",
|
||||
}
|
||||
}
|
||||
|
||||
var i platform.ID
|
||||
|
@ -280,16 +279,13 @@ func decodeDeleteViewRequest(ctx context.Context, r *http.Request) (*deleteViewR
|
|||
func (h *ViewHandler) handlePatchView(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
|
||||
req, err := decodePatchViewRequest(ctx, r)
|
||||
if err != nil {
|
||||
EncodeError(ctx, err, w)
|
||||
req, pe := decodePatchViewRequest(ctx, r)
|
||||
if pe != nil {
|
||||
EncodeError(ctx, pe, w)
|
||||
return
|
||||
}
|
||||
view, err := h.ViewService.UpdateView(ctx, req.ViewID, req.Upd)
|
||||
if err != nil {
|
||||
if err == platform.ErrViewNotFound {
|
||||
err = errors.New(err.Error(), errors.NotFound)
|
||||
}
|
||||
EncodeError(ctx, err, w)
|
||||
return
|
||||
}
|
||||
|
@ -305,11 +301,13 @@ type patchViewRequest struct {
|
|||
Upd platform.ViewUpdate
|
||||
}
|
||||
|
||||
func decodePatchViewRequest(ctx context.Context, r *http.Request) (*patchViewRequest, error) {
|
||||
func decodePatchViewRequest(ctx context.Context, r *http.Request) (*patchViewRequest, *platform.Error) {
|
||||
req := &patchViewRequest{}
|
||||
upd := platform.ViewUpdate{}
|
||||
if err := json.NewDecoder(r.Body).Decode(&upd); err != nil {
|
||||
return nil, errors.MalformedDataf(err.Error())
|
||||
return nil, &platform.Error{
|
||||
Err: err,
|
||||
}
|
||||
}
|
||||
|
||||
req.Upd = upd
|
||||
|
@ -317,26 +315,36 @@ func decodePatchViewRequest(ctx context.Context, r *http.Request) (*patchViewReq
|
|||
params := httprouter.ParamsFromContext(ctx)
|
||||
id := params.ByName("id")
|
||||
if id == "" {
|
||||
return nil, errors.InvalidDataf("url missing id")
|
||||
return nil, &platform.Error{
|
||||
Code: platform.EInvalid,
|
||||
Msg: "url missing id",
|
||||
}
|
||||
}
|
||||
var i platform.ID
|
||||
if err := i.DecodeFromString(id); err != nil {
|
||||
return nil, err
|
||||
return nil, &platform.Error{
|
||||
Err: err,
|
||||
}
|
||||
}
|
||||
|
||||
req.ViewID = i
|
||||
|
||||
if err := req.Valid(); err != nil {
|
||||
return nil, errors.MalformedDataf(err.Error())
|
||||
return nil, &platform.Error{
|
||||
Err: err,
|
||||
}
|
||||
}
|
||||
|
||||
return req, nil
|
||||
}
|
||||
|
||||
// Valid validates that the view ID is non zero valued and update has expected values set.
|
||||
func (r *patchViewRequest) Valid() error {
|
||||
func (r *patchViewRequest) Valid() *platform.Error {
|
||||
if !r.ViewID.Valid() {
|
||||
return fmt.Errorf("missing view ID")
|
||||
return &platform.Error{
|
||||
Code: platform.EInvalid,
|
||||
Msg: "missing view ID",
|
||||
}
|
||||
}
|
||||
|
||||
return r.Upd.Valid()
|
||||
|
|
|
@ -222,7 +222,10 @@ func TestService_handleGetView(t *testing.T) {
|
|||
fields: fields{
|
||||
&mock.ViewService{
|
||||
FindViewByIDF: func(ctx context.Context, id platform.ID) (*platform.View, error) {
|
||||
return nil, platform.ErrViewNotFound
|
||||
return nil, &platform.Error{
|
||||
Code: platform.ENotFound,
|
||||
Msg: platform.ErrViewNotFound,
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -416,7 +419,10 @@ func TestService_handleDeleteView(t *testing.T) {
|
|||
fields: fields{
|
||||
&mock.ViewService{
|
||||
DeleteViewF: func(ctx context.Context, id platform.ID) error {
|
||||
return platform.ErrViewNotFound
|
||||
return &platform.Error{
|
||||
Code: platform.ENotFound,
|
||||
Msg: platform.ErrViewNotFound,
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -571,7 +577,10 @@ func TestService_handlePatchView(t *testing.T) {
|
|||
fields: fields{
|
||||
&mock.ViewService{
|
||||
UpdateViewF: func(ctx context.Context, id platform.ID, upd platform.ViewUpdate) (*platform.View, error) {
|
||||
return nil, platform.ErrViewNotFound
|
||||
return nil, &platform.Error{
|
||||
Code: platform.ENotFound,
|
||||
Msg: platform.ErrViewNotFound,
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
@ -7,22 +7,35 @@ import (
|
|||
"github.com/influxdata/platform"
|
||||
)
|
||||
|
||||
func (s *Service) loadView(ctx context.Context, id platform.ID) (*platform.View, error) {
|
||||
func (s *Service) loadView(ctx context.Context, id platform.ID) (*platform.View, *platform.Error) {
|
||||
i, ok := s.viewKV.Load(id.String())
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("view not found")
|
||||
return nil, &platform.Error{
|
||||
Code: platform.ENotFound,
|
||||
Msg: "view not found",
|
||||
}
|
||||
}
|
||||
|
||||
d, ok := i.(*platform.View)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("type %T is not a view", i)
|
||||
return nil, &platform.Error{
|
||||
Code: platform.EInvalid,
|
||||
Msg: fmt.Sprintf("type %T is not a view", i),
|
||||
}
|
||||
}
|
||||
return d, nil
|
||||
}
|
||||
|
||||
// FindViewByID returns a single view by ID.
|
||||
func (s *Service) FindViewByID(ctx context.Context, id platform.ID) (*platform.View, error) {
|
||||
return s.loadView(ctx, id)
|
||||
v, pe := s.loadView(ctx, id)
|
||||
if pe != nil {
|
||||
return nil, &platform.Error{
|
||||
Err: pe,
|
||||
Op: OpPrefix + platform.OpFindViewByID,
|
||||
}
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
func filterViewFn(filter platform.ViewFilter) func(d *platform.View) bool {
|
||||
|
@ -37,16 +50,22 @@ func filterViewFn(filter platform.ViewFilter) func(d *platform.View) bool {
|
|||
|
||||
// FindViews implements platform.ViewService interface.
|
||||
func (s *Service) FindViews(ctx context.Context, filter platform.ViewFilter) ([]*platform.View, int, error) {
|
||||
var ds []*platform.View
|
||||
if filter.ID != nil {
|
||||
d, err := s.FindViewByID(ctx, *filter.ID)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
if err != nil && platform.ErrorCode(err) != platform.ENotFound {
|
||||
return nil, 0, &platform.Error{
|
||||
Err: err,
|
||||
Op: OpPrefix + platform.OpFindViews,
|
||||
}
|
||||
}
|
||||
if d != nil {
|
||||
ds = append(ds, d)
|
||||
}
|
||||
|
||||
return []*platform.View{d}, 1, nil
|
||||
return ds, len(ds), nil
|
||||
}
|
||||
|
||||
var ds []*platform.View
|
||||
var err error
|
||||
filterF := filterViewFn(filter)
|
||||
s.viewKV.Range(func(k, v interface{}) bool {
|
||||
|
@ -66,7 +85,13 @@ func (s *Service) FindViews(ctx context.Context, filter platform.ViewFilter) ([]
|
|||
// CreateView implements platform.ViewService interface.
|
||||
func (s *Service) CreateView(ctx context.Context, c *platform.View) error {
|
||||
c.ID = s.IDGenerator.ID()
|
||||
return s.PutView(ctx, c)
|
||||
if err := s.PutView(ctx, c); err != nil {
|
||||
return &platform.Error{
|
||||
Err: err,
|
||||
Op: OpPrefix + platform.OpCreateView,
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// PutView implements platform.ViewService interface.
|
||||
|
@ -82,7 +107,10 @@ func (s *Service) PutView(ctx context.Context, c *platform.View) error {
|
|||
func (s *Service) UpdateView(ctx context.Context, id platform.ID, upd platform.ViewUpdate) (*platform.View, error) {
|
||||
c, err := s.FindViewByID(ctx, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, &platform.Error{
|
||||
Err: err,
|
||||
Op: OpPrefix + platform.OpUpdateView,
|
||||
}
|
||||
}
|
||||
|
||||
if upd.Name != nil {
|
||||
|
@ -101,7 +129,10 @@ func (s *Service) UpdateView(ctx context.Context, id platform.ID, upd platform.V
|
|||
// DeleteView implements platform.ViewService interface.
|
||||
func (s *Service) DeleteView(ctx context.Context, id platform.ID) error {
|
||||
if _, err := s.FindViewByID(ctx, id); err != nil {
|
||||
return err
|
||||
return &platform.Error{
|
||||
Err: err,
|
||||
Op: OpPrefix + platform.OpDeleteView,
|
||||
}
|
||||
}
|
||||
s.viewKV.Delete(id.String())
|
||||
return nil
|
||||
|
|
|
@ -8,7 +8,7 @@ import (
|
|||
platformtesting "github.com/influxdata/platform/testing"
|
||||
)
|
||||
|
||||
func initViewService(f platformtesting.ViewFields, t *testing.T) (platform.ViewService, func()) {
|
||||
func initViewService(f platformtesting.ViewFields, t *testing.T) (platform.ViewService, string, func()) {
|
||||
s := NewService()
|
||||
s.IDGenerator = f.IDGenerator
|
||||
ctx := context.TODO()
|
||||
|
@ -17,7 +17,7 @@ func initViewService(f platformtesting.ViewFields, t *testing.T) (platform.ViewS
|
|||
t.Fatalf("failed to populate Views")
|
||||
}
|
||||
}
|
||||
return s, func() {}
|
||||
return s, OpPrefix, func() {}
|
||||
}
|
||||
|
||||
func TestViewService_CreateView(t *testing.T) {
|
||||
|
|
176
testing/cells.go
176
testing/cells.go
|
@ -3,7 +3,6 @@ package testing
|
|||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"sort"
|
||||
"testing"
|
||||
|
||||
|
@ -39,7 +38,7 @@ type ViewFields struct {
|
|||
|
||||
// CreateView testing
|
||||
func CreateView(
|
||||
init func(ViewFields, *testing.T) (platform.ViewService, func()),
|
||||
init func(ViewFields, *testing.T) (platform.ViewService, string, func()),
|
||||
t *testing.T,
|
||||
) {
|
||||
type args struct {
|
||||
|
@ -110,19 +109,11 @@ func CreateView(
|
|||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
s, done := init(tt.fields, t)
|
||||
s, opPrefix, done := init(tt.fields, t)
|
||||
defer done()
|
||||
ctx := context.TODO()
|
||||
err := s.CreateView(ctx, tt.args.view)
|
||||
if (err != nil) != (tt.wants.err != nil) {
|
||||
t.Fatalf("expected error '%v' got '%v'", tt.wants.err, err)
|
||||
}
|
||||
|
||||
if err != nil && tt.wants.err != nil {
|
||||
if err.Error() != tt.wants.err.Error() {
|
||||
t.Fatalf("expected error messages to match '%v' got '%v'", tt.wants.err, err.Error())
|
||||
}
|
||||
}
|
||||
diffPlatformErrors(tt.name, err, tt.wants.err, opPrefix, t)
|
||||
defer s.DeleteView(ctx, tt.args.view.ID)
|
||||
|
||||
views, _, err := s.FindViews(ctx, platform.ViewFilter{})
|
||||
|
@ -138,7 +129,7 @@ func CreateView(
|
|||
|
||||
// FindViewByID testing
|
||||
func FindViewByID(
|
||||
init func(ViewFields, *testing.T) (platform.ViewService, func()),
|
||||
init func(ViewFields, *testing.T) (platform.ViewService, string, func()),
|
||||
t *testing.T,
|
||||
) {
|
||||
type args struct {
|
||||
|
@ -194,24 +185,50 @@ func FindViewByID(
|
|||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "find view by id not found",
|
||||
fields: ViewFields{
|
||||
Views: []*platform.View{
|
||||
{
|
||||
ViewContents: platform.ViewContents{
|
||||
ID: MustIDBase16(viewOneID),
|
||||
Name: "view1",
|
||||
},
|
||||
Properties: platform.EmptyViewProperties{},
|
||||
},
|
||||
{
|
||||
ViewContents: platform.ViewContents{
|
||||
ID: MustIDBase16(viewTwoID),
|
||||
Name: "view2",
|
||||
},
|
||||
Properties: platform.TableViewProperties{
|
||||
Type: "table",
|
||||
TimeFormat: "rfc3339",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
args: args{
|
||||
id: MustIDBase16(threeID),
|
||||
},
|
||||
wants: wants{
|
||||
err: &platform.Error{
|
||||
Code: platform.ENotFound,
|
||||
Op: platform.OpFindViewByID,
|
||||
Msg: "view not found",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
s, done := init(tt.fields, t)
|
||||
s, opPrefix, done := init(tt.fields, t)
|
||||
defer done()
|
||||
ctx := context.TODO()
|
||||
|
||||
view, err := s.FindViewByID(ctx, tt.args.id)
|
||||
if (err != nil) != (tt.wants.err != nil) {
|
||||
t.Fatalf("expected errors to be equal '%v' got '%v'", tt.wants.err, err)
|
||||
}
|
||||
|
||||
if err != nil && tt.wants.err != nil {
|
||||
if err.Error() != tt.wants.err.Error() {
|
||||
t.Fatalf("expected error '%v' got '%v'", tt.wants.err, err)
|
||||
}
|
||||
}
|
||||
diffPlatformErrors(tt.name, err, tt.wants.err, opPrefix, t)
|
||||
|
||||
if diff := cmp.Diff(view, tt.wants.view, viewCmpOptions...); diff != "" {
|
||||
t.Errorf("view is different -got/+want\ndiff %s", diff)
|
||||
|
@ -222,7 +239,7 @@ func FindViewByID(
|
|||
|
||||
// FindViews testing
|
||||
func FindViews(
|
||||
init func(ViewFields, *testing.T) (platform.ViewService, func()),
|
||||
init func(ViewFields, *testing.T) (platform.ViewService, string, func()),
|
||||
t *testing.T,
|
||||
) {
|
||||
type args struct {
|
||||
|
@ -326,11 +343,41 @@ func FindViews(
|
|||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "find view by id not found",
|
||||
fields: ViewFields{
|
||||
Views: []*platform.View{
|
||||
{
|
||||
ViewContents: platform.ViewContents{
|
||||
ID: MustIDBase16(viewOneID),
|
||||
Name: "view1",
|
||||
},
|
||||
Properties: platform.EmptyViewProperties{},
|
||||
},
|
||||
{
|
||||
ViewContents: platform.ViewContents{
|
||||
ID: MustIDBase16(viewTwoID),
|
||||
Name: "view2",
|
||||
},
|
||||
Properties: platform.TableViewProperties{
|
||||
Type: "table",
|
||||
TimeFormat: "rfc3339",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
args: args{
|
||||
ID: MustIDBase16(threeID),
|
||||
},
|
||||
wants: wants{
|
||||
views: []*platform.View{},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
s, done := init(tt.fields, t)
|
||||
s, opPrefix, done := init(tt.fields, t)
|
||||
defer done()
|
||||
ctx := context.TODO()
|
||||
|
||||
|
@ -340,15 +387,7 @@ func FindViews(
|
|||
}
|
||||
|
||||
views, _, err := s.FindViews(ctx, filter)
|
||||
if (err != nil) != (tt.wants.err != nil) {
|
||||
t.Fatalf("expected errors to be equal '%v' got '%v'", tt.wants.err, err)
|
||||
}
|
||||
|
||||
if err != nil && tt.wants.err != nil {
|
||||
if err.Error() != tt.wants.err.Error() {
|
||||
t.Fatalf("expected error '%v' got '%v'", tt.wants.err, err)
|
||||
}
|
||||
}
|
||||
diffPlatformErrors(tt.name, err, tt.wants.err, opPrefix, t)
|
||||
|
||||
if diff := cmp.Diff(views, tt.wants.views, viewCmpOptions...); diff != "" {
|
||||
t.Errorf("views are different -got/+want\ndiff %s", diff)
|
||||
|
@ -359,7 +398,7 @@ func FindViews(
|
|||
|
||||
// DeleteView testing
|
||||
func DeleteView(
|
||||
init func(ViewFields, *testing.T) (platform.ViewService, func()),
|
||||
init func(ViewFields, *testing.T) (platform.ViewService, string, func()),
|
||||
t *testing.T,
|
||||
) {
|
||||
type args struct {
|
||||
|
@ -444,7 +483,11 @@ func DeleteView(
|
|||
ID: MustIDBase16(viewThreeID),
|
||||
},
|
||||
wants: wants{
|
||||
err: fmt.Errorf("view not found"),
|
||||
err: &platform.Error{
|
||||
Code: platform.ENotFound,
|
||||
Op: platform.OpDeleteView,
|
||||
Msg: "view not found",
|
||||
},
|
||||
views: []*platform.View{
|
||||
{
|
||||
ViewContents: platform.ViewContents{
|
||||
|
@ -470,19 +513,11 @@ func DeleteView(
|
|||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
s, done := init(tt.fields, t)
|
||||
s, opPrefix, done := init(tt.fields, t)
|
||||
defer done()
|
||||
ctx := context.TODO()
|
||||
err := s.DeleteView(ctx, tt.args.ID)
|
||||
if (err != nil) != (tt.wants.err != nil) {
|
||||
t.Fatalf("expected error '%v' got '%v'", tt.wants.err, err)
|
||||
}
|
||||
|
||||
if err != nil && tt.wants.err != nil {
|
||||
if err.Error() != tt.wants.err.Error() {
|
||||
t.Fatalf("expected error messages to match '%v' got '%v'", tt.wants.err, err.Error())
|
||||
}
|
||||
}
|
||||
diffPlatformErrors(tt.name, err, tt.wants.err, opPrefix, t)
|
||||
|
||||
filter := platform.ViewFilter{}
|
||||
views, _, err := s.FindViews(ctx, filter)
|
||||
|
@ -498,7 +533,7 @@ func DeleteView(
|
|||
|
||||
// UpdateView testing
|
||||
func UpdateView(
|
||||
init func(ViewFields, *testing.T) (platform.ViewService, func()),
|
||||
init func(ViewFields, *testing.T) (platform.ViewService, string, func()),
|
||||
t *testing.T,
|
||||
) {
|
||||
type args struct {
|
||||
|
@ -597,11 +632,46 @@ func UpdateView(
|
|||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "update id not exists",
|
||||
fields: ViewFields{
|
||||
Views: []*platform.View{
|
||||
{
|
||||
ViewContents: platform.ViewContents{
|
||||
ID: MustIDBase16(viewOneID),
|
||||
Name: "view1",
|
||||
},
|
||||
Properties: platform.EmptyViewProperties{},
|
||||
},
|
||||
{
|
||||
ViewContents: platform.ViewContents{
|
||||
ID: MustIDBase16(viewTwoID),
|
||||
Name: "view2",
|
||||
},
|
||||
Properties: platform.TableViewProperties{
|
||||
Type: "table",
|
||||
TimeFormat: "rfc3339",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
args: args{
|
||||
id: MustIDBase16(threeID),
|
||||
name: "changed",
|
||||
},
|
||||
wants: wants{
|
||||
err: &platform.Error{
|
||||
Code: platform.ENotFound,
|
||||
Op: platform.OpUpdateView,
|
||||
Msg: "view not found",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
s, done := init(tt.fields, t)
|
||||
s, opPrefix, done := init(tt.fields, t)
|
||||
defer done()
|
||||
ctx := context.TODO()
|
||||
|
||||
|
@ -614,15 +684,7 @@ func UpdateView(
|
|||
}
|
||||
|
||||
view, err := s.UpdateView(ctx, tt.args.id, upd)
|
||||
if (err != nil) != (tt.wants.err != nil) {
|
||||
t.Fatalf("expected error '%v' got '%v'", tt.wants.err, err)
|
||||
}
|
||||
|
||||
if err != nil && tt.wants.err != nil {
|
||||
if err.Error() != tt.wants.err.Error() {
|
||||
t.Fatalf("expected error messages to match '%v' got '%v'", tt.wants.err, err.Error())
|
||||
}
|
||||
}
|
||||
diffPlatformErrors(tt.name, err, tt.wants.err, opPrefix, t)
|
||||
|
||||
if diff := cmp.Diff(view, tt.wants.view, viewCmpOptions...); diff != "" {
|
||||
t.Errorf("view is different -got/+want\ndiff %s", diff)
|
||||
|
|
20
view.go
20
view.go
|
@ -6,8 +6,17 @@ import (
|
|||
"fmt"
|
||||
)
|
||||
|
||||
// ErrViewNotFound is the error for a missing View.
|
||||
const ErrViewNotFound = ChronografError("view not found")
|
||||
// ErrViewNotFound is the error msg for a missing View.
|
||||
const ErrViewNotFound = "view not found"
|
||||
|
||||
// ops for view.
|
||||
const (
|
||||
OpFindViewByID = "FindViewByID"
|
||||
OpFindViews = "FindViews"
|
||||
OpCreateView = "CreateView"
|
||||
OpUpdateView = "UpdateView"
|
||||
OpDeleteView = "DeleteView"
|
||||
)
|
||||
|
||||
// ViewService represents a service for managing View data.
|
||||
type ViewService interface {
|
||||
|
@ -36,10 +45,13 @@ type ViewUpdate struct {
|
|||
}
|
||||
|
||||
// Valid validates the update struct. It expects minimal values to be set.
|
||||
func (u ViewUpdate) Valid() error {
|
||||
func (u ViewUpdate) Valid() *Error {
|
||||
_, ok := u.Properties.(EmptyViewProperties)
|
||||
if u.Name == nil && ok {
|
||||
return fmt.Errorf("expected at least one attribute to be updated")
|
||||
return &Error{
|
||||
Code: EInvalid,
|
||||
Msg: "expected at least one attribute to be updated",
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
Loading…
Reference in New Issue