diff --git a/cmd/influxd/launcher/launcher.go b/cmd/influxd/launcher/launcher.go index b7aa2f2746a..f4a33ffd961 100644 --- a/cmd/influxd/launcher/launcher.go +++ b/cmd/influxd/launcher/launcher.go @@ -24,7 +24,6 @@ import ( "github.com/influxdata/influxdb/v2/chronograf/server" "github.com/influxdata/influxdb/v2/cmd/influxd/inspect" "github.com/influxdata/influxdb/v2/dbrp" - "github.com/influxdata/influxdb/v2/endpoints" "github.com/influxdata/influxdb/v2/gather" "github.com/influxdata/influxdb/v2/http" iqlcontrol "github.com/influxdata/influxdb/v2/influxql/control" @@ -46,6 +45,7 @@ import ( "github.com/influxdata/influxdb/v2/label" influxlogger "github.com/influxdata/influxdb/v2/logger" "github.com/influxdata/influxdb/v2/nats" + endpointservice "github.com/influxdata/influxdb/v2/notification/endpoint/service" ruleservice "github.com/influxdata/influxdb/v2/notification/rule/service" "github.com/influxdata/influxdb/v2/pkger" infprom "github.com/influxdata/influxdb/v2/prometheus" @@ -759,17 +759,16 @@ func (m *Launcher) run(ctx context.Context) (err error) { m.reg.MustRegister(m.boltClient) var ( - variableSvc platform.VariableService = m.kvService - sourceSvc platform.SourceService = m.kvService - dashboardSvc platform.DashboardService = m.kvService - dashboardLogSvc platform.DashboardOperationLogService = m.kvService - userLogSvc platform.UserOperationLogService = m.kvService - bucketLogSvc platform.BucketOperationLogService = m.kvService - orgLogSvc platform.OrganizationOperationLogService = m.kvService - scraperTargetSvc platform.ScraperTargetStoreService = m.kvService - telegrafSvc platform.TelegrafConfigStore = m.kvService - lookupSvc platform.LookupService = m.kvService - notificationEndpointStore platform.NotificationEndpointService = m.kvService + variableSvc platform.VariableService = m.kvService + sourceSvc platform.SourceService = m.kvService + dashboardSvc platform.DashboardService = m.kvService + dashboardLogSvc platform.DashboardOperationLogService = m.kvService + userLogSvc platform.UserOperationLogService = m.kvService + bucketLogSvc platform.BucketOperationLogService = m.kvService + orgLogSvc platform.OrganizationOperationLogService = m.kvService + scraperTargetSvc platform.ScraperTargetStoreService = m.kvService + telegrafSvc platform.TelegrafConfigStore = m.kvService + lookupSvc platform.LookupService = m.kvService ) tenantStore := tenant.NewStore(m.kvStore) @@ -988,10 +987,15 @@ func (m *Launcher) run(ctx context.Context) (err error) { checkSvc = middleware.NewCheckService(checkSvc, m.kvService, coordinator) } + var notificationEndpointSvc platform.NotificationEndpointService + { + notificationEndpointSvc = endpointservice.New(endpointservice.NewStore(m.kvStore), secretSvc) + } + var notificationRuleSvc platform.NotificationRuleStore { coordinator := coordinator.NewCoordinator(m.log, m.scheduler, m.executor) - notificationRuleSvc, err = ruleservice.NewRuleService(m.log, m.kvStore, m.kvService, ts.OrganizationService, m.kvService) + notificationRuleSvc, err = ruleservice.New(m.log, m.kvStore, m.kvService, ts.OrganizationService, notificationEndpointSvc) if err != nil { return err } @@ -1145,7 +1149,7 @@ func (m *Launcher) run(ctx context.Context) (err error) { VariableFinder: variableSvc, TargetFinder: scraperTargetSvc, CheckFinder: checkSvc, - NotificationEndpointFinder: notificationEndpointStore, + NotificationEndpointFinder: notificationEndpointSvc, NotificationRuleFinder: notificationRuleSvc, } @@ -1190,7 +1194,7 @@ func (m *Launcher) run(ctx context.Context) (err error) { TaskService: taskSvc, TelegrafService: telegrafSvc, NotificationRuleStore: notificationRuleSvc, - NotificationEndpointService: endpoints.NewService(notificationEndpointStore, secretSvc, ts.UserResourceMappingService, ts.OrganizationService), + NotificationEndpointService: notificationEndpointSvc, CheckService: checkSvc, ScraperTargetStoreService: scraperTargetSvc, ChronografService: chronografSvc, diff --git a/http/notification_endpoint.go b/http/notification_endpoint.go index a1165b14088..d426bb83a1d 100644 --- a/http/notification_endpoint.go +++ b/http/notification_endpoint.go @@ -26,7 +26,6 @@ type NotificationEndpointBackend struct { UserResourceMappingService influxdb.UserResourceMappingService LabelService influxdb.LabelService UserService influxdb.UserService - OrganizationService influxdb.OrganizationService } // NewNotificationEndpointBackend returns a new instance of NotificationEndpointBackend. @@ -38,7 +37,6 @@ func NewNotificationEndpointBackend(log *zap.Logger, b *APIBackend) *Notificatio UserResourceMappingService: b.UserResourceMappingService, LabelService: b.LabelService, UserService: b.UserService, - OrganizationService: b.OrganizationService, } } @@ -56,7 +54,6 @@ type NotificationEndpointHandler struct { UserResourceMappingService influxdb.UserResourceMappingService LabelService influxdb.LabelService UserService influxdb.UserService - OrganizationService influxdb.OrganizationService } const ( @@ -81,7 +78,6 @@ func NewNotificationEndpointHandler(log *zap.Logger, b *NotificationEndpointBack UserResourceMappingService: b.UserResourceMappingService, LabelService: b.LabelService, UserService: b.UserService, - OrganizationService: b.OrganizationService, } h.HandlerFunc("POST", prefixNotificationEndpoints, h.handlePostNotificationEndpoint) h.HandlerFunc("GET", prefixNotificationEndpoints, h.handleGetNotificationEndpoints) @@ -551,20 +547,12 @@ func (h *NotificationEndpointHandler) handleDeleteNotificationEndpoint(w http.Re // NotificationEndpointService is an http client for the influxdb.NotificationEndpointService server implementation. type NotificationEndpointService struct { Client *httpc.Client - *UserResourceMappingService - *OrganizationService } // NewNotificationEndpointService constructs a new http NotificationEndpointService. func NewNotificationEndpointService(client *httpc.Client) *NotificationEndpointService { return &NotificationEndpointService{ Client: client, - UserResourceMappingService: &UserResourceMappingService{ - Client: client, - }, - OrganizationService: &OrganizationService{ - Client: client, - }, } } diff --git a/http/notification_endpoint_test.go b/http/notification_endpoint_test.go index c803accc906..4aa5cbe4e5a 100644 --- a/http/notification_endpoint_test.go +++ b/http/notification_endpoint_test.go @@ -18,7 +18,10 @@ import ( "github.com/influxdata/influxdb/v2/kv" "github.com/influxdata/influxdb/v2/mock" "github.com/influxdata/influxdb/v2/notification/endpoint" + "github.com/influxdata/influxdb/v2/notification/endpoint/service" + endpointTesting "github.com/influxdata/influxdb/v2/notification/endpoint/service/testing" "github.com/influxdata/influxdb/v2/pkg/testttp" + "github.com/influxdata/influxdb/v2/tenant" influxTesting "github.com/influxdata/influxdb/v2/testing" "go.uber.org/zap/zaptest" ) @@ -32,7 +35,6 @@ func NewMockNotificationEndpointBackend(t *testing.T) *NotificationEndpointBacke UserResourceMappingService: mock.NewUserResourceMappingService(), LabelService: mock.NewLabelService(), UserService: mock.NewUserService(), - OrganizationService: mock.NewOrganizationService(), } } @@ -489,7 +491,6 @@ func TestService_handlePostNotificationEndpoint(t *testing.T) { t.Run(tt.name, func(t *testing.T) { notificationEndpointBackend := NewMockNotificationEndpointBackend(t) notificationEndpointBackend.NotificationEndpointService = tt.fields.NotificationEndpointService - notificationEndpointBackend.OrganizationService = tt.fields.OrganizationService testttp. PostJSON(t, prefixNotificationEndpoints, tt.args.endpoint). @@ -1060,37 +1061,40 @@ func TestService_handlePostNotificationEndpointOwner(t *testing.T) { } } -func initNotificationEndpointService(f influxTesting.NotificationEndpointFields, t *testing.T) (influxdb.NotificationEndpointService, influxdb.SecretService, func()) { +func initNotificationEndpointService(f endpointTesting.NotificationEndpointFields, t *testing.T) (influxdb.NotificationEndpointService, influxdb.SecretService, func()) { ctx := context.Background() store := NewTestInmemStore(t) logger := zaptest.NewLogger(t) - svc := kv.NewService(logger, store) - svc.IDGenerator = f.IDGenerator - svc.TimeGenerator = f.TimeGenerator - - for _, v := range f.Orgs { - if err := svc.PutOrganization(ctx, v); err != nil { - t.Fatalf("failed to replace org: %v", err) - } - } - - for _, m := range f.UserResourceMappings { - if err := svc.CreateUserResourceMapping(ctx, m); err != nil { - t.Fatalf("failed to populate user resource mapping: %v", err) - } + kvSvc := kv.NewService(logger, store) + kvSvc.IDGenerator = f.IDGenerator + kvSvc.TimeGenerator = f.TimeGenerator + + endpointStore := service.NewStore(store) + endpointStore.IDGenerator = f.IDGenerator + endpointStore.TimeGenerator = f.TimeGenerator + endpointService := service.New(endpointStore, kvSvc) + + tenantStore := tenant.NewStore(store) + tenantService := tenant.NewService(tenantStore) + + for _, o := range f.Orgs { + withOrgID(tenantStore, o.ID, func() { + if err := tenantService.CreateOrganization(ctx, o); err != nil { + t.Fatalf("failed to populate org: %v", err) + } + }) } for _, v := range f.NotificationEndpoints { - if err := svc.PutNotificationEndpoint(ctx, v); err != nil { + if err := endpointStore.PutNotificationEndpoint(ctx, v); err != nil { t.Fatalf("failed to update endpoint: %v", err) } } fakeBackend := NewMockNotificationEndpointBackend(t) - fakeBackend.NotificationEndpointService = svc - fakeBackend.UserService = svc - fakeBackend.UserResourceMappingService = svc - fakeBackend.OrganizationService = svc + fakeBackend.NotificationEndpointService = endpointService + fakeBackend.UserResourceMappingService = tenantService + fakeBackend.UserService = tenantService handler := NewNotificationEndpointHandler(zaptest.NewLogger(t), fakeBackend) auth := func(next http.Handler) http.HandlerFunc { @@ -1103,7 +1107,7 @@ func initNotificationEndpointService(f influxTesting.NotificationEndpointFields, done := server.Close client := mustNewHTTPClient(t, server.URL, "") - return NewNotificationEndpointService(client), svc, done + return NewNotificationEndpointService(client), kvSvc, done } func TestNotificationEndpointService(t *testing.T) { @@ -1111,11 +1115,11 @@ func TestNotificationEndpointService(t *testing.T) { tests := []struct { name string - testFn func(init func(influxTesting.NotificationEndpointFields, *testing.T) (influxdb.NotificationEndpointService, influxdb.SecretService, func()), t *testing.T) + testFn func(init func(endpointTesting.NotificationEndpointFields, *testing.T) (influxdb.NotificationEndpointService, influxdb.SecretService, func()), t *testing.T) }{ { name: "CreateNotificationEndpoint", - testFn: influxTesting.CreateNotificationEndpoint, + testFn: endpointTesting.CreateNotificationEndpoint, }, } @@ -1131,3 +1135,12 @@ func authCtxFn(userID influxdb.ID) func(context.Context) context.Context { return pcontext.SetAuthorizer(ctx, &influxdb.Session{UserID: userID}) } } + +func withOrgID(store *tenant.Store, orgID influxdb.ID, fn func()) { + backup := store.OrgIDGen + defer func() { store.OrgIDGen = backup }() + + store.OrgIDGen = mock.NewStaticIDGenerator(orgID) + + fn() +} diff --git a/kv/check_test.go b/kv/check_test.go index daac631da32..5c3e50fd6de 100644 --- a/kv/check_test.go +++ b/kv/check_test.go @@ -6,7 +6,9 @@ import ( "github.com/influxdata/influxdb/v2" "github.com/influxdata/influxdb/v2/kv" + "github.com/influxdata/influxdb/v2/mock" "github.com/influxdata/influxdb/v2/query/fluxlang" + "github.com/influxdata/influxdb/v2/tenant" influxdbtesting "github.com/influxdata/influxdb/v2/testing" "go.uber.org/zap/zaptest" ) @@ -15,20 +17,20 @@ func TestBoltCheckService(t *testing.T) { influxdbtesting.CheckService(initBoltCheckService, t) } -func initBoltCheckService(f influxdbtesting.CheckFields, t *testing.T) (influxdb.CheckService, *kv.Service, string, func()) { +func initBoltCheckService(f influxdbtesting.CheckFields, t *testing.T) (influxdb.CheckService, influxdb.UserResourceMappingService, string, func()) { s, closeBolt, err := NewTestBoltStore(t) if err != nil { t.Fatalf("failed to create new kv store: %v", err) } - svc, op, closeSvc := initCheckService(s, f, t) - return svc, svc, op, func() { + svc, urmSvc, op, closeSvc := initCheckService(s, f, t) + return svc, urmSvc, op, func() { closeSvc() closeBolt() } } -func initCheckService(s kv.SchemaStore, f influxdbtesting.CheckFields, t *testing.T) (*kv.Service, string, func()) { +func initCheckService(s kv.SchemaStore, f influxdbtesting.CheckFields, t *testing.T) (influxdb.CheckService, influxdb.UserResourceMappingService, string, func()) { ctx := context.Background() svc := kv.NewService(zaptest.NewLogger(t), s, kv.ServiceConfig{ FluxLanguageService: fluxlang.DefaultService, @@ -39,15 +41,20 @@ func initCheckService(s kv.SchemaStore, f influxdbtesting.CheckFields, t *testin svc.TimeGenerator = influxdb.RealTimeGenerator{} } + tenantStore := tenant.NewStore(s) + tenantSvc := tenant.NewService(tenantStore) + for _, m := range f.UserResourceMappings { - if err := svc.CreateUserResourceMapping(ctx, m); err != nil { + if err := tenantSvc.CreateUserResourceMapping(ctx, m); err != nil { t.Fatalf("failed to populate user resource mapping: %v", err) } } for _, o := range f.Organizations { - if err := svc.PutOrganization(ctx, o); err != nil { - t.Fatalf("failed to populate organizations") - } + withOrgID(tenantStore, o.ID, func() { + if err := tenantSvc.CreateOrganization(ctx, o); err != nil { + t.Fatalf("failed to populate org: %v", err) + } + }) } for _, c := range f.Checks { if err := svc.PutCheck(ctx, c); err != nil { @@ -59,14 +66,14 @@ func initCheckService(s kv.SchemaStore, f influxdbtesting.CheckFields, t *testin t.Fatalf("failed to populate tasks: %v", err) } } - return svc, kv.OpPrefix, func() { + return svc, tenantSvc, kv.OpPrefix, func() { for _, o := range f.Organizations { - if err := svc.DeleteOrganization(ctx, o.ID); err != nil { + if err := tenantSvc.DeleteOrganization(ctx, o.ID); err != nil { t.Logf("failed to remove organization: %v", err) } } for _, urm := range f.UserResourceMappings { - if err := svc.DeleteUserResourceMapping(ctx, urm.ResourceID, urm.UserID); err != nil && influxdb.ErrorCode(err) != influxdb.ENotFound { + if err := tenantSvc.DeleteUserResourceMapping(ctx, urm.ResourceID, urm.UserID); err != nil && influxdb.ErrorCode(err) != influxdb.ENotFound { t.Logf("failed to remove urm rule: %v", err) } } @@ -77,3 +84,12 @@ func initCheckService(s kv.SchemaStore, f influxdbtesting.CheckFields, t *testin } } } + +func withOrgID(store *tenant.Store, orgID influxdb.ID, fn func()) { + backup := store.OrgIDGen + defer func() { store.OrgIDGen = backup }() + + store.OrgIDGen = mock.NewStaticIDGenerator(orgID) + + fn() +} diff --git a/kv/initial_migration.go b/kv/initial_migration.go index 17661be0908..c4c092208c8 100644 --- a/kv/initial_migration.go +++ b/kv/initial_migration.go @@ -56,8 +56,8 @@ func (m InitialMigration) Up(ctx context.Context, store SchemaStore) error { // store base backed services checkBucket, checkIndexBucket, - notificationEndpointBucket, - notificationEndpointIndexBucket, + []byte("notificationEndpointv1"), + []byte("notificationEndpointIndexv1"), variableBucket, variableIndexBucket, variableOrgsIndex, diff --git a/kv/notification_endpoint.go b/kv/notification_endpoint.go deleted file mode 100644 index 2bcb5288b2b..00000000000 --- a/kv/notification_endpoint.go +++ /dev/null @@ -1,334 +0,0 @@ -package kv - -import ( - "context" - - "github.com/influxdata/influxdb/v2" - "github.com/influxdata/influxdb/v2/kit/tracing" - "github.com/influxdata/influxdb/v2/notification/endpoint" -) - -var ( - // ErrNotificationEndpointNotFound is used when the notification endpoint is not found. - ErrNotificationEndpointNotFound = &influxdb.Error{ - Msg: "notification endpoint not found", - Code: influxdb.ENotFound, - } - - notificationEndpointBucket = []byte("notificationEndpointv1") - notificationEndpointIndexBucket = []byte("notificationEndpointIndexv1") -) - -var _ influxdb.NotificationEndpointService = (*Service)(nil) - -func newEndpointStore() *IndexStore { - const resource = "notification endpoint" - - var decEndpointEntFn DecodeBucketValFn = func(key, val []byte) ([]byte, interface{}, error) { - edp, err := endpoint.UnmarshalJSON(val) - return key, edp, err - } - - var decValToEntFn ConvertValToEntFn = func(_ []byte, v interface{}) (Entity, error) { - edp, ok := v.(influxdb.NotificationEndpoint) - if err := IsErrUnexpectedDecodeVal(ok); err != nil { - return Entity{}, err - } - return Entity{ - PK: EncID(edp.GetID()), - UniqueKey: Encode(EncID(edp.GetOrgID()), EncString(edp.GetName())), - Body: edp, - }, nil - } - - return &IndexStore{ - Resource: resource, - EntStore: NewStoreBase(resource, notificationEndpointBucket, EncIDKey, EncBodyJSON, decEndpointEntFn, decValToEntFn), - IndexStore: NewOrgNameKeyStore(resource, notificationEndpointIndexBucket, true), - } -} - -// CreateNotificationEndpoint creates a new notification endpoint and sets b.ID with the new identifier. -func (s *Service) CreateNotificationEndpoint(ctx context.Context, edp influxdb.NotificationEndpoint, userID influxdb.ID) error { - return s.kv.Update(ctx, func(tx Tx) error { - return s.createNotificationEndpoint(ctx, tx, edp, userID) - }) -} - -func (s *Service) createNotificationEndpoint(ctx context.Context, tx Tx, edp influxdb.NotificationEndpoint, userID influxdb.ID) error { - // TODO(jsteenb2): why is org id check not necesssary if orgID isn't valid... feels odd - if edp.GetOrgID().Valid() { - span, ctx := tracing.StartSpanFromContext(ctx) - // TODO(jsteenb2): this defer doesn't get called until the end of entire function, - // need to rip this out as is - defer span.Finish() - - if _, err := s.findOrganizationByID(ctx, tx, edp.GetOrgID()); err != nil { - return err - } - } - - id := s.IDGenerator.ID() - edp.SetID(id) - now := s.TimeGenerator.Now() - edp.SetCreatedAt(now) - edp.SetUpdatedAt(now) - edp.BackfillSecretKeys() - - if err := edp.Valid(); err != nil { - return err - } - - ent := Entity{ - PK: EncID(edp.GetID()), - UniqueKey: Encode(EncID(edp.GetOrgID()), EncString(edp.GetName())), - Body: edp, - } - if err := s.endpointStore.Put(ctx, tx, ent, PutNew()); err != nil { - return err - } - - urm := &influxdb.UserResourceMapping{ - ResourceID: edp.GetID(), - UserID: userID, - UserType: influxdb.Owner, - ResourceType: influxdb.NotificationEndpointResourceType, - } - return s.createUserResourceMapping(ctx, tx, urm) -} - -// UpdateNotificationEndpoint updates a single notification endpoint. -// Returns the new notification endpoint after update. -func (s *Service) UpdateNotificationEndpoint(ctx context.Context, id influxdb.ID, edp influxdb.NotificationEndpoint, userID influxdb.ID) (influxdb.NotificationEndpoint, error) { - var err error - err = s.kv.Update(ctx, func(tx Tx) error { - edp, err = s.updateNotificationEndpoint(ctx, tx, id, edp, userID) - return err - }) - return edp, err -} - -func (s *Service) updateNotificationEndpoint(ctx context.Context, tx Tx, id influxdb.ID, edp influxdb.NotificationEndpoint, userID influxdb.ID) (influxdb.NotificationEndpoint, error) { - current, err := s.findNotificationEndpointByID(ctx, tx, id) - if err != nil { - return nil, err - } - - // ID and OrganizationID can not be updated - edp.SetCreatedAt(current.GetCRUDLog().CreatedAt) - edp.SetUpdatedAt(s.TimeGenerator.Now()) - - if err := edp.Valid(); err != nil { - return nil, err - } - - ent := Entity{ - PK: EncID(edp.GetID()), - UniqueKey: Encode(EncID(edp.GetOrgID()), EncString(edp.GetName())), - Body: edp, - } - if err := s.endpointStore.Put(ctx, tx, ent, PutUpdate()); err != nil { - return nil, err - } - - return edp, nil -} - -// PatchNotificationEndpoint updates a single notification endpoint with changeset. -// Returns the new notification endpoint state after update. -func (s *Service) PatchNotificationEndpoint(ctx context.Context, id influxdb.ID, upd influxdb.NotificationEndpointUpdate) (influxdb.NotificationEndpoint, error) { - var edp influxdb.NotificationEndpoint - if err := s.kv.Update(ctx, func(tx Tx) (err error) { - edp, err = s.patchNotificationEndpoint(ctx, tx, id, upd) - if err != nil { - return err - } - return nil - }); err != nil { - return nil, err - } - - return edp, nil -} - -func (s *Service) patchNotificationEndpoint(ctx context.Context, tx Tx, id influxdb.ID, upd influxdb.NotificationEndpointUpdate) (influxdb.NotificationEndpoint, error) { - edp, err := s.findNotificationEndpointByID(ctx, tx, id) - if err != nil { - return nil, err - } - - if upd.Name != nil { - edp.SetName(*upd.Name) - } - if upd.Description != nil { - edp.SetDescription(*upd.Description) - } - if upd.Status != nil { - edp.SetStatus(*upd.Status) - } - edp.SetUpdatedAt(s.TimeGenerator.Now()) - - if err := edp.Valid(); err != nil { - return nil, err - } - - // TODO(jsteenb2): every above here moves into service layer - - ent := Entity{ - PK: EncID(edp.GetID()), - UniqueKey: Encode(EncID(edp.GetOrgID()), EncString(edp.GetName())), - Body: edp, - } - if err := s.endpointStore.Put(ctx, tx, ent, PutUpdate()); err != nil { - return nil, err - } - - return edp, nil -} - -// PutNotificationEndpoint put a notification endpoint to storage. -func (s *Service) PutNotificationEndpoint(ctx context.Context, edp influxdb.NotificationEndpoint) error { - // TODO(jsteenb2): all the stuffs before the update should be moved up into the - // service layer as well as all the id/time setting items - if err := edp.Valid(); err != nil { - return err - } - - return s.kv.Update(ctx, func(tx Tx) (err error) { - ent := Entity{ - PK: EncID(edp.GetID()), - UniqueKey: Encode(EncID(edp.GetOrgID()), EncString(edp.GetName())), - Body: edp, - } - return s.endpointStore.Put(ctx, tx, ent) - }) -} - -// FindNotificationEndpointByID returns a single notification endpoint by ID. -func (s *Service) FindNotificationEndpointByID(ctx context.Context, id influxdb.ID) (influxdb.NotificationEndpoint, error) { - var ( - edp influxdb.NotificationEndpoint - err error - ) - - err = s.kv.View(ctx, func(tx Tx) error { - edp, err = s.findNotificationEndpointByID(ctx, tx, id) - return err - }) - - return edp, err -} - -func (s *Service) findNotificationEndpointByID(ctx context.Context, tx Tx, id influxdb.ID) (influxdb.NotificationEndpoint, error) { - decodedEnt, err := s.endpointStore.FindEnt(ctx, tx, Entity{PK: EncID(id)}) - if err != nil { - return nil, err - } - edp, ok := decodedEnt.(influxdb.NotificationEndpoint) - return edp, IsErrUnexpectedDecodeVal(ok) -} - -// FindNotificationEndpoints returns a list of notification endpoints that match isNext and the total count of matching notification endpoints. -// Additional options provide pagination & sorting. -func (s *Service) FindNotificationEndpoints(ctx context.Context, filter influxdb.NotificationEndpointFilter, opt ...influxdb.FindOptions) (edps []influxdb.NotificationEndpoint, n int, err error) { - err = s.kv.View(ctx, func(tx Tx) error { - edps, n, err = s.findNotificationEndpoints(ctx, tx, filter, opt...) - return err - }) - return edps, n, err -} - -func (s *Service) findNotificationEndpoints(ctx context.Context, tx Tx, filter influxdb.NotificationEndpointFilter, opt ...influxdb.FindOptions) ([]influxdb.NotificationEndpoint, int, error) { - m, err := s.findUserResourceMappings(ctx, tx, filter.UserResourceMappingFilter) - if err != nil { - return nil, 0, err - } - - if len(m) == 0 { - return []influxdb.NotificationEndpoint{}, 0, nil - } - - idMap := make(map[influxdb.ID]bool) - for _, item := range m { - idMap[item.ResourceID] = true - } - - if filter.Org != nil { - o, err := s.findOrganizationByName(ctx, tx, *filter.Org) - if err != nil { - return nil, 0, &influxdb.Error{ - Err: err, - } - } - filter.OrgID = &o.ID - } - - var o influxdb.FindOptions - if len(opt) > 0 { - o = opt[0] - } - - edps := make([]influxdb.NotificationEndpoint, 0) - err = s.endpointStore.Find(ctx, tx, FindOpts{ - Descending: o.Descending, - Offset: o.Offset, - Limit: o.Limit, - FilterEntFn: filterEndpointsFn(idMap, filter), - CaptureFn: func(k []byte, v interface{}) error { - edp, ok := v.(influxdb.NotificationEndpoint) - if err := IsErrUnexpectedDecodeVal(ok); err != nil { - return err - } - edps = append(edps, edp) - return nil - }, - }) - if err != nil { - return nil, 0, err - } - - return edps, len(edps), err -} - -func filterEndpointsFn(idMap map[influxdb.ID]bool, filter influxdb.NotificationEndpointFilter) func([]byte, interface{}) bool { - return func(key []byte, val interface{}) bool { - edp := val.(influxdb.NotificationEndpoint) - if filter.ID != nil && edp.GetID() != *filter.ID { - return false - } - - if filter.OrgID != nil && edp.GetOrgID() != *filter.OrgID { - return false - } - - if idMap == nil { - return true - } - return idMap[edp.GetID()] - } -} - -// DeleteNotificationEndpoint removes a notification endpoint by ID. -func (s *Service) DeleteNotificationEndpoint(ctx context.Context, id influxdb.ID) (flds []influxdb.SecretField, orgID influxdb.ID, err error) { - err = s.kv.Update(ctx, func(tx Tx) error { - flds, orgID, err = s.deleteNotificationEndpoint(ctx, tx, id) - return err - }) - return flds, orgID, err -} - -func (s *Service) deleteNotificationEndpoint(ctx context.Context, tx Tx, id influxdb.ID) (flds []influxdb.SecretField, orgID influxdb.ID, err error) { - edp, err := s.findNotificationEndpointByID(ctx, tx, id) - if err != nil { - return nil, 0, err - } - - if err := s.endpointStore.DeleteEnt(ctx, tx, Entity{PK: EncID(id)}); err != nil { - return nil, 0, err - } - - return edp.SecretFields(), edp.GetOrgID(), s.deleteUserResourceMappings(ctx, tx, influxdb.UserResourceMappingFilter{ - ResourceID: id, - ResourceType: influxdb.NotificationEndpointResourceType, - }) -} diff --git a/kv/notification_endpoint_test.go b/kv/notification_endpoint_test.go deleted file mode 100644 index 96c3f8842c8..00000000000 --- a/kv/notification_endpoint_test.go +++ /dev/null @@ -1,77 +0,0 @@ -package kv_test - -import ( - "context" - "testing" - - "github.com/influxdata/influxdb/v2" - "github.com/influxdata/influxdb/v2/endpoints" - "github.com/influxdata/influxdb/v2/kv" - influxdbtesting "github.com/influxdata/influxdb/v2/testing" - "go.uber.org/zap/zaptest" -) - -func TestNotificationEndpointService(t *testing.T) { - influxdbtesting.NotificationEndpointService(initBoltNotificationEndpointService, t) -} - -func initBoltNotificationEndpointService(f influxdbtesting.NotificationEndpointFields, t *testing.T) (influxdb.NotificationEndpointService, influxdb.SecretService, func()) { - store, closeBolt, err := NewTestBoltStore(t) - if err != nil { - t.Fatalf("failed to create new kv store: %v", err) - } - - svc, secretSVC, closeSvc := initNotificationEndpointService(store, f, t) - return svc, secretSVC, func() { - closeSvc() - closeBolt() - } -} - -func initNotificationEndpointService(s kv.SchemaStore, f influxdbtesting.NotificationEndpointFields, t *testing.T) (influxdb.NotificationEndpointService, influxdb.SecretService, func()) { - ctx := context.Background() - svc := kv.NewService(zaptest.NewLogger(t), s) - svc.IDGenerator = f.IDGenerator - svc.TimeGenerator = f.TimeGenerator - if f.TimeGenerator == nil { - svc.TimeGenerator = influxdb.RealTimeGenerator{} - } - - for _, edp := range f.NotificationEndpoints { - if err := svc.PutNotificationEndpoint(ctx, edp); err != nil { - t.Fatalf("failed to populate notification endpoint: %v", err) - } - } - - for _, o := range f.Orgs { - if err := svc.PutOrganization(ctx, o); err != nil { - t.Fatalf("failed to populate org: %v", err) - } - } - - for _, m := range f.UserResourceMappings { - if err := svc.CreateUserResourceMapping(ctx, m); err != nil { - t.Fatalf("failed to populate user resource mapping: %v", err) - } - } - - endpointSVC := endpoints.NewService(svc, svc, svc, svc) - return endpointSVC, svc, func() { - for _, edp := range f.NotificationEndpoints { - if _, _, err := svc.DeleteNotificationEndpoint(ctx, edp.GetID()); err != nil && err != kv.ErrNotificationEndpointNotFound { - t.Logf("failed to remove notification endpoint: %v", err) - } - } - for _, o := range f.Orgs { - if err := svc.DeleteOrganization(ctx, o.ID); err != nil { - t.Fatalf("failed to remove org: %v", err) - } - } - - for _, urm := range f.UserResourceMappings { - if err := svc.DeleteUserResourceMapping(ctx, urm.ResourceID, urm.UserID); err != nil && influxdb.ErrorCode(err) != influxdb.ENotFound { - t.Logf("failed to remove urm rule: %v", err) - } - } - } -} diff --git a/kv/service.go b/kv/service.go index 9a7cd63f793..5829df96465 100644 --- a/kv/service.go +++ b/kv/service.go @@ -45,7 +45,6 @@ type Service struct { Hash Crypt checkStore *IndexStore - endpointStore *IndexStore variableStore *IndexStore urmByUserIndex *Index @@ -65,7 +64,6 @@ func NewService(log *zap.Logger, kv Store, configs ...ServiceConfig) *Service { audit: noop.ResourceLogger{}, TimeGenerator: influxdb.RealTimeGenerator{}, checkStore: newCheckStore(), - endpointStore: newEndpointStore(), variableStore: newVariableStore(), urmByUserIndex: NewIndex(URMByUserIndexMapping, WithIndexReadPathEnabled), } diff --git a/notification/endpoint/endpoint_test.go b/notification/endpoint/endpoint_test.go index db16e9130fb..ea94df19e53 100644 --- a/notification/endpoint/endpoint_test.go +++ b/notification/endpoint/endpoint_test.go @@ -16,18 +16,21 @@ import ( influxTesting "github.com/influxdata/influxdb/v2/testing" ) -const ( - id1 = "020f755c3c082000" - id3 = "020f755c3c082002" -) +var ( + id1 = influxTesting.MustIDBase16Ptr("020f755c3c082000") + id3 = influxTesting.MustIDBase16Ptr("020f755c3c082002") -var goodBase = endpoint.Base{ - ID: influxTesting.MustIDBase16Ptr(id1), - Name: "name1", - OrgID: influxTesting.MustIDBase16Ptr(id3), - Status: influxdb.Active, - Description: "desc1", -} + timeGen1 = mock.TimeGenerator{FakeValue: time.Date(2006, time.July, 13, 4, 19, 10, 0, time.UTC)} + timeGen2 = mock.TimeGenerator{FakeValue: time.Date(2006, time.July, 14, 5, 23, 53, 10, time.UTC)} + + goodBase = endpoint.Base{ + ID: id1, + Name: "name1", + OrgID: id3, + Status: influxdb.Active, + Description: "desc1", + } +) func TestValidEndpoint(t *testing.T) { cases := []struct { @@ -48,9 +51,9 @@ func TestValidEndpoint(t *testing.T) { name: "invalid status", src: &endpoint.PagerDuty{ Base: endpoint.Base{ - ID: influxTesting.MustIDBase16Ptr(id1), + ID: id1, Name: "name1", - OrgID: influxTesting.MustIDBase16Ptr(id3), + OrgID: id3, }, }, err: &influxdb.Error{ @@ -62,12 +65,12 @@ func TestValidEndpoint(t *testing.T) { name: "empty name PagerDuty", src: &endpoint.PagerDuty{ Base: endpoint.Base{ - ID: influxTesting.MustIDBase16Ptr(id1), - OrgID: influxTesting.MustIDBase16Ptr(id3), + ID: id1, + OrgID: id3, Status: influxdb.Active, }, ClientURL: "https://events.pagerduty.com/v2/enqueue", - RoutingKey: influxdb.SecretField{Key: id1 + "-routing-key"}, + RoutingKey: influxdb.SecretField{Key: id1.String() + "-routing-key"}, }, err: &influxdb.Error{ Code: influxdb.EInvalid, @@ -78,11 +81,11 @@ func TestValidEndpoint(t *testing.T) { name: "empty name Telegram", src: &endpoint.Telegram{ Base: endpoint.Base{ - ID: influxTesting.MustIDBase16Ptr(id1), - OrgID: influxTesting.MustIDBase16Ptr(id3), + ID: id1, + OrgID: id3, Status: influxdb.Active, }, - Token: influxdb.SecretField{Key: id1 + "-token"}, + Token: influxdb.SecretField{Key: id1.String() + "-token"}, Channel: "-1001406363649", }, err: &influxdb.Error{ @@ -177,7 +180,7 @@ func TestValidEndpoint(t *testing.T) { name: "empty telegram channel", src: &endpoint.Telegram{ Base: goodBase, - Token: influxdb.SecretField{Key: id1 + "-token"}, + Token: influxdb.SecretField{Key: id1.String() + "-token"}, }, err: &influxdb.Error{ Code: influxdb.EInvalid, @@ -188,7 +191,7 @@ func TestValidEndpoint(t *testing.T) { name: "valid telegram token", src: &endpoint.Telegram{ Base: goodBase, - Token: influxdb.SecretField{Key: id1 + "-token"}, + Token: influxdb.SecretField{Key: id1.String() + "-token"}, Channel: "-1001406363649", }, err: nil, @@ -208,9 +211,6 @@ func TestValidEndpoint(t *testing.T) { } } -var timeGen1 = mock.TimeGenerator{FakeValue: time.Date(2006, time.July, 13, 4, 19, 10, 0, time.UTC)} -var timeGen2 = mock.TimeGenerator{FakeValue: time.Date(2006, time.July, 14, 5, 23, 53, 10, time.UTC)} - func TestJSON(t *testing.T) { cases := []struct { name string @@ -220,9 +220,9 @@ func TestJSON(t *testing.T) { name: "simple Slack", src: &endpoint.Slack{ Base: endpoint.Base{ - ID: influxTesting.MustIDBase16Ptr(id1), + ID: id1, Name: "name1", - OrgID: influxTesting.MustIDBase16Ptr(id3), + OrgID: id3, Status: influxdb.Active, CRUDLog: influxdb.CRUDLog{ CreatedAt: timeGen1.Now(), @@ -237,9 +237,9 @@ func TestJSON(t *testing.T) { name: "Slack without token", src: &endpoint.Slack{ Base: endpoint.Base{ - ID: influxTesting.MustIDBase16Ptr(id1), + ID: id1, Name: "name1", - OrgID: influxTesting.MustIDBase16Ptr(id3), + OrgID: id3, Status: influxdb.Active, CRUDLog: influxdb.CRUDLog{ CreatedAt: timeGen1.Now(), @@ -253,9 +253,9 @@ func TestJSON(t *testing.T) { name: "simple pagerduty", src: &endpoint.PagerDuty{ Base: endpoint.Base{ - ID: influxTesting.MustIDBase16Ptr(id1), + ID: id1, Name: "name1", - OrgID: influxTesting.MustIDBase16Ptr(id3), + OrgID: id3, Status: influxdb.Active, CRUDLog: influxdb.CRUDLog{ CreatedAt: timeGen1.Now(), @@ -270,9 +270,9 @@ func TestJSON(t *testing.T) { name: "simple http", src: &endpoint.HTTP{ Base: endpoint.Base{ - ID: influxTesting.MustIDBase16Ptr(id1), + ID: id1, Name: "name1", - OrgID: influxTesting.MustIDBase16Ptr(id3), + OrgID: id3, Status: influxdb.Active, CRUDLog: influxdb.CRUDLog{ CreatedAt: timeGen1.Now(), @@ -293,9 +293,9 @@ func TestJSON(t *testing.T) { name: "simple Telegram", src: &endpoint.Telegram{ Base: endpoint.Base{ - ID: influxTesting.MustIDBase16Ptr(id1), + ID: id1, Name: "nameTelegram", - OrgID: influxTesting.MustIDBase16Ptr(id3), + OrgID: id3, Status: influxdb.Active, CRUDLog: influxdb.CRUDLog{ CreatedAt: timeGen1.Now(), @@ -331,9 +331,9 @@ func TestBackFill(t *testing.T) { name: "simple Slack", src: &endpoint.Slack{ Base: endpoint.Base{ - ID: influxTesting.MustIDBase16Ptr(id1), + ID: id1, Name: "name1", - OrgID: influxTesting.MustIDBase16Ptr(id3), + OrgID: id3, Status: influxdb.Active, CRUDLog: influxdb.CRUDLog{ CreatedAt: timeGen1.Now(), @@ -347,9 +347,9 @@ func TestBackFill(t *testing.T) { }, target: &endpoint.Slack{ Base: endpoint.Base{ - ID: influxTesting.MustIDBase16Ptr(id1), + ID: id1, Name: "name1", - OrgID: influxTesting.MustIDBase16Ptr(id3), + OrgID: id3, Status: influxdb.Active, CRUDLog: influxdb.CRUDLog{ CreatedAt: timeGen1.Now(), @@ -358,7 +358,7 @@ func TestBackFill(t *testing.T) { }, URL: "https://slack.com/api/chat.postMessage", Token: influxdb.SecretField{ - Key: id1 + "-token", + Key: id1.String() + "-token", Value: strPtr("token-value"), }, }, @@ -367,9 +367,9 @@ func TestBackFill(t *testing.T) { name: "simple pagerduty", src: &endpoint.PagerDuty{ Base: endpoint.Base{ - ID: influxTesting.MustIDBase16Ptr(id1), + ID: id1, Name: "name1", - OrgID: influxTesting.MustIDBase16Ptr(id3), + OrgID: id3, Status: influxdb.Active, CRUDLog: influxdb.CRUDLog{ CreatedAt: timeGen1.Now(), @@ -383,9 +383,9 @@ func TestBackFill(t *testing.T) { }, target: &endpoint.PagerDuty{ Base: endpoint.Base{ - ID: influxTesting.MustIDBase16Ptr(id1), + ID: id1, Name: "name1", - OrgID: influxTesting.MustIDBase16Ptr(id3), + OrgID: id3, Status: influxdb.Active, CRUDLog: influxdb.CRUDLog{ CreatedAt: timeGen1.Now(), @@ -394,7 +394,7 @@ func TestBackFill(t *testing.T) { }, ClientURL: "https://events.pagerduty.com/v2/enqueue", RoutingKey: influxdb.SecretField{ - Key: id1 + "-routing-key", + Key: id1.String() + "-routing-key", Value: strPtr("routing-key-value"), }, }, @@ -403,9 +403,9 @@ func TestBackFill(t *testing.T) { name: "http with token", src: &endpoint.HTTP{ Base: endpoint.Base{ - ID: influxTesting.MustIDBase16Ptr(id1), + ID: id1, Name: "name1", - OrgID: influxTesting.MustIDBase16Ptr(id3), + OrgID: id3, Status: influxdb.Active, CRUDLog: influxdb.CRUDLog{ CreatedAt: timeGen1.Now(), @@ -423,9 +423,9 @@ func TestBackFill(t *testing.T) { }, target: &endpoint.HTTP{ Base: endpoint.Base{ - ID: influxTesting.MustIDBase16Ptr(id1), + ID: id1, Name: "name1", - OrgID: influxTesting.MustIDBase16Ptr(id3), + OrgID: id3, Status: influxdb.Active, CRUDLog: influxdb.CRUDLog{ CreatedAt: timeGen1.Now(), @@ -435,11 +435,11 @@ func TestBackFill(t *testing.T) { AuthMethod: "basic", URL: "http://example.com", Username: influxdb.SecretField{ - Key: id1 + "-username", + Key: id1.String() + "-username", Value: strPtr("username1"), }, Password: influxdb.SecretField{ - Key: id1 + "-password", + Key: id1.String() + "-password", Value: strPtr("password1"), }, }, @@ -448,9 +448,9 @@ func TestBackFill(t *testing.T) { name: "simple Telegram", src: &endpoint.Telegram{ Base: endpoint.Base{ - ID: influxTesting.MustIDBase16Ptr(id1), + ID: id1, Name: "name1", - OrgID: influxTesting.MustIDBase16Ptr(id3), + OrgID: id3, Status: influxdb.Active, CRUDLog: influxdb.CRUDLog{ CreatedAt: timeGen1.Now(), @@ -463,9 +463,9 @@ func TestBackFill(t *testing.T) { }, target: &endpoint.Telegram{ Base: endpoint.Base{ - ID: influxTesting.MustIDBase16Ptr(id1), + ID: id1, Name: "name1", - OrgID: influxTesting.MustIDBase16Ptr(id3), + OrgID: id3, Status: influxdb.Active, CRUDLog: influxdb.CRUDLog{ CreatedAt: timeGen1.Now(), @@ -473,7 +473,7 @@ func TestBackFill(t *testing.T) { }, }, Token: influxdb.SecretField{ - Key: id1 + "-token", + Key: id1.String() + "-token", Value: strPtr("token-value"), }, }, @@ -497,9 +497,9 @@ func TestSecretFields(t *testing.T) { name: "simple Slack", src: &endpoint.Slack{ Base: endpoint.Base{ - ID: influxTesting.MustIDBase16Ptr(id1), + ID: id1, Name: "name1", - OrgID: influxTesting.MustIDBase16Ptr(id3), + OrgID: id3, Status: influxdb.Active, CRUDLog: influxdb.CRUDLog{ CreatedAt: timeGen1.Now(), @@ -508,13 +508,13 @@ func TestSecretFields(t *testing.T) { }, URL: "https://slack.com/api/chat.postMessage", Token: influxdb.SecretField{ - Key: id1 + "-token", + Key: id1.String() + "-token", Value: strPtr("token-value"), }, }, secrets: []influxdb.SecretField{ { - Key: id1 + "-token", + Key: id1.String() + "-token", Value: strPtr("token-value"), }, }, @@ -523,9 +523,9 @@ func TestSecretFields(t *testing.T) { name: "simple pagerduty", src: &endpoint.PagerDuty{ Base: endpoint.Base{ - ID: influxTesting.MustIDBase16Ptr(id1), + ID: id1, Name: "name1", - OrgID: influxTesting.MustIDBase16Ptr(id3), + OrgID: id3, Status: influxdb.Active, CRUDLog: influxdb.CRUDLog{ CreatedAt: timeGen1.Now(), @@ -534,13 +534,13 @@ func TestSecretFields(t *testing.T) { }, ClientURL: "https://events.pagerduty.com/v2/enqueue", RoutingKey: influxdb.SecretField{ - Key: id1 + "-routing-key", + Key: id1.String() + "-routing-key", Value: strPtr("routing-key-value"), }, }, secrets: []influxdb.SecretField{ { - Key: id1 + "-routing-key", + Key: id1.String() + "-routing-key", Value: strPtr("routing-key-value"), }, }, @@ -549,9 +549,9 @@ func TestSecretFields(t *testing.T) { name: "http with user and password", src: &endpoint.HTTP{ Base: endpoint.Base{ - ID: influxTesting.MustIDBase16Ptr(id1), + ID: id1, Name: "name1", - OrgID: influxTesting.MustIDBase16Ptr(id3), + OrgID: id3, Status: influxdb.Active, CRUDLog: influxdb.CRUDLog{ CreatedAt: timeGen1.Now(), @@ -561,21 +561,21 @@ func TestSecretFields(t *testing.T) { AuthMethod: "basic", URL: "http://example.com", Username: influxdb.SecretField{ - Key: id1 + "-username", + Key: id1.String() + "-username", Value: strPtr("user1"), }, Password: influxdb.SecretField{ - Key: id1 + "-password", + Key: id1.String() + "-password", Value: strPtr("password1"), }, }, secrets: []influxdb.SecretField{ { - Key: id1 + "-username", + Key: id1.String() + "-username", Value: strPtr("user1"), }, { - Key: id1 + "-password", + Key: id1.String() + "-password", Value: strPtr("password1"), }, }, @@ -584,9 +584,9 @@ func TestSecretFields(t *testing.T) { name: "simple Telegram", src: &endpoint.Telegram{ Base: endpoint.Base{ - ID: influxTesting.MustIDBase16Ptr(id1), + ID: id1, Name: "name1", - OrgID: influxTesting.MustIDBase16Ptr(id3), + OrgID: id3, Status: influxdb.Active, CRUDLog: influxdb.CRUDLog{ CreatedAt: timeGen1.Now(), @@ -594,13 +594,13 @@ func TestSecretFields(t *testing.T) { }, }, Token: influxdb.SecretField{ - Key: id1 + "-token", + Key: id1.String() + "-token", Value: strPtr("token-value"), }, }, secrets: []influxdb.SecretField{ { - Key: id1 + "-token", + Key: id1.String() + "-token", Value: strPtr("token-value"), }, }, diff --git a/endpoints/service.go b/notification/endpoint/service/service.go similarity index 84% rename from endpoints/service.go rename to notification/endpoint/service/service.go index 76c402479aa..418805f6845 100644 --- a/endpoints/service.go +++ b/notification/endpoint/service/service.go @@ -1,28 +1,22 @@ -package endpoints +package service import ( "context" - "github.com/influxdata/influxdb/v2" + influxdb "github.com/influxdata/influxdb/v2" ) // Service provides all the notification endpoint service behavior. type Service struct { endpointStore influxdb.NotificationEndpointService secretSVC influxdb.SecretService - - // TODO(jsteenb2): NUKE THESE 2 embedded services after fixing up the domain! - influxdb.UserResourceMappingService - influxdb.OrganizationService } -// NewService constructs a new Service. -func NewService(store influxdb.NotificationEndpointService, secretSVC influxdb.SecretService, urmSVC influxdb.UserResourceMappingService, orgSVC influxdb.OrganizationService) *Service { +// New constructs a new Service. +func New(store influxdb.NotificationEndpointService, secretSVC influxdb.SecretService) *Service { return &Service{ - endpointStore: store, - secretSVC: secretSVC, - UserResourceMappingService: urmSVC, - OrganizationService: orgSVC, + endpointStore: store, + secretSVC: secretSVC, } } diff --git a/endpoints/service_test.go b/notification/endpoint/service/service_test.go similarity index 76% rename from endpoints/service_test.go rename to notification/endpoint/service/service_test.go index 2523b1f3abf..80dc51bd976 100644 --- a/endpoints/service_test.go +++ b/notification/endpoint/service/service_test.go @@ -1,45 +1,43 @@ -package endpoints_test +package service_test import ( "context" "testing" "time" - "github.com/influxdata/influxdb/v2" - "github.com/influxdata/influxdb/v2/endpoints" + influxdb "github.com/influxdata/influxdb/v2" "github.com/influxdata/influxdb/v2/inmem" "github.com/influxdata/influxdb/v2/kv" "github.com/influxdata/influxdb/v2/kv/migration/all" "github.com/influxdata/influxdb/v2/mock" "github.com/influxdata/influxdb/v2/notification/endpoint" + "github.com/influxdata/influxdb/v2/notification/endpoint/service" + "github.com/influxdata/influxdb/v2/pkg/pointer" + "github.com/influxdata/influxdb/v2/tenant" influxTesting "github.com/influxdata/influxdb/v2/testing" + "go.uber.org/zap" "go.uber.org/zap/zaptest" ) -var id1 = influxTesting.MustIDBase16Ptr("020f755c3c082000") -var id2 = influxTesting.MustIDBase16Ptr("020f755c3c082001") -var orgID = influxTesting.MustIDBase16Ptr("a10f755c3c082001") -var userID = influxTesting.MustIDBase16Ptr("b10f755c3c082001") +var ( + id1 = influxTesting.MustIDBase16Ptr("020f755c3c082000") + id2 = influxTesting.MustIDBase16Ptr("020f755c3c082001") + orgID = influxTesting.MustIDBase16Ptr("a10f755c3c082001") + userID = influxTesting.MustIDBase16Ptr("b10f755c3c082001") -var timeGen1 = mock.TimeGenerator{FakeValue: time.Date(2006, time.July, 13, 4, 19, 10, 0, time.UTC)} -var timeGen2 = mock.TimeGenerator{FakeValue: time.Date(2006, time.July, 14, 5, 23, 53, 10, time.UTC)} -var testCrudLog = influxdb.CRUDLog{ - CreatedAt: timeGen1.Now(), - UpdatedAt: timeGen2.Now(), -} + timeGen1 = mock.TimeGenerator{FakeValue: time.Date(2006, time.July, 13, 4, 19, 10, 0, time.UTC)} + timeGen2 = mock.TimeGenerator{FakeValue: time.Date(2006, time.July, 14, 5, 23, 53, 10, time.UTC)} -// newInmemService creates a new in-memory secret service -func newInmemService(t *testing.T) *kv.Service { + testCrudLog = influxdb.CRUDLog{ + CreatedAt: timeGen1.Now(), + UpdatedAt: timeGen2.Now(), + } +) + +func newSecretService(t *testing.T, ctx context.Context, logger *zap.Logger, s kv.Store) influxdb.SecretService { t.Helper() - store := inmem.NewKVStore() - logger := zaptest.NewLogger(t) - ctx := context.Background() - // initialize the store - if err := all.Up(ctx, logger, store); err != nil { - t.Fatal(err) - } - svc := kv.NewService(logger, store) + tenantSvc := tenant.NewService(tenant.NewStore(s)) // initialize organization org := influxdb.Organization{ @@ -48,21 +46,26 @@ func newInmemService(t *testing.T) *kv.Service { CRUDLog: testCrudLog, } - if err := svc.CreateOrganization(ctx, &org); err != nil { + if err := tenantSvc.CreateOrganization(ctx, &org); err != nil { t.Fatal(err) } orgID = &org.ID // orgID is generated - return svc + return kv.NewService(logger, s) } // TestEndpointService_cummulativeSecrets tests that secrets are cummulatively added/updated and removed upon delete // see https://github.com/influxdata/influxdb/pull/19082 for details func TestEndpointService_cummulativeSecrets(t *testing.T) { - inMemService := newInmemService(t) - endpointService := endpoints.NewService(inMemService, inMemService, inMemService, inMemService) - secretService := inMemService ctx := context.Background() + store := inmem.NewKVStore() + logger := zaptest.NewLogger(t) + if err := all.Up(ctx, logger, store); err != nil { + t.Fatal(err) + } + + secretService := newSecretService(t, ctx, logger, store) + endpointService := service.New(service.NewStore(store), secretService) var endpoint1 = endpoint.HTTP{ Base: endpoint.Base{ @@ -79,8 +82,8 @@ func TestEndpointService_cummulativeSecrets(t *testing.T) { AuthMethod: "basic", Method: "POST", URL: "http://example.com", - Username: influxdb.SecretField{Key: id1.String() + "username-key", Value: strPtr("val1")}, - Password: influxdb.SecretField{Key: id1.String() + "password-key", Value: strPtr("val2")}, + Username: influxdb.SecretField{Key: id1.String() + "username-key", Value: pointer.String("val1")}, + Password: influxdb.SecretField{Key: id1.String() + "password-key", Value: pointer.String("val2")}, } var endpoint2 = endpoint.HTTP{ Base: endpoint.Base{ @@ -97,8 +100,8 @@ func TestEndpointService_cummulativeSecrets(t *testing.T) { AuthMethod: "basic", Method: "POST", URL: "http://example2.com", - Username: influxdb.SecretField{Key: id2.String() + "username-key", Value: strPtr("val3")}, - Password: influxdb.SecretField{Key: id2.String() + "password-key", Value: strPtr("val4")}, + Username: influxdb.SecretField{Key: id2.String() + "username-key", Value: pointer.String("val3")}, + Password: influxdb.SecretField{Key: id2.String() + "password-key", Value: pointer.String("val4")}, } var err error var secretKeys []string @@ -127,7 +130,7 @@ func TestEndpointService_cummulativeSecrets(t *testing.T) { // update 1st endpoint and validate secrets const updatedSecretValue = "updatedSecVal" - endpoint1.Username.Value = strPtr(updatedSecretValue) + endpoint1.Username.Value = pointer.String(updatedSecretValue) if _, err = endpointService.UpdateNotificationEndpoint(ctx, *endpoint1.ID, &endpoint1, *userID); err != nil { t.Fatal(err) } @@ -175,8 +178,3 @@ func TestEndpointService_cummulativeSecrets(t *testing.T) { t.Errorf("secrets after deleting the 2nd endpoint = %v, want %v", len(secretKeys), 2) } } - -// strPtr returns string pointer -func strPtr(s string) *string { - return &s -} diff --git a/notification/endpoint/service/store.go b/notification/endpoint/service/store.go new file mode 100644 index 00000000000..bc2da6c31be --- /dev/null +++ b/notification/endpoint/service/store.go @@ -0,0 +1,305 @@ +package service + +import ( + "context" + + influxdb "github.com/influxdata/influxdb/v2" + "github.com/influxdata/influxdb/v2/kv" + "github.com/influxdata/influxdb/v2/notification/endpoint" + "github.com/influxdata/influxdb/v2/snowflake" +) + +var ( + // ErrNotificationEndpointNotFound is used when the notification endpoint is not found. + ErrNotificationEndpointNotFound = &influxdb.Error{ + Msg: "notification endpoint not found", + Code: influxdb.ENotFound, + } + + notificationEndpointBucket = []byte("notificationEndpointv1") + notificationEndpointIndexBucket = []byte("notificationEndpointIndexv1") +) + +var _ influxdb.NotificationEndpointService = (*Store)(nil) + +func newEndpointStore() *kv.IndexStore { + const resource = "notification endpoint" + + var decEndpointEntFn kv.DecodeBucketValFn = func(key, val []byte) ([]byte, interface{}, error) { + edp, err := endpoint.UnmarshalJSON(val) + return key, edp, err + } + + var decValToEntFn kv.ConvertValToEntFn = func(_ []byte, v interface{}) (kv.Entity, error) { + edp, ok := v.(influxdb.NotificationEndpoint) + if err := kv.IsErrUnexpectedDecodeVal(ok); err != nil { + return kv.Entity{}, err + } + return kv.Entity{ + PK: kv.EncID(edp.GetID()), + UniqueKey: kv.Encode(kv.EncID(edp.GetOrgID()), kv.EncString(edp.GetName())), + Body: edp, + }, nil + } + + return &kv.IndexStore{ + Resource: resource, + EntStore: kv.NewStoreBase(resource, notificationEndpointBucket, kv.EncIDKey, kv.EncBodyJSON, decEndpointEntFn, decValToEntFn), + IndexStore: kv.NewOrgNameKeyStore(resource, notificationEndpointIndexBucket, true), + } +} + +type Store struct { + kv kv.Store + + endpointStore *kv.IndexStore + + IDGenerator influxdb.IDGenerator + TimeGenerator influxdb.TimeGenerator +} + +func NewStore(store kv.Store) *Store { + return &Store{ + kv: store, + endpointStore: newEndpointStore(), + IDGenerator: snowflake.NewDefaultIDGenerator(), + TimeGenerator: influxdb.RealTimeGenerator{}, + } +} + +// CreateNotificationEndpoint creates a new notification endpoint and sets b.ID with the new identifier. +func (s *Store) CreateNotificationEndpoint(ctx context.Context, edp influxdb.NotificationEndpoint, userID influxdb.ID) error { + return s.kv.Update(ctx, func(tx kv.Tx) error { + return s.createNotificationEndpoint(ctx, tx, edp, userID) + }) +} + +func (s *Store) createNotificationEndpoint(ctx context.Context, tx kv.Tx, edp influxdb.NotificationEndpoint, userID influxdb.ID) error { + id := s.IDGenerator.ID() + edp.SetID(id) + now := s.TimeGenerator.Now() + edp.SetCreatedAt(now) + edp.SetUpdatedAt(now) + edp.BackfillSecretKeys() + + if err := edp.Valid(); err != nil { + return err + } + + ent := kv.Entity{ + PK: kv.EncID(edp.GetID()), + UniqueKey: kv.Encode(kv.EncID(edp.GetOrgID()), kv.EncString(edp.GetName())), + Body: edp, + } + if err := s.endpointStore.Put(ctx, tx, ent, kv.PutNew()); err != nil { + return err + } + + return nil +} + +// UpdateNotificationEndpoint updates a single notification endpoint. +// Returns the new notification endpoint after update. +func (s *Store) UpdateNotificationEndpoint(ctx context.Context, id influxdb.ID, edp influxdb.NotificationEndpoint, userID influxdb.ID) (influxdb.NotificationEndpoint, error) { + var err error + err = s.kv.Update(ctx, func(tx kv.Tx) error { + edp, err = s.updateNotificationEndpoint(ctx, tx, id, edp, userID) + return err + }) + return edp, err +} + +func (s *Store) updateNotificationEndpoint(ctx context.Context, tx kv.Tx, id influxdb.ID, edp influxdb.NotificationEndpoint, userID influxdb.ID) (influxdb.NotificationEndpoint, error) { + current, err := s.findNotificationEndpointByID(ctx, tx, id) + if err != nil { + return nil, err + } + + // ID and OrganizationID can not be updated + edp.SetCreatedAt(current.GetCRUDLog().CreatedAt) + edp.SetUpdatedAt(s.TimeGenerator.Now()) + + if err := edp.Valid(); err != nil { + return nil, err + } + + ent := kv.Entity{ + PK: kv.EncID(edp.GetID()), + UniqueKey: kv.Encode(kv.EncID(edp.GetOrgID()), kv.EncString(edp.GetName())), + Body: edp, + } + if err := s.endpointStore.Put(ctx, tx, ent, kv.PutUpdate()); err != nil { + return nil, err + } + + return edp, nil +} + +// PatchNotificationEndpoint updates a single notification endpoint with changeset. +// Returns the new notification endpoint state after update. +func (s *Store) PatchNotificationEndpoint(ctx context.Context, id influxdb.ID, upd influxdb.NotificationEndpointUpdate) (influxdb.NotificationEndpoint, error) { + var edp influxdb.NotificationEndpoint + if err := s.kv.Update(ctx, func(tx kv.Tx) (err error) { + edp, err = s.patchNotificationEndpoint(ctx, tx, id, upd) + if err != nil { + return err + } + return nil + }); err != nil { + return nil, err + } + + return edp, nil +} + +func (s *Store) patchNotificationEndpoint(ctx context.Context, tx kv.Tx, id influxdb.ID, upd influxdb.NotificationEndpointUpdate) (influxdb.NotificationEndpoint, error) { + edp, err := s.findNotificationEndpointByID(ctx, tx, id) + if err != nil { + return nil, err + } + + if upd.Name != nil { + edp.SetName(*upd.Name) + } + if upd.Description != nil { + edp.SetDescription(*upd.Description) + } + if upd.Status != nil { + edp.SetStatus(*upd.Status) + } + edp.SetUpdatedAt(s.TimeGenerator.Now()) + + if err := edp.Valid(); err != nil { + return nil, err + } + + // TODO(jsteenb2): every above here moves into service layer + + ent := kv.Entity{ + PK: kv.EncID(edp.GetID()), + UniqueKey: kv.Encode(kv.EncID(edp.GetOrgID()), kv.EncString(edp.GetName())), + Body: edp, + } + if err := s.endpointStore.Put(ctx, tx, ent, kv.PutUpdate()); err != nil { + return nil, err + } + + return edp, nil +} + +// PutNotificationEndpoint put a notification endpoint to storage. +func (s *Store) PutNotificationEndpoint(ctx context.Context, edp influxdb.NotificationEndpoint) error { + // TODO(jsteenb2): all the stuffs before the update should be moved up into the + // service layer as well as all the id/time setting items + if err := edp.Valid(); err != nil { + return err + } + + return s.kv.Update(ctx, func(tx kv.Tx) (err error) { + ent := kv.Entity{ + PK: kv.EncID(edp.GetID()), + UniqueKey: kv.Encode(kv.EncID(edp.GetOrgID()), kv.EncString(edp.GetName())), + Body: edp, + } + return s.endpointStore.Put(ctx, tx, ent) + }) +} + +// FindNotificationEndpointByID returns a single notification endpoint by ID. +func (s *Store) FindNotificationEndpointByID(ctx context.Context, id influxdb.ID) (influxdb.NotificationEndpoint, error) { + var ( + edp influxdb.NotificationEndpoint + err error + ) + + err = s.kv.View(ctx, func(tx kv.Tx) error { + edp, err = s.findNotificationEndpointByID(ctx, tx, id) + return err + }) + + return edp, err +} + +func (s *Store) findNotificationEndpointByID(ctx context.Context, tx kv.Tx, id influxdb.ID) (influxdb.NotificationEndpoint, error) { + decodedEnt, err := s.endpointStore.FindEnt(ctx, tx, kv.Entity{PK: kv.EncID(id)}) + if err != nil { + return nil, err + } + edp, ok := decodedEnt.(influxdb.NotificationEndpoint) + return edp, kv.IsErrUnexpectedDecodeVal(ok) +} + +// FindNotificationEndpoints returns a list of notification endpoints that match isNext and the total count of matching notification endpoints. +// Additional options provide pagination & sorting. +func (s *Store) FindNotificationEndpoints(ctx context.Context, filter influxdb.NotificationEndpointFilter, opt ...influxdb.FindOptions) (edps []influxdb.NotificationEndpoint, n int, err error) { + err = s.kv.View(ctx, func(tx kv.Tx) error { + edps, n, err = s.findNotificationEndpoints(ctx, tx, filter, opt...) + return err + }) + return edps, n, err +} + +func (s *Store) findNotificationEndpoints(ctx context.Context, tx kv.Tx, filter influxdb.NotificationEndpointFilter, opt ...influxdb.FindOptions) ([]influxdb.NotificationEndpoint, int, error) { + var o influxdb.FindOptions + if len(opt) > 0 { + o = opt[0] + } + + edps := make([]influxdb.NotificationEndpoint, 0) + err := s.endpointStore.Find(ctx, tx, kv.FindOpts{ + Descending: o.Descending, + Offset: o.Offset, + Limit: o.Limit, + FilterEntFn: filterEndpointsFn(filter), + CaptureFn: func(k []byte, v interface{}) error { + edp, ok := v.(influxdb.NotificationEndpoint) + if err := kv.IsErrUnexpectedDecodeVal(ok); err != nil { + return err + } + edps = append(edps, edp) + return nil + }, + }) + if err != nil { + return nil, 0, err + } + + return edps, len(edps), err +} + +func filterEndpointsFn(filter influxdb.NotificationEndpointFilter) func([]byte, interface{}) bool { + return func(key []byte, val interface{}) bool { + edp := val.(influxdb.NotificationEndpoint) + if filter.ID != nil && edp.GetID() != *filter.ID { + return false + } + + if filter.OrgID != nil && edp.GetOrgID() != *filter.OrgID { + return false + } + + return true + } +} + +// DeleteNotificationEndpoint removes a notification endpoint by ID. +func (s *Store) DeleteNotificationEndpoint(ctx context.Context, id influxdb.ID) (flds []influxdb.SecretField, orgID influxdb.ID, err error) { + err = s.kv.Update(ctx, func(tx kv.Tx) error { + flds, orgID, err = s.deleteNotificationEndpoint(ctx, tx, id) + return err + }) + return flds, orgID, err +} + +func (s *Store) deleteNotificationEndpoint(ctx context.Context, tx kv.Tx, id influxdb.ID) (flds []influxdb.SecretField, orgID influxdb.ID, err error) { + edp, err := s.findNotificationEndpointByID(ctx, tx, id) + if err != nil { + return nil, 0, err + } + + if err := s.endpointStore.DeleteEnt(ctx, tx, kv.Entity{PK: kv.EncID(id)}); err != nil { + return nil, 0, err + } + + return edp.SecretFields(), edp.GetOrgID(), nil +} diff --git a/notification/endpoint/service/store_test.go b/notification/endpoint/service/store_test.go new file mode 100644 index 00000000000..e7fb7468e1f --- /dev/null +++ b/notification/endpoint/service/store_test.go @@ -0,0 +1,127 @@ +package service_test + +import ( + "context" + "io/ioutil" + "os" + "testing" + + influxdb "github.com/influxdata/influxdb/v2" + "github.com/influxdata/influxdb/v2/bolt" + "github.com/influxdata/influxdb/v2/inmem" + "github.com/influxdata/influxdb/v2/kit/errors" + "github.com/influxdata/influxdb/v2/kv" + "github.com/influxdata/influxdb/v2/kv/migration/all" + "github.com/influxdata/influxdb/v2/notification/endpoint/service" + endpointsTesting "github.com/influxdata/influxdb/v2/notification/endpoint/service/testing" + "github.com/influxdata/influxdb/v2/tenant" + "go.uber.org/zap/zaptest" +) + +func TestNotificationEndpointService_WithInmem(t *testing.T) { + endpointsTesting.NotificationEndpointService(initInmemNotificationEndpointService, t) +} + +func TestNotificationEndpointService_WithBolt(t *testing.T) { + endpointsTesting.NotificationEndpointService(initBoltNotificationEndpointService, t) +} + +func NewTestBoltStore(t *testing.T) (kv.SchemaStore, func(), error) { + f, err := ioutil.TempFile("", "influxdata-bolt-") + if err != nil { + return nil, nil, errors.New("unable to open temporary boltdb file") + } + f.Close() + + ctx := context.Background() + logger := zaptest.NewLogger(t) + path := f.Name() + + // skip fsync to improve test performance + s := bolt.NewKVStore(logger, path, bolt.WithNoSync) + if err := s.Open(context.Background()); err != nil { + return nil, nil, err + } + + if err := all.Up(ctx, logger, s); err != nil { + return nil, nil, err + } + + close := func() { + s.Close() + os.Remove(path) + } + + return s, close, nil +} + +func initBoltNotificationEndpointService(f endpointsTesting.NotificationEndpointFields, t *testing.T) (influxdb.NotificationEndpointService, influxdb.SecretService, func()) { + store, closeStore, err := NewTestBoltStore(t) + if err != nil { + t.Fatal(err) + } + + svc, secretSVC, closeSvc := initNotificationEndpointService(store, f, t) + return svc, secretSVC, func() { + closeSvc() + closeStore() + } +} + +func initInmemNotificationEndpointService(f endpointsTesting.NotificationEndpointFields, t *testing.T) (influxdb.NotificationEndpointService, influxdb.SecretService, func()) { + store := inmem.NewKVStore() + if err := all.Up(context.Background(), zaptest.NewLogger(t), store); err != nil { + t.Fatal(err) + } + + svc, secretSVC, closeSvc := initNotificationEndpointService(store, f, t) + return svc, secretSVC, closeSvc +} + +func initNotificationEndpointService(s kv.SchemaStore, f endpointsTesting.NotificationEndpointFields, t *testing.T) (influxdb.NotificationEndpointService, influxdb.SecretService, func()) { + ctx := context.Background() + logger := zaptest.NewLogger(t) + + tenantStore := tenant.NewStore(s) + if f.IDGenerator != nil { + tenantStore.OrgIDGen = f.IDGenerator + tenantStore.IDGen = f.IDGenerator + } + + tenantSvc := tenant.NewService(tenantStore) + + secretSvc := kv.NewService(logger, s) + + store := service.NewStore(s) + store.IDGenerator = f.IDGenerator + if f.TimeGenerator != nil { + store.TimeGenerator = f.TimeGenerator + } + + endpointSvc := service.New(store, secretSvc) + + for _, edp := range f.NotificationEndpoints { + if err := store.PutNotificationEndpoint(ctx, edp); err != nil { + t.Fatalf("failed to populate notification endpoint: %v", err) + } + } + + for _, o := range f.Orgs { + if err := tenantSvc.CreateOrganization(ctx, o); err != nil { + t.Fatalf("failed to populate org: %v", err) + } + } + + return endpointSvc, secretSvc, func() { + for _, edp := range f.NotificationEndpoints { + if _, _, err := endpointSvc.DeleteNotificationEndpoint(ctx, edp.GetID()); err != nil && err != service.ErrNotificationEndpointNotFound { + t.Logf("failed to remove notification endpoint: %v", err) + } + } + for _, o := range f.Orgs { + if err := tenantSvc.DeleteOrganization(ctx, o.ID); err != nil { + t.Fatalf("failed to remove org: %v", err) + } + } + } +} diff --git a/testing/notification_endpoint.go b/notification/endpoint/service/testing/service.go similarity index 55% rename from testing/notification_endpoint.go rename to notification/endpoint/service/testing/service.go index 1f71b3ab5f6..fdc6d9448c3 100644 --- a/testing/notification_endpoint.go +++ b/notification/endpoint/service/testing/service.go @@ -2,6 +2,7 @@ package testing import ( "context" + "fmt" "net/http" "sort" "strings" @@ -9,25 +10,37 @@ import ( "time" "github.com/google/go-cmp/cmp" - "github.com/influxdata/influxdb/v2" + influxdb "github.com/influxdata/influxdb/v2" "github.com/influxdata/influxdb/v2/mock" "github.com/influxdata/influxdb/v2/notification/endpoint" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) +const ( + oneID = influxdb.ID(iota + 1) + twoID + threeID + fourID + fiveID + sixID +) + +var ( + fakeDate = time.Date(2006, 5, 4, 1, 2, 3, 0, time.UTC) + fakeGenerator = mock.TimeGenerator{FakeValue: fakeDate} + timeGen1 = mock.TimeGenerator{FakeValue: time.Date(2006, time.July, 13, 4, 19, 10, 0, time.UTC)} + timeGen2 = mock.TimeGenerator{FakeValue: time.Date(2006, time.July, 14, 5, 23, 53, 10, time.UTC)} +) + // NotificationEndpointFields includes prepopulated data for mapping tests. type NotificationEndpointFields struct { IDGenerator influxdb.IDGenerator TimeGenerator influxdb.TimeGenerator NotificationEndpoints []influxdb.NotificationEndpoint Orgs []*influxdb.Organization - UserResourceMappings []*influxdb.UserResourceMapping } -var timeGen1 = mock.TimeGenerator{FakeValue: time.Date(2006, time.July, 13, 4, 19, 10, 0, time.UTC)} -var timeGen2 = mock.TimeGenerator{FakeValue: time.Date(2006, time.July, 14, 5, 23, 53, 10, time.UTC)} - var notificationEndpointCmpOptions = cmp.Options{ cmp.Transformer("Sort", func(in []influxdb.NotificationEndpoint) []influxdb.NotificationEndpoint { out := append([]influxdb.NotificationEndpoint(nil), in...) @@ -93,7 +106,6 @@ func CreateNotificationEndpoint( type wants struct { err error notificationEndpoints []influxdb.NotificationEndpoint - userResourceMapping []*influxdb.UserResourceMapping } tests := []struct { @@ -105,27 +117,19 @@ func CreateNotificationEndpoint( { name: "basic create notification endpoint", fields: NotificationEndpointFields{ - IDGenerator: mock.NewIDGenerator(twoID, t), + IDGenerator: mock.NewStaticIDGenerator(twoID), TimeGenerator: fakeGenerator, Orgs: []*influxdb.Organization{ - {ID: MustIDBase16(fourID), Name: "org1"}, + {ID: fourID, Name: "org1"}, }, NotificationEndpoints: []influxdb.NotificationEndpoint{}, - UserResourceMappings: []*influxdb.UserResourceMapping{ - { - ResourceID: MustIDBase16(oneID), - ResourceType: influxdb.NotificationEndpointResourceType, - UserID: MustIDBase16(sixID), - UserType: influxdb.Member, - }, - }, }, args: args{ - userID: MustIDBase16(sixID), + userID: sixID, notificationEndpoint: &endpoint.PagerDuty{ Base: endpoint.Base{ Name: "name2", - OrgID: MustIDBase16Ptr(fourID), + OrgID: idPtr(fourID), Status: influxdb.Active, }, ClientURL: "example-pagerduty.com", @@ -138,31 +142,19 @@ func CreateNotificationEndpoint( notificationEndpoints: []influxdb.NotificationEndpoint{ &endpoint.PagerDuty{ Base: endpoint.Base{ - ID: MustIDBase16Ptr(twoID), + ID: idPtr(twoID), Name: "name2", - OrgID: MustIDBase16Ptr(fourID), + OrgID: idPtr(fourID), Status: influxdb.Active, CRUDLog: influxdb.CRUDLog{ CreatedAt: fakeDate, UpdatedAt: fakeDate, }, }, - ClientURL: "example-pagerduty.com", - RoutingKey: influxdb.SecretField{Key: twoID + "-routing-key"}, - }, - }, - userResourceMapping: []*influxdb.UserResourceMapping{ - { - ResourceID: MustIDBase16(oneID), - ResourceType: influxdb.NotificationEndpointResourceType, - UserID: MustIDBase16(sixID), - UserType: influxdb.Member, - }, - { - ResourceID: MustIDBase16(twoID), - ResourceType: influxdb.NotificationEndpointResourceType, - UserID: MustIDBase16(sixID), - UserType: influxdb.Owner, + ClientURL: "example-pagerduty.com", + RoutingKey: influxdb.SecretField{ + Key: fmt.Sprintf("%s-routing-key", twoID), + }, }, }, }, @@ -178,11 +170,6 @@ func CreateNotificationEndpoint( err := s.CreateNotificationEndpoint(ctx, tt.args.notificationEndpoint, tt.args.userID) ErrorsEqual(t, err, tt.wants.err) - urmFilter := influxdb.UserResourceMappingFilter{ - UserID: tt.args.userID, - ResourceType: influxdb.NotificationEndpointResourceType, - } - filter := influxdb.NotificationEndpointFilter{} edps, _, err := s.FindNotificationEndpoints(ctx, filter) if err != nil { @@ -192,14 +179,6 @@ func CreateNotificationEndpoint( t.Errorf("notificationEndpoints are different -got/+want\ndiff %s", diff) } - urms, _, err := s.FindUserResourceMappings(ctx, urmFilter) - if err != nil { - t.Fatalf("failed to retrieve user resource mappings: %v", err) - } - if diff := cmp.Diff(urms, tt.wants.userResourceMapping, userResourceMappingCmpOptions...); diff != "" { - t.Errorf("user resource mappings are different -got/+want\ndiff %s", diff) - } - for _, edp := range tt.wants.notificationEndpoints { secrets, err := secretSVC.GetSecretKeys(ctx, edp.GetOrgID()) if err != nil { @@ -235,48 +214,38 @@ func FindNotificationEndpointByID( { name: "bad id", fields: NotificationEndpointFields{ - UserResourceMappings: []*influxdb.UserResourceMapping{ - { - ResourceID: MustIDBase16(oneID), - UserID: MustIDBase16(sixID), - UserType: influxdb.Owner, - ResourceType: influxdb.NotificationEndpointResourceType, - }, - { - ResourceID: MustIDBase16(twoID), - UserID: MustIDBase16(sixID), - UserType: influxdb.Member, - ResourceType: influxdb.NotificationEndpointResourceType, - }, - }, NotificationEndpoints: []influxdb.NotificationEndpoint{ &endpoint.Slack{ Base: endpoint.Base{ - ID: MustIDBase16Ptr(oneID), + ID: idPtr(oneID), Name: "name1", - OrgID: MustIDBase16Ptr(fourID), + OrgID: idPtr(fourID), Status: influxdb.Active, CRUDLog: influxdb.CRUDLog{ CreatedAt: timeGen1.Now(), UpdatedAt: timeGen2.Now(), }, }, - URL: "example-slack.com", - Token: influxdb.SecretField{Key: oneID + "-token"}, + URL: "example-slack.com", + Token: influxdb.SecretField{ + Key: fmt.Sprintf("%s-token", oneID), + }, }, &endpoint.PagerDuty{ Base: endpoint.Base{ - ID: MustIDBase16Ptr(twoID), + ID: idPtr(twoID), Name: "name2", - OrgID: MustIDBase16Ptr(fourID), + OrgID: idPtr(fourID), Status: influxdb.Active, CRUDLog: influxdb.CRUDLog{ CreatedAt: timeGen1.Now(), UpdatedAt: timeGen2.Now(), }, }, - ClientURL: "example-pagerduty.com", - RoutingKey: influxdb.SecretField{Key: twoID + "-routing-key"}, + ClientURL: "example-pagerduty.com", + RoutingKey: influxdb.SecretField{ + Key: fmt.Sprintf("%s-routing-key", twoID), + }, }, }, }, @@ -293,26 +262,12 @@ func FindNotificationEndpointByID( { name: "not found", fields: NotificationEndpointFields{ - UserResourceMappings: []*influxdb.UserResourceMapping{ - { - ResourceID: MustIDBase16(oneID), - UserID: MustIDBase16(sixID), - UserType: influxdb.Owner, - ResourceType: influxdb.NotificationEndpointResourceType, - }, - { - ResourceID: MustIDBase16(twoID), - UserID: MustIDBase16(sixID), - UserType: influxdb.Member, - ResourceType: influxdb.NotificationEndpointResourceType, - }, - }, NotificationEndpoints: []influxdb.NotificationEndpoint{ &endpoint.Slack{ Base: endpoint.Base{ - ID: MustIDBase16Ptr(oneID), + ID: idPtr(oneID), Name: "name1", - OrgID: MustIDBase16Ptr(fourID), + OrgID: idPtr(fourID), Status: influxdb.Active, CRUDLog: influxdb.CRUDLog{ CreatedAt: timeGen1.Now(), @@ -320,13 +275,13 @@ func FindNotificationEndpointByID( }, }, URL: "example-slack.com", - Token: influxdb.SecretField{Key: oneID + "-token"}, + Token: influxdb.SecretField{Key: fmt.Sprintf("%s-token", oneID)}, }, &endpoint.PagerDuty{ Base: endpoint.Base{ - ID: MustIDBase16Ptr(twoID), + ID: idPtr(twoID), Name: "name2", - OrgID: MustIDBase16Ptr(fourID), + OrgID: idPtr(fourID), Status: influxdb.Active, CRUDLog: influxdb.CRUDLog{ CreatedAt: timeGen1.Now(), @@ -334,12 +289,12 @@ func FindNotificationEndpointByID( }, }, ClientURL: "example-pagerduty.com", - RoutingKey: influxdb.SecretField{Key: twoID + "-routing-key"}, + RoutingKey: influxdb.SecretField{Key: fmt.Sprintf("%s-routing-key", twoID)}, }, }, }, args: args{ - id: MustIDBase16(threeID), + id: threeID, }, wants: wants{ err: &influxdb.Error{ @@ -351,26 +306,12 @@ func FindNotificationEndpointByID( { name: "basic find telegraf config by id", fields: NotificationEndpointFields{ - UserResourceMappings: []*influxdb.UserResourceMapping{ - { - ResourceID: MustIDBase16(oneID), - UserID: MustIDBase16(sixID), - UserType: influxdb.Owner, - ResourceType: influxdb.NotificationEndpointResourceType, - }, - { - ResourceID: MustIDBase16(twoID), - UserID: MustIDBase16(sixID), - UserType: influxdb.Member, - ResourceType: influxdb.NotificationEndpointResourceType, - }, - }, NotificationEndpoints: []influxdb.NotificationEndpoint{ &endpoint.Slack{ Base: endpoint.Base{ - ID: MustIDBase16Ptr(oneID), + ID: idPtr(oneID), Name: "name1", - OrgID: MustIDBase16Ptr(fourID), + OrgID: idPtr(fourID), Status: influxdb.Active, CRUDLog: influxdb.CRUDLog{ CreatedAt: timeGen1.Now(), @@ -378,13 +319,13 @@ func FindNotificationEndpointByID( }, }, URL: "example-slack.com", - Token: influxdb.SecretField{Key: oneID + "-token"}, + Token: influxdb.SecretField{Key: fmt.Sprintf("%s-token", oneID)}, }, &endpoint.PagerDuty{ Base: endpoint.Base{ - ID: MustIDBase16Ptr(twoID), + ID: idPtr(twoID), Name: "name2", - OrgID: MustIDBase16Ptr(fourID), + OrgID: idPtr(fourID), Status: influxdb.Active, CRUDLog: influxdb.CRUDLog{ CreatedAt: timeGen1.Now(), @@ -392,19 +333,19 @@ func FindNotificationEndpointByID( }, }, ClientURL: "example-pagerduty.com", - RoutingKey: influxdb.SecretField{Key: twoID + "-routing-key"}, + RoutingKey: influxdb.SecretField{Key: fmt.Sprintf("%s-routing-key", twoID)}, }, }, }, args: args{ - id: MustIDBase16(twoID), + id: twoID, }, wants: wants{ notificationEndpoint: &endpoint.PagerDuty{ Base: endpoint.Base{ - ID: MustIDBase16Ptr(twoID), + ID: idPtr(twoID), Name: "name2", - OrgID: MustIDBase16Ptr(fourID), + OrgID: idPtr(fourID), Status: influxdb.Active, CRUDLog: influxdb.CRUDLog{ CreatedAt: timeGen1.Now(), @@ -412,7 +353,7 @@ func FindNotificationEndpointByID( }, }, ClientURL: "example-pagerduty.com", - RoutingKey: influxdb.SecretField{Key: twoID + "-routing-key"}, + RoutingKey: influxdb.SecretField{Key: fmt.Sprintf("%s-routing-key", twoID)}, }, }, }, @@ -467,26 +408,12 @@ func FindNotificationEndpoints( { name: "find all notification endpoints", fields: NotificationEndpointFields{ - UserResourceMappings: []*influxdb.UserResourceMapping{ - { - ResourceID: MustIDBase16(oneID), - UserID: MustIDBase16(sixID), - UserType: influxdb.Member, - ResourceType: influxdb.NotificationEndpointResourceType, - }, - { - ResourceID: MustIDBase16(twoID), - UserID: MustIDBase16(sixID), - UserType: influxdb.Member, - ResourceType: influxdb.NotificationEndpointResourceType, - }, - }, NotificationEndpoints: []influxdb.NotificationEndpoint{ &endpoint.Slack{ Base: endpoint.Base{ - ID: MustIDBase16Ptr(oneID), + ID: idPtr(oneID), Name: "name1", - OrgID: MustIDBase16Ptr(fourID), + OrgID: idPtr(fourID), Status: influxdb.Active, CRUDLog: influxdb.CRUDLog{ CreatedAt: timeGen1.Now(), @@ -494,13 +421,13 @@ func FindNotificationEndpoints( }, }, URL: "example-slack.com", - Token: influxdb.SecretField{Key: oneID + "-token"}, + Token: influxdb.SecretField{Key: fmt.Sprintf("%s-token", oneID)}, }, &endpoint.PagerDuty{ Base: endpoint.Base{ - ID: MustIDBase16Ptr(twoID), + ID: idPtr(twoID), Name: "name2", - OrgID: MustIDBase16Ptr(fourID), + OrgID: idPtr(fourID), Status: influxdb.Active, CRUDLog: influxdb.CRUDLog{ CreatedAt: timeGen1.Now(), @@ -508,15 +435,7 @@ func FindNotificationEndpoints( }, }, ClientURL: "example-pagerduty.com", - RoutingKey: influxdb.SecretField{Key: twoID + "-routing-key"}, - }, - }, - }, - args: args{ - filter: influxdb.NotificationEndpointFilter{ - UserResourceMappingFilter: influxdb.UserResourceMappingFilter{ - UserID: MustIDBase16(sixID), - ResourceType: influxdb.NotificationEndpointResourceType, + RoutingKey: influxdb.SecretField{Key: fmt.Sprintf("%s-routing-key", twoID)}, }, }, }, @@ -524,9 +443,9 @@ func FindNotificationEndpoints( notificationEndpoints: []influxdb.NotificationEndpoint{ &endpoint.Slack{ Base: endpoint.Base{ - ID: MustIDBase16Ptr(oneID), + ID: idPtr(oneID), Name: "name1", - OrgID: MustIDBase16Ptr(fourID), + OrgID: idPtr(fourID), Status: influxdb.Active, CRUDLog: influxdb.CRUDLog{ CreatedAt: timeGen1.Now(), @@ -534,13 +453,13 @@ func FindNotificationEndpoints( }, }, URL: "example-slack.com", - Token: influxdb.SecretField{Key: oneID + "-token"}, + Token: influxdb.SecretField{Key: fmt.Sprintf("%s-token", oneID)}, }, &endpoint.PagerDuty{ Base: endpoint.Base{ - ID: MustIDBase16Ptr(twoID), + ID: idPtr(twoID), Name: "name2", - OrgID: MustIDBase16Ptr(fourID), + OrgID: idPtr(fourID), Status: influxdb.Active, CRUDLog: influxdb.CRUDLog{ CreatedAt: timeGen1.Now(), @@ -548,7 +467,7 @@ func FindNotificationEndpoints( }, }, ClientURL: "example-pagerduty.com", - RoutingKey: influxdb.SecretField{Key: twoID + "-routing-key"}, + RoutingKey: influxdb.SecretField{Key: fmt.Sprintf("%s-routing-key", twoID)}, }, }, }, @@ -558,183 +477,63 @@ func FindNotificationEndpoints( fields: NotificationEndpointFields{ Orgs: []*influxdb.Organization{ { - ID: MustIDBase16(oneID), + ID: oneID, Name: "org1", }, { - ID: MustIDBase16(fourID), + ID: fourID, Name: "org4", }, }, - UserResourceMappings: []*influxdb.UserResourceMapping{ - { - ResourceID: MustIDBase16(oneID), - UserID: MustIDBase16(sixID), - UserType: influxdb.Member, - ResourceType: influxdb.NotificationEndpointResourceType, - }, - { - ResourceID: MustIDBase16(twoID), - UserID: MustIDBase16(sixID), - UserType: influxdb.Member, - ResourceType: influxdb.NotificationEndpointResourceType, - }, - { - ResourceID: MustIDBase16(fourID), - UserID: MustIDBase16(sixID), - UserType: influxdb.Member, - ResourceType: influxdb.NotificationEndpointResourceType, - }, - }, NotificationEndpoints: []influxdb.NotificationEndpoint{ &endpoint.Slack{ Base: endpoint.Base{ - ID: MustIDBase16Ptr(oneID), - OrgID: MustIDBase16Ptr(fourID), + ID: idPtr(oneID), + OrgID: idPtr(fourID), Status: influxdb.Active, Name: "edp1", }, URL: "example-slack.com", - Token: influxdb.SecretField{Key: oneID + "-token"}, + Token: influxdb.SecretField{Key: fmt.Sprintf("%s-token", oneID)}, }, &endpoint.PagerDuty{ Base: endpoint.Base{ - ID: MustIDBase16Ptr(twoID), - OrgID: MustIDBase16Ptr(fourID), + ID: idPtr(twoID), + OrgID: idPtr(fourID), Status: influxdb.Active, Name: "edp2", }, ClientURL: "example-pagerduty.com", - RoutingKey: influxdb.SecretField{Key: twoID + "-routing-key"}, + RoutingKey: influxdb.SecretField{Key: fmt.Sprintf("%s-routing-key", twoID)}, }, &endpoint.PagerDuty{ Base: endpoint.Base{ - ID: MustIDBase16Ptr(fourID), - OrgID: MustIDBase16Ptr(oneID), + ID: idPtr(fourID), + OrgID: idPtr(oneID), Status: influxdb.Active, Name: "edp3", }, ClientURL: "example-pagerduty2.com", - RoutingKey: influxdb.SecretField{Key: fourID + "-routing-key"}, + RoutingKey: influxdb.SecretField{Key: fmt.Sprintf("%s-routing-key", fourID)}, }, }, }, args: args{ filter: influxdb.NotificationEndpointFilter{ - OrgID: idPtr(MustIDBase16(oneID)), - UserResourceMappingFilter: influxdb.UserResourceMappingFilter{ - ResourceType: influxdb.NotificationEndpointResourceType, - UserID: MustIDBase16(sixID), - }, + OrgID: idPtr(oneID), }, }, wants: wants{ notificationEndpoints: []influxdb.NotificationEndpoint{ &endpoint.PagerDuty{ Base: endpoint.Base{ - ID: MustIDBase16Ptr(fourID), - OrgID: MustIDBase16Ptr(oneID), + ID: idPtr(fourID), + OrgID: idPtr(oneID), Status: influxdb.Active, Name: "edp3", }, ClientURL: "example-pagerduty2.com", - RoutingKey: influxdb.SecretField{Key: fourID + "-routing-key"}, - }, - }, - }, - }, - { - name: "filter by organization name only", - fields: NotificationEndpointFields{ - Orgs: []*influxdb.Organization{ - { - ID: MustIDBase16(oneID), - Name: "org1", - }, - { - ID: MustIDBase16(fourID), - Name: "org4", - }, - }, - UserResourceMappings: []*influxdb.UserResourceMapping{ - { - ResourceID: MustIDBase16(oneID), - UserID: MustIDBase16(sixID), - UserType: influxdb.Member, - ResourceType: influxdb.NotificationEndpointResourceType, - }, - { - ResourceID: MustIDBase16(twoID), - UserID: MustIDBase16(sixID), - UserType: influxdb.Member, - ResourceType: influxdb.NotificationEndpointResourceType, - }, - }, - NotificationEndpoints: []influxdb.NotificationEndpoint{ - &endpoint.Slack{ - Base: endpoint.Base{ - ID: MustIDBase16Ptr(oneID), - OrgID: MustIDBase16Ptr(fourID), - Status: influxdb.Active, - Name: "edp1", - }, - URL: "example-slack.com", - Token: influxdb.SecretField{Key: oneID + "-token"}, - }, - &endpoint.HTTP{ - Base: endpoint.Base{ - ID: MustIDBase16Ptr(twoID), - OrgID: MustIDBase16Ptr(fourID), - Status: influxdb.Active, - Name: "edp2", - }, - URL: "example-webhook.com", - Method: http.MethodGet, - AuthMethod: "none", - }, - &endpoint.PagerDuty{ - Base: endpoint.Base{ - ID: MustIDBase16Ptr(fourID), - OrgID: MustIDBase16Ptr(oneID), - Status: influxdb.Active, - Name: "edp3", - }, - ClientURL: "example-pagerduty.com", - RoutingKey: influxdb.SecretField{Key: fourID + "-routing-key"}, - }, - }, - }, - args: args{ - filter: influxdb.NotificationEndpointFilter{ - Org: strPtr("org4"), - UserResourceMappingFilter: influxdb.UserResourceMappingFilter{ - UserID: MustIDBase16(sixID), - ResourceType: influxdb.NotificationEndpointResourceType, - }, - }, - }, - wants: wants{ - notificationEndpoints: []influxdb.NotificationEndpoint{ - &endpoint.Slack{ - Base: endpoint.Base{ - ID: MustIDBase16Ptr(oneID), - OrgID: MustIDBase16Ptr(fourID), - Status: influxdb.Active, - Name: "edp1", - }, - URL: "example-slack.com", - Token: influxdb.SecretField{Key: oneID + "-token"}, - }, - &endpoint.HTTP{ - Base: endpoint.Base{ - ID: MustIDBase16Ptr(twoID), - OrgID: MustIDBase16Ptr(fourID), - Status: influxdb.Active, - Name: "edp2", - }, - URL: "example-webhook.com", - Method: http.MethodGet, - AuthMethod: "none", + RoutingKey: influxdb.SecretField{Key: fmt.Sprintf("%s-routing-key", fourID)}, }, }, }, @@ -744,43 +543,29 @@ func FindNotificationEndpoints( fields: NotificationEndpointFields{ Orgs: []*influxdb.Organization{ { - ID: MustIDBase16(oneID), + ID: oneID, Name: "org1", }, { - ID: MustIDBase16(fourID), + ID: fourID, Name: "org4", }, }, - UserResourceMappings: []*influxdb.UserResourceMapping{ - { - ResourceID: MustIDBase16(oneID), - UserID: MustIDBase16(sixID), - UserType: influxdb.Member, - ResourceType: influxdb.NotificationEndpointResourceType, - }, - { - ResourceID: MustIDBase16(twoID), - UserID: MustIDBase16(sixID), - UserType: influxdb.Member, - ResourceType: influxdb.NotificationEndpointResourceType, - }, - }, NotificationEndpoints: []influxdb.NotificationEndpoint{ &endpoint.Slack{ Base: endpoint.Base{ - ID: MustIDBase16Ptr(oneID), - OrgID: MustIDBase16Ptr(fourID), + ID: idPtr(oneID), + OrgID: idPtr(fourID), Status: influxdb.Active, Name: "edp1", }, URL: "example-slack.com", - Token: influxdb.SecretField{Key: oneID + "-token"}, + Token: influxdb.SecretField{Key: fmt.Sprintf("%s-token", oneID)}, }, &endpoint.HTTP{ Base: endpoint.Base{ - ID: MustIDBase16Ptr(twoID), - OrgID: MustIDBase16Ptr(fourID), + ID: idPtr(twoID), + OrgID: idPtr(fourID), Status: influxdb.Active, Name: "edp2", }, @@ -790,33 +575,29 @@ func FindNotificationEndpoints( }, &endpoint.PagerDuty{ Base: endpoint.Base{ - ID: MustIDBase16Ptr(fourID), - OrgID: MustIDBase16Ptr(fourID), + ID: idPtr(fourID), + OrgID: idPtr(fourID), Status: influxdb.Active, Name: "edp3", }, ClientURL: "example-pagerduty.com", - RoutingKey: influxdb.SecretField{Key: fourID + "-routing-key"}, + RoutingKey: influxdb.SecretField{Key: fmt.Sprintf("%s-routing-key", fourID)}, }, &endpoint.PagerDuty{ Base: endpoint.Base{ - ID: MustIDBase16Ptr(fiveID), - OrgID: MustIDBase16Ptr(fourID), + ID: idPtr(fiveID), + OrgID: idPtr(fourID), Status: influxdb.Active, Name: "edp4", }, ClientURL: "example-pagerduty.com", - RoutingKey: influxdb.SecretField{Key: fourID + "-routing-key"}, + RoutingKey: influxdb.SecretField{Key: fmt.Sprintf("%s-routing-key", fourID)}, }, }, }, args: args{ filter: influxdb.NotificationEndpointFilter{ Org: strPtr("org4"), - UserResourceMappingFilter: influxdb.UserResourceMappingFilter{ - UserID: MustIDBase16(sixID), - ResourceType: influxdb.NotificationEndpointResourceType, - }, }, opts: influxdb.FindOptions{ Limit: 2, @@ -826,18 +607,18 @@ func FindNotificationEndpoints( notificationEndpoints: []influxdb.NotificationEndpoint{ &endpoint.Slack{ Base: endpoint.Base{ - ID: MustIDBase16Ptr(oneID), - OrgID: MustIDBase16Ptr(fourID), + ID: idPtr(oneID), + OrgID: idPtr(fourID), Status: influxdb.Active, Name: "edp1", }, URL: "example-slack.com", - Token: influxdb.SecretField{Key: oneID + "-token"}, + Token: influxdb.SecretField{Key: fmt.Sprintf("%s-token", oneID)}, }, &endpoint.HTTP{ Base: endpoint.Base{ - ID: MustIDBase16Ptr(twoID), - OrgID: MustIDBase16Ptr(fourID), + ID: idPtr(twoID), + OrgID: idPtr(fourID), Status: influxdb.Active, Name: "edp2", }, @@ -853,50 +634,29 @@ func FindNotificationEndpoints( fields: NotificationEndpointFields{ Orgs: []*influxdb.Organization{ { - ID: MustIDBase16(oneID), + ID: oneID, Name: "org1", }, { - ID: MustIDBase16(fourID), + ID: fourID, Name: "org4", }, }, - UserResourceMappings: []*influxdb.UserResourceMapping{ - { - ResourceID: MustIDBase16(oneID), - UserID: MustIDBase16(sixID), - UserType: influxdb.Member, - ResourceType: influxdb.NotificationEndpointResourceType, - }, - { - ResourceID: MustIDBase16(twoID), - UserID: MustIDBase16(sixID), - UserType: influxdb.Member, - ResourceType: influxdb.NotificationEndpointResourceType, - }, - - { - ResourceID: MustIDBase16(fourID), - UserID: MustIDBase16(sixID), - UserType: influxdb.Member, - ResourceType: influxdb.NotificationEndpointResourceType, - }, - }, NotificationEndpoints: []influxdb.NotificationEndpoint{ &endpoint.Slack{ Base: endpoint.Base{ - ID: MustIDBase16Ptr(oneID), - OrgID: MustIDBase16Ptr(fourID), + ID: idPtr(oneID), + OrgID: idPtr(fourID), Status: influxdb.Active, Name: "edp1", }, URL: "example-slack.com", - Token: influxdb.SecretField{Key: oneID + "-token"}, + Token: influxdb.SecretField{Key: fmt.Sprintf("%s-token", oneID)}, }, &endpoint.HTTP{ Base: endpoint.Base{ - ID: MustIDBase16Ptr(twoID), - OrgID: MustIDBase16Ptr(fourID), + ID: idPtr(twoID), + OrgID: idPtr(fourID), Status: influxdb.Active, Name: "edp2", }, @@ -906,23 +666,19 @@ func FindNotificationEndpoints( }, &endpoint.PagerDuty{ Base: endpoint.Base{ - ID: MustIDBase16Ptr(fourID), - OrgID: MustIDBase16Ptr(fourID), + ID: idPtr(fourID), + OrgID: idPtr(fourID), Status: influxdb.Active, Name: "edp3", }, ClientURL: "example-pagerduty.com", - RoutingKey: influxdb.SecretField{Key: fourID + "-routing-key"}, + RoutingKey: influxdb.SecretField{Key: fmt.Sprintf("%s-routing-key", fourID)}, }, }, }, args: args{ filter: influxdb.NotificationEndpointFilter{ Org: strPtr("org4"), - UserResourceMappingFilter: influxdb.UserResourceMappingFilter{ - UserID: MustIDBase16(sixID), - ResourceType: influxdb.NotificationEndpointResourceType, - }, }, opts: influxdb.FindOptions{ Offset: 1, @@ -932,8 +688,8 @@ func FindNotificationEndpoints( notificationEndpoints: []influxdb.NotificationEndpoint{ &endpoint.HTTP{ Base: endpoint.Base{ - ID: MustIDBase16Ptr(twoID), - OrgID: MustIDBase16Ptr(fourID), + ID: idPtr(twoID), + OrgID: idPtr(fourID), Status: influxdb.Active, Name: "edp2", }, @@ -943,13 +699,13 @@ func FindNotificationEndpoints( }, &endpoint.PagerDuty{ Base: endpoint.Base{ - ID: MustIDBase16Ptr(fourID), - OrgID: MustIDBase16Ptr(fourID), + ID: idPtr(fourID), + OrgID: idPtr(fourID), Status: influxdb.Active, Name: "edp3", }, ClientURL: "example-pagerduty.com", - RoutingKey: influxdb.SecretField{Key: fourID + "-routing-key"}, + RoutingKey: influxdb.SecretField{Key: fmt.Sprintf("%s-routing-key", fourID)}, }, }, }, @@ -959,50 +715,29 @@ func FindNotificationEndpoints( fields: NotificationEndpointFields{ Orgs: []*influxdb.Organization{ { - ID: MustIDBase16(oneID), + ID: oneID, Name: "org1", }, { - ID: MustIDBase16(fourID), + ID: fourID, Name: "org4", }, }, - UserResourceMappings: []*influxdb.UserResourceMapping{ - { - ResourceID: MustIDBase16(oneID), - UserID: MustIDBase16(sixID), - UserType: influxdb.Member, - ResourceType: influxdb.NotificationEndpointResourceType, - }, - { - ResourceID: MustIDBase16(twoID), - UserID: MustIDBase16(sixID), - UserType: influxdb.Member, - ResourceType: influxdb.NotificationEndpointResourceType, - }, - - { - ResourceID: MustIDBase16(fourID), - UserID: MustIDBase16(sixID), - UserType: influxdb.Member, - ResourceType: influxdb.NotificationEndpointResourceType, - }, - }, NotificationEndpoints: []influxdb.NotificationEndpoint{ &endpoint.Slack{ Base: endpoint.Base{ - ID: MustIDBase16Ptr(oneID), - OrgID: MustIDBase16Ptr(fourID), + ID: idPtr(oneID), + OrgID: idPtr(fourID), Status: influxdb.Active, Name: "edp1", }, URL: "example-slack.com", - Token: influxdb.SecretField{Key: oneID + "-token"}, + Token: influxdb.SecretField{Key: fmt.Sprintf("%s-token", oneID)}, }, &endpoint.HTTP{ Base: endpoint.Base{ - ID: MustIDBase16Ptr(twoID), - OrgID: MustIDBase16Ptr(fourID), + ID: idPtr(twoID), + OrgID: idPtr(fourID), Status: influxdb.Active, Name: "edp2", }, @@ -1012,23 +747,19 @@ func FindNotificationEndpoints( }, &endpoint.PagerDuty{ Base: endpoint.Base{ - ID: MustIDBase16Ptr(fourID), - OrgID: MustIDBase16Ptr(fourID), + ID: idPtr(fourID), + OrgID: idPtr(fourID), Status: influxdb.Active, Name: "edp3", }, ClientURL: "example-pagerduty.com", - RoutingKey: influxdb.SecretField{Key: fourID + "-routing-key"}, + RoutingKey: influxdb.SecretField{Key: fmt.Sprintf("%s-routing-key", fourID)}, }, }, }, args: args{ filter: influxdb.NotificationEndpointFilter{ Org: strPtr("org4"), - UserResourceMappingFilter: influxdb.UserResourceMappingFilter{ - UserID: MustIDBase16(sixID), - ResourceType: influxdb.NotificationEndpointResourceType, - }, }, opts: influxdb.FindOptions{ Limit: 1, @@ -1039,8 +770,8 @@ func FindNotificationEndpoints( notificationEndpoints: []influxdb.NotificationEndpoint{ &endpoint.HTTP{ Base: endpoint.Base{ - ID: MustIDBase16Ptr(twoID), - OrgID: MustIDBase16Ptr(fourID), + ID: idPtr(twoID), + OrgID: idPtr(fourID), Status: influxdb.Active, Name: "edp2", }, @@ -1056,49 +787,29 @@ func FindNotificationEndpoints( fields: NotificationEndpointFields{ Orgs: []*influxdb.Organization{ { - ID: MustIDBase16(oneID), + ID: oneID, Name: "org1", }, { - ID: MustIDBase16(fourID), + ID: fourID, Name: "org4", }, }, - UserResourceMappings: []*influxdb.UserResourceMapping{ - { - ResourceID: MustIDBase16(oneID), - UserID: MustIDBase16(sixID), - UserType: influxdb.Member, - ResourceType: influxdb.NotificationEndpointResourceType, - }, - { - ResourceID: MustIDBase16(twoID), - UserID: MustIDBase16(sixID), - UserType: influxdb.Member, - ResourceType: influxdb.NotificationEndpointResourceType, - }, - { - ResourceID: MustIDBase16(fourID), - UserID: MustIDBase16(sixID), - UserType: influxdb.Member, - ResourceType: influxdb.NotificationEndpointResourceType, - }, - }, NotificationEndpoints: []influxdb.NotificationEndpoint{ &endpoint.Slack{ Base: endpoint.Base{ - ID: MustIDBase16Ptr(oneID), - OrgID: MustIDBase16Ptr(fourID), + ID: idPtr(oneID), + OrgID: idPtr(fourID), Status: influxdb.Active, Name: "edp1", }, URL: "example-slack.com", - Token: influxdb.SecretField{Key: oneID + "-token"}, + Token: influxdb.SecretField{Key: fmt.Sprintf("%s-token", oneID)}, }, &endpoint.HTTP{ Base: endpoint.Base{ - ID: MustIDBase16Ptr(twoID), - OrgID: MustIDBase16Ptr(fourID), + ID: idPtr(twoID), + OrgID: idPtr(fourID), Status: influxdb.Active, Name: "edp2", }, @@ -1108,36 +819,32 @@ func FindNotificationEndpoints( }, &endpoint.PagerDuty{ Base: endpoint.Base{ - ID: MustIDBase16Ptr(fourID), - OrgID: MustIDBase16Ptr(oneID), + ID: idPtr(fourID), + OrgID: idPtr(oneID), Status: influxdb.Active, Name: "edp3", }, ClientURL: "example-pagerduty.com", - RoutingKey: influxdb.SecretField{Key: fourID + "-routing-key"}, + RoutingKey: influxdb.SecretField{Key: fmt.Sprintf("%s-routing-key", fourID)}, }, }, }, args: args{ filter: influxdb.NotificationEndpointFilter{ - ID: idPtr(MustIDBase16(fourID)), - UserResourceMappingFilter: influxdb.UserResourceMappingFilter{ - UserID: MustIDBase16(sixID), - ResourceType: influxdb.NotificationEndpointResourceType, - }, + ID: idPtr(fourID), }, }, wants: wants{ notificationEndpoints: []influxdb.NotificationEndpoint{ &endpoint.PagerDuty{ Base: endpoint.Base{ - ID: MustIDBase16Ptr(fourID), - OrgID: MustIDBase16Ptr(oneID), + ID: idPtr(fourID), + OrgID: idPtr(oneID), Status: influxdb.Active, Name: "edp3", }, ClientURL: "example-pagerduty.com", - RoutingKey: influxdb.SecretField{Key: fourID + "-routing-key"}, + RoutingKey: influxdb.SecretField{Key: fmt.Sprintf("%s-routing-key", fourID)}, }, }, }, @@ -1147,49 +854,29 @@ func FindNotificationEndpoints( fields: NotificationEndpointFields{ Orgs: []*influxdb.Organization{ { - ID: MustIDBase16(oneID), + ID: oneID, Name: "org1", }, { - ID: MustIDBase16(fourID), + ID: fourID, Name: "org4", }, }, - UserResourceMappings: []*influxdb.UserResourceMapping{ - { - ResourceID: MustIDBase16(oneID), - UserID: MustIDBase16(sixID), - UserType: influxdb.Member, - ResourceType: influxdb.NotificationEndpointResourceType, - }, - { - ResourceID: MustIDBase16(twoID), - UserID: MustIDBase16(sixID), - UserType: influxdb.Member, - ResourceType: influxdb.NotificationEndpointResourceType, - }, - { - ResourceID: MustIDBase16(threeID), - UserID: MustIDBase16(sixID), - UserType: influxdb.Member, - ResourceType: influxdb.NotificationEndpointResourceType, - }, - }, NotificationEndpoints: []influxdb.NotificationEndpoint{ &endpoint.Slack{ Base: endpoint.Base{ - ID: MustIDBase16Ptr(oneID), - OrgID: MustIDBase16Ptr(fourID), + ID: idPtr(oneID), + OrgID: idPtr(fourID), Status: influxdb.Active, Name: "edp1", }, URL: "example-slack.com", - Token: influxdb.SecretField{Key: oneID + "-token"}, + Token: influxdb.SecretField{Key: fmt.Sprintf("%s-token", oneID)}, }, &endpoint.HTTP{ Base: endpoint.Base{ - ID: MustIDBase16Ptr(twoID), - OrgID: MustIDBase16Ptr(fourID), + ID: idPtr(twoID), + OrgID: idPtr(fourID), Status: influxdb.Active, Name: "edp2", }, @@ -1199,22 +886,19 @@ func FindNotificationEndpoints( }, &endpoint.PagerDuty{ Base: endpoint.Base{ - ID: MustIDBase16Ptr(threeID), - OrgID: MustIDBase16Ptr(fourID), + ID: idPtr(threeID), + OrgID: idPtr(fourID), Status: influxdb.Active, Name: "edp3", }, - ClientURL: "example-pagerduty.com", RoutingKey: influxdb.SecretField{Key: threeID + "-routing-key"}, + ClientURL: "example-pagerduty.com", + RoutingKey: influxdb.SecretField{Key: fmt.Sprintf("%s-routing-key", threeID)}, }, }, }, args: args{ filter: influxdb.NotificationEndpointFilter{ - OrgID: idPtr(MustIDBase16(oneID)), - UserResourceMappingFilter: influxdb.UserResourceMappingFilter{ - UserID: MustIDBase16(sixID), - ResourceType: influxdb.NotificationEndpointResourceType, - }, + OrgID: idPtr(oneID), }, }, wants: wants{ @@ -1226,43 +910,29 @@ func FindNotificationEndpoints( fields: NotificationEndpointFields{ Orgs: []*influxdb.Organization{ { - ID: MustIDBase16(oneID), + ID: oneID, Name: "org1", }, { - ID: MustIDBase16(fourID), + ID: fourID, Name: "org4", }, }, - UserResourceMappings: []*influxdb.UserResourceMapping{ - { - ResourceID: MustIDBase16(oneID), - UserID: MustIDBase16(sixID), - UserType: influxdb.Member, - ResourceType: influxdb.NotificationEndpointResourceType, - }, - { - ResourceID: MustIDBase16(twoID), - UserID: MustIDBase16(sixID), - UserType: influxdb.Member, - ResourceType: influxdb.NotificationEndpointResourceType, - }, - }, NotificationEndpoints: []influxdb.NotificationEndpoint{ &endpoint.Slack{ Base: endpoint.Base{ - ID: MustIDBase16Ptr(oneID), - OrgID: MustIDBase16Ptr(fourID), + ID: idPtr(oneID), + OrgID: idPtr(fourID), Status: influxdb.Active, Name: "edp1", }, URL: "example-slack.com", - Token: influxdb.SecretField{Key: oneID + "-token"}, + Token: influxdb.SecretField{Key: fmt.Sprintf("%s-token", oneID)}, }, &endpoint.HTTP{ Base: endpoint.Base{ - ID: MustIDBase16Ptr(twoID), - OrgID: MustIDBase16Ptr(fourID), + ID: idPtr(twoID), + OrgID: idPtr(fourID), Status: influxdb.Active, Name: "edp2", }, @@ -1272,22 +942,18 @@ func FindNotificationEndpoints( }, &endpoint.PagerDuty{ Base: endpoint.Base{ - ID: MustIDBase16Ptr(threeID), - OrgID: MustIDBase16Ptr(fourID), + ID: idPtr(threeID), + OrgID: idPtr(fourID), Status: influxdb.Active, Name: "edp3", }, - ClientURL: "example-pagerduty.com", RoutingKey: influxdb.SecretField{Key: threeID + "-routing-key"}, + ClientURL: "example-pagerduty.com", RoutingKey: influxdb.SecretField{Key: fmt.Sprintf("%s-routing-key", threeID)}, }, }, }, args: args{ filter: influxdb.NotificationEndpointFilter{ - ID: idPtr(MustIDBase16(fiveID)), - UserResourceMappingFilter: influxdb.UserResourceMappingFilter{ - UserID: MustIDBase16(sixID), - ResourceType: influxdb.NotificationEndpointResourceType, - }, + ID: idPtr(fiveID), }, }, wants: wants{}, @@ -1339,26 +1005,12 @@ func UpdateNotificationEndpoint( name: "can't find the id", fields: NotificationEndpointFields{ TimeGenerator: fakeGenerator, - UserResourceMappings: []*influxdb.UserResourceMapping{ - { - ResourceID: MustIDBase16(oneID), - UserID: MustIDBase16(sixID), - UserType: influxdb.Owner, - ResourceType: influxdb.NotificationEndpointResourceType, - }, - { - ResourceID: MustIDBase16(twoID), - UserID: MustIDBase16(sixID), - UserType: influxdb.Member, - ResourceType: influxdb.NotificationEndpointResourceType, - }, - }, NotificationEndpoints: []influxdb.NotificationEndpoint{ &endpoint.Slack{ Base: endpoint.Base{ - ID: MustIDBase16Ptr(oneID), + ID: idPtr(oneID), Name: "name1", - OrgID: MustIDBase16Ptr(fourID), + OrgID: idPtr(fourID), Status: influxdb.Active, CRUDLog: influxdb.CRUDLog{ CreatedAt: timeGen1.Now(), @@ -1366,32 +1018,32 @@ func UpdateNotificationEndpoint( }, }, URL: "example-slack.com", - Token: influxdb.SecretField{Key: oneID + "-token"}, + Token: influxdb.SecretField{Key: fmt.Sprintf("%s-token", oneID)}, }, &endpoint.PagerDuty{ Base: endpoint.Base{ - ID: MustIDBase16Ptr(twoID), + ID: idPtr(twoID), Name: "name2", - OrgID: MustIDBase16Ptr(fourID), + OrgID: idPtr(fourID), Status: influxdb.Active, CRUDLog: influxdb.CRUDLog{ CreatedAt: timeGen1.Now(), UpdatedAt: timeGen2.Now(), }, }, - ClientURL: "example-pagerduty.com", RoutingKey: influxdb.SecretField{Key: twoID + "-routing-key"}, + ClientURL: "example-pagerduty.com", RoutingKey: influxdb.SecretField{Key: fmt.Sprintf("%s-routing-key", twoID)}, }, }, }, args: args{ - userID: MustIDBase16(sixID), - id: MustIDBase16(fourID), - orgID: MustIDBase16(fourID), + userID: sixID, + id: fourID, + orgID: fourID, notificationEndpoint: &endpoint.PagerDuty{ Base: endpoint.Base{ - ID: MustIDBase16Ptr(twoID), + ID: idPtr(twoID), Name: "name2", - OrgID: MustIDBase16Ptr(fourID), + OrgID: idPtr(fourID), Status: influxdb.Inactive, }, ClientURL: "example-pagerduty.com", @@ -1401,7 +1053,7 @@ func UpdateNotificationEndpoint( wants: wants{ err: &influxdb.Error{ Code: influxdb.ENotFound, - Msg: "notification endpoint not found", + Msg: `notification endpoint not found for key "0000000000000004"`, }, }, }, @@ -1409,26 +1061,12 @@ func UpdateNotificationEndpoint( name: "regular update", fields: NotificationEndpointFields{ TimeGenerator: fakeGenerator, - UserResourceMappings: []*influxdb.UserResourceMapping{ - { - ResourceID: MustIDBase16(oneID), - UserID: MustIDBase16(sixID), - UserType: influxdb.Owner, - ResourceType: influxdb.NotificationEndpointResourceType, - }, - { - ResourceID: MustIDBase16(twoID), - UserID: MustIDBase16(sixID), - UserType: influxdb.Member, - ResourceType: influxdb.NotificationEndpointResourceType, - }, - }, NotificationEndpoints: []influxdb.NotificationEndpoint{ &endpoint.Slack{ Base: endpoint.Base{ - ID: MustIDBase16Ptr(oneID), + ID: idPtr(oneID), Name: "name1", - OrgID: MustIDBase16Ptr(fourID), + OrgID: idPtr(fourID), Status: influxdb.Active, CRUDLog: influxdb.CRUDLog{ CreatedAt: timeGen1.Now(), @@ -1436,32 +1074,32 @@ func UpdateNotificationEndpoint( }, }, URL: "example-slack.com", - Token: influxdb.SecretField{Key: oneID + "-token"}, + Token: influxdb.SecretField{Key: fmt.Sprintf("%s-token", oneID)}, }, &endpoint.PagerDuty{ Base: endpoint.Base{ - ID: MustIDBase16Ptr(twoID), + ID: idPtr(twoID), Name: "name2", - OrgID: MustIDBase16Ptr(fourID), + OrgID: idPtr(fourID), Status: influxdb.Active, CRUDLog: influxdb.CRUDLog{ CreatedAt: timeGen1.Now(), UpdatedAt: timeGen2.Now(), }, }, - ClientURL: "example-pagerduty.com", RoutingKey: influxdb.SecretField{Key: twoID + "-routing-key"}, + ClientURL: "example-pagerduty.com", RoutingKey: influxdb.SecretField{Key: fmt.Sprintf("%s-routing-key", twoID)}, }, }, }, args: args{ - userID: MustIDBase16(sixID), - id: MustIDBase16(twoID), - orgID: MustIDBase16(fourID), + userID: sixID, + id: twoID, + orgID: fourID, notificationEndpoint: &endpoint.PagerDuty{ Base: endpoint.Base{ - ID: MustIDBase16Ptr(twoID), + ID: idPtr(twoID), Name: "name3", - OrgID: MustIDBase16Ptr(fourID), + OrgID: idPtr(fourID), Status: influxdb.Inactive, }, ClientURL: "example-pagerduty2.com", @@ -1471,9 +1109,9 @@ func UpdateNotificationEndpoint( wants: wants{ notificationEndpoint: &endpoint.PagerDuty{ Base: endpoint.Base{ - ID: MustIDBase16Ptr(twoID), + ID: idPtr(twoID), Name: "name3", - OrgID: MustIDBase16Ptr(fourID), + OrgID: idPtr(fourID), Status: influxdb.Inactive, CRUDLog: influxdb.CRUDLog{ CreatedAt: timeGen1.Now(), @@ -1481,7 +1119,7 @@ func UpdateNotificationEndpoint( }, }, ClientURL: "example-pagerduty2.com", - RoutingKey: influxdb.SecretField{Key: twoID + "-routing-key"}, + RoutingKey: influxdb.SecretField{Key: fmt.Sprintf("%s-routing-key", twoID)}, }, }, }, @@ -1489,26 +1127,12 @@ func UpdateNotificationEndpoint( name: "update secret", fields: NotificationEndpointFields{ TimeGenerator: fakeGenerator, - UserResourceMappings: []*influxdb.UserResourceMapping{ - { - ResourceID: MustIDBase16(oneID), - UserID: MustIDBase16(sixID), - UserType: influxdb.Owner, - ResourceType: influxdb.NotificationEndpointResourceType, - }, - { - ResourceID: MustIDBase16(twoID), - UserID: MustIDBase16(sixID), - UserType: influxdb.Member, - ResourceType: influxdb.NotificationEndpointResourceType, - }, - }, NotificationEndpoints: []influxdb.NotificationEndpoint{ &endpoint.PagerDuty{ Base: endpoint.Base{ - ID: MustIDBase16Ptr(twoID), + ID: idPtr(twoID), Name: "name2", - OrgID: MustIDBase16Ptr(fourID), + OrgID: idPtr(fourID), Status: influxdb.Active, CRUDLog: influxdb.CRUDLog{ CreatedAt: timeGen1.Now(), @@ -1516,19 +1140,19 @@ func UpdateNotificationEndpoint( }, }, ClientURL: "example-pagerduty.com", - RoutingKey: influxdb.SecretField{Key: twoID + "-routing-key"}, + RoutingKey: influxdb.SecretField{Key: fmt.Sprintf("%s-routing-key", twoID)}, }, }, }, args: args{ - userID: MustIDBase16(sixID), - id: MustIDBase16(twoID), - orgID: MustIDBase16(fourID), + userID: sixID, + id: twoID, + orgID: fourID, notificationEndpoint: &endpoint.PagerDuty{ Base: endpoint.Base{ - ID: MustIDBase16Ptr(twoID), + ID: idPtr(twoID), Name: "name3", - OrgID: MustIDBase16Ptr(fourID), + OrgID: idPtr(fourID), Status: influxdb.Inactive, }, ClientURL: "example-pagerduty2.com", @@ -1540,9 +1164,9 @@ func UpdateNotificationEndpoint( wants: wants{ notificationEndpoint: &endpoint.PagerDuty{ Base: endpoint.Base{ - ID: MustIDBase16Ptr(twoID), + ID: idPtr(twoID), Name: "name3", - OrgID: MustIDBase16Ptr(fourID), + OrgID: idPtr(fourID), Status: influxdb.Inactive, CRUDLog: influxdb.CRUDLog{ CreatedAt: timeGen1.Now(), @@ -1562,9 +1186,7 @@ func UpdateNotificationEndpoint( edp, err := s.UpdateNotificationEndpoint(ctx, tt.args.id, tt.args.notificationEndpoint, tt.args.userID) if err != nil { - iErr, ok := err.(*influxdb.Error) - require.True(t, ok) - assert.Equal(t, tt.wants.err.Code, iErr.Code) + require.Equal(t, tt.wants.err, err) return } @@ -1621,26 +1243,12 @@ func PatchNotificationEndpoint( name: "can't find the id", fields: NotificationEndpointFields{ TimeGenerator: fakeGenerator, - UserResourceMappings: []*influxdb.UserResourceMapping{ - { - ResourceID: MustIDBase16(oneID), - UserID: MustIDBase16(sixID), - UserType: influxdb.Owner, - ResourceType: influxdb.NotificationEndpointResourceType, - }, - { - ResourceID: MustIDBase16(twoID), - UserID: MustIDBase16(sixID), - UserType: influxdb.Member, - ResourceType: influxdb.NotificationEndpointResourceType, - }, - }, NotificationEndpoints: []influxdb.NotificationEndpoint{ &endpoint.Slack{ Base: endpoint.Base{ - ID: MustIDBase16Ptr(oneID), + ID: idPtr(oneID), Name: "name1", - OrgID: MustIDBase16Ptr(fourID), + OrgID: idPtr(fourID), Status: influxdb.Active, CRUDLog: influxdb.CRUDLog{ CreatedAt: timeGen1.Now(), @@ -1648,13 +1256,13 @@ func PatchNotificationEndpoint( }, }, URL: "example-slack.com", - Token: influxdb.SecretField{Key: oneID + "-token"}, + Token: influxdb.SecretField{Key: fmt.Sprintf("%s-token", oneID)}, }, &endpoint.PagerDuty{ Base: endpoint.Base{ - ID: MustIDBase16Ptr(twoID), + ID: idPtr(twoID), Name: "name2", - OrgID: MustIDBase16Ptr(fourID), + OrgID: idPtr(fourID), Status: influxdb.Active, CRUDLog: influxdb.CRUDLog{ CreatedAt: timeGen1.Now(), @@ -1662,12 +1270,12 @@ func PatchNotificationEndpoint( }, }, ClientURL: "example-pagerduty.com", - RoutingKey: influxdb.SecretField{Key: twoID + "-routing-key"}, + RoutingKey: influxdb.SecretField{Key: fmt.Sprintf("%s-routing-key", twoID)}, }, }, }, args: args{ - id: MustIDBase16(fourID), + id: fourID, upd: influxdb.NotificationEndpointUpdate{ Name: &name3, Status: &status3, @@ -1684,53 +1292,39 @@ func PatchNotificationEndpoint( name: "regular update", fields: NotificationEndpointFields{ TimeGenerator: fakeGenerator, - UserResourceMappings: []*influxdb.UserResourceMapping{ - { - ResourceID: MustIDBase16(oneID), - UserID: MustIDBase16(sixID), - UserType: influxdb.Owner, - ResourceType: influxdb.NotificationEndpointResourceType, - }, - { - ResourceID: MustIDBase16(twoID), - UserID: MustIDBase16(sixID), - UserType: influxdb.Member, - ResourceType: influxdb.NotificationEndpointResourceType, - }, - }, NotificationEndpoints: []influxdb.NotificationEndpoint{ &endpoint.Slack{ Base: endpoint.Base{ - ID: MustIDBase16Ptr(oneID), + ID: idPtr(oneID), Name: "name1", Status: influxdb.Active, - OrgID: MustIDBase16Ptr(fourID), + OrgID: idPtr(fourID), CRUDLog: influxdb.CRUDLog{ CreatedAt: timeGen1.Now(), UpdatedAt: timeGen2.Now(), }, }, URL: "example-slack.com", - Token: influxdb.SecretField{Key: oneID + "-token"}, + Token: influxdb.SecretField{Key: fmt.Sprintf("%s-token", oneID)}, }, &endpoint.PagerDuty{ Base: endpoint.Base{ - ID: MustIDBase16Ptr(twoID), + ID: idPtr(twoID), Name: "name2", Status: influxdb.Active, - OrgID: MustIDBase16Ptr(fourID), + OrgID: idPtr(fourID), CRUDLog: influxdb.CRUDLog{ CreatedAt: timeGen1.Now(), UpdatedAt: timeGen2.Now(), }, }, ClientURL: "example-pagerduty.com", - RoutingKey: influxdb.SecretField{Key: twoID + "-routing-key"}, + RoutingKey: influxdb.SecretField{Key: fmt.Sprintf("%s-routing-key", twoID)}, }, }, }, args: args{ - id: MustIDBase16(twoID), + id: twoID, upd: influxdb.NotificationEndpointUpdate{ Name: &name3, Status: &status3, @@ -1739,17 +1333,17 @@ func PatchNotificationEndpoint( wants: wants{ notificationEndpoint: &endpoint.PagerDuty{ Base: endpoint.Base{ - ID: MustIDBase16Ptr(twoID), + ID: idPtr(twoID), Name: name3, Status: status3, - OrgID: MustIDBase16Ptr(fourID), + OrgID: idPtr(fourID), CRUDLog: influxdb.CRUDLog{ CreatedAt: timeGen1.Now(), UpdatedAt: fakeDate, }, }, ClientURL: "example-pagerduty.com", - RoutingKey: influxdb.SecretField{Key: twoID + "-routing-key"}, + RoutingKey: influxdb.SecretField{Key: fmt.Sprintf("%s-routing-key", twoID)}, }, }, }, @@ -1790,7 +1384,6 @@ func DeleteNotificationEndpoint( type wants struct { notificationEndpoints []influxdb.NotificationEndpoint - userResourceMappings []*influxdb.UserResourceMapping secretFlds []influxdb.SecretField orgID influxdb.ID err *influxdb.Error @@ -1804,26 +1397,12 @@ func DeleteNotificationEndpoint( { name: "bad id", fields: NotificationEndpointFields{ - UserResourceMappings: []*influxdb.UserResourceMapping{ - { - ResourceID: MustIDBase16(oneID), - UserID: MustIDBase16(sixID), - UserType: influxdb.Owner, - ResourceType: influxdb.NotificationEndpointResourceType, - }, - { - ResourceID: MustIDBase16(twoID), - UserID: MustIDBase16(sixID), - UserType: influxdb.Member, - ResourceType: influxdb.NotificationEndpointResourceType, - }, - }, NotificationEndpoints: []influxdb.NotificationEndpoint{ &endpoint.Slack{ Base: endpoint.Base{ - ID: MustIDBase16Ptr(oneID), + ID: idPtr(oneID), Name: "name1", - OrgID: MustIDBase16Ptr(fourID), + OrgID: idPtr(fourID), Status: influxdb.Active, CRUDLog: influxdb.CRUDLog{ CreatedAt: timeGen1.Now(), @@ -1831,13 +1410,13 @@ func DeleteNotificationEndpoint( }, }, URL: "example-slack.com", - Token: influxdb.SecretField{Key: oneID + "-token"}, + Token: influxdb.SecretField{Key: fmt.Sprintf("%s-token", oneID)}, }, &endpoint.PagerDuty{ Base: endpoint.Base{ - ID: MustIDBase16Ptr(twoID), + ID: idPtr(twoID), Name: "name2", - OrgID: MustIDBase16Ptr(fourID), + OrgID: idPtr(fourID), Status: influxdb.Active, CRUDLog: influxdb.CRUDLog{ CreatedAt: timeGen1.Now(), @@ -1845,40 +1424,26 @@ func DeleteNotificationEndpoint( }, }, ClientURL: "example-pagerduty.com", - RoutingKey: influxdb.SecretField{Key: twoID + "-routing-key"}, + RoutingKey: influxdb.SecretField{Key: fmt.Sprintf("%s-routing-key", twoID)}, }, }, }, args: args{ id: influxdb.ID(0), - orgID: MustIDBase16(fourID), - userID: MustIDBase16(sixID), + orgID: fourID, + userID: sixID, }, wants: wants{ err: &influxdb.Error{ Code: influxdb.EInvalid, Msg: "no key was provided for notification endpoint", }, - userResourceMappings: []*influxdb.UserResourceMapping{ - { - ResourceID: MustIDBase16(oneID), - UserID: MustIDBase16(sixID), - UserType: influxdb.Owner, - ResourceType: influxdb.NotificationEndpointResourceType, - }, - { - ResourceID: MustIDBase16(twoID), - UserID: MustIDBase16(sixID), - UserType: influxdb.Member, - ResourceType: influxdb.NotificationEndpointResourceType, - }, - }, notificationEndpoints: []influxdb.NotificationEndpoint{ &endpoint.Slack{ Base: endpoint.Base{ - ID: MustIDBase16Ptr(oneID), + ID: idPtr(oneID), Name: "name1", - OrgID: MustIDBase16Ptr(fourID), + OrgID: idPtr(fourID), Status: influxdb.Active, CRUDLog: influxdb.CRUDLog{ CreatedAt: timeGen1.Now(), @@ -1886,20 +1451,20 @@ func DeleteNotificationEndpoint( }, }, URL: "example-slack.com", - Token: influxdb.SecretField{Key: oneID + "-token"}, + Token: influxdb.SecretField{Key: fmt.Sprintf("%s-token", oneID)}, }, &endpoint.PagerDuty{ Base: endpoint.Base{ - ID: MustIDBase16Ptr(twoID), + ID: idPtr(twoID), Name: "name2", - OrgID: MustIDBase16Ptr(fourID), + OrgID: idPtr(fourID), Status: influxdb.Active, CRUDLog: influxdb.CRUDLog{ CreatedAt: timeGen1.Now(), UpdatedAt: timeGen2.Now(), }, }, - ClientURL: "example-pagerduty.com", RoutingKey: influxdb.SecretField{Key: twoID + "-routing-key"}, + ClientURL: "example-pagerduty.com", RoutingKey: influxdb.SecretField{Key: fmt.Sprintf("%s-routing-key", twoID)}, }, }, }, @@ -1907,26 +1472,12 @@ func DeleteNotificationEndpoint( { name: "none existing endpoint", fields: NotificationEndpointFields{ - UserResourceMappings: []*influxdb.UserResourceMapping{ - { - ResourceID: MustIDBase16(oneID), - UserID: MustIDBase16(sixID), - UserType: influxdb.Owner, - ResourceType: influxdb.NotificationEndpointResourceType, - }, - { - ResourceID: MustIDBase16(twoID), - UserID: MustIDBase16(sixID), - UserType: influxdb.Member, - ResourceType: influxdb.NotificationEndpointResourceType, - }, - }, NotificationEndpoints: []influxdb.NotificationEndpoint{ &endpoint.Slack{ Base: endpoint.Base{ - ID: MustIDBase16Ptr(oneID), + ID: idPtr(oneID), Name: "name1", - OrgID: MustIDBase16Ptr(fourID), + OrgID: idPtr(fourID), Status: influxdb.Active, CRUDLog: influxdb.CRUDLog{ CreatedAt: timeGen1.Now(), @@ -1934,53 +1485,39 @@ func DeleteNotificationEndpoint( }, }, URL: "example-slack.com", - Token: influxdb.SecretField{Key: oneID + "-token"}, + Token: influxdb.SecretField{Key: fmt.Sprintf("%s-token", oneID)}, }, &endpoint.PagerDuty{ Base: endpoint.Base{ - ID: MustIDBase16Ptr(twoID), + ID: idPtr(twoID), Name: "name2", - OrgID: MustIDBase16Ptr(fourID), + OrgID: idPtr(fourID), Status: influxdb.Active, CRUDLog: influxdb.CRUDLog{ CreatedAt: timeGen1.Now(), UpdatedAt: timeGen2.Now(), }, }, - ClientURL: "example-pagerduty.com", RoutingKey: influxdb.SecretField{Key: twoID + "-routing-key"}, + ClientURL: "example-pagerduty.com", RoutingKey: influxdb.SecretField{Key: fmt.Sprintf("%s-routing-key", twoID)}, }, }, }, args: args{ - id: MustIDBase16(fourID), - orgID: MustIDBase16(fourID), - userID: MustIDBase16(sixID), + id: fourID, + orgID: fourID, + userID: sixID, }, wants: wants{ err: &influxdb.Error{ Code: influxdb.ENotFound, Msg: "notification endpoint not found", }, - userResourceMappings: []*influxdb.UserResourceMapping{ - { - ResourceID: MustIDBase16(oneID), - UserID: MustIDBase16(sixID), - UserType: influxdb.Owner, - ResourceType: influxdb.NotificationEndpointResourceType, - }, - { - ResourceID: MustIDBase16(twoID), - UserID: MustIDBase16(sixID), - UserType: influxdb.Member, - ResourceType: influxdb.NotificationEndpointResourceType, - }, - }, notificationEndpoints: []influxdb.NotificationEndpoint{ &endpoint.Slack{ Base: endpoint.Base{ - ID: MustIDBase16Ptr(oneID), + ID: idPtr(oneID), Name: "name1", - OrgID: MustIDBase16Ptr(fourID), + OrgID: idPtr(fourID), Status: influxdb.Active, CRUDLog: influxdb.CRUDLog{ CreatedAt: timeGen1.Now(), @@ -1988,13 +1525,13 @@ func DeleteNotificationEndpoint( }, }, URL: "example-slack.com", - Token: influxdb.SecretField{Key: oneID + "-token"}, + Token: influxdb.SecretField{Key: fmt.Sprintf("%s-token", oneID)}, }, &endpoint.PagerDuty{ Base: endpoint.Base{ - ID: MustIDBase16Ptr(twoID), + ID: idPtr(twoID), Name: "name2", - OrgID: MustIDBase16Ptr(fourID), + OrgID: idPtr(fourID), Status: influxdb.Active, CRUDLog: influxdb.CRUDLog{ CreatedAt: timeGen1.Now(), @@ -2002,7 +1539,7 @@ func DeleteNotificationEndpoint( }, }, ClientURL: "example-pagerduty.com", - RoutingKey: influxdb.SecretField{Key: twoID + "-routing-key"}, + RoutingKey: influxdb.SecretField{Key: fmt.Sprintf("%s-routing-key", twoID)}, }, }, }, @@ -2010,26 +1547,12 @@ func DeleteNotificationEndpoint( { name: "regular delete", fields: NotificationEndpointFields{ - UserResourceMappings: []*influxdb.UserResourceMapping{ - { - ResourceID: MustIDBase16(oneID), - UserID: MustIDBase16(sixID), - UserType: influxdb.Owner, - ResourceType: influxdb.NotificationEndpointResourceType, - }, - { - ResourceID: MustIDBase16(twoID), - UserID: MustIDBase16(sixID), - UserType: influxdb.Member, - ResourceType: influxdb.NotificationEndpointResourceType, - }, - }, NotificationEndpoints: []influxdb.NotificationEndpoint{ &endpoint.Slack{ Base: endpoint.Base{ - ID: MustIDBase16Ptr(oneID), + ID: idPtr(oneID), Name: "name1", - OrgID: MustIDBase16Ptr(fourID), + OrgID: idPtr(fourID), Status: influxdb.Active, CRUDLog: influxdb.CRUDLog{ CreatedAt: timeGen1.Now(), @@ -2037,13 +1560,13 @@ func DeleteNotificationEndpoint( }, }, URL: "example-slack.com", - Token: influxdb.SecretField{Key: oneID + "-token"}, + Token: influxdb.SecretField{Key: fmt.Sprintf("%s-token", oneID)}, }, &endpoint.PagerDuty{ Base: endpoint.Base{ - ID: MustIDBase16Ptr(twoID), + ID: idPtr(twoID), Name: "name2", - OrgID: MustIDBase16Ptr(fourID), + OrgID: idPtr(fourID), Status: influxdb.Active, CRUDLog: influxdb.CRUDLog{ CreatedAt: timeGen1.Now(), @@ -2051,34 +1574,26 @@ func DeleteNotificationEndpoint( }, }, ClientURL: "example-pagerduty.com", - RoutingKey: influxdb.SecretField{Key: twoID + "-routing-key"}, + RoutingKey: influxdb.SecretField{Key: fmt.Sprintf("%s-routing-key", twoID)}, }, }, }, args: args{ - id: MustIDBase16(twoID), - orgID: MustIDBase16(fourID), - userID: MustIDBase16(sixID), + id: twoID, + orgID: fourID, + userID: sixID, }, wants: wants{ secretFlds: []influxdb.SecretField{ - {Key: twoID + "-routing-key"}, - }, - orgID: MustIDBase16(fourID), - userResourceMappings: []*influxdb.UserResourceMapping{ - { - ResourceID: MustIDBase16(oneID), - UserID: MustIDBase16(sixID), - UserType: influxdb.Owner, - ResourceType: influxdb.NotificationEndpointResourceType, - }, + {Key: fmt.Sprintf("%s-routing-key", twoID)}, }, + orgID: fourID, notificationEndpoints: []influxdb.NotificationEndpoint{ &endpoint.Slack{ Base: endpoint.Base{ - ID: MustIDBase16Ptr(oneID), + ID: idPtr(oneID), Name: "name1", - OrgID: MustIDBase16Ptr(fourID), + OrgID: idPtr(fourID), Status: influxdb.Active, CRUDLog: influxdb.CRUDLog{ CreatedAt: timeGen1.Now(), @@ -2086,7 +1601,7 @@ func DeleteNotificationEndpoint( }, }, URL: "example-slack.com", - Token: influxdb.SecretField{Key: oneID + "-token"}, + Token: influxdb.SecretField{Key: fmt.Sprintf("%s-token", oneID)}, }, }, }, @@ -2120,17 +1635,6 @@ func DeleteNotificationEndpoint( t.Errorf("notification endpoints are different -got/+want\ndiff %s", diff) } - urms, _, err := s.FindUserResourceMappings(ctx, influxdb.UserResourceMappingFilter{ - UserID: tt.args.userID, - ResourceType: influxdb.NotificationEndpointResourceType, - }) - 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) - } - var deletedEndpoint influxdb.NotificationEndpoint for _, ne := range tt.fields.NotificationEndpoints { if ne.GetID() == tt.args.id { @@ -2171,3 +1675,35 @@ func influxErrsEqual(t *testing.T, expected *influxdb.Error, actual error) { assert.Equal(t, expected.Code, iErr.Code) assert.Truef(t, strings.HasPrefix(iErr.Error(), expected.Error()), "expected: %s got err: %s", expected.Error(), actual.Error()) } + +func idPtr(id influxdb.ID) *influxdb.ID { + return &id +} + +func strPtr(s string) *string { return &s } + +// ErrorsEqual checks to see if the provided errors are equivalent. +func ErrorsEqual(t *testing.T, actual, expected error) { + t.Helper() + if expected == nil && actual == nil { + return + } + + if expected == nil && actual != nil { + t.Errorf("unexpected error %s", actual.Error()) + } + + if expected != nil && actual == nil { + t.Errorf("expected error %s but received nil", expected.Error()) + } + + if influxdb.ErrorCode(expected) != influxdb.ErrorCode(actual) { + t.Logf("\nexpected: %v\nactual: %v\n\n", expected, actual) + t.Errorf("expected error code %q but received %q", influxdb.ErrorCode(expected), influxdb.ErrorCode(actual)) + } + + if influxdb.ErrorMessage(expected) != influxdb.ErrorMessage(actual) { + t.Logf("\nexpected: %v\nactual: %v\n\n", expected, actual) + t.Errorf("expected error message %q but received %q", influxdb.ErrorMessage(expected), influxdb.ErrorMessage(actual)) + } +} diff --git a/notification/rule/service/service.go b/notification/rule/service/service.go index de4aa40d833..4b2c3ce5f56 100644 --- a/notification/rule/service/service.go +++ b/notification/rule/service/service.go @@ -44,8 +44,8 @@ type RuleService struct { timeGenerator influxdb.TimeGenerator } -// NewRuleService constructs and configures a notification rule service -func NewRuleService(logger *zap.Logger, store kv.Store, tasks influxdb.TaskService, orgs influxdb.OrganizationService, endpoints influxdb.NotificationEndpointService) (*RuleService, error) { +// New constructs and configures a notification rule service +func New(logger *zap.Logger, store kv.Store, tasks influxdb.TaskService, orgs influxdb.OrganizationService, endpoints influxdb.NotificationEndpointService) (*RuleService, error) { s := &RuleService{ log: logger, kv: store, diff --git a/notification/rule/service/service_test.go b/notification/rule/service/service_test.go index e0395222eff..f1d2d259484 100644 --- a/notification/rule/service/service_test.go +++ b/notification/rule/service/service_test.go @@ -13,6 +13,7 @@ import ( "github.com/influxdata/influxdb/v2/kv" "github.com/influxdata/influxdb/v2/kv/migration/all" "github.com/influxdata/influxdb/v2/mock" + endpointservice "github.com/influxdata/influxdb/v2/notification/endpoint/service" _ "github.com/influxdata/influxdb/v2/query/builtin" "github.com/influxdata/influxdb/v2/query/fluxlang" "github.com/influxdata/influxdb/v2/tenant" @@ -68,7 +69,12 @@ func initNotificationRuleStore(s kv.Store, f NotificationRuleFields, t *testing. tenantSvc = tenant.NewService(tenantStore) ) - svc, err := NewRuleService(logger, s, kvsvc, tenantSvc, kvsvc) + endpStore := endpointservice.NewStore(s) + endpStore.IDGenerator = f.IDGenerator + endpStore.TimeGenerator = f.TimeGenerator + endp := endpointservice.New(endpStore, kvsvc) + + svc, err := New(logger, s, kvsvc, tenantSvc, endp) if err != nil { t.Fatal(err) } @@ -88,7 +94,7 @@ func initNotificationRuleStore(s kv.Store, f NotificationRuleFields, t *testing. } for _, e := range f.Endpoints { - if err := kvsvc.CreateNotificationEndpoint(ctx, e, 1); err != nil { + if err := endp.CreateNotificationEndpoint(ctx, e, 1); err != nil { t.Fatalf("failed to populate notification endpoint: %v", err) } } diff --git a/notification_endpoint.go b/notification_endpoint.go index 7f264f91c96..bcbcd3141ca 100644 --- a/notification_endpoint.go +++ b/notification_endpoint.go @@ -104,12 +104,6 @@ func (n *NotificationEndpointUpdate) Valid() error { // NotificationEndpointService represents a service for managing notification endpoints. type NotificationEndpointService interface { - // UserResourceMappingService must be part of all NotificationEndpointStore service, - // for create, delete. - UserResourceMappingService - // OrganizationService is needed for search filter - OrganizationService - // FindNotificationEndpointByID returns a single notification endpoint by ID. FindNotificationEndpointByID(ctx context.Context, id ID) (NotificationEndpoint, error) diff --git a/testing/checks.go b/testing/checks.go index 1cca38abdbc..d1a9a5f2dde 100644 --- a/testing/checks.go +++ b/testing/checks.go @@ -12,7 +12,6 @@ import ( "github.com/influxdata/flux/ast" "github.com/influxdata/flux/parser" "github.com/influxdata/influxdb/v2" - "github.com/influxdata/influxdb/v2/kv" "github.com/influxdata/influxdb/v2/mock" "github.com/influxdata/influxdb/v2/notification" "github.com/influxdata/influxdb/v2/notification/check" @@ -160,7 +159,7 @@ type CheckFields struct { Tasks []influxdb.TaskCreate } -type checkServiceFactory func(CheckFields, *testing.T) (influxdb.CheckService, *kv.Service, string, func()) +type checkServiceFactory func(CheckFields, *testing.T) (influxdb.CheckService, influxdb.UserResourceMappingService, string, func()) type checkServiceF func( init checkServiceFactory, diff --git a/testing/util.go b/testing/util.go index 1caea3b44fc..e4aa6fcb464 100644 --- a/testing/util.go +++ b/testing/util.go @@ -2,10 +2,13 @@ package testing import ( "context" + "strings" "testing" + "github.com/influxdata/influxdb/v2" platform "github.com/influxdata/influxdb/v2" - "github.com/influxdata/influxdb/v2/kv" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) // TODO(goller): remove opPrefix argument @@ -66,7 +69,7 @@ func MustIDBase16Ptr(s string) *platform.ID { return &id } -func MustCreateOrgs(ctx context.Context, svc *kv.Service, os ...*platform.Organization) { +func MustCreateOrgs(ctx context.Context, svc influxdb.OrganizationService, os ...*platform.Organization) { for _, o := range os { if err := svc.CreateOrganization(ctx, o); err != nil { panic(err) @@ -74,7 +77,7 @@ func MustCreateOrgs(ctx context.Context, svc *kv.Service, os ...*platform.Organi } } -func MustCreateLabels(ctx context.Context, svc *kv.Service, labels ...*platform.Label) { +func MustCreateLabels(ctx context.Context, svc influxdb.LabelService, labels ...*platform.Label) { for _, l := range labels { if err := svc.CreateLabel(ctx, l); err != nil { panic(err) @@ -82,7 +85,7 @@ func MustCreateLabels(ctx context.Context, svc *kv.Service, labels ...*platform. } } -func MustCreateUsers(ctx context.Context, svc *kv.Service, us ...*platform.User) { +func MustCreateUsers(ctx context.Context, svc influxdb.UserService, us ...*platform.User) { for _, u := range us { if err := svc.CreateUser(ctx, u); err != nil { panic(err) @@ -90,7 +93,7 @@ func MustCreateUsers(ctx context.Context, svc *kv.Service, us ...*platform.User) } } -func MustCreateMappings(ctx context.Context, svc *kv.Service, ms ...*platform.UserResourceMapping) { +func MustCreateMappings(ctx context.Context, svc influxdb.UserResourceMappingService, ms ...*platform.UserResourceMapping) { for _, m := range ms { if err := svc.CreateUserResourceMapping(ctx, m); err != nil { panic(err) @@ -98,7 +101,7 @@ func MustCreateMappings(ctx context.Context, svc *kv.Service, ms ...*platform.Us } } -func MustMakeUsersOrgOwner(ctx context.Context, svc *kv.Service, oid platform.ID, uids ...platform.ID) { +func MustMakeUsersOrgOwner(ctx context.Context, svc influxdb.UserResourceMappingService, oid platform.ID, uids ...platform.ID) { ms := make([]*platform.UserResourceMapping, len(uids)) for i, uid := range uids { ms[i] = &platform.UserResourceMapping{ @@ -111,7 +114,7 @@ func MustMakeUsersOrgOwner(ctx context.Context, svc *kv.Service, oid platform.ID MustCreateMappings(ctx, svc, ms...) } -func MustMakeUsersOrgMember(ctx context.Context, svc *kv.Service, oid platform.ID, uids ...platform.ID) { +func MustMakeUsersOrgMember(ctx context.Context, svc influxdb.UserResourceMappingService, oid platform.ID, uids ...platform.ID) { ms := make([]*platform.UserResourceMapping, len(uids)) for i, uid := range uids { ms[i] = &platform.UserResourceMapping{ @@ -131,3 +134,24 @@ func MustNewPermissionAtID(id platform.ID, a platform.Action, rt platform.Resour } return perm } + +func influxErrsEqual(t *testing.T, expected *influxdb.Error, actual error) { + t.Helper() + + if expected != nil { + require.Error(t, actual) + } + + if actual == nil { + return + } + + if expected == nil { + require.NoError(t, actual) + return + } + iErr, ok := actual.(*influxdb.Error) + require.True(t, ok) + assert.Equal(t, expected.Code, iErr.Code) + assert.Truef(t, strings.HasPrefix(iErr.Error(), expected.Error()), "expected: %s got err: %s", expected.Error(), actual.Error()) +}