influxdb/tenant/service_test.go

943 lines
25 KiB
Go

package tenant_test
import (
"context"
"sort"
"strings"
"testing"
"github.com/google/go-cmp/cmp"
"github.com/influxdata/influxdb/v2"
"github.com/influxdata/influxdb/v2/kit/platform"
"github.com/influxdata/influxdb/v2/mock"
"github.com/influxdata/influxdb/v2/tenant"
itesting "github.com/influxdata/influxdb/v2/testing"
)
type tenantFields struct {
OrgIDGenerator platform.IDGenerator
BucketIDGenerator platform.IDGenerator
Users []*influxdb.User
Passwords []string // passwords are indexed against the Users field
UserResourceMappings []*influxdb.UserResourceMapping
Organizations []*influxdb.Organization
Buckets []*influxdb.Bucket
}
// TestBoltTenantService tests the tenant service functions.
// These tests stress the relation between the services embedded by the TenantService.
// The individual functionality of services is tested elsewhere.
func TestBoltTenantService(t *testing.T) {
tests := []struct {
name string
fn func(t *testing.T, init func(*testing.T, tenantFields) (*tenant.Service, func()))
}{
{
name: "Create",
fn: Create,
},
{
name: "Delete",
fn: Delete,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tt.fn(t, initBoltTenantService)
})
}
}
type bucketsByName []*influxdb.Bucket
func (b bucketsByName) Len() int {
return len(b)
}
func (b bucketsByName) Less(i, j int) bool {
return strings.Compare(b[i].Name, b[j].Name) < 0
}
func (b bucketsByName) Swap(i, j int) {
b[i], b[j] = b[j], b[i]
}
type urmByResourceID []*influxdb.UserResourceMapping
func (u urmByResourceID) Len() int {
return len(u)
}
func (u urmByResourceID) Less(i, j int) bool {
return u[i].ResourceID < u[j].ResourceID
}
func (u urmByResourceID) Swap(i, j int) {
u[i], u[j] = u[j], u[i]
}
type urmByUserID []*influxdb.UserResourceMapping
func (u urmByUserID) Len() int {
return len(u)
}
func (u urmByUserID) Less(i, j int) bool {
return u[i].UserID < u[j].UserID
}
func (u urmByUserID) Swap(i, j int) {
u[i], u[j] = u[j], u[i]
}
// Create tests various cases of creation for the services in the TenantService.
// For example, when you create a user, do you create system buckets? How are URMs organized?
func Create(t *testing.T, init func(*testing.T, tenantFields) (*tenant.Service, func())) {
t.Helper()
// Blank fields, we are testing creation.
fields := func() tenantFields {
return tenantFields{
OrgIDGenerator: mock.NewIncrementingIDGenerator(1),
BucketIDGenerator: mock.NewIncrementingIDGenerator(1),
}
}
// NOTE(affo)(*kv.Service): tests that contain s.CreateOrganization() generate error in logs:
// Failed to make user owner of organization: {"error": "could not find authorizer on context when adding user to resource type orgs"}.
// This happens because kv requires an authorization to be in context.
// This is a bad dependency pattern (store -> auth) and should not be there.
// Anyways this does not prevent the org to be created. If you add the urm manually you'll obtain the same result.
// NOTE(affo)(*kv.Service): it also creates urms for the non existing user found in context.
t.Run("creating an org creates system buckets", func(t *testing.T) {
data := fields()
s, done := init(t, data)
defer done()
ctx := context.Background()
o := &influxdb.Organization{
// ID(1)
Name: "org1",
}
if err := s.CreateOrganization(ctx, o); err != nil {
t.Fatal(err)
}
// Check existence
orgs, norgs, err := s.FindOrganizations(ctx, influxdb.OrganizationFilter{})
if err != nil {
t.Fatal(err)
}
if norgs != 1 {
t.Errorf("expected 1 org, got: %v", orgs)
}
usrs, nusrs, err := s.FindUsers(ctx, influxdb.UserFilter{})
if err != nil {
t.Fatal(err)
}
if nusrs > 0 {
t.Errorf("expected no user, got: %v", usrs)
}
urms, nurms, err := s.FindUserResourceMappings(ctx, influxdb.UserResourceMappingFilter{})
if err != nil {
t.Fatal(err)
}
if nurms > 0 {
t.Errorf("expected no urm, got: %+v", urms)
}
bs, nbs, err := s.FindBuckets(ctx, influxdb.BucketFilter{})
if err != nil {
t.Fatal(err)
}
if nbs != 2 {
t.Errorf("expected 2 buckets, got: %v", bs)
}
sort.Sort(bucketsByName(bs))
if name := bs[0].Name; name != "_monitoring" {
t.Errorf("unexpected nam for bucket: %s", name)
}
if name := bs[1].Name; name != "_tasks" {
t.Errorf("unexpected nam for bucket: %s", name)
}
})
// NOTE(affo)(*kv.Service): nope, it does create system buckets with invalid OrgIDs.
t.Run("creating user creates only the user", func(t *testing.T) {
data := fields()
s, done := init(t, data)
defer done()
ctx := context.Background()
// Number of buckets prior to user creation.
// This is because, for now, system buckets always get returned for compatibility with the old system.
_, nbs, err := s.FindBuckets(ctx, influxdb.BucketFilter{})
if err != nil {
t.Fatal(err)
}
u := &influxdb.User{
ID: 1,
Name: "user1",
}
if err := s.CreateUser(ctx, u); err != nil {
t.Fatal(err)
}
// Check existence
orgs, norgs, err := s.FindOrganizations(ctx, influxdb.OrganizationFilter{})
if err != nil {
t.Fatal(err)
}
if norgs != 0 {
t.Errorf("expected no org, got: %v", orgs)
}
usrs, nusrs, err := s.FindUsers(ctx, influxdb.UserFilter{})
if err != nil {
t.Fatal(err)
}
if nusrs != 1 {
t.Errorf("expected 1 user, got: %v", usrs)
}
urms, nurms, err := s.FindUserResourceMappings(ctx, influxdb.UserResourceMappingFilter{})
if err != nil {
t.Fatal(err)
}
if nurms > 0 {
t.Errorf("expected no urm, got: %v", urms)
}
bs, nnbs, err := s.FindBuckets(ctx, influxdb.BucketFilter{})
if err != nil {
t.Fatal(err)
}
// Compare new number of buckets with the one prior to user creation.
if nnbs != nbs {
t.Errorf("expected no bucket created, got: %+v", bs)
}
})
// NOTE(affo)(*kv.Service): nope, it does create a useless URM, no existence check.
// Apparently, system buckets are created too :thinking.
t.Run("creating urm pointing to non existing user fails", func(t *testing.T) {
data := fields()
s, done := init(t, data)
defer done()
ctx := context.Background()
// First create an org and a user.
u := &influxdb.User{
ID: 1,
Name: "user1",
}
if err := s.CreateUser(ctx, u); err != nil {
t.Fatal(err)
}
o := &influxdb.Organization{
// ID(1)
Name: "org1",
}
if err := s.CreateOrganization(ctx, o); err != nil {
t.Fatal(err)
}
checkInvariance := func(nurms int) {
orgs, norgs, err := s.FindOrganizations(ctx, influxdb.OrganizationFilter{})
if err != nil {
t.Fatal(err)
}
if norgs != 1 {
t.Errorf("expected 1 org, got: %v", orgs)
}
usrs, nusrs, err := s.FindUsers(ctx, influxdb.UserFilter{})
if err != nil {
t.Fatal(err)
}
if nusrs != 1 {
t.Errorf("expected 1 user, got: %v", usrs)
}
urms, nnurms, err := s.FindUserResourceMappings(ctx, influxdb.UserResourceMappingFilter{})
if err != nil {
t.Fatal(err)
}
if nnurms != nurms {
t.Errorf("expected %d urms got %d: %+v", nurms, nnurms, urms)
}
bs, nbs, err := s.FindBuckets(ctx, influxdb.BucketFilter{})
if err != nil {
t.Fatal(err)
}
if nbs != 2 {
t.Errorf("expected 2 buckets, got: %v", bs)
}
}
checkInvariance(0)
// Wrong userID.
urm := &influxdb.UserResourceMapping{
UserID: 2,
UserType: influxdb.Owner,
MappingType: influxdb.UserMappingType,
ResourceType: influxdb.OrgsResourceType,
ResourceID: 1,
}
if err := s.CreateUserResourceMapping(ctx, urm); err == nil {
t.Errorf("expected error got none")
}
checkInvariance(0)
// Wrong orgID. The URM gets created successfully.
urm = &influxdb.UserResourceMapping{
UserID: 1,
UserType: influxdb.Owner,
MappingType: influxdb.UserMappingType,
ResourceType: influxdb.OrgsResourceType,
ResourceID: 2,
}
if err := s.CreateUserResourceMapping(ctx, urm); err != nil {
t.Errorf("unexpected error: %v", err)
}
checkInvariance(1)
})
// NOTE(affo)(*kv.Service): errors on bucket creation.
// But, apparently, system buckets are created too :thinking.
t.Run("should not be possible to create bucket without org", func(t *testing.T) {
data := fields()
s, done := init(t, data)
defer done()
ctx := context.Background()
// Number of buckets prior to bucket creation.
// This is because, for now, system buckets always get returned for compatibility with the old system.
_, nbs, err := s.FindBuckets(ctx, influxdb.BucketFilter{})
if err != nil {
t.Fatal(err)
}
b := &influxdb.Bucket{
// ID(1)
OrgID: 1,
Name: "bucket1",
}
if err := s.CreateBucket(ctx, b); err == nil {
t.Errorf("expected error got none")
}
// Check existence
orgs, norgs, err := s.FindOrganizations(ctx, influxdb.OrganizationFilter{})
if err != nil {
t.Fatal(err)
}
if norgs != 0 {
t.Errorf("expected no org, got: %v", orgs)
}
usrs, nusrs, err := s.FindUsers(ctx, influxdb.UserFilter{})
if err != nil {
t.Fatal(err)
}
if nusrs != 0 {
t.Errorf("expected no user, got: %v", usrs)
}
urms, nurms, err := s.FindUserResourceMappings(ctx, influxdb.UserResourceMappingFilter{})
if err != nil {
t.Fatal(err)
}
if nurms > 0 {
t.Errorf("expected no urm, got: %v", urms)
}
bs, nnbs, err := s.FindBuckets(ctx, influxdb.BucketFilter{})
if err != nil {
t.Fatal(err)
}
// Compare new number of buckets with the one prior to bucket creation.
if nnbs != nbs {
t.Errorf("expected bucket created, got: %+v", bs)
}
})
t.Run("making user part of org creates mapping to org only", func(t *testing.T) {
for _, userType := range []influxdb.UserType{influxdb.Owner, influxdb.Member} {
t.Run(string(userType), func(t *testing.T) {
data := fields()
s, done := init(t, data)
defer done()
ctx := context.Background()
u := &influxdb.User{
ID: 1,
Name: "user1",
}
if err := s.CreateUser(ctx, u); err != nil {
t.Fatal(err)
}
o := &influxdb.Organization{
// ID(1)
Name: "org1",
}
if err := s.CreateOrganization(ctx, o); err != nil {
t.Fatal(err)
}
urm := &influxdb.UserResourceMapping{
UserID: u.ID,
UserType: userType,
MappingType: influxdb.UserMappingType,
ResourceType: influxdb.OrgsResourceType,
ResourceID: o.ID,
}
if err := s.CreateUserResourceMapping(ctx, urm); err != nil {
t.Fatal(err)
}
// Check existence
orgs, norgs, err := s.FindOrganizations(ctx, influxdb.OrganizationFilter{})
if err != nil {
t.Fatal(err)
}
if norgs != 1 {
t.Errorf("expected 1 org, got: %v", orgs)
}
usrs, nusrs, err := s.FindUsers(ctx, influxdb.UserFilter{})
if err != nil {
t.Fatal(err)
}
if nusrs != 1 {
t.Errorf("expected 1 user, got: %v", usrs)
}
bs, nbs, err := s.FindBuckets(ctx, influxdb.BucketFilter{})
if err != nil {
t.Fatal(err)
}
if nbs != 2 {
t.Errorf("expected 2 buckets, got: %v", bs)
}
sort.Sort(bucketsByName(bs))
if name := bs[0].Name; name != "_monitoring" {
t.Errorf("unexpected name for bucket: %s", name)
}
if name := bs[1].Name; name != "_tasks" {
t.Errorf("unexpected name for bucket: %v", name)
}
urms, _, err := s.FindUserResourceMappings(ctx, influxdb.UserResourceMappingFilter{})
if err != nil {
t.Fatal(err)
}
want := []*influxdb.UserResourceMapping{
{
UserID: u.ID,
UserType: userType,
MappingType: influxdb.UserMappingType,
ResourceType: influxdb.OrgsResourceType,
ResourceID: o.ID,
},
}
sort.Sort(urmByResourceID(want))
sort.Sort(urmByResourceID(urms))
if diff := cmp.Diff(want, urms); diff != "" {
t.Errorf("unexpected urms -want/+got:\n\t%s", diff)
}
// Now add a new bucket and check the URMs.
b := &influxdb.Bucket{
// ID(1)
OrgID: o.ID,
Name: "bucket1",
}
if err := s.CreateBucket(ctx, b); err != nil {
t.Fatal(err)
}
urms, _, err = s.FindUserResourceMappings(ctx, influxdb.UserResourceMappingFilter{})
if err != nil {
t.Fatal(err)
}
sort.Sort(urmByResourceID(urms))
if diff := cmp.Diff(want, urms); diff != "" {
t.Errorf("unexpected urms -want/+got:\n\t%s", diff)
}
})
}
})
}
// Delete tests various cases of deletion for the services in the TenantService.
// An example: if you delete a bucket the corresponding user resource mapping is not present.
func Delete(t *testing.T, init func(*testing.T, tenantFields) (*tenant.Service, func())) {
t.Helper()
fields := func() tenantFields {
return tenantFields{
OrgIDGenerator: mock.NewIncrementingIDGenerator(1),
// URM are userID + resourceID (they do not include resource type)
// so same IDs across different resources leads to collisions
// therefore, we need to start bucket IDs at higher offset for
// test.
BucketIDGenerator: mock.NewIncrementingIDGenerator(10),
Users: []*influxdb.User{
{
ID: 1,
Name: "user1",
},
{
ID: 2,
Name: "user2",
},
},
Passwords: []string{"password1", "password2"},
Organizations: []*influxdb.Organization{
{
// ID(1)
Name: "org1",
},
{
// ID(2)
Name: "org2",
},
},
// 2 organizations create 2 system buckets each
// so start at 14
Buckets: []*influxdb.Bucket{
{
// ID(14)
OrgID: 1,
Name: "bucket1",
},
{
// ID(15)
OrgID: 2,
Name: "bucket2",
},
},
UserResourceMappings: []*influxdb.UserResourceMapping{
// NOTE(affo): bucket URMs should not be here, create them only for deletion purposes.
// user 1 owns org1 (and so bucket1)
{
UserID: 1,
UserType: influxdb.Owner,
MappingType: influxdb.UserMappingType,
ResourceType: influxdb.OrgsResourceType,
ResourceID: 1,
},
{
UserID: 1,
UserType: influxdb.Owner,
MappingType: influxdb.UserMappingType,
ResourceType: influxdb.BucketsResourceType,
ResourceID: 14,
},
// user 1 is member of org2 (and so bucket2)
{
UserID: 1,
UserType: influxdb.Member,
MappingType: influxdb.UserMappingType,
ResourceType: influxdb.OrgsResourceType,
ResourceID: 2,
},
{
UserID: 1,
UserType: influxdb.Member,
MappingType: influxdb.UserMappingType,
ResourceType: influxdb.BucketsResourceType,
ResourceID: 15,
},
// user 2 owns org2 (and so bucket2)
{
UserID: 2,
UserType: influxdb.Owner,
MappingType: influxdb.UserMappingType,
ResourceType: influxdb.OrgsResourceType,
ResourceID: 2,
},
{
UserID: 2,
UserType: influxdb.Owner,
MappingType: influxdb.UserMappingType,
ResourceType: influxdb.BucketsResourceType,
ResourceID: 15,
},
},
}
}
t.Run("deleting bucket deletes urm", func(t *testing.T) {
data := fields()
s, done := init(t, data)
defer done()
ctx := context.Background()
f := influxdb.UserResourceMappingFilter{
ResourceID: data.Buckets[0].ID,
ResourceType: influxdb.BucketsResourceType,
}
urms, n, err := s.FindUserResourceMappings(ctx, f)
if err != nil {
t.Fatal(err)
}
if n != 1 {
t.Fatalf("expected 1 urm, got: %v", urms)
}
if err := s.DeleteBucket(ctx, data.Buckets[0].ID); err != nil {
t.Fatal(err)
}
f = influxdb.UserResourceMappingFilter{
ResourceID: data.Buckets[0].ID,
ResourceType: influxdb.BucketsResourceType,
}
urms, n, err = s.FindUserResourceMappings(ctx, f)
if err != nil {
t.Fatal(err)
}
if n > 0 {
t.Fatalf("expected no urm, got: %v", urms)
}
})
// NOTE(affo): those resources could not be dangling (URM could be inferred from an user being in the owner org).
// We do not want to automatically propagate this kind of delete because an resource will always have an owner org.
t.Run("deleting bucket urm does create dangling bucket", func(t *testing.T) {
data := fields()
s, done := init(t, data)
defer done()
ctx := context.Background()
// Pre-check the current situation.
// bucket1 is owned by user1.
// Check it.
urms, _, err := s.FindUserResourceMappings(ctx, influxdb.UserResourceMappingFilter{
ResourceType: influxdb.BucketsResourceType,
ResourceID: data.Buckets[0].ID,
})
if err != nil {
t.Fatal(err)
}
want := []*influxdb.UserResourceMapping{
{
UserID: data.Users[0].ID,
UserType: influxdb.Owner,
MappingType: influxdb.UserMappingType,
ResourceType: influxdb.BucketsResourceType,
ResourceID: data.Buckets[0].ID,
},
}
sort.Sort(urmByUserID(want))
sort.Sort(urmByUserID(urms))
if diff := cmp.Diff(want, urms); diff != "" {
t.Fatalf("unexpected urms -want/+got:\n\t%s", diff)
}
// bucket2 is owned by user2.
// bucket2 is readable by user2.
// Check it.
urms, _, err = s.FindUserResourceMappings(ctx, influxdb.UserResourceMappingFilter{
ResourceType: influxdb.BucketsResourceType,
ResourceID: data.Buckets[1].ID,
})
if err != nil {
t.Fatal(err)
}
want = []*influxdb.UserResourceMapping{
{
UserID: data.Users[1].ID,
UserType: influxdb.Owner,
MappingType: influxdb.UserMappingType,
ResourceType: influxdb.BucketsResourceType,
ResourceID: data.Buckets[1].ID,
},
{
UserID: data.Users[0].ID,
UserType: influxdb.Member,
MappingType: influxdb.UserMappingType,
ResourceType: influxdb.BucketsResourceType,
ResourceID: data.Buckets[1].ID,
},
}
sort.Sort(urmByUserID(want))
sort.Sort(urmByUserID(urms))
if diff := cmp.Diff(want, urms); diff != "" {
t.Fatalf("unexpected urms -want/+got:\n\t%s", diff)
}
// Now delete user2 -> bucket2.
// Still expect bucket2 to exist (user1 still points to it).
if err := s.DeleteUserResourceMapping(ctx, data.Buckets[1].ID, data.Users[1].ID); err != nil {
t.Fatal(err)
}
bs, nbs, err := s.FindBuckets(ctx, influxdb.BucketFilter{ID: &data.Buckets[1].ID})
if err != nil {
t.Fatal(err)
}
if nbs != 1 {
t.Errorf("expected 1 buckets, got: %v", bs)
}
// Now delete user1 -> bucket2.
// Still expect bucket2 to exist (nobody points to it).
if err := s.DeleteUserResourceMapping(ctx, data.Buckets[1].ID, data.Users[0].ID); err != nil {
t.Fatal(err)
}
bs, nbs, err = s.FindBuckets(ctx, influxdb.BucketFilter{ID: &data.Buckets[1].ID})
if err != nil {
t.Fatal(err)
}
if nbs != 1 {
t.Errorf("expected 1 buckets, got: %v", bs)
}
urms, nurms, err := s.FindUserResourceMappings(ctx, influxdb.UserResourceMappingFilter{
ResourceType: influxdb.BucketsResourceType,
ResourceID: data.Buckets[1].ID,
})
if err != nil {
t.Fatal(err)
}
if nurms != 0 {
t.Errorf("expected bucket2, to be dangling, got: %+v", urms)
}
// Now delete user1 -> bucket1.
// Still expect bucket1 to exist (nobody points to it).
if err := s.DeleteUserResourceMapping(ctx, data.Buckets[0].ID, data.Users[0].ID); err != nil {
t.Fatal(err)
}
bs, nbs, err = s.FindBuckets(ctx, influxdb.BucketFilter{ID: &data.Buckets[0].ID})
if err != nil {
t.Fatal(err)
}
if nbs != 1 {
t.Errorf("expected 1 buckets, got: %v", bs)
}
urms, nurms, err = s.FindUserResourceMappings(ctx, influxdb.UserResourceMappingFilter{
ResourceType: influxdb.BucketsResourceType,
ResourceID: data.Buckets[0].ID,
})
if err != nil {
t.Fatal(err)
}
if nurms != 0 {
t.Errorf("expected bucket1, to be dangling, got: %+v", urms)
}
})
t.Run("deleting a user deletes every related urm and nothing else", func(t *testing.T) {
data := fields()
s, done := init(t, data)
defer done()
ctx := context.Background()
// bucket1 is owned by user1.
// Check it.
urms, _, err := s.FindUserResourceMappings(ctx, influxdb.UserResourceMappingFilter{
ResourceType: influxdb.BucketsResourceType,
ResourceID: data.Buckets[0].ID,
})
if err != nil {
t.Fatal(err)
}
want := []*influxdb.UserResourceMapping{
{
UserID: data.Users[0].ID,
UserType: influxdb.Owner,
MappingType: influxdb.UserMappingType,
ResourceType: influxdb.BucketsResourceType,
ResourceID: data.Buckets[0].ID,
},
}
sort.Sort(urmByUserID(want))
sort.Sort(urmByUserID(urms))
if diff := cmp.Diff(want, urms); diff != "" {
t.Fatalf("unexpected urms -want/+got:\n\t%s", diff)
}
// Delete user1.
// We expect his urms deleted but not bucket1.
if err := s.DeleteUser(ctx, data.Users[0].ID); err != nil {
t.Fatal(err)
}
urms, nurms, err := s.FindUserResourceMappings(ctx, influxdb.UserResourceMappingFilter{
UserID: data.Users[0].ID,
})
if err != nil {
t.Fatal(err)
}
if nurms > 0 {
t.Errorf("expected that user deletion would remove dangling urms, got: %+v", urms)
}
bs, nbs, err := s.FindBuckets(ctx, influxdb.BucketFilter{ID: &data.Buckets[0].ID})
if err != nil {
t.Fatal(err)
}
if nbs != 1 {
t.Errorf("expected 1 buckets, got: %v", bs)
}
})
t.Run("deleting a bucket deletes every related urm", func(t *testing.T) {
data := fields()
s, done := init(t, data)
defer done()
ctx := context.Background()
// Delete bucket2.
// We expect its urms deleted.
if err := s.DeleteBucket(ctx, data.Buckets[1].ID); err != nil {
t.Fatal(err)
}
urms, nurms, err := s.FindUserResourceMappings(ctx, influxdb.UserResourceMappingFilter{
ResourceType: influxdb.BucketsResourceType,
ResourceID: data.Buckets[1].ID,
})
if err != nil {
t.Fatal(err)
}
if nurms > 0 {
t.Errorf("expected that bucket deletion would remove dangling urms, got: %+v", urms)
}
})
// NOTE(affo)(*kv.Service): buckets, users, and urms survive.
t.Run("deleting an organization should delete everything that depends on it", func(t *testing.T) {
data := fields()
s, done := init(t, data)
defer done()
ctx := context.Background()
// Delete org1.
// We expect its buckets to be deleted.
// We expect urms to those buckets to be deleted too.
// No user should be deleted.
preDeletionBuckets, _, err := s.FindBuckets(ctx, influxdb.BucketFilter{OrganizationID: &data.Organizations[0].ID})
if err != nil {
t.Fatal(err)
}
if err := s.DeleteOrganization(ctx, data.Organizations[0].ID); err != nil {
t.Fatal(err)
}
bs, nbs, err := s.FindBuckets(ctx, influxdb.BucketFilter{OrganizationID: &data.Organizations[0].ID})
if err != nil {
t.Fatal(err)
}
if nbs != 0 {
t.Errorf("expected org buckets to be deleted, got: %+v", bs)
}
urms, _, err := s.FindUserResourceMappings(ctx, influxdb.UserResourceMappingFilter{
UserID: data.Users[0].ID,
ResourceType: influxdb.BucketsResourceType,
})
if err != nil {
t.Fatal(err)
}
for _, urm := range urms {
for _, b := range preDeletionBuckets {
if urm.ResourceID == b.ID {
t.Errorf("expected this urm to be deleted, got %+v instead", urm)
}
}
}
if _, err := s.FindUser(ctx, influxdb.UserFilter{ID: &data.Users[0].ID}); err != nil {
t.Fatal(err)
}
// Delete org2.
// Everything should disappear.
if err := s.DeleteOrganization(ctx, data.Organizations[1].ID); err != nil {
t.Fatal(err)
}
orgs, norgs, err := s.FindOrganizations(ctx, influxdb.OrganizationFilter{})
if err != nil {
t.Fatal(err)
}
if norgs != 0 {
t.Errorf("expected no org, got: %v", orgs)
}
usrs, nusrs, err := s.FindUsers(ctx, influxdb.UserFilter{})
if err != nil {
t.Fatal(err)
}
if nusrs != 2 {
t.Errorf("expected 2 users, got: %v", usrs)
}
urms, nurms, err := s.FindUserResourceMappings(ctx, influxdb.UserResourceMappingFilter{})
if err != nil {
t.Fatal(err)
}
if nurms > 0 {
t.Errorf("expected no urm, got: %v", urms)
}
bs, nbs, err = s.FindBuckets(ctx, influxdb.BucketFilter{})
if err != nil {
t.Fatal(err)
}
if nbs != 0 {
t.Errorf("expected buckets to be deleted, got: %+v", bs)
}
})
}
func initBoltTenantService(t *testing.T, f tenantFields) (*tenant.Service, func()) {
s, closeBolt := itesting.NewTestBoltStore(t)
store := tenant.NewStore(s)
if f.OrgIDGenerator != nil {
store.OrgIDGen = f.OrgIDGenerator
}
if f.BucketIDGenerator != nil {
store.BucketIDGen = f.BucketIDGenerator
}
svc := tenant.NewService(store)
for _, u := range f.Users {
if err := svc.CreateUser(context.Background(), u); err != nil {
t.Fatalf("error populating users: %v", err)
}
}
for i := range f.Passwords {
if err := svc.SetPassword(context.Background(), f.Users[i].ID, f.Passwords[i]); err != nil {
t.Fatalf("error setting passsword user, %s %s: %v", f.Users[i].Name, f.Passwords[i], err)
}
}
for _, o := range f.Organizations {
if err := svc.CreateOrganization(context.Background(), o); err != nil {
t.Fatalf("failed to populate organizations: %s", err)
}
}
for _, b := range f.Buckets {
if err := svc.CreateBucket(context.Background(), b); err != nil {
t.Fatalf("failed to populate buckets: %s", err)
}
}
for _, m := range f.UserResourceMappings {
if err := svc.CreateUserResourceMapping(context.Background(), m); err != nil {
t.Fatalf("failed to populate mappings: %v", err)
}
}
return svc, func() {
for _, u := range f.Users {
if err := svc.DeleteUser(context.Background(), u.ID); err != nil {
t.Logf("error removing users: %v", err)
}
}
for _, m := range f.UserResourceMappings {
if err := svc.DeleteUserResourceMapping(context.Background(), m.ResourceID, m.UserID); err != nil {
t.Logf("failed to remove user resource mapping: %v", err)
}
}
for _, o := range f.Organizations {
if err := svc.DeleteOrganization(context.Background(), o.ID); err != nil {
t.Logf("failed to remove organization: %v", err)
}
}
closeBolt()
}
}