feat(kv): random ids without comma, space, backslash for org a… (#15049)

feat(kv): random ids without comma, space, backslash for org and bucket
pull/15062/head
Chris Goller 2019-09-08 03:11:20 -05:00 committed by GitHub
commit 80e3efa37a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 722 additions and 328 deletions

View File

@ -36,5 +36,6 @@ func initOrganizationService(f platformtesting.OrganizationFields, t *testing.T)
} }
func TestOrganizationService(t *testing.T) { func TestOrganizationService(t *testing.T) {
t.Skip("organization service no longer used. Remove all of this bolt stuff")
platformtesting.OrganizationService(initOrganizationService, t) platformtesting.OrganizationService(initOrganizationService, t)
} }

View File

@ -13,6 +13,7 @@ import (
platform "github.com/influxdata/influxdb" platform "github.com/influxdata/influxdb"
"github.com/influxdata/influxdb/inmem" "github.com/influxdata/influxdb/inmem"
"github.com/influxdata/influxdb/kv"
"github.com/influxdata/influxdb/mock" "github.com/influxdata/influxdb/mock"
platformtesting "github.com/influxdata/influxdb/testing" platformtesting "github.com/influxdata/influxdb/testing"
"github.com/julienschmidt/httprouter" "github.com/julienschmidt/httprouter"
@ -1075,14 +1076,19 @@ func TestService_handlePostBucketOwner(t *testing.T) {
} }
func initBucketService(f platformtesting.BucketFields, t *testing.T) (platform.BucketService, string, func()) { func initBucketService(f platformtesting.BucketFields, t *testing.T) (platform.BucketService, string, func()) {
svc := inmem.NewService() svc := kv.NewService(inmem.NewKVStore())
svc.IDGenerator = f.IDGenerator svc.IDGenerator = f.IDGenerator
svc.OrgBucketIDs = f.OrgBucketIDs
svc.TimeGenerator = f.TimeGenerator svc.TimeGenerator = f.TimeGenerator
if f.TimeGenerator == nil { if f.TimeGenerator == nil {
svc.TimeGenerator = platform.RealTimeGenerator{} svc.TimeGenerator = platform.RealTimeGenerator{}
} }
ctx := context.Background() ctx := context.Background()
if err := svc.Initialize(ctx); err != nil {
t.Fatal(err)
}
for _, o := range f.Organizations { for _, o := range f.Organizations {
if err := svc.PutOrganization(ctx, o); err != nil { if err := svc.PutOrganization(ctx, o); err != nil {
t.Fatalf("failed to populate organizations") t.Fatalf("failed to populate organizations")

View File

@ -14,6 +14,7 @@ import (
platform "github.com/influxdata/influxdb" platform "github.com/influxdata/influxdb"
"github.com/influxdata/influxdb/inmem" "github.com/influxdata/influxdb/inmem"
"github.com/influxdata/influxdb/kv"
"github.com/influxdata/influxdb/mock" "github.com/influxdata/influxdb/mock"
platformtesting "github.com/influxdata/influxdb/testing" platformtesting "github.com/influxdata/influxdb/testing"
) )
@ -34,14 +35,19 @@ func NewMockOrgBackend() *OrgBackend {
func initOrganizationService(f platformtesting.OrganizationFields, t *testing.T) (platform.OrganizationService, string, func()) { func initOrganizationService(f platformtesting.OrganizationFields, t *testing.T) (platform.OrganizationService, string, func()) {
t.Helper() t.Helper()
svc := inmem.NewService() svc := kv.NewService(inmem.NewKVStore())
svc.IDGenerator = f.IDGenerator svc.IDGenerator = f.IDGenerator
svc.OrgBucketIDs = f.OrgBucketIDs
svc.TimeGenerator = f.TimeGenerator svc.TimeGenerator = f.TimeGenerator
if f.TimeGenerator == nil { if f.TimeGenerator == nil {
svc.TimeGenerator = platform.RealTimeGenerator{} svc.TimeGenerator = platform.RealTimeGenerator{}
} }
ctx := context.Background() ctx := context.Background()
if err := svc.Initialize(ctx); err != nil {
t.Fatal(err)
}
for _, o := range f.Organizations { for _, o := range f.Organizations {
if err := svc.PutOrganization(ctx, o); err != nil { if err := svc.PutOrganization(ctx, o); err != nil {
t.Fatalf("failed to populate organizations") t.Fatalf("failed to populate organizations")
@ -62,6 +68,7 @@ func initOrganizationService(f platformtesting.OrganizationFields, t *testing.T)
return &client, inmem.OpPrefix, done return &client, inmem.OpPrefix, done
} }
func TestOrganizationService(t *testing.T) { func TestOrganizationService(t *testing.T) {
t.Parallel() t.Parallel()
platformtesting.OrganizationService(initOrganizationService, t) platformtesting.OrganizationService(initOrganizationService, t)
} }

View File

@ -30,5 +30,6 @@ func initBucketService(f platformtesting.BucketFields, t *testing.T) (platform.B
} }
func TestBucketService(t *testing.T) { func TestBucketService(t *testing.T) {
t.Skip("bucket service no longer used. Remove all of this inmem stuff")
platformtesting.BucketService(initBucketService, t) platformtesting.BucketService(initBucketService, t)
} }

View File

@ -25,5 +25,6 @@ func initOrganizationService(f platformtesting.OrganizationFields, t *testing.T)
} }
func TestOrganizationService(t *testing.T) { func TestOrganizationService(t *testing.T) {
t.Skip("organization service no longer used. Remove all of this inmem stuff")
platformtesting.OrganizationService(initOrganizationService, t) platformtesting.OrganizationService(initOrganizationService, t)
} }

View File

@ -3,7 +3,6 @@ package kv
import ( import (
"context" "context"
"encoding/json" "encoding/json"
"errors"
"fmt" "fmt"
"strings" "strings"
"time" "time"
@ -425,7 +424,7 @@ func (s *Service) createBucket(ctx context.Context, tx Tx, b *influxdb.Bucket) (
return err return err
} }
if b.ID, err = s.generateBucketID(); err != nil { if b.ID, err = s.generateBucketID(ctx, tx); err != nil {
return err return err
} }
@ -448,14 +447,8 @@ func (s *Service) createBucket(ctx context.Context, tx Tx, b *influxdb.Bucket) (
return nil return nil
} }
func (s *Service) generateBucketID() (influxdb.ID, error) { func (s *Service) generateBucketID(ctx context.Context, tx Tx) (influxdb.ID, error) {
for i := 0; i < MaxIDGenerationN; i++ { return s.generateSafeID(ctx, tx, bucketBucket)
id := s.IDGenerator.ID()
if s.IsValidOrgBucketID == nil || s.IsValidOrgBucketID(id) {
return id, nil
}
}
return 0, errors.New("unable to generate valid bucket id")
} }
// PutBucket will put a bucket without setting an ID. // PutBucket will put a bucket without setting an ID.

View File

@ -5,7 +5,6 @@ import (
"testing" "testing"
"github.com/influxdata/influxdb" "github.com/influxdata/influxdb"
"github.com/influxdata/influxdb/inmem"
"github.com/influxdata/influxdb/kv" "github.com/influxdata/influxdb/kv"
influxdbtesting "github.com/influxdata/influxdb/testing" influxdbtesting "github.com/influxdata/influxdb/testing"
) )
@ -46,6 +45,7 @@ func initInmemBucketService(f influxdbtesting.BucketFields, t *testing.T) (influ
func initBucketService(s kv.Store, f influxdbtesting.BucketFields, t *testing.T) (influxdb.BucketService, string, func()) { func initBucketService(s kv.Store, f influxdbtesting.BucketFields, t *testing.T) (influxdb.BucketService, string, func()) {
svc := kv.NewService(s) svc := kv.NewService(s)
svc.OrgBucketIDs = f.OrgBucketIDs
svc.IDGenerator = f.IDGenerator svc.IDGenerator = f.IDGenerator
svc.TimeGenerator = f.TimeGenerator svc.TimeGenerator = f.TimeGenerator
if f.TimeGenerator == nil { if f.TimeGenerator == nil {
@ -79,16 +79,3 @@ func initBucketService(s kv.Store, f influxdbtesting.BucketFields, t *testing.T)
} }
} }
} }
func TestService_CreateBucket(t *testing.T) {
t.Run("InvalidBucketID", func(t *testing.T) {
svc := kv.NewService(inmem.NewKVStore())
if err := svc.PutOrganization(context.Background(), &influxdb.Organization{ID: 123, Name: "ORG"}); err != nil {
t.Fatal(err)
}
svc.IsValidOrgBucketID = func(id influxdb.ID) bool { return false }
if err := svc.CreateBucket(context.Background(), &influxdb.Bucket{OrgID: 123, Name: "BUCKET"}); err == nil || err.Error() != `unable to generate valid bucket id` {
t.Fatalf("unexpected error: %s", err)
}
})
}

View File

@ -11,7 +11,7 @@ import (
) )
var ( var (
testID = influxdb.ID(1) testID = influxdb.ID(10000)
testIDStr = testID.String() testIDStr = testID.String()
) )
@ -84,9 +84,11 @@ func testLookupName(newStore StoreFn, t *testing.T) {
ID: influxdbtesting.IDPtr(testID), ID: influxdbtesting.IDPtr(testID),
}, },
init: func(ctx context.Context, s *kv.Service) error { init: func(ctx context.Context, s *kv.Service) error {
_ = s.CreateOrganization(ctx, &influxdb.Organization{ o1 := &influxdb.Organization{
Name: "o1", Name: "o1",
}) }
_ = s.CreateOrganization(ctx, o1)
t.Log(o1)
return s.CreateBucket(ctx, &influxdb.Bucket{ return s.CreateBucket(ctx, &influxdb.Bucket{
Name: "b1", Name: "b1",
OrgID: testID, OrgID: testID,
@ -243,6 +245,7 @@ func testLookupName(newStore StoreFn, t *testing.T) {
defer done() defer done()
svc.IDGenerator = mock.NewIDGenerator(testIDStr, t) svc.IDGenerator = mock.NewIDGenerator(testIDStr, t)
svc.WithSpecialOrgBucketIDs(svc.IDGenerator)
ctx := context.Background() ctx := context.Background()
if tt.args.init != nil { if tt.args.init != nil {
if err := tt.args.init(ctx, svc); err != nil { if err := tt.args.init(ctx, svc); err != nil {

View File

@ -46,6 +46,7 @@ func initInmemOnboardingService(f influxdbtesting.OnboardingFields, t *testing.T
func initOnboardingService(s kv.Store, f influxdbtesting.OnboardingFields, t *testing.T) (influxdb.OnboardingService, func()) { func initOnboardingService(s kv.Store, f influxdbtesting.OnboardingFields, t *testing.T) (influxdb.OnboardingService, func()) {
svc := kv.NewService(s) svc := kv.NewService(s)
svc.IDGenerator = f.IDGenerator svc.IDGenerator = f.IDGenerator
svc.OrgBucketIDs = f.IDGenerator
svc.TokenGenerator = f.TokenGenerator svc.TokenGenerator = f.TokenGenerator
svc.TimeGenerator = f.TimeGenerator svc.TimeGenerator = f.TimeGenerator
if f.TimeGenerator == nil { if f.TimeGenerator == nil {

View File

@ -3,7 +3,6 @@ package kv
import ( import (
"context" "context"
"encoding/json" "encoding/json"
"errors"
"fmt" "fmt"
"strings" "strings"
"time" "time"
@ -15,14 +14,26 @@ import (
"github.com/influxdata/influxdb/kit/tracing" "github.com/influxdata/influxdb/kit/tracing"
) )
const (
// MaxIDGenerationN is the maximum number of times an ID generation is done before failing. // MaxIDGenerationN is the maximum number of times an ID generation is done before failing.
const MaxIDGenerationN = 100 MaxIDGenerationN = 100
// ReservedIDs are the number of IDs reserved from 1 - ReservedIDs we use
// for our system org/buckets
ReservedIDs = 1000
)
var ( var (
organizationBucket = []byte("organizationsv1") organizationBucket = []byte("organizationsv1")
organizationIndex = []byte("organizationindexv1") organizationIndex = []byte("organizationindexv1")
) )
// ErrFailureGeneratingID occurs ony when the random number generator
// cannot generate an ID in MaxIDGenerationN times.
var ErrFailureGeneratingID = &influxdb.Error{
Code: influxdb.EInternal,
Msg: "unable to generate valid id",
}
var _ influxdb.OrganizationService = (*Service)(nil) var _ influxdb.OrganizationService = (*Service)(nil)
var _ influxdb.OrganizationOperationLogService = (*Service)(nil) var _ influxdb.OrganizationOperationLogService = (*Service)(nil)
@ -271,7 +282,7 @@ func (s *Service) createOrganization(ctx context.Context, tx Tx, o *influxdb.Org
return err return err
} }
if o.ID, err = s.generateOrgID(); err != nil { if o.ID, err = s.generateOrgID(ctx, tx); err != nil {
return err return err
} }
o.CreatedAt = s.Now() o.CreatedAt = s.Now()
@ -290,14 +301,8 @@ func (s *Service) createOrganization(ctx context.Context, tx Tx, o *influxdb.Org
return nil return nil
} }
func (s *Service) generateOrgID() (influxdb.ID, error) { func (s *Service) generateOrgID(ctx context.Context, tx Tx) (influxdb.ID, error) {
for i := 0; i < MaxIDGenerationN; i++ { return s.generateSafeID(ctx, tx, organizationBucket)
id := s.IDGenerator.ID()
if s.IsValidOrgBucketID == nil || s.IsValidOrgBucketID(id) {
return id, nil
}
}
return 0, errors.New("unable to generate valid org id")
} }
// PutOrganization will put a organization without setting an ID. // PutOrganization will put a organization without setting an ID.

View File

@ -5,7 +5,6 @@ import (
"testing" "testing"
"github.com/influxdata/influxdb" "github.com/influxdata/influxdb"
"github.com/influxdata/influxdb/inmem"
"github.com/influxdata/influxdb/kv" "github.com/influxdata/influxdb/kv"
influxdbtesting "github.com/influxdata/influxdb/testing" influxdbtesting "github.com/influxdata/influxdb/testing"
) )
@ -46,6 +45,7 @@ func initInmemOrganizationService(f influxdbtesting.OrganizationFields, t *testi
func initOrganizationService(s kv.Store, f influxdbtesting.OrganizationFields, t *testing.T) (influxdb.OrganizationService, string, func()) { func initOrganizationService(s kv.Store, f influxdbtesting.OrganizationFields, t *testing.T) (influxdb.OrganizationService, string, func()) {
svc := kv.NewService(s) svc := kv.NewService(s)
svc.OrgBucketIDs = f.OrgBucketIDs
svc.IDGenerator = f.IDGenerator svc.IDGenerator = f.IDGenerator
svc.TimeGenerator = f.TimeGenerator svc.TimeGenerator = f.TimeGenerator
if f.TimeGenerator == nil { if f.TimeGenerator == nil {
@ -71,13 +71,3 @@ func initOrganizationService(s kv.Store, f influxdbtesting.OrganizationFields, t
} }
} }
} }
func TestService_CreateOrganization(t *testing.T) {
t.Run("InvalidOrgID", func(t *testing.T) {
svc := kv.NewService(inmem.NewKVStore())
svc.IsValidOrgBucketID = func(id influxdb.ID) bool { return false }
if err := svc.CreateOrganization(context.Background(), &influxdb.Organization{Name: "ORG"}); err == nil || err.Error() != `unable to generate valid org id` {
t.Fatalf("unexpected error: %#v", err)
}
})
}

View File

@ -25,12 +25,15 @@ type Service struct {
Config ServiceConfig Config ServiceConfig
IDGenerator influxdb.IDGenerator IDGenerator influxdb.IDGenerator
// special ID generator that never returns bytes with backslash,
// comma, or space. Used to support very specific encoding of org &
// bucket into the old measurement in storage.
OrgBucketIDs influxdb.IDGenerator
TokenGenerator influxdb.TokenGenerator TokenGenerator influxdb.TokenGenerator
influxdb.TimeGenerator influxdb.TimeGenerator
Hash Crypt Hash Crypt
// Organization & bucket specific validation.
IsValidOrgBucketID func(influxdb.ID) bool
} }
// NewService returns an instance of a Service. // NewService returns an instance of a Service.
@ -38,6 +41,8 @@ func NewService(kv Store, configs ...ServiceConfig) *Service {
s := &Service{ s := &Service{
Logger: zap.NewNop(), Logger: zap.NewNop(),
IDGenerator: snowflake.NewIDGenerator(), IDGenerator: snowflake.NewIDGenerator(),
// Seed the random number generator with the current time
OrgBucketIDs: rand.NewOrgBucketID(time.Now().UnixNano()),
TokenGenerator: rand.NewTokenGenerator(64), TokenGenerator: rand.NewTokenGenerator(64),
Hash: &Bcrypt{}, Hash: &Bcrypt{},
kv: kv, kv: kv,
@ -150,3 +155,11 @@ func (s *Service) Initialize(ctx context.Context) error {
func (s *Service) WithStore(store Store) { func (s *Service) WithStore(store Store) {
s.kv = store s.kv = store
} }
// WithSpecialOrgBucketIDs sets the generator for the org
// and bucket ids.
//
// Should only be used in tests for mocking.
func (s *Service) WithSpecialOrgBucketIDs(gen influxdb.IDGenerator) {
s.OrgBucketIDs = gen
}

View File

@ -5,6 +5,7 @@ import (
"fmt" "fmt"
influxdb "github.com/influxdata/influxdb" influxdb "github.com/influxdata/influxdb"
"github.com/influxdata/influxdb/kit/tracing"
) )
// UnexpectedIndexError is used when the error comes from an internal system. // UnexpectedIndexError is used when the error comes from an internal system.
@ -20,7 +21,14 @@ func UnexpectedIndexError(err error) *influxdb.Error {
// exists. // exists.
var NotUniqueError = &influxdb.Error{ var NotUniqueError = &influxdb.Error{
Code: influxdb.EConflict, Code: influxdb.EConflict,
Msg: fmt.Sprintf("name already exists"), Msg: "name already exists",
}
// NotUniqueIDError is used when attempting to create an org or bucket that already
// exists.
var NotUniqueIDError = &influxdb.Error{
Code: influxdb.EConflict,
Msg: "ID already exists",
} }
func (s *Service) unique(ctx context.Context, tx Tx, indexBucket, indexKey []byte) error { func (s *Service) unique(ctx context.Context, tx Tx, indexBucket, indexKey []byte) error {
@ -43,3 +51,52 @@ func (s *Service) unique(ctx context.Context, tx Tx, indexBucket, indexKey []byt
// any other error is some sort of internal server error // any other error is some sort of internal server error
return UnexpectedIndexError(err) return UnexpectedIndexError(err)
} }
func (s *Service) uniqueID(ctx context.Context, tx Tx, bucket []byte, id influxdb.ID) error {
span, _ := tracing.StartSpanFromContext(ctx)
defer span.Finish()
encodedID, err := id.Encode()
if err != nil {
return &influxdb.Error{
Code: influxdb.EInvalid,
Err: err,
}
}
b, err := tx.Bucket(bucket)
if err != nil {
return err
}
_, err = b.Get(encodedID)
if IsNotFound(err) {
return nil
}
return NotUniqueIDError
}
// generateSafeID attempts to create ids for buckets
// and orgs that are without backslash, commas, and spaces, BUT ALSO do not already exist.
func (s *Service) generateSafeID(ctx context.Context, tx Tx, bucket []byte) (influxdb.ID, error) {
for i := 0; i < MaxIDGenerationN; i++ {
id := s.OrgBucketIDs.ID()
// we have reserved a certain number of IDs
// for orgs and buckets.
if id < ReservedIDs {
continue
}
err := s.uniqueID(ctx, tx, bucket, id)
if err == nil {
return id, nil
}
if err == NotUniqueIDError {
continue
}
return influxdb.InvalidID(), err
}
return influxdb.InvalidID(), ErrFailureGeneratingID
}

72
rand/id.go Normal file
View File

@ -0,0 +1,72 @@
package rand
import (
"encoding/binary"
"math/rand"
"sync"
"github.com/influxdata/influxdb"
)
var _ influxdb.IDGenerator = (*OrgBucketID)(nil)
// OrgBucketID creates an id that does not have ascii
// backslash, commas, or spaces. Used to create IDs for organizations
// and buckets.
//
// It is implemented without those characters because orgbucket
// pairs are placed in the old measurement field. Measurement
// was interpreted as a string delimited with commas. Therefore,
// to continue to use the underlying storage engine we need to
// sanitize ids.
//
// Safe for concurrent use by multiple goroutines.
type OrgBucketID struct {
m sync.Mutex
src *rand.Rand
}
// NewOrgBucketID creates an influxdb.IDGenerator that creates
// random numbers seeded with seed. Ascii backslash, comma,
// and space are manipulated by incrementing.
//
// Typically, seed with `time.Now().UnixNano()`
func NewOrgBucketID(seed int64) *OrgBucketID {
return &OrgBucketID{
src: rand.New(rand.NewSource(seed)),
}
}
// Seed allows one to override the current seed.
// Typically, this override is done for tests.
func (r *OrgBucketID) Seed(seed int64) {
r.m.Lock()
r.src = rand.New(rand.NewSource(seed))
r.m.Unlock()
}
// ID generates an ID that does not have backslashes, commas, or spaces.
func (r *OrgBucketID) ID() influxdb.ID {
r.m.Lock()
n := r.src.Uint64()
r.m.Unlock()
n = sanitize(n)
return influxdb.ID(n)
}
func sanitize(n uint64) uint64 {
b := make([]byte, 8)
binary.BigEndian.PutUint64(b, n)
for i := range b {
switch b[i] {
// these bytes must be remove here to prevent the need
// to escape/unescape. See the models package for
// additional detail.
// \ , " "
case 0x5C, 0x2C, 0x20:
b[i] = b[i] + 1
}
}
return binary.BigEndian.Uint64(b)
}

51
rand/id_test.go Normal file
View File

@ -0,0 +1,51 @@
package rand
import (
"encoding/binary"
"reflect"
"testing"
"github.com/influxdata/influxdb"
)
func TestOrgBucketID_ID(t *testing.T) {
tests := []struct {
name string
seed int64
want influxdb.ID
}{
{
name: "when seeded with 6 the first random number contains characters",
seed: 6,
want: influxdb.ID(0xaddff35d7fe88f15),
},
{
name: "when seeded with 1234567890 we get a random number without any bad chars",
seed: 1234567890,
want: influxdb.ID(0x8a95c1bf40518fee),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
r := NewOrgBucketID(tt.seed)
if got := r.ID(); !reflect.DeepEqual(got, tt.want) {
t.Errorf("OrgBucketID.ID() = %v, want %v", got, tt.want)
}
})
}
}
func TestOrgBucketID_ID_sanitized(t *testing.T) {
r := NewOrgBucketID(42)
b := make([]byte, 8)
for i := 0; i < 1000; i++ {
id := r.ID()
binary.LittleEndian.PutUint64(b, uint64(id))
for j := range b {
switch b[j] {
case 0x5C, 0x2C, 0x20:
t.Fatalf("unexpected bytes found in IDs")
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -3,13 +3,15 @@ package testing
import ( import (
"bytes" "bytes"
"context" "context"
"fmt"
"sort" "sort"
"testing" "testing"
"time" "time"
"github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp"
platform "github.com/influxdata/influxdb" "github.com/influxdata/influxdb"
"github.com/influxdata/influxdb/mock" "github.com/influxdata/influxdb/mock"
"github.com/influxdata/influxdb/rand"
) )
const ( const (
@ -21,8 +23,8 @@ var organizationCmpOptions = cmp.Options{
cmp.Comparer(func(x, y []byte) bool { cmp.Comparer(func(x, y []byte) bool {
return bytes.Equal(x, y) return bytes.Equal(x, y)
}), }),
cmp.Transformer("Sort", func(in []*platform.Organization) []*platform.Organization { cmp.Transformer("Sort", func(in []*influxdb.Organization) []*influxdb.Organization {
out := append([]*platform.Organization(nil), in...) // Copy input to avoid mutating it out := append([]*influxdb.Organization(nil), in...) // Copy input to avoid mutating it
sort.Slice(out, func(i, j int) bool { sort.Slice(out, func(i, j int) bool {
return out[i].ID.String() > out[j].ID.String() return out[i].ID.String() > out[j].ID.String()
}) })
@ -32,18 +34,19 @@ var organizationCmpOptions = cmp.Options{
// OrganizationFields will include the IDGenerator, and organizations // OrganizationFields will include the IDGenerator, and organizations
type OrganizationFields struct { type OrganizationFields struct {
IDGenerator platform.IDGenerator IDGenerator influxdb.IDGenerator
Organizations []*platform.Organization Organizations []*influxdb.Organization
TimeGenerator platform.TimeGenerator TimeGenerator influxdb.TimeGenerator
OrgBucketIDs influxdb.IDGenerator
} }
// OrganizationService tests all the service functions. // OrganizationService tests all the service functions.
func OrganizationService( func OrganizationService(
init func(OrganizationFields, *testing.T) (platform.OrganizationService, string, func()), t *testing.T, init func(OrganizationFields, *testing.T) (influxdb.OrganizationService, string, func()), t *testing.T,
) { ) {
tests := []struct { tests := []struct {
name string name string
fn func(init func(OrganizationFields, *testing.T) (platform.OrganizationService, string, func()), fn func(init func(OrganizationFields, *testing.T) (influxdb.OrganizationService, string, func()),
t *testing.T) t *testing.T)
}{ }{
{ {
@ -80,15 +83,15 @@ func OrganizationService(
// CreateOrganization testing // CreateOrganization testing
func CreateOrganization( func CreateOrganization(
init func(OrganizationFields, *testing.T) (platform.OrganizationService, string, func()), init func(OrganizationFields, *testing.T) (influxdb.OrganizationService, string, func()),
t *testing.T, t *testing.T,
) { ) {
type args struct { type args struct {
organization *platform.Organization organization *influxdb.Organization
} }
type wants struct { type wants struct {
err error err error
organizations []*platform.Organization organizations []*influxdb.Organization
} }
tests := []struct { tests := []struct {
@ -101,23 +104,24 @@ func CreateOrganization(
name: "create organizations with empty set", name: "create organizations with empty set",
fields: OrganizationFields{ fields: OrganizationFields{
IDGenerator: mock.NewIDGenerator(orgOneID, t), IDGenerator: mock.NewIDGenerator(orgOneID, t),
OrgBucketIDs: mock.NewIDGenerator(orgOneID, t),
TimeGenerator: mock.TimeGenerator{FakeValue: time.Date(2006, 5, 4, 1, 2, 3, 0, time.UTC)}, TimeGenerator: mock.TimeGenerator{FakeValue: time.Date(2006, 5, 4, 1, 2, 3, 0, time.UTC)},
Organizations: []*platform.Organization{}, Organizations: []*influxdb.Organization{},
}, },
args: args{ args: args{
organization: &platform.Organization{ organization: &influxdb.Organization{
Name: "name1", Name: "name1",
ID: MustIDBase16(orgOneID), ID: MustIDBase16(orgOneID),
Description: "desc1", Description: "desc1",
}, },
}, },
wants: wants{ wants: wants{
organizations: []*platform.Organization{ organizations: []*influxdb.Organization{
{ {
Name: "name1", Name: "name1",
ID: MustIDBase16(orgOneID), ID: MustIDBase16(orgOneID),
Description: "desc1", Description: "desc1",
CRUDLog: platform.CRUDLog{ CRUDLog: influxdb.CRUDLog{
CreatedAt: time.Date(2006, 5, 4, 1, 2, 3, 0, time.UTC), CreatedAt: time.Date(2006, 5, 4, 1, 2, 3, 0, time.UTC),
UpdatedAt: time.Date(2006, 5, 4, 1, 2, 3, 0, time.UTC), UpdatedAt: time.Date(2006, 5, 4, 1, 2, 3, 0, time.UTC),
}, },
@ -129,8 +133,9 @@ func CreateOrganization(
name: "basic create organization", name: "basic create organization",
fields: OrganizationFields{ fields: OrganizationFields{
IDGenerator: mock.NewIDGenerator(orgTwoID, t), IDGenerator: mock.NewIDGenerator(orgTwoID, t),
OrgBucketIDs: mock.NewIDGenerator(orgTwoID, t),
TimeGenerator: mock.TimeGenerator{FakeValue: time.Date(2006, 5, 4, 1, 2, 3, 0, time.UTC)}, TimeGenerator: mock.TimeGenerator{FakeValue: time.Date(2006, 5, 4, 1, 2, 3, 0, time.UTC)},
Organizations: []*platform.Organization{ Organizations: []*influxdb.Organization{
{ {
ID: MustIDBase16(orgOneID), ID: MustIDBase16(orgOneID),
Name: "organization1", Name: "organization1",
@ -138,13 +143,13 @@ func CreateOrganization(
}, },
}, },
args: args{ args: args{
organization: &platform.Organization{ organization: &influxdb.Organization{
ID: MustIDBase16(orgTwoID), ID: MustIDBase16(orgTwoID),
Name: "organization2", Name: "organization2",
}, },
}, },
wants: wants{ wants: wants{
organizations: []*platform.Organization{ organizations: []*influxdb.Organization{
{ {
ID: MustIDBase16(orgOneID), ID: MustIDBase16(orgOneID),
Name: "organization1", Name: "organization1",
@ -152,7 +157,7 @@ func CreateOrganization(
{ {
ID: MustIDBase16(orgTwoID), ID: MustIDBase16(orgTwoID),
Name: "organization2", Name: "organization2",
CRUDLog: platform.CRUDLog{ CRUDLog: influxdb.CRUDLog{
CreatedAt: time.Date(2006, 5, 4, 1, 2, 3, 0, time.UTC), CreatedAt: time.Date(2006, 5, 4, 1, 2, 3, 0, time.UTC),
UpdatedAt: time.Date(2006, 5, 4, 1, 2, 3, 0, time.UTC), UpdatedAt: time.Date(2006, 5, 4, 1, 2, 3, 0, time.UTC),
}, },
@ -164,8 +169,9 @@ func CreateOrganization(
name: "empty name", name: "empty name",
fields: OrganizationFields{ fields: OrganizationFields{
IDGenerator: mock.NewIDGenerator(orgTwoID, t), IDGenerator: mock.NewIDGenerator(orgTwoID, t),
OrgBucketIDs: mock.NewIDGenerator(orgTwoID, t),
TimeGenerator: mock.TimeGenerator{FakeValue: time.Date(2006, 5, 4, 1, 2, 3, 0, time.UTC)}, TimeGenerator: mock.TimeGenerator{FakeValue: time.Date(2006, 5, 4, 1, 2, 3, 0, time.UTC)},
Organizations: []*platform.Organization{ Organizations: []*influxdb.Organization{
{ {
ID: MustIDBase16(orgOneID), ID: MustIDBase16(orgOneID),
Name: "organization1", Name: "organization1",
@ -173,26 +179,27 @@ func CreateOrganization(
}, },
}, },
args: args{ args: args{
organization: &platform.Organization{ organization: &influxdb.Organization{
ID: MustIDBase16(orgOneID), ID: MustIDBase16(orgOneID),
}, },
}, },
wants: wants{ wants: wants{
organizations: []*platform.Organization{ organizations: []*influxdb.Organization{
{ {
ID: MustIDBase16(orgOneID), ID: MustIDBase16(orgOneID),
Name: "organization1", Name: "organization1",
}, },
}, },
err: platform.ErrOrgNameisEmpty, err: influxdb.ErrOrgNameisEmpty,
}, },
}, },
{ {
name: "name only have spaces", name: "name only have spaces",
fields: OrganizationFields{ fields: OrganizationFields{
IDGenerator: mock.NewIDGenerator(orgTwoID, t), IDGenerator: mock.NewIDGenerator(orgTwoID, t),
OrgBucketIDs: mock.NewIDGenerator(orgTwoID, t),
TimeGenerator: mock.TimeGenerator{FakeValue: time.Date(2006, 5, 4, 1, 2, 3, 0, time.UTC)}, TimeGenerator: mock.TimeGenerator{FakeValue: time.Date(2006, 5, 4, 1, 2, 3, 0, time.UTC)},
Organizations: []*platform.Organization{ Organizations: []*influxdb.Organization{
{ {
ID: MustIDBase16(orgOneID), ID: MustIDBase16(orgOneID),
Name: "organization1", Name: "organization1",
@ -200,27 +207,28 @@ func CreateOrganization(
}, },
}, },
args: args{ args: args{
organization: &platform.Organization{ organization: &influxdb.Organization{
ID: MustIDBase16(orgOneID), ID: MustIDBase16(orgOneID),
Name: " ", Name: " ",
}, },
}, },
wants: wants{ wants: wants{
organizations: []*platform.Organization{ organizations: []*influxdb.Organization{
{ {
ID: MustIDBase16(orgOneID), ID: MustIDBase16(orgOneID),
Name: "organization1", Name: "organization1",
}, },
}, },
err: platform.ErrOrgNameisEmpty, err: influxdb.ErrOrgNameisEmpty,
}, },
}, },
{ {
name: "names should be unique", name: "names should be unique",
fields: OrganizationFields{ fields: OrganizationFields{
IDGenerator: mock.NewIDGenerator(orgTwoID, t), IDGenerator: mock.NewIDGenerator(orgTwoID, t),
OrgBucketIDs: mock.NewIDGenerator(orgTwoID, t),
TimeGenerator: mock.TimeGenerator{FakeValue: time.Date(2006, 5, 4, 1, 2, 3, 0, time.UTC)}, TimeGenerator: mock.TimeGenerator{FakeValue: time.Date(2006, 5, 4, 1, 2, 3, 0, time.UTC)},
Organizations: []*platform.Organization{ Organizations: []*influxdb.Organization{
{ {
ID: MustIDBase16(orgOneID), ID: MustIDBase16(orgOneID),
Name: "organization1", Name: "organization1",
@ -228,21 +236,21 @@ func CreateOrganization(
}, },
}, },
args: args{ args: args{
organization: &platform.Organization{ organization: &influxdb.Organization{
ID: MustIDBase16(orgOneID), ID: MustIDBase16(orgOneID),
Name: "organization1", Name: "organization1",
}, },
}, },
wants: wants{ wants: wants{
organizations: []*platform.Organization{ organizations: []*influxdb.Organization{
{ {
ID: MustIDBase16(orgOneID), ID: MustIDBase16(orgOneID),
Name: "organization1", Name: "organization1",
}, },
}, },
err: &platform.Error{ err: &influxdb.Error{
Code: platform.EConflict, Code: influxdb.EConflict,
Op: platform.OpCreateOrganization, Op: influxdb.OpCreateOrganization,
Msg: "organization with name organization1 already exists", Msg: "organization with name organization1 already exists",
}, },
}, },
@ -251,8 +259,9 @@ func CreateOrganization(
name: "create organization with no id", name: "create organization with no id",
fields: OrganizationFields{ fields: OrganizationFields{
IDGenerator: mock.NewIDGenerator(orgTwoID, t), IDGenerator: mock.NewIDGenerator(orgTwoID, t),
OrgBucketIDs: mock.NewIDGenerator(orgTwoID, t),
TimeGenerator: mock.TimeGenerator{FakeValue: time.Date(2006, 5, 4, 1, 2, 3, 0, time.UTC)}, TimeGenerator: mock.TimeGenerator{FakeValue: time.Date(2006, 5, 4, 1, 2, 3, 0, time.UTC)},
Organizations: []*platform.Organization{ Organizations: []*influxdb.Organization{
{ {
ID: MustIDBase16(orgOneID), ID: MustIDBase16(orgOneID),
Name: "organization1", Name: "organization1",
@ -260,12 +269,12 @@ func CreateOrganization(
}, },
}, },
args: args{ args: args{
organization: &platform.Organization{ organization: &influxdb.Organization{
Name: "organization2", Name: "organization2",
}, },
}, },
wants: wants{ wants: wants{
organizations: []*platform.Organization{ organizations: []*influxdb.Organization{
{ {
ID: MustIDBase16(orgOneID), ID: MustIDBase16(orgOneID),
Name: "organization1", Name: "organization1",
@ -273,7 +282,130 @@ func CreateOrganization(
{ {
ID: MustIDBase16(orgTwoID), ID: MustIDBase16(orgTwoID),
Name: "organization2", Name: "organization2",
CRUDLog: platform.CRUDLog{ CRUDLog: influxdb.CRUDLog{
CreatedAt: time.Date(2006, 5, 4, 1, 2, 3, 0, time.UTC),
UpdatedAt: time.Date(2006, 5, 4, 1, 2, 3, 0, time.UTC),
},
},
},
},
},
{
name: "names should be unique",
fields: OrganizationFields{
IDGenerator: mock.NewIDGenerator(orgTwoID, t),
OrgBucketIDs: mock.NewIDGenerator(orgTwoID, t),
TimeGenerator: mock.TimeGenerator{FakeValue: time.Date(2006, 5, 4, 1, 2, 3, 0, time.UTC)},
Organizations: []*influxdb.Organization{
{
ID: MustIDBase16(orgOneID),
Name: "organization1",
},
},
},
args: args{
organization: &influxdb.Organization{
ID: MustIDBase16(orgOneID),
Name: "organization1",
},
},
wants: wants{
organizations: []*influxdb.Organization{
{
ID: MustIDBase16(orgOneID),
Name: "organization1",
},
},
err: &influxdb.Error{
Code: influxdb.EConflict,
Op: influxdb.OpCreateOrganization,
Msg: "organization with name organization1 already exists",
},
},
},
{
name: "ids should be unique",
fields: OrganizationFields{
IDGenerator: mock.NewIDGenerator(orgOneID, t),
OrgBucketIDs: mock.NewIDGenerator(orgOneID, t),
TimeGenerator: mock.TimeGenerator{FakeValue: time.Date(2006, 5, 4, 1, 2, 3, 0, time.UTC)},
Organizations: []*influxdb.Organization{
{
ID: MustIDBase16(orgOneID),
Name: "organization1",
},
},
},
args: args{
organization: &influxdb.Organization{
ID: MustIDBase16(orgOneID),
Name: "organization2",
},
},
wants: wants{
organizations: []*influxdb.Organization{
{
ID: MustIDBase16(orgOneID),
Name: "organization1",
},
},
err: &influxdb.Error{
Code: influxdb.EInternal,
Msg: fmt.Sprintf("unable to generate valid id"),
},
},
},
{
name: "reserved ids should not be created",
fields: OrganizationFields{
IDGenerator: mock.NewIDGenerator("000000000000000a", t),
OrgBucketIDs: mock.NewIDGenerator("000000000000000a", t),
TimeGenerator: mock.TimeGenerator{FakeValue: time.Date(2006, 5, 4, 1, 2, 3, 0, time.UTC)},
Organizations: []*influxdb.Organization{
{
ID: MustIDBase16(orgOneID),
Name: "organization1",
},
},
},
args: args{
organization: &influxdb.Organization{
ID: MustIDBase16(orgOneID),
Name: "organization2",
},
},
wants: wants{
organizations: []*influxdb.Organization{
{
ID: MustIDBase16(orgOneID),
Name: "organization1",
},
},
err: &influxdb.Error{
Code: influxdb.EInternal,
Msg: fmt.Sprintf("unable to generate valid id"),
},
},
},
{
name: "randomly generted org ids should not have commas, spaces, or backslashes",
fields: OrganizationFields{
OrgBucketIDs: rand.NewOrgBucketID(42),
TimeGenerator: mock.TimeGenerator{FakeValue: time.Date(2006, 5, 4, 1, 2, 3, 0, time.UTC)},
Organizations: []*influxdb.Organization{},
},
args: args{
organization: &influxdb.Organization{
Name: "o1",
},
},
wants: wants{
organizations: []*influxdb.Organization{
{
ID: MustIDBase16("afbf64b1967f8c53"),
Name: "o1",
CRUDLog: influxdb.CRUDLog{
CreatedAt: time.Date(2006, 5, 4, 1, 2, 3, 0, time.UTC), CreatedAt: time.Date(2006, 5, 4, 1, 2, 3, 0, time.UTC),
UpdatedAt: time.Date(2006, 5, 4, 1, 2, 3, 0, time.UTC), UpdatedAt: time.Date(2006, 5, 4, 1, 2, 3, 0, time.UTC),
}, },
@ -296,7 +428,7 @@ func CreateOrganization(
defer s.DeleteOrganization(ctx, tt.args.organization.ID) defer s.DeleteOrganization(ctx, tt.args.organization.ID)
// } // }
organizations, _, err := s.FindOrganizations(ctx, platform.OrganizationFilter{}) organizations, _, err := s.FindOrganizations(ctx, influxdb.OrganizationFilter{})
diffPlatformErrors(tt.name, err, nil, opPrefix, t) diffPlatformErrors(tt.name, err, nil, opPrefix, t)
if diff := cmp.Diff(organizations, tt.wants.organizations, organizationCmpOptions...); diff != "" { if diff := cmp.Diff(organizations, tt.wants.organizations, organizationCmpOptions...); diff != "" {
t.Errorf("organizations are different -got/+want\ndiff %s", diff) t.Errorf("organizations are different -got/+want\ndiff %s", diff)
@ -307,15 +439,15 @@ func CreateOrganization(
// FindOrganizationByID testing // FindOrganizationByID testing
func FindOrganizationByID( func FindOrganizationByID(
init func(OrganizationFields, *testing.T) (platform.OrganizationService, string, func()), init func(OrganizationFields, *testing.T) (influxdb.OrganizationService, string, func()),
t *testing.T, t *testing.T,
) { ) {
type args struct { type args struct {
id platform.ID id influxdb.ID
} }
type wants struct { type wants struct {
err error err error
organization *platform.Organization organization *influxdb.Organization
} }
tests := []struct { tests := []struct {
@ -327,7 +459,7 @@ func FindOrganizationByID(
{ {
name: "basic find organization by id", name: "basic find organization by id",
fields: OrganizationFields{ fields: OrganizationFields{
Organizations: []*platform.Organization{ Organizations: []*influxdb.Organization{
{ {
ID: MustIDBase16(orgOneID), ID: MustIDBase16(orgOneID),
Name: "organization1", Name: "organization1",
@ -342,7 +474,7 @@ func FindOrganizationByID(
id: MustIDBase16(orgTwoID), id: MustIDBase16(orgTwoID),
}, },
wants: wants{ wants: wants{
organization: &platform.Organization{ organization: &influxdb.Organization{
ID: MustIDBase16(orgTwoID), ID: MustIDBase16(orgTwoID),
Name: "organization2", Name: "organization2",
}, },
@ -351,7 +483,7 @@ func FindOrganizationByID(
{ {
name: "didn't find organization by id", name: "didn't find organization by id",
fields: OrganizationFields{ fields: OrganizationFields{
Organizations: []*platform.Organization{ Organizations: []*influxdb.Organization{
{ {
ID: MustIDBase16(orgOneID), ID: MustIDBase16(orgOneID),
Name: "organization1", Name: "organization1",
@ -367,9 +499,9 @@ func FindOrganizationByID(
}, },
wants: wants{ wants: wants{
organization: nil, organization: nil,
err: &platform.Error{ err: &influxdb.Error{
Code: platform.ENotFound, Code: influxdb.ENotFound,
Op: platform.OpFindOrganizationByID, Op: influxdb.OpFindOrganizationByID,
Msg: "organization not found", Msg: "organization not found",
}, },
}, },
@ -394,16 +526,16 @@ func FindOrganizationByID(
// FindOrganizations testing // FindOrganizations testing
func FindOrganizations( func FindOrganizations(
init func(OrganizationFields, *testing.T) (platform.OrganizationService, string, func()), init func(OrganizationFields, *testing.T) (influxdb.OrganizationService, string, func()),
t *testing.T, t *testing.T,
) { ) {
type args struct { type args struct {
ID platform.ID ID influxdb.ID
name string name string
} }
type wants struct { type wants struct {
organizations []*platform.Organization organizations []*influxdb.Organization
err error err error
} }
tests := []struct { tests := []struct {
@ -415,7 +547,7 @@ func FindOrganizations(
{ {
name: "find all organizations", name: "find all organizations",
fields: OrganizationFields{ fields: OrganizationFields{
Organizations: []*platform.Organization{ Organizations: []*influxdb.Organization{
{ {
ID: MustIDBase16(orgOneID), ID: MustIDBase16(orgOneID),
Name: "abc", Name: "abc",
@ -429,7 +561,7 @@ func FindOrganizations(
}, },
args: args{}, args: args{},
wants: wants{ wants: wants{
organizations: []*platform.Organization{ organizations: []*influxdb.Organization{
{ {
ID: MustIDBase16(orgOneID), ID: MustIDBase16(orgOneID),
Name: "abc", Name: "abc",
@ -445,7 +577,7 @@ func FindOrganizations(
{ {
name: "find organization by id", name: "find organization by id",
fields: OrganizationFields{ fields: OrganizationFields{
Organizations: []*platform.Organization{ Organizations: []*influxdb.Organization{
{ {
ID: MustIDBase16(orgOneID), ID: MustIDBase16(orgOneID),
Name: "abc", Name: "abc",
@ -460,7 +592,7 @@ func FindOrganizations(
ID: MustIDBase16(orgTwoID), ID: MustIDBase16(orgTwoID),
}, },
wants: wants{ wants: wants{
organizations: []*platform.Organization{ organizations: []*influxdb.Organization{
{ {
ID: MustIDBase16(orgTwoID), ID: MustIDBase16(orgTwoID),
Name: "xyz", Name: "xyz",
@ -471,7 +603,7 @@ func FindOrganizations(
{ {
name: "find organization by name", name: "find organization by name",
fields: OrganizationFields{ fields: OrganizationFields{
Organizations: []*platform.Organization{ Organizations: []*influxdb.Organization{
{ {
ID: MustIDBase16(orgOneID), ID: MustIDBase16(orgOneID),
Name: "abc", Name: "abc",
@ -486,7 +618,7 @@ func FindOrganizations(
name: "xyz", name: "xyz",
}, },
wants: wants{ wants: wants{
organizations: []*platform.Organization{ organizations: []*influxdb.Organization{
{ {
ID: MustIDBase16(orgTwoID), ID: MustIDBase16(orgTwoID),
Name: "xyz", Name: "xyz",
@ -497,7 +629,7 @@ func FindOrganizations(
{ {
name: "find organization by id not exists", name: "find organization by id not exists",
fields: OrganizationFields{ fields: OrganizationFields{
Organizations: []*platform.Organization{ Organizations: []*influxdb.Organization{
{ {
ID: MustIDBase16(orgOneID), ID: MustIDBase16(orgOneID),
Name: "abc", Name: "abc",
@ -512,10 +644,10 @@ func FindOrganizations(
ID: MustIDBase16(threeID), ID: MustIDBase16(threeID),
}, },
wants: wants{ wants: wants{
organizations: []*platform.Organization{}, organizations: []*influxdb.Organization{},
err: &platform.Error{ err: &influxdb.Error{
Code: platform.ENotFound, Code: influxdb.ENotFound,
Op: platform.OpFindOrganizations, Op: influxdb.OpFindOrganizations,
Msg: "organization not found", Msg: "organization not found",
}, },
}, },
@ -523,7 +655,7 @@ func FindOrganizations(
{ {
name: "find organization by name not exists", name: "find organization by name not exists",
fields: OrganizationFields{ fields: OrganizationFields{
Organizations: []*platform.Organization{ Organizations: []*influxdb.Organization{
{ {
ID: MustIDBase16(orgOneID), ID: MustIDBase16(orgOneID),
Name: "abc", Name: "abc",
@ -538,10 +670,10 @@ func FindOrganizations(
name: "na", name: "na",
}, },
wants: wants{ wants: wants{
organizations: []*platform.Organization{}, organizations: []*influxdb.Organization{},
err: &platform.Error{ err: &influxdb.Error{
Code: platform.ENotFound, Code: influxdb.ENotFound,
Op: platform.OpFindOrganizations, Op: influxdb.OpFindOrganizations,
Msg: "organization name \"na\" not found", Msg: "organization name \"na\" not found",
}, },
}, },
@ -554,7 +686,7 @@ func FindOrganizations(
defer done() defer done()
ctx := context.Background() ctx := context.Background()
filter := platform.OrganizationFilter{} filter := influxdb.OrganizationFilter{}
if tt.args.ID.Valid() { if tt.args.ID.Valid() {
filter.ID = &tt.args.ID filter.ID = &tt.args.ID
} }
@ -574,7 +706,7 @@ func FindOrganizations(
// DeleteOrganization testing // DeleteOrganization testing
func DeleteOrganization( func DeleteOrganization(
init func(OrganizationFields, *testing.T) (platform.OrganizationService, string, func()), init func(OrganizationFields, *testing.T) (influxdb.OrganizationService, string, func()),
t *testing.T, t *testing.T,
) { ) {
type args struct { type args struct {
@ -582,7 +714,7 @@ func DeleteOrganization(
} }
type wants struct { type wants struct {
err error err error
organizations []*platform.Organization organizations []*influxdb.Organization
} }
tests := []struct { tests := []struct {
@ -594,7 +726,7 @@ func DeleteOrganization(
{ {
name: "delete organizations using exist id", name: "delete organizations using exist id",
fields: OrganizationFields{ fields: OrganizationFields{
Organizations: []*platform.Organization{ Organizations: []*influxdb.Organization{
{ {
Name: "orgA", Name: "orgA",
ID: MustIDBase16(orgOneID), ID: MustIDBase16(orgOneID),
@ -609,7 +741,7 @@ func DeleteOrganization(
ID: orgOneID, ID: orgOneID,
}, },
wants: wants{ wants: wants{
organizations: []*platform.Organization{ organizations: []*influxdb.Organization{
{ {
Name: "orgB", Name: "orgB",
ID: MustIDBase16(orgTwoID), ID: MustIDBase16(orgTwoID),
@ -620,7 +752,7 @@ func DeleteOrganization(
{ {
name: "delete organizations using id that does not exist", name: "delete organizations using id that does not exist",
fields: OrganizationFields{ fields: OrganizationFields{
Organizations: []*platform.Organization{ Organizations: []*influxdb.Organization{
{ {
Name: "orgA", Name: "orgA",
ID: MustIDBase16(orgOneID), ID: MustIDBase16(orgOneID),
@ -635,12 +767,12 @@ func DeleteOrganization(
ID: "1234567890654321", ID: "1234567890654321",
}, },
wants: wants{ wants: wants{
err: &platform.Error{ err: &influxdb.Error{
Code: platform.ENotFound, Code: influxdb.ENotFound,
Op: platform.OpDeleteOrganization, Op: influxdb.OpDeleteOrganization,
Msg: "organization not found", Msg: "organization not found",
}, },
organizations: []*platform.Organization{ organizations: []*influxdb.Organization{
{ {
Name: "orgA", Name: "orgA",
ID: MustIDBase16(orgOneID), ID: MustIDBase16(orgOneID),
@ -662,7 +794,7 @@ func DeleteOrganization(
err := s.DeleteOrganization(ctx, MustIDBase16(tt.args.ID)) err := s.DeleteOrganization(ctx, MustIDBase16(tt.args.ID))
diffPlatformErrors(tt.name, err, tt.wants.err, opPrefix, t) diffPlatformErrors(tt.name, err, tt.wants.err, opPrefix, t)
filter := platform.OrganizationFilter{} filter := influxdb.OrganizationFilter{}
organizations, _, err := s.FindOrganizations(ctx, filter) organizations, _, err := s.FindOrganizations(ctx, filter)
diffPlatformErrors(tt.name, err, nil, opPrefix, t) diffPlatformErrors(tt.name, err, nil, opPrefix, t)
@ -675,16 +807,16 @@ func DeleteOrganization(
// FindOrganization testing // FindOrganization testing
func FindOrganization( func FindOrganization(
init func(OrganizationFields, *testing.T) (platform.OrganizationService, string, func()), init func(OrganizationFields, *testing.T) (influxdb.OrganizationService, string, func()),
t *testing.T, t *testing.T,
) { ) {
type args struct { type args struct {
name string name string
id platform.ID id influxdb.ID
} }
type wants struct { type wants struct {
organization *platform.Organization organization *influxdb.Organization
err error err error
} }
@ -697,7 +829,7 @@ func FindOrganization(
{ {
name: "find organization by name", name: "find organization by name",
fields: OrganizationFields{ fields: OrganizationFields{
Organizations: []*platform.Organization{ Organizations: []*influxdb.Organization{
{ {
ID: MustIDBase16(orgOneID), ID: MustIDBase16(orgOneID),
Name: "abc", Name: "abc",
@ -712,7 +844,7 @@ func FindOrganization(
name: "abc", name: "abc",
}, },
wants: wants{ wants: wants{
organization: &platform.Organization{ organization: &influxdb.Organization{
ID: MustIDBase16(orgOneID), ID: MustIDBase16(orgOneID),
Name: "abc", Name: "abc",
}, },
@ -724,9 +856,9 @@ func FindOrganization(
name: "unknown", name: "unknown",
}, },
wants: wants{ wants: wants{
err: &platform.Error{ err: &influxdb.Error{
Code: platform.ENotFound, Code: influxdb.ENotFound,
Op: platform.OpFindOrganization, Op: influxdb.OpFindOrganization,
Msg: "organization name \"unknown\" not found", Msg: "organization name \"unknown\" not found",
}, },
}, },
@ -734,11 +866,11 @@ func FindOrganization(
{ {
name: "find organization in which no id filter matches should return no org", name: "find organization in which no id filter matches should return no org",
args: args{ args: args{
id: platform.ID(3), id: influxdb.ID(3),
}, },
wants: wants{ wants: wants{
err: &platform.Error{ err: &influxdb.Error{
Code: platform.ENotFound, Code: influxdb.ENotFound,
Msg: "organization not found", Msg: "organization not found",
}, },
}, },
@ -746,7 +878,7 @@ func FindOrganization(
{ {
name: "find organization no filter is set returns an error about filters not provided", name: "find organization no filter is set returns an error about filters not provided",
fields: OrganizationFields{ fields: OrganizationFields{
Organizations: []*platform.Organization{ Organizations: []*influxdb.Organization{
{ {
ID: MustIDBase16(orgOneID), ID: MustIDBase16(orgOneID),
Name: "o1", Name: "o1",
@ -754,21 +886,21 @@ func FindOrganization(
}, },
}, },
wants: wants{ wants: wants{
err: platform.ErrInvalidOrgFilter, err: influxdb.ErrInvalidOrgFilter,
}, },
}, },
{ {
name: "missing organization returns error", name: "missing organization returns error",
fields: OrganizationFields{ fields: OrganizationFields{
Organizations: []*platform.Organization{}, Organizations: []*influxdb.Organization{},
}, },
args: args{ args: args{
name: "abc", name: "abc",
}, },
wants: wants{ wants: wants{
err: &platform.Error{ err: &influxdb.Error{
Code: platform.ENotFound, Code: influxdb.ENotFound,
Op: platform.OpFindOrganization, Op: influxdb.OpFindOrganization,
Msg: "organization name \"abc\" not found", Msg: "organization name \"abc\" not found",
}, },
}, },
@ -780,11 +912,11 @@ func FindOrganization(
s, opPrefix, done := init(tt.fields, t) s, opPrefix, done := init(tt.fields, t)
defer done() defer done()
ctx := context.Background() ctx := context.Background()
filter := platform.OrganizationFilter{} filter := influxdb.OrganizationFilter{}
if tt.args.name != "" { if tt.args.name != "" {
filter.Name = &tt.args.name filter.Name = &tt.args.name
} }
if tt.args.id != platform.InvalidID() { if tt.args.id != influxdb.InvalidID() {
filter.ID = &tt.args.id filter.ID = &tt.args.id
} }
@ -800,17 +932,17 @@ func FindOrganization(
// UpdateOrganization testing // UpdateOrganization testing
func UpdateOrganization( func UpdateOrganization(
init func(OrganizationFields, *testing.T) (platform.OrganizationService, string, func()), init func(OrganizationFields, *testing.T) (influxdb.OrganizationService, string, func()),
t *testing.T, t *testing.T,
) { ) {
type args struct { type args struct {
id platform.ID id influxdb.ID
name *string name *string
description *string description *string
} }
type wants struct { type wants struct {
err error err error
organization *platform.Organization organization *influxdb.Organization
} }
tests := []struct { tests := []struct {
@ -823,7 +955,7 @@ func UpdateOrganization(
name: "update id not exists", name: "update id not exists",
fields: OrganizationFields{ fields: OrganizationFields{
TimeGenerator: mock.TimeGenerator{FakeValue: time.Date(2006, 5, 4, 1, 2, 3, 0, time.UTC)}, TimeGenerator: mock.TimeGenerator{FakeValue: time.Date(2006, 5, 4, 1, 2, 3, 0, time.UTC)},
Organizations: []*platform.Organization{ Organizations: []*influxdb.Organization{
{ {
ID: MustIDBase16(orgOneID), ID: MustIDBase16(orgOneID),
Name: "organization1", Name: "organization1",
@ -839,9 +971,9 @@ func UpdateOrganization(
name: strPtr("changed"), name: strPtr("changed"),
}, },
wants: wants{ wants: wants{
err: &platform.Error{ err: &influxdb.Error{
Code: platform.ENotFound, Code: influxdb.ENotFound,
Op: platform.OpUpdateOrganization, Op: influxdb.OpUpdateOrganization,
Msg: "organization not found", Msg: "organization not found",
}, },
}, },
@ -850,7 +982,7 @@ func UpdateOrganization(
name: "update name", name: "update name",
fields: OrganizationFields{ fields: OrganizationFields{
TimeGenerator: mock.TimeGenerator{FakeValue: time.Date(2006, 5, 4, 1, 2, 3, 0, time.UTC)}, TimeGenerator: mock.TimeGenerator{FakeValue: time.Date(2006, 5, 4, 1, 2, 3, 0, time.UTC)},
Organizations: []*platform.Organization{ Organizations: []*influxdb.Organization{
{ {
ID: MustIDBase16(orgOneID), ID: MustIDBase16(orgOneID),
Name: "organization1", Name: "organization1",
@ -866,10 +998,10 @@ func UpdateOrganization(
name: strPtr("changed"), name: strPtr("changed"),
}, },
wants: wants{ wants: wants{
organization: &platform.Organization{ organization: &influxdb.Organization{
ID: MustIDBase16(orgOneID), ID: MustIDBase16(orgOneID),
Name: "changed", Name: "changed",
CRUDLog: platform.CRUDLog{ CRUDLog: influxdb.CRUDLog{
UpdatedAt: time.Date(2006, 5, 4, 1, 2, 3, 0, time.UTC), UpdatedAt: time.Date(2006, 5, 4, 1, 2, 3, 0, time.UTC),
}, },
}, },
@ -879,7 +1011,7 @@ func UpdateOrganization(
name: "update name not unique", name: "update name not unique",
fields: OrganizationFields{ fields: OrganizationFields{
TimeGenerator: mock.TimeGenerator{FakeValue: time.Date(2006, 5, 4, 1, 2, 3, 0, time.UTC)}, TimeGenerator: mock.TimeGenerator{FakeValue: time.Date(2006, 5, 4, 1, 2, 3, 0, time.UTC)},
Organizations: []*platform.Organization{ Organizations: []*influxdb.Organization{
{ {
ID: MustIDBase16(orgOneID), ID: MustIDBase16(orgOneID),
Name: "organization1", Name: "organization1",
@ -895,9 +1027,9 @@ func UpdateOrganization(
name: strPtr("organization2"), name: strPtr("organization2"),
}, },
wants: wants{ wants: wants{
err: &platform.Error{ err: &influxdb.Error{
Code: platform.EConflict, Code: influxdb.EConflict,
Op: platform.OpUpdateOrganization, Op: influxdb.OpUpdateOrganization,
Msg: "organization with name organization2 already exists", Msg: "organization with name organization2 already exists",
}, },
}, },
@ -906,7 +1038,7 @@ func UpdateOrganization(
name: "update name is empty", name: "update name is empty",
fields: OrganizationFields{ fields: OrganizationFields{
TimeGenerator: mock.TimeGenerator{FakeValue: time.Date(2006, 5, 4, 1, 2, 3, 0, time.UTC)}, TimeGenerator: mock.TimeGenerator{FakeValue: time.Date(2006, 5, 4, 1, 2, 3, 0, time.UTC)},
Organizations: []*platform.Organization{ Organizations: []*influxdb.Organization{
{ {
ID: MustIDBase16(orgOneID), ID: MustIDBase16(orgOneID),
Name: "organization1", Name: "organization1",
@ -922,14 +1054,14 @@ func UpdateOrganization(
name: strPtr(""), name: strPtr(""),
}, },
wants: wants{ wants: wants{
err: platform.ErrOrgNameisEmpty, err: influxdb.ErrOrgNameisEmpty,
}, },
}, },
{ {
name: "update name only has space", name: "update name only has space",
fields: OrganizationFields{ fields: OrganizationFields{
TimeGenerator: mock.TimeGenerator{FakeValue: time.Date(2006, 5, 4, 1, 2, 3, 0, time.UTC)}, TimeGenerator: mock.TimeGenerator{FakeValue: time.Date(2006, 5, 4, 1, 2, 3, 0, time.UTC)},
Organizations: []*platform.Organization{ Organizations: []*influxdb.Organization{
{ {
ID: MustIDBase16(orgOneID), ID: MustIDBase16(orgOneID),
Name: "organization1", Name: "organization1",
@ -945,14 +1077,14 @@ func UpdateOrganization(
name: strPtr(" "), name: strPtr(" "),
}, },
wants: wants{ wants: wants{
err: platform.ErrOrgNameisEmpty, err: influxdb.ErrOrgNameisEmpty,
}, },
}, },
{ {
name: "update description", name: "update description",
fields: OrganizationFields{ fields: OrganizationFields{
TimeGenerator: mock.TimeGenerator{FakeValue: time.Date(2006, 5, 4, 1, 2, 3, 0, time.UTC)}, TimeGenerator: mock.TimeGenerator{FakeValue: time.Date(2006, 5, 4, 1, 2, 3, 0, time.UTC)},
Organizations: []*platform.Organization{ Organizations: []*influxdb.Organization{
{ {
ID: MustIDBase16(orgOneID), ID: MustIDBase16(orgOneID),
Name: "organization1", Name: "organization1",
@ -970,11 +1102,11 @@ func UpdateOrganization(
description: strPtr("changed"), description: strPtr("changed"),
}, },
wants: wants{ wants: wants{
organization: &platform.Organization{ organization: &influxdb.Organization{
ID: MustIDBase16(orgOneID), ID: MustIDBase16(orgOneID),
Name: "organization1", Name: "organization1",
Description: "changed", Description: "changed",
CRUDLog: platform.CRUDLog{ CRUDLog: influxdb.CRUDLog{
UpdatedAt: time.Date(2006, 5, 4, 1, 2, 3, 0, time.UTC), UpdatedAt: time.Date(2006, 5, 4, 1, 2, 3, 0, time.UTC),
}, },
}, },
@ -988,7 +1120,7 @@ func UpdateOrganization(
defer done() defer done()
ctx := context.Background() ctx := context.Background()
upd := platform.OrganizationUpdate{} upd := influxdb.OrganizationUpdate{}
upd.Name = tt.args.name upd.Name = tt.args.name
upd.Description = tt.args.description upd.Description = tt.args.description