feat(influxdb): add urm for scraper

pull/11309/head
Kelvin Wang 2019-01-18 15:46:37 -05:00
parent abe6ed3b8b
commit 6e3e4503c2
14 changed files with 293 additions and 100 deletions

View File

@ -11,13 +11,15 @@ var _ influxdb.ScraperTargetStoreService = (*ScraperTargetStoreService)(nil)
// ScraperTargetStoreService wraps a influxdb.ScraperTargetStoreService and authorizes actions
// against it appropriately.
type ScraperTargetStoreService struct {
influxdb.UserResourceMappingService
s influxdb.ScraperTargetStoreService
}
// NewScraperTargetStoreService constructs an instance of an authorizing scraper target store serivce.
func NewScraperTargetStoreService(s influxdb.ScraperTargetStoreService) *ScraperTargetStoreService {
func NewScraperTargetStoreService(s influxdb.ScraperTargetStoreService, urm influxdb.UserResourceMappingService) *ScraperTargetStoreService {
return &ScraperTargetStoreService{
s: s,
UserResourceMappingService: urm,
s: s,
}
}
@ -94,7 +96,7 @@ func (s *ScraperTargetStoreService) ListTargets(ctx context.Context) ([]influxdb
}
// AddTarget checks to see if the authorizer on context has write access to the global scraper target resource.
func (s *ScraperTargetStoreService) AddTarget(ctx context.Context, st *influxdb.ScraperTarget) error {
func (s *ScraperTargetStoreService) AddTarget(ctx context.Context, st *influxdb.ScraperTarget, userID influxdb.ID) error {
p, err := influxdb.NewPermission(influxdb.WriteAction, influxdb.ScraperResourceType, st.OrgID)
if err != nil {
return err
@ -104,11 +106,11 @@ func (s *ScraperTargetStoreService) AddTarget(ctx context.Context, st *influxdb.
return err
}
return s.s.AddTarget(ctx, st)
return s.s.AddTarget(ctx, st, userID)
}
// UpdateTarget checks to see if the authorizer on context has write access to the scraper target provided.
func (s *ScraperTargetStoreService) UpdateTarget(ctx context.Context, upd *influxdb.ScraperTarget) (*influxdb.ScraperTarget, error) {
func (s *ScraperTargetStoreService) UpdateTarget(ctx context.Context, upd *influxdb.ScraperTarget, userID influxdb.ID) (*influxdb.ScraperTarget, error) {
st, err := s.s.GetTargetByID(ctx, upd.ID)
if err != nil {
return nil, err
@ -118,7 +120,7 @@ func (s *ScraperTargetStoreService) UpdateTarget(ctx context.Context, upd *influ
return nil, err
}
return s.s.UpdateTarget(ctx, upd)
return s.s.UpdateTarget(ctx, upd, userID)
}
// RemoveTarget checks to see if the authorizer on context has write access to the scraper target provided.

View File

@ -104,7 +104,7 @@ func TestScraperTargetStoreService_GetTargetByID(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
s := authorizer.NewScraperTargetStoreService(tt.fields.ScraperTargetStoreService)
s := authorizer.NewScraperTargetStoreService(tt.fields.ScraperTargetStoreService, mock.NewUserResourceMappingService())
ctx := context.Background()
ctx = influxdbcontext.SetAuthorizer(ctx, &Authorizer{[]influxdb.Permission{tt.args.permission}})
@ -228,7 +228,7 @@ func TestScraperTargetStoreService_ListTargets(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
s := authorizer.NewScraperTargetStoreService(tt.fields.ScraperTargetStoreService)
s := authorizer.NewScraperTargetStoreService(tt.fields.ScraperTargetStoreService, mock.NewUserResourceMappingService())
ctx := context.Background()
ctx = influxdbcontext.SetAuthorizer(ctx, &Authorizer{[]influxdb.Permission{tt.args.permission}})
@ -271,7 +271,7 @@ func TestScraperTargetStoreService_UpdateTarget(t *testing.T) {
OrgID: 10,
}, nil
},
UpdateTargetF: func(ctx context.Context, upd *influxdb.ScraperTarget) (*influxdb.ScraperTarget, error) {
UpdateTargetF: func(ctx context.Context, upd *influxdb.ScraperTarget, userID influxdb.ID) (*influxdb.ScraperTarget, error) {
return &influxdb.ScraperTarget{
ID: 1,
OrgID: 10,
@ -312,7 +312,7 @@ func TestScraperTargetStoreService_UpdateTarget(t *testing.T) {
OrgID: 10,
}, nil
},
UpdateTargetF: func(ctx context.Context, upd *influxdb.ScraperTarget) (*influxdb.ScraperTarget, error) {
UpdateTargetF: func(ctx context.Context, upd *influxdb.ScraperTarget, userID influxdb.ID) (*influxdb.ScraperTarget, error) {
return &influxdb.ScraperTarget{
ID: 1,
OrgID: 10,
@ -343,12 +343,12 @@ func TestScraperTargetStoreService_UpdateTarget(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
s := authorizer.NewScraperTargetStoreService(tt.fields.ScraperTargetStoreService)
s := authorizer.NewScraperTargetStoreService(tt.fields.ScraperTargetStoreService, mock.NewUserResourceMappingService())
ctx := context.Background()
ctx = influxdbcontext.SetAuthorizer(ctx, &Authorizer{tt.args.permissions})
_, err := s.UpdateTarget(ctx, &influxdb.ScraperTarget{ID: tt.args.id})
_, err := s.UpdateTarget(ctx, &influxdb.ScraperTarget{ID: tt.args.id}, influxdb.ID(1))
influxdbtesting.ErrorsEqual(t, err, tt.wants.err)
})
}
@ -448,7 +448,7 @@ func TestScraperTargetStoreService_RemoveTarget(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
s := authorizer.NewScraperTargetStoreService(tt.fields.ScraperTargetStoreService)
s := authorizer.NewScraperTargetStoreService(tt.fields.ScraperTargetStoreService, mock.NewUserResourceMappingService())
ctx := context.Background()
ctx = influxdbcontext.SetAuthorizer(ctx, &Authorizer{tt.args.permissions})
@ -481,7 +481,7 @@ func TestScraperTargetStoreService_AddTarget(t *testing.T) {
name: "authorized to create scraper",
fields: fields{
ScraperTargetStoreService: &mock.ScraperTargetStoreService{
AddTargetF: func(ctx context.Context, st *influxdb.ScraperTarget) error {
AddTargetF: func(ctx context.Context, st *influxdb.ScraperTarget, userID influxdb.ID) error {
return nil
},
},
@ -504,7 +504,7 @@ func TestScraperTargetStoreService_AddTarget(t *testing.T) {
name: "unauthorized to create scraper",
fields: fields{
ScraperTargetStoreService: &mock.ScraperTargetStoreService{
AddTargetF: func(ctx context.Context, st *influxdb.ScraperTarget) error {
AddTargetF: func(ctx context.Context, st *influxdb.ScraperTarget, userID influxdb.ID) error {
return nil
},
},
@ -530,12 +530,12 @@ func TestScraperTargetStoreService_AddTarget(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
s := authorizer.NewScraperTargetStoreService(tt.fields.ScraperTargetStoreService)
s := authorizer.NewScraperTargetStoreService(tt.fields.ScraperTargetStoreService, mock.NewUserResourceMappingService())
ctx := context.Background()
ctx = influxdbcontext.SetAuthorizer(ctx, &Authorizer{[]influxdb.Permission{tt.args.permission}})
err := s.AddTarget(ctx, &influxdb.ScraperTarget{OrgID: tt.args.orgID})
err := s.AddTarget(ctx, &influxdb.ScraperTarget{OrgID: tt.args.orgID}, influxdb.ID(1))
influxdbtesting.ErrorsEqual(t, err, tt.wants.err)
})
}

View File

@ -45,7 +45,7 @@ func (c *Client) ListTargets(ctx context.Context) (list []platform.ScraperTarget
}
// AddTarget add a new scraper target into storage.
func (c *Client) AddTarget(ctx context.Context, target *platform.ScraperTarget) (err error) {
func (c *Client) AddTarget(ctx context.Context, target *platform.ScraperTarget, userID platform.ID) (err error) {
if !target.OrgID.Valid() {
return &platform.Error{
Code: platform.EInvalid,
@ -62,7 +62,16 @@ func (c *Client) AddTarget(ctx context.Context, target *platform.ScraperTarget)
}
err = c.db.Update(func(tx *bolt.Tx) error {
target.ID = c.IDGenerator.ID()
return c.putTarget(ctx, tx, target)
if err := c.putTarget(ctx, tx, target); err != nil {
return err
}
urm := &platform.UserResourceMapping{
ResourceID: target.ID,
UserID: userID,
UserType: platform.Owner,
ResourceType: platform.ScraperResourceType,
}
return c.createUserResourceMapping(ctx, tx, urm)
})
if err != nil {
return &platform.Error{
@ -87,7 +96,13 @@ func (c *Client) RemoveTarget(ctx context.Context, id platform.ID) error {
Err: err,
}
}
return tx.Bucket(scraperBucket).Delete(encID)
if err = tx.Bucket(scraperBucket).Delete(encID); err != nil {
return nil
}
return c.deleteUserResourceMappings(ctx, tx, platform.UserResourceMappingFilter{
ResourceID: id,
ResourceType: platform.ScraperResourceType,
})
})
if err != nil {
return &platform.Error{
@ -99,7 +114,7 @@ func (c *Client) RemoveTarget(ctx context.Context, id platform.ID) error {
}
// UpdateTarget updates a scraper target.
func (c *Client) UpdateTarget(ctx context.Context, update *platform.ScraperTarget) (target *platform.ScraperTarget, err error) {
func (c *Client) UpdateTarget(ctx context.Context, update *platform.ScraperTarget, userID platform.ID) (target *platform.ScraperTarget, err error) {
op := getOp(platform.OpUpdateTarget)
var pe *platform.Error
if !update.ID.Valid() {

View File

@ -21,6 +21,11 @@ func initScraperTargetStoreService(f platformtesting.TargetFields, t *testing.T)
t.Fatalf("failed to populate targets: %v", err)
}
}
for _, m := range f.UserResourceMappings {
if err := c.CreateUserResourceMapping(ctx, m); err != nil {
t.Fatalf("failed to populate user resource mapping")
}
}
return c, bolt.OpPrefix, func() {
defer closeFn()
for _, target := range f.Targets {
@ -31,22 +36,6 @@ func initScraperTargetStoreService(f platformtesting.TargetFields, t *testing.T)
}
}
func TestScraperTargetStoreService_AddTarget(t *testing.T) {
platformtesting.AddTarget(initScraperTargetStoreService, t)
}
func TestScraperTargetStoreService_ListTargets(t *testing.T) {
platformtesting.ListTargets(initScraperTargetStoreService, t)
}
func TestScraperTargetStoreService_RemoveTarget(t *testing.T) {
platformtesting.RemoveTarget(initScraperTargetStoreService, t)
}
func TestScraperTargetStoreService_UpdateTarget(t *testing.T) {
platformtesting.UpdateTarget(initScraperTargetStoreService, t)
}
func TestScraperTargetStoreService_GetTargetByID(t *testing.T) {
platformtesting.GetTargetByID(initScraperTargetStoreService, t)
func TestScraperTargetStoreService(t *testing.T) {
platformtesting.ScraperService(initScraperTargetStoreService, t)
}

View File

@ -192,6 +192,7 @@ go_memstats_gc_cpu_fraction 1.972734963012756e-05
// and influxdb.ScraperTargetStoreService interface.
type mockStorage struct {
sync.RWMutex
influxdb.UserResourceMappingService
TotalGatherJobs chan struct{}
Metrics map[time.Time]Metrics
Targets []influxdb.ScraperTarget
@ -218,7 +219,7 @@ func (s *mockStorage) ListTargets(ctx context.Context) (targets []influxdb.Scrap
return s.Targets, nil
}
func (s *mockStorage) AddTarget(ctx context.Context, t *influxdb.ScraperTarget) error {
func (s *mockStorage) AddTarget(ctx context.Context, t *influxdb.ScraperTarget, userID influxdb.ID) error {
s.Lock()
defer s.Unlock()
if s.Targets == nil {
@ -259,7 +260,7 @@ func (s *mockStorage) GetTargetByID(ctx context.Context, id influxdb.ID) (target
}
func (s *mockStorage) UpdateTarget(ctx context.Context, update *influxdb.ScraperTarget) (target *influxdb.ScraperTarget, err error) {
func (s *mockStorage) UpdateTarget(ctx context.Context, update *influxdb.ScraperTarget, userID influxdb.ID) (target *influxdb.ScraperTarget, err error) {
s.Lock()
defer s.Unlock()

View File

@ -112,7 +112,7 @@ func NewAPIHandler(b *APIBackend) *APIHandler {
h.AuthorizationHandler.Logger = b.Logger.With(zap.String("handler", "auth"))
h.ScraperHandler = NewScraperHandler()
h.ScraperHandler.ScraperStorageService = authorizer.NewScraperTargetStoreService(b.ScraperTargetStoreService)
h.ScraperHandler.ScraperStorageService = authorizer.NewScraperTargetStoreService(b.ScraperTargetStoreService, b.UserResourceMappingService)
h.ScraperHandler.BucketService = b.BucketService
h.ScraperHandler.OrganizationService = b.OrganizationService
h.ScraperHandler.Logger = b.Logger.With(zap.String("handler", "scraper"))

View File

@ -8,6 +8,7 @@ import (
"path"
"github.com/influxdata/influxdb"
pctx "github.com/influxdata/influxdb/context"
"github.com/julienschmidt/httprouter"
"go.uber.org/zap"
)
@ -41,14 +42,19 @@ func NewScraperHandler() *ScraperHandler {
// handlePostScraperTarget is HTTP handler for the POST /api/v2/scrapers route.
func (h *ScraperHandler) handlePostScraperTarget(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
req, err := decodeScraperTargetAddRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
return
}
if err := h.ScraperStorageService.AddTarget(ctx, req); err != nil {
auth, err := pctx.GetAuthorizer(ctx)
if err != nil {
EncodeError(ctx, err, w)
return
}
if err := h.ScraperStorageService.AddTarget(ctx, req, auth.GetUserID()); err != nil {
EncodeError(ctx, err, w)
return
}
@ -91,7 +97,13 @@ func (h *ScraperHandler) handlePatchScraperTarget(w http.ResponseWriter, r *http
return
}
target, err := h.ScraperStorageService.UpdateTarget(ctx, update)
auth, err := pctx.GetAuthorizer(ctx)
if err != nil {
EncodeError(ctx, err, w)
return
}
target, err := h.ScraperStorageService.UpdateTarget(ctx, update, auth.GetUserID())
if err != nil {
EncodeError(ctx, err, w)
return
@ -247,7 +259,7 @@ func (s *ScraperService) ListTargets(ctx context.Context) ([]influxdb.ScraperTar
// UpdateTarget updates a single scraper target with changeset.
// Returns the new target state after update.
func (s *ScraperService) UpdateTarget(ctx context.Context, update *influxdb.ScraperTarget) (*influxdb.ScraperTarget, error) {
func (s *ScraperService) UpdateTarget(ctx context.Context, update *influxdb.ScraperTarget, userID influxdb.ID) (*influxdb.ScraperTarget, error) {
if !update.ID.Valid() {
return nil, &influxdb.Error{
Code: influxdb.EInvalid,
@ -291,7 +303,7 @@ func (s *ScraperService) UpdateTarget(ctx context.Context, update *influxdb.Scra
}
// AddTarget creates a new scraper target and sets target.ID with the new identifier.
func (s *ScraperService) AddTarget(ctx context.Context, target *influxdb.ScraperTarget) error {
func (s *ScraperService) AddTarget(ctx context.Context, target *influxdb.ScraperTarget, userID influxdb.ID) error {
url, err := newURL(s.Addr, targetPath)
if err != nil {
return err

View File

@ -11,6 +11,7 @@ import (
"testing"
platform "github.com/influxdata/influxdb"
platcontext "github.com/influxdata/influxdb/context"
"github.com/influxdata/influxdb/inmem"
"github.com/influxdata/influxdb/mock"
platformtesting "github.com/influxdata/influxdb/testing"
@ -494,7 +495,7 @@ func TestService_handlePostScraperTarget(t *testing.T) {
},
},
ScraperTargetStoreService: &mock.ScraperTargetStoreService{
AddTargetF: func(ctx context.Context, st *platform.ScraperTarget) error {
AddTargetF: func(ctx context.Context, st *platform.ScraperTarget, userID platform.ID) error {
st.ID = targetOneID
return nil
},
@ -549,6 +550,7 @@ func TestService_handlePostScraperTarget(t *testing.T) {
}
r := httptest.NewRequest("GET", "http://any.tld", bytes.NewReader(st))
r = r.WithContext(platcontext.SetAuthorizer(r.Context(), &platform.Authorization{}))
w := httptest.NewRecorder()
h.handlePostScraperTarget(w, r)
@ -614,7 +616,7 @@ func TestService_handlePatchScraperTarget(t *testing.T) {
},
},
ScraperTargetStoreService: &mock.ScraperTargetStoreService{
UpdateTargetF: func(ctx context.Context, t *platform.ScraperTarget) (*platform.ScraperTarget, error) {
UpdateTargetF: func(ctx context.Context, t *platform.ScraperTarget, userID platform.ID) (*platform.ScraperTarget, error) {
if t.ID == targetOneID {
return t, nil
}
@ -680,7 +682,7 @@ func TestService_handlePatchScraperTarget(t *testing.T) {
},
},
ScraperTargetStoreService: &mock.ScraperTargetStoreService{
UpdateTargetF: func(ctx context.Context, upd *platform.ScraperTarget) (*platform.ScraperTarget, error) {
UpdateTargetF: func(ctx context.Context, upd *platform.ScraperTarget, userID platform.ID) (*platform.ScraperTarget, error) {
return nil, &platform.Error{
Code: platform.ENotFound,
Msg: platform.ErrScraperTargetNotFound,
@ -732,7 +734,7 @@ func TestService_handlePatchScraperTarget(t *testing.T) {
Value: tt.args.id,
},
}))
r = r.WithContext(platcontext.SetAuthorizer(r.Context(), &platform.Authorization{}))
w := httptest.NewRecorder()
h.handlePatchScraperTarget(w, r)
@ -765,6 +767,11 @@ func initScraperService(f platformtesting.TargetFields, t *testing.T) (platform.
t.Fatalf("failed to populate scraper targets")
}
}
for _, m := range f.UserResourceMappings {
if err := svc.PutUserResourceMapping(ctx, m); err != nil {
t.Fatalf("failed to populate user resource mapping")
}
}
handler := NewScraperHandler()
handler.ScraperStorageService = svc
@ -784,10 +791,23 @@ func initScraperService(f platformtesting.TargetFields, t *testing.T) (platform.
}, nil
},
}
server := httptest.NewServer(handler)
client := ScraperService{
Addr: server.URL,
OpPrefix: inmem.OpPrefix,
userID, _ := platform.IDFromString("020f755c3c082002")
server := httptest.NewServer(mock.NewMiddlewareHandler(
handler, &platform.Authorization{
UserID: *userID,
Token: "tok",
},
))
client := struct {
platform.UserResourceMappingService
ScraperService
}{
UserResourceMappingService: svc,
ScraperService: ScraperService{
Token: "tok",
Addr: server.URL,
OpPrefix: inmem.OpPrefix,
},
}
done := server.Close

View File

@ -51,7 +51,7 @@ func (s *Service) ListTargets(ctx context.Context) (list []platform.ScraperTarge
}
// AddTarget add a new scraper target into storage.
func (s *Service) AddTarget(ctx context.Context, target *platform.ScraperTarget) (err error) {
func (s *Service) AddTarget(ctx context.Context, target *platform.ScraperTarget, userID platform.ID) (err error) {
target.ID = s.IDGenerator.ID()
if !target.OrgID.Valid() {
return &platform.Error{
@ -73,6 +73,15 @@ func (s *Service) AddTarget(ctx context.Context, target *platform.ScraperTarget)
Err: err,
}
}
urm := &platform.UserResourceMapping{
ResourceID: target.ID,
UserID: userID,
UserType: platform.Owner,
ResourceType: platform.ScraperResourceType,
}
if err := s.CreateUserResourceMapping(ctx, urm); err != nil {
return err
}
return nil
}
@ -85,11 +94,23 @@ func (s *Service) RemoveTarget(ctx context.Context, id platform.ID) error {
}
}
s.scraperTargetKV.Delete(id.String())
err := s.deleteUserResourceMapping(ctx, platform.UserResourceMappingFilter{
ResourceID: id,
ResourceType: platform.ScraperResourceType,
})
if err != nil {
return &platform.Error{
Code: platform.ErrorCode(err),
Op: OpPrefix + platform.OpRemoveTarget,
Err: err,
}
}
return nil
}
// UpdateTarget updates a scraper target.
func (s *Service) UpdateTarget(ctx context.Context, update *platform.ScraperTarget) (target *platform.ScraperTarget, err error) {
func (s *Service) UpdateTarget(ctx context.Context, update *platform.ScraperTarget, userID platform.ID) (target *platform.ScraperTarget, err error) {
op := OpPrefix + platform.OpUpdateTarget
if !update.ID.Valid() {
return nil, &platform.Error{

View File

@ -17,25 +17,14 @@ func initScraperTargetStoreService(f platformtesting.TargetFields, t *testing.T)
t.Fatalf("failed to populate scraper targets")
}
}
for _, m := range f.UserResourceMappings {
if err := s.PutUserResourceMapping(ctx, m); err != nil {
t.Fatalf("failed to populate user resource mapping")
}
}
return s, OpPrefix, func() {}
}
func TestScraperTargetStoreService_AddTarget(t *testing.T) {
platformtesting.AddTarget(initScraperTargetStoreService, t)
}
func TestScraperTargetStoreService_ListTargets(t *testing.T) {
platformtesting.ListTargets(initScraperTargetStoreService, t)
}
func TestScraperTargetStoreService_RemoveTarget(t *testing.T) {
platformtesting.RemoveTarget(initScraperTargetStoreService, t)
}
func TestScraperTargetStoreService_UpdateTarget(t *testing.T) {
platformtesting.UpdateTarget(initScraperTargetStoreService, t)
}
func TestScraperTargetStoreService_GetTargetByID(t *testing.T) {
platformtesting.GetTargetByID(initScraperTargetStoreService, t)
func TestScraperTargetStoreService(t *testing.T) {
platformtesting.ScraperService(initScraperTargetStoreService, t)
}

27
mock/middle_ware.go Normal file
View File

@ -0,0 +1,27 @@
package mock
import (
"net/http"
"github.com/influxdata/influxdb"
platcontext "github.com/influxdata/influxdb/context"
)
// NewMiddlewareHandler create a mocked middleware handler.
func NewMiddlewareHandler(handler http.Handler, auth influxdb.Authorizer) http.Handler {
return &middlewareHandler{
handler: handler,
auth: auth,
}
}
type middlewareHandler struct {
handler http.Handler
auth influxdb.Authorizer
}
func (m *middlewareHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
r = r.WithContext(platcontext.SetAuthorizer(ctx, m.auth))
m.handler.ServeHTTP(w, r)
}

View File

@ -10,11 +10,12 @@ var _ platform.ScraperTargetStoreService = &ScraperTargetStoreService{}
// ScraperTargetStoreService is a mock implementation of a platform.ScraperTargetStoreService.
type ScraperTargetStoreService struct {
UserResourceMappingService
ListTargetsF func(ctx context.Context) ([]platform.ScraperTarget, error)
AddTargetF func(ctx context.Context, t *platform.ScraperTarget) error
AddTargetF func(ctx context.Context, t *platform.ScraperTarget, userID platform.ID) error
GetTargetByIDF func(ctx context.Context, id platform.ID) (*platform.ScraperTarget, error)
RemoveTargetF func(ctx context.Context, id platform.ID) error
UpdateTargetF func(ctx context.Context, t *platform.ScraperTarget) (*platform.ScraperTarget, error)
UpdateTargetF func(ctx context.Context, t *platform.ScraperTarget, userID platform.ID) (*platform.ScraperTarget, error)
}
// ListTargets lists all the scraper targets.
@ -23,8 +24,8 @@ func (s *ScraperTargetStoreService) ListTargets(ctx context.Context) ([]platform
}
// AddTarget adds a scraper target.
func (s *ScraperTargetStoreService) AddTarget(ctx context.Context, t *platform.ScraperTarget) error {
return s.AddTargetF(ctx, t)
func (s *ScraperTargetStoreService) AddTarget(ctx context.Context, t *platform.ScraperTarget, userID platform.ID) error {
return s.AddTargetF(ctx, t, userID)
}
// GetTargetByID retrieves a scraper target by id.
@ -38,6 +39,6 @@ func (s *ScraperTargetStoreService) RemoveTarget(ctx context.Context, id platfor
}
// UpdateTarget updates a scraper target.
func (s *ScraperTargetStoreService) UpdateTarget(ctx context.Context, t *platform.ScraperTarget) (*platform.ScraperTarget, error) {
return s.UpdateTargetF(ctx, t)
func (s *ScraperTargetStoreService) UpdateTarget(ctx context.Context, t *platform.ScraperTarget, userID platform.ID) (*platform.ScraperTarget, error) {
return s.UpdateTargetF(ctx, t, userID)
}

View File

@ -28,11 +28,12 @@ type ScraperTarget struct {
// ScraperTargetStoreService defines the crud service for ScraperTarget.
type ScraperTargetStoreService interface {
UserResourceMappingService
ListTargets(ctx context.Context) ([]ScraperTarget, error)
AddTarget(ctx context.Context, t *ScraperTarget) error
AddTarget(ctx context.Context, t *ScraperTarget, userID ID) error
GetTargetByID(ctx context.Context, id ID) (*ScraperTarget, error)
RemoveTarget(ctx context.Context, id ID) error
UpdateTarget(ctx context.Context, t *ScraperTarget) (*ScraperTarget, error)
UpdateTarget(ctx context.Context, t *ScraperTarget, userID ID) (*ScraperTarget, error)
}
// ScraperTargetFilter represents a set of filter that restrict the returned results.

View File

@ -19,8 +19,9 @@ const (
// TargetFields will include the IDGenerator, and targets
type TargetFields struct {
IDGenerator platform.IDGenerator
Targets []*platform.ScraperTarget
IDGenerator platform.IDGenerator
Targets []*platform.ScraperTarget
UserResourceMappings []*platform.UserResourceMapping
}
var targetCmpOptions = cmp.Options{
@ -79,11 +80,13 @@ func AddTarget(
t *testing.T,
) {
type args struct {
userID platform.ID
target *platform.ScraperTarget
}
type wants struct {
err error
targets []platform.ScraperTarget
err error
targets []platform.ScraperTarget
userResourceMappings []*platform.UserResourceMapping
}
tests := []struct {
name string
@ -94,10 +97,12 @@ func AddTarget(
{
name: "create targets with empty set",
fields: TargetFields{
IDGenerator: mock.NewIDGenerator(targetOneID, t),
Targets: []*platform.ScraperTarget{},
IDGenerator: mock.NewIDGenerator(targetOneID, t),
Targets: []*platform.ScraperTarget{},
UserResourceMappings: []*platform.UserResourceMapping{},
},
args: args{
userID: MustIDBase16(threeID),
target: &platform.ScraperTarget{
Name: "name1",
Type: platform.PrometheusScraperType,
@ -107,6 +112,14 @@ func AddTarget(
},
},
wants: wants{
userResourceMappings: []*platform.UserResourceMapping{
{
ResourceID: MustIDBase16(oneID),
ResourceType: platform.ScraperResourceType,
UserID: MustIDBase16(threeID),
UserType: platform.Owner,
},
},
targets: []platform.ScraperTarget{
{
Name: "name1",
@ -122,7 +135,8 @@ func AddTarget(
{
name: "create target with invalid org id",
fields: TargetFields{
IDGenerator: mock.NewIDGenerator(targetTwoID, t),
IDGenerator: mock.NewIDGenerator(targetTwoID, t),
UserResourceMappings: []*platform.UserResourceMapping{},
Targets: []*platform.ScraperTarget{
{
Name: "name1",
@ -149,6 +163,7 @@ func AddTarget(
Msg: "org id is invalid",
Op: platform.OpAddTarget,
},
userResourceMappings: []*platform.UserResourceMapping{},
targets: []platform.ScraperTarget{
{
Name: "name1",
@ -164,7 +179,8 @@ func AddTarget(
{
name: "create target with invalid bucket id",
fields: TargetFields{
IDGenerator: mock.NewIDGenerator(targetTwoID, t),
IDGenerator: mock.NewIDGenerator(targetTwoID, t),
UserResourceMappings: []*platform.UserResourceMapping{},
Targets: []*platform.ScraperTarget{
{
Name: "name1",
@ -191,6 +207,7 @@ func AddTarget(
Msg: "bucket id is invalid",
Op: platform.OpAddTarget,
},
userResourceMappings: []*platform.UserResourceMapping{},
targets: []platform.ScraperTarget{
{
Name: "name1",
@ -217,8 +234,17 @@ func AddTarget(
ID: MustIDBase16(targetOneID),
},
},
UserResourceMappings: []*platform.UserResourceMapping{
{
ResourceID: MustIDBase16(targetOneID),
ResourceType: platform.ScraperResourceType,
UserID: MustIDBase16(threeID),
UserType: platform.Member,
},
},
},
args: args{
userID: MustIDBase16(threeID),
target: &platform.ScraperTarget{
ID: MustIDBase16(targetTwoID),
Name: "name2",
@ -229,6 +255,20 @@ func AddTarget(
},
},
wants: wants{
userResourceMappings: []*platform.UserResourceMapping{
{
ResourceID: MustIDBase16(oneID),
ResourceType: platform.ScraperResourceType,
UserID: MustIDBase16(threeID),
UserType: platform.Member,
},
{
ResourceID: MustIDBase16(twoID),
ResourceType: platform.ScraperResourceType,
UserID: MustIDBase16(threeID),
UserType: platform.Owner,
},
},
targets: []platform.ScraperTarget{
{
Name: "name1",
@ -255,7 +295,7 @@ func AddTarget(
s, opPrefix, done := init(tt.fields, t)
defer done()
ctx := context.Background()
err := s.AddTarget(ctx, tt.args.target)
err := s.AddTarget(ctx, tt.args.target, tt.args.userID)
diffPlatformErrors(tt.name, err, tt.wants.err, opPrefix, t)
defer s.RemoveTarget(ctx, tt.args.target.ID)
@ -266,6 +306,16 @@ func AddTarget(
if diff := cmp.Diff(targets, tt.wants.targets, targetCmpOptions...); diff != "" {
t.Errorf("scraper targets are different -got/+want\ndiff %s", diff)
}
urms, _, err := s.FindUserResourceMappings(ctx, platform.UserResourceMappingFilter{
UserID: tt.args.userID,
ResourceType: platform.ScraperResourceType,
})
if err != nil {
t.Fatalf("failed to retrieve user resource mappings: %v", err)
}
if diff := cmp.Diff(urms, tt.wants.userResourceMappings, userResourceMappingCmpOptions...); diff != "" {
t.Errorf("user resource mappings are different -got/+want\ndiff %s", diff)
}
})
}
@ -446,11 +496,13 @@ func GetTargetByID(
func RemoveTarget(init func(TargetFields, *testing.T) (platform.ScraperTargetStoreService, string, func()),
t *testing.T) {
type args struct {
ID platform.ID
ID platform.ID
userID platform.ID
}
type wants struct {
err error
targets []platform.ScraperTarget
err error
userResourceMappings []*platform.UserResourceMapping
targets []platform.ScraperTarget
}
tests := []struct {
name string
@ -461,6 +513,20 @@ func RemoveTarget(init func(TargetFields, *testing.T) (platform.ScraperTargetSto
{
name: "delete targets using exist id",
fields: TargetFields{
UserResourceMappings: []*platform.UserResourceMapping{
{
ResourceID: MustIDBase16(oneID),
UserID: MustIDBase16(threeID),
UserType: platform.Owner,
ResourceType: platform.ScraperResourceType,
},
{
ResourceID: MustIDBase16(twoID),
UserID: MustIDBase16(threeID),
UserType: platform.Member,
ResourceType: platform.ScraperResourceType,
},
},
Targets: []*platform.ScraperTarget{
{
ID: MustIDBase16(targetOneID),
@ -475,9 +541,18 @@ func RemoveTarget(init func(TargetFields, *testing.T) (platform.ScraperTargetSto
},
},
args: args{
ID: MustIDBase16(targetOneID),
ID: MustIDBase16(targetOneID),
userID: MustIDBase16(threeID),
},
wants: wants{
userResourceMappings: []*platform.UserResourceMapping{
{
ResourceID: MustIDBase16(twoID),
UserID: MustIDBase16(threeID),
UserType: platform.Member,
ResourceType: platform.ScraperResourceType,
},
},
targets: []platform.ScraperTarget{
{
ID: MustIDBase16(targetTwoID),
@ -490,6 +565,20 @@ func RemoveTarget(init func(TargetFields, *testing.T) (platform.ScraperTargetSto
{
name: "delete targets using id that does not exist",
fields: TargetFields{
UserResourceMappings: []*platform.UserResourceMapping{
{
ResourceID: MustIDBase16(oneID),
UserID: MustIDBase16(threeID),
UserType: platform.Owner,
ResourceType: platform.ScraperResourceType,
},
{
ResourceID: MustIDBase16(twoID),
UserID: MustIDBase16(threeID),
UserType: platform.Member,
ResourceType: platform.ScraperResourceType,
},
},
Targets: []*platform.ScraperTarget{
{
ID: MustIDBase16(targetOneID),
@ -504,7 +593,8 @@ func RemoveTarget(init func(TargetFields, *testing.T) (platform.ScraperTargetSto
},
},
args: args{
ID: MustIDBase16(targetThreeID),
ID: MustIDBase16(targetThreeID),
userID: MustIDBase16(threeID),
},
wants: wants{
err: &platform.Error{
@ -524,6 +614,20 @@ func RemoveTarget(init func(TargetFields, *testing.T) (platform.ScraperTargetSto
BucketID: MustIDBase16(bucketOneID),
},
},
userResourceMappings: []*platform.UserResourceMapping{
{
ResourceID: MustIDBase16(oneID),
UserID: MustIDBase16(threeID),
UserType: platform.Owner,
ResourceType: platform.ScraperResourceType,
},
{
ResourceID: MustIDBase16(twoID),
UserID: MustIDBase16(threeID),
UserType: platform.Member,
ResourceType: platform.ScraperResourceType,
},
},
},
},
}
@ -542,6 +646,16 @@ func RemoveTarget(init func(TargetFields, *testing.T) (platform.ScraperTargetSto
if diff := cmp.Diff(targets, tt.wants.targets, targetCmpOptions...); diff != "" {
t.Errorf("targets are different -got/+want\ndiff %s", diff)
}
urms, _, err := s.FindUserResourceMappings(ctx, platform.UserResourceMappingFilter{
UserID: tt.args.userID,
ResourceType: platform.ScraperResourceType,
})
if err != nil {
t.Fatalf("failed to retrieve user resource mappings: %v", err)
}
if diff := cmp.Diff(urms, tt.wants.userResourceMappings, userResourceMappingCmpOptions...); diff != "" {
t.Errorf("user resource mappings are different -got/+want\ndiff %s", diff)
}
})
}
}
@ -552,8 +666,9 @@ func UpdateTarget(
t *testing.T,
) {
type args struct {
url string
id platform.ID
url string
userID platform.ID
id platform.ID
}
type wants struct {
err error
@ -669,7 +784,7 @@ func UpdateTarget(
URL: tt.args.url,
}
target, err := s.UpdateTarget(ctx, upd)
target, err := s.UpdateTarget(ctx, upd, tt.args.userID)
diffPlatformErrors(tt.name, err, tt.wants.err, opPrefix, t)
if diff := cmp.Diff(target, tt.wants.target, targetCmpOptions...); diff != "" {