2018-09-14 14:25:14 +00:00
|
|
|
package inmem
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"fmt"
|
|
|
|
|
|
|
|
"github.com/influxdata/platform"
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
2018-11-29 17:02:32 +00:00
|
|
|
errBucketNotFound = fmt.Errorf("bucket not found")
|
2018-09-14 14:25:14 +00:00
|
|
|
)
|
|
|
|
|
2018-11-29 17:02:32 +00:00
|
|
|
func (c *Service) loadBucket(ctx context.Context, id platform.ID) (*platform.Bucket, error) {
|
|
|
|
i, ok := c.bucketKV.Load(id.String())
|
2018-09-14 14:25:14 +00:00
|
|
|
if !ok {
|
2018-11-29 17:02:32 +00:00
|
|
|
return nil, errBucketNotFound
|
2018-09-14 14:25:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
b, ok := i.(platform.Bucket)
|
|
|
|
if !ok {
|
2018-11-29 17:02:32 +00:00
|
|
|
return nil, fmt.Errorf("type %T is not a bucket", i)
|
2018-09-14 14:25:14 +00:00
|
|
|
}
|
|
|
|
|
2018-11-29 17:02:32 +00:00
|
|
|
if err := c.setOrganizationNameOnBucket(ctx, &b); err != nil {
|
|
|
|
return nil, err
|
2018-09-14 14:25:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return &b, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Service) setOrganizationNameOnBucket(ctx context.Context, b *platform.Bucket) error {
|
|
|
|
o, err := c.loadOrganization(b.OrganizationID)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
b.Organization = o.Name
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// FindBucketByID returns a single bucket by ID.
|
|
|
|
func (s *Service) FindBucketByID(ctx context.Context, id platform.ID) (*platform.Bucket, error) {
|
2018-11-29 17:02:32 +00:00
|
|
|
return s.loadBucket(ctx, id)
|
2018-09-14 14:25:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Service) forEachBucket(ctx context.Context, fn func(b *platform.Bucket) bool) error {
|
|
|
|
var err error
|
|
|
|
c.bucketKV.Range(func(k, v interface{}) bool {
|
|
|
|
b, ok := v.(platform.Bucket)
|
|
|
|
if !ok {
|
|
|
|
err = fmt.Errorf("type %T is not a bucket", v)
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
return fn(&b)
|
|
|
|
})
|
|
|
|
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *Service) filterBuckets(ctx context.Context, fn func(b *platform.Bucket) bool) ([]*platform.Bucket, error) {
|
|
|
|
buckets := []*platform.Bucket{}
|
|
|
|
err := s.forEachBucket(ctx, func(b *platform.Bucket) bool {
|
|
|
|
if fn(b) {
|
|
|
|
buckets = append(buckets, b)
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
})
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return buckets, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// FindBucket returns the first bucket that matches filter.
|
|
|
|
func (s *Service) FindBucket(ctx context.Context, filter platform.BucketFilter) (*platform.Bucket, error) {
|
|
|
|
if filter.ID == nil && filter.Name == nil && filter.OrganizationID == nil {
|
2018-11-29 17:02:32 +00:00
|
|
|
return nil, fmt.Errorf("no filter parameters provided")
|
2018-09-14 14:25:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// filter by bucket id
|
|
|
|
if filter.ID != nil {
|
2018-11-29 17:02:32 +00:00
|
|
|
return s.FindBucketByID(ctx, *filter.ID)
|
2018-09-14 14:25:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bs, n, err := s.FindBuckets(ctx, filter)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
if n < 1 {
|
2018-11-29 17:02:32 +00:00
|
|
|
return nil, fmt.Errorf("bucket not found")
|
2018-09-14 14:25:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return bs[0], nil
|
|
|
|
}
|
|
|
|
|
2018-11-29 17:02:32 +00:00
|
|
|
func (s *Service) findBuckets(ctx context.Context, filter platform.BucketFilter, opt ...platform.FindOptions) ([]*platform.Bucket, error) {
|
2018-09-14 14:25:14 +00:00
|
|
|
// filter by bucket id
|
|
|
|
if filter.ID != nil {
|
|
|
|
b, err := s.FindBucketByID(ctx, *filter.ID)
|
|
|
|
if err != nil {
|
2018-11-29 17:02:32 +00:00
|
|
|
return nil, err
|
2018-09-14 14:25:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return []*platform.Bucket{b}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
if filter.Organization != nil {
|
|
|
|
o, err := s.findOrganizationByName(ctx, *filter.Organization)
|
|
|
|
if err != nil {
|
2018-11-29 17:02:32 +00:00
|
|
|
return nil, err
|
2018-09-14 14:25:14 +00:00
|
|
|
}
|
|
|
|
filter.OrganizationID = &o.ID
|
|
|
|
}
|
|
|
|
|
|
|
|
filterFunc := func(b *platform.Bucket) bool { return true }
|
|
|
|
|
|
|
|
if filter.Name != nil && filter.OrganizationID != nil {
|
|
|
|
filterFunc = func(b *platform.Bucket) bool {
|
2018-09-24 14:27:38 +00:00
|
|
|
return b.Name == *filter.Name && b.OrganizationID == *filter.OrganizationID
|
2018-09-14 14:25:14 +00:00
|
|
|
}
|
|
|
|
} else if filter.Name != nil {
|
|
|
|
// filter by bucket name
|
|
|
|
filterFunc = func(b *platform.Bucket) bool {
|
|
|
|
return b.Name == *filter.Name
|
|
|
|
}
|
|
|
|
} else if filter.OrganizationID != nil {
|
|
|
|
// filter by organization id
|
|
|
|
filterFunc = func(b *platform.Bucket) bool {
|
2018-09-24 14:27:38 +00:00
|
|
|
return b.OrganizationID == *filter.OrganizationID
|
2018-09-14 14:25:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bs, err := s.filterBuckets(ctx, filterFunc)
|
|
|
|
if err != nil {
|
2018-11-29 17:02:32 +00:00
|
|
|
return nil, err
|
2018-09-14 14:25:14 +00:00
|
|
|
}
|
|
|
|
return bs, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// FindBuckets returns a list of buckets that match filter and the total count of matching buckets.
|
|
|
|
// Additional options provide pagination & sorting.
|
|
|
|
func (s *Service) FindBuckets(ctx context.Context, filter platform.BucketFilter, opt ...platform.FindOptions) ([]*platform.Bucket, int, error) {
|
2018-11-29 17:02:32 +00:00
|
|
|
bs, err := s.findBuckets(ctx, filter, opt...)
|
|
|
|
if err != nil {
|
2018-09-14 14:25:14 +00:00
|
|
|
return nil, 0, err
|
|
|
|
}
|
|
|
|
for _, b := range bs {
|
|
|
|
if err := s.setOrganizationNameOnBucket(ctx, b); err != nil {
|
|
|
|
return nil, 0, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return bs, len(bs), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// CreateBucket creates a new bucket and sets b.ID with the new identifier.
|
|
|
|
func (s *Service) CreateBucket(ctx context.Context, b *platform.Bucket) error {
|
2018-09-24 14:27:38 +00:00
|
|
|
if !b.OrganizationID.Valid() {
|
2018-09-14 14:25:14 +00:00
|
|
|
o, err := s.findOrganizationByName(ctx, b.Organization)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
b.OrganizationID = o.ID
|
|
|
|
}
|
|
|
|
filter := platform.BucketFilter{
|
|
|
|
Name: &b.Name,
|
|
|
|
OrganizationID: &b.OrganizationID,
|
|
|
|
}
|
|
|
|
if _, err := s.FindBucket(ctx, filter); err == nil {
|
2018-11-29 17:02:32 +00:00
|
|
|
return fmt.Errorf("bucket with name %s already exists", b.Name)
|
2018-09-14 14:25:14 +00:00
|
|
|
}
|
|
|
|
b.ID = s.IDGenerator.ID()
|
|
|
|
return s.PutBucket(ctx, b)
|
|
|
|
}
|
|
|
|
|
|
|
|
// PutBucket sets bucket with the current ID.
|
|
|
|
func (s *Service) PutBucket(ctx context.Context, b *platform.Bucket) error {
|
|
|
|
s.bucketKV.Store(b.ID.String(), *b)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// UpdateBucket updates a single bucket with changeset.
|
|
|
|
// Returns the new bucket state after update.
|
|
|
|
func (s *Service) UpdateBucket(ctx context.Context, id platform.ID, upd platform.BucketUpdate) (*platform.Bucket, error) {
|
|
|
|
b, err := s.FindBucketByID(ctx, id)
|
|
|
|
if err != nil {
|
2018-11-29 17:02:32 +00:00
|
|
|
return nil, err
|
2018-09-14 14:25:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if upd.Name != nil {
|
|
|
|
b.Name = *upd.Name
|
|
|
|
}
|
|
|
|
|
|
|
|
if upd.RetentionPeriod != nil {
|
|
|
|
b.RetentionPeriod = *upd.RetentionPeriod
|
|
|
|
}
|
|
|
|
|
|
|
|
s.bucketKV.Store(b.ID.String(), b)
|
|
|
|
|
|
|
|
return b, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// DeleteBucket removes a bucket by ID.
|
|
|
|
func (s *Service) DeleteBucket(ctx context.Context, id platform.ID) error {
|
|
|
|
if _, err := s.FindBucketByID(ctx, id); err != nil {
|
2018-11-29 17:02:32 +00:00
|
|
|
return err
|
2018-09-14 14:25:14 +00:00
|
|
|
}
|
|
|
|
s.bucketKV.Delete(id.String())
|
|
|
|
return nil
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// DeleteOrganizationBuckets removes all the buckets for a given org
|
|
|
|
func (s *Service) DeleteOrganizationBuckets(ctx context.Context, id platform.ID) error {
|
|
|
|
bucks, err := s.findBuckets(ctx, platform.BucketFilter{
|
|
|
|
OrganizationID: &id,
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
for _, buck := range bucks {
|
|
|
|
s.bucketKV.Delete(buck.ID.String())
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|