Skip to content

Commit

Permalink
feat(tenant): Build the crud actions for the new tenant service (#17171)
Browse files Browse the repository at this point in the history
* feat(tenant): Build the crud actions for the new tenant service

To faciliate the isolation of domain specific systems we need to have a
isolated CRUD action system that we can layer business logic on top.

Co-authored-by: George <[email protected]>
  • Loading branch information
lyondhill and GeorgeMac authored Mar 11, 2020
1 parent 76067d5 commit 8e4fdce
Show file tree
Hide file tree
Showing 14 changed files with 2,636 additions and 0 deletions.
30 changes: 30 additions & 0 deletions tenant/error.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package tenant

import (
"github.com/influxdata/influxdb"
)

var (
// ErrNameisEmpty is when a name is empty
ErrNameisEmpty = &influxdb.Error{
Code: influxdb.EInvalid,
Msg: "name is empty",
}
)

// ErrCorruptID the ID stored in the Store is corrupt.
func ErrCorruptID(err error) *influxdb.Error {
return &influxdb.Error{
Code: influxdb.EInvalid,
Msg: "corrupt ID provided",
Err: err,
}
}

// ErrInternalServiceError is used when the error comes from an internal system.
func ErrInternalServiceError(err error) *influxdb.Error {
return &influxdb.Error{
Code: influxdb.EInternal,
Err: err,
}
}
40 changes: 40 additions & 0 deletions tenant/error_bucket.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package tenant

import (
"github.com/influxdata/influxdb"
)

var (
invalidBucketListRequest = &influxdb.Error{
Code: influxdb.EInternal,
Msg: "invalid bucket list action, call should be GetBucketByName",
Op: "kv/listBucket",
}

// ErrBucketNotFound is used when the user is not found.
ErrBucketNotFound = &influxdb.Error{
Msg: "bucket not found",
Code: influxdb.ENotFound,
}
)

// ErrCorruptBucket is used when the user cannot be unmarshalled from the bytes
// stored in the kv.
func ErrCorruptBucket(err error) *influxdb.Error {
return &influxdb.Error{
Code: influxdb.EInternal,
Msg: "user could not be unmarshalled",
Err: err,
Op: "kv/UnmarshalBucket",
}
}

// ErrUnprocessableBucket is used when a org is not able to be processed.
func ErrUnprocessableBucket(err error) *influxdb.Error {
return &influxdb.Error{
Code: influxdb.EUnprocessableEntity,
Msg: "user could not be marshalled",
Err: err,
Op: "kv/MarshalBucket",
}
}
55 changes: 55 additions & 0 deletions tenant/error_org.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package tenant

import (
"fmt"

"github.com/influxdata/influxdb"
)

var (
// ErrOrgNotFound is used when the user is not found.
ErrOrgNotFound = &influxdb.Error{
Msg: "org not found",
Code: influxdb.ENotFound,
}
)

// OrgAlreadyExistsError is used when creating a new organization with
// a name that has already been used. Organization names must be unique.
func OrgAlreadyExistsError(name string) error {
return &influxdb.Error{
Code: influxdb.EConflict,
Msg: fmt.Sprintf("organization with name %s already exists", name),
}
}

// ErrCorruptOrg is used when the user cannot be unmarshalled from the bytes
// stored in the kv.
func ErrCorruptOrg(err error) *influxdb.Error {
return &influxdb.Error{
Code: influxdb.EInternal,
Msg: "user could not be unmarshalled",
Err: err,
Op: "kv/UnmarshalOrg",
}
}

// ErrUnprocessableOrg is used when a org is not able to be processed.
func ErrUnprocessableOrg(err error) *influxdb.Error {
return &influxdb.Error{
Code: influxdb.EUnprocessableEntity,
Msg: "user could not be marshalled",
Err: err,
Op: "kv/MarshalOrg",
}
}

// InvalidOrgIDError is used when a service was provided an invalid ID.
// This is some sort of internal server error.
func InvalidOrgIDError(err error) *influxdb.Error {
return &influxdb.Error{
Code: influxdb.EInvalid,
Msg: "org id provided is invalid",
Err: err,
}
}
59 changes: 59 additions & 0 deletions tenant/error_urm.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package tenant

import (
"fmt"

"github.com/influxdata/influxdb"
)

var (
// ErrInvalidURMID is used when the service was provided
// an invalid ID format.
ErrInvalidURMID = &influxdb.Error{
Code: influxdb.EInvalid,
Msg: "provided user resource mapping ID has invalid format",
}

// ErrURMNotFound is used when the user resource mapping is not found.
ErrURMNotFound = &influxdb.Error{
Msg: "user to resource mapping not found",
Code: influxdb.ENotFound,
}
)

// UnavailableURMServiceError is used if we aren't able to interact with the
// store, it means the store is not available at the moment (e.g. network).
func UnavailableURMServiceError(err error) *influxdb.Error {
return &influxdb.Error{
Code: influxdb.EInternal,
Msg: fmt.Sprintf("Unable to connect to resource mapping service. Please try again; Err: %v", err),
Op: "kv/userResourceMapping",
}
}

// CorruptURMError is used when the config cannot be unmarshalled from the
// bytes stored in the kv.
func CorruptURMError(err error) *influxdb.Error {
return &influxdb.Error{
Code: influxdb.EInternal,
Msg: fmt.Sprintf("Unknown internal user resource mapping data error; Err: %v", err),
Op: "kv/userResourceMapping",
}
}

// ErrUnprocessableMapping is used when a user resource mapping is not able to be converted to JSON.
func ErrUnprocessableMapping(err error) *influxdb.Error {
return &influxdb.Error{
Code: influxdb.EUnprocessableEntity,
Msg: fmt.Sprintf("unable to convert mapping of user to resource into JSON; Err %v", err),
}
}

// NonUniqueMappingError is an internal error when a user already has
// been mapped to a resource
func NonUniqueMappingError(userID influxdb.ID) error {
return &influxdb.Error{
Code: influxdb.EInternal,
Msg: fmt.Sprintf("Unexpected error when assigning user to a resource: mapping for user %s already exists", userID.String()),
}
}
73 changes: 73 additions & 0 deletions tenant/error_user.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package tenant

import (
"fmt"

"github.com/influxdata/influxdb"
)

var (
// ErrUserNotFound is used when the user is not found.
ErrUserNotFound = &influxdb.Error{
Msg: "user not found",
Code: influxdb.ENotFound,
}
)

// UserAlreadyExistsError is used when attempting to create a user with a name
// that already exists.
func UserAlreadyExistsError(n string) *influxdb.Error {
return &influxdb.Error{
Code: influxdb.EConflict,
Msg: fmt.Sprintf("user with name %s already exists", n),
}
}

// UnexpectedUserBucketError is used when the error comes from an internal system.
func UnexpectedUserBucketError(err error) *influxdb.Error {
return &influxdb.Error{
Code: influxdb.EInternal,
Msg: fmt.Sprintf("unexpected error retrieving user bucket; Err: %v", err),
Op: "kv/userBucket",
}
}

// UnexpectedUserIndexError is used when the error comes from an internal system.
func UnexpectedUserIndexError(err error) *influxdb.Error {
return &influxdb.Error{
Code: influxdb.EInternal,
Msg: fmt.Sprintf("unexpected error retrieving user index; Err: %v", err),
Op: "kv/userIndex",
}
}

// InvalidUserIDError is used when a service was provided an invalid ID.
// This is some sort of internal server error.
func InvalidUserIDError(err error) *influxdb.Error {
return &influxdb.Error{
Code: influxdb.EInvalid,
Msg: "user id provided is invalid",
Err: err,
}
}

// ErrCorruptUser is used when the user cannot be unmarshalled from the bytes
// stored in the kv.
func ErrCorruptUser(err error) *influxdb.Error {
return &influxdb.Error{
Code: influxdb.EInternal,
Msg: "user could not be unmarshalled",
Err: err,
Op: "kv/UnmarshalUser",
}
}

// ErrUnprocessableUser is used when a user is not able to be processed.
func ErrUnprocessableUser(err error) *influxdb.Error {
return &influxdb.Error{
Code: influxdb.EUnprocessableEntity,
Msg: "user could not be marshalled",
Err: err,
Op: "kv/MarshalUser",
}
}
62 changes: 62 additions & 0 deletions tenant/storage.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package tenant

import (
"context"

"github.com/influxdata/influxdb/kv"
)

type Store struct {
kvStore kv.Store
}

func NewStore(kvStore kv.Store) (*Store, error) {
st := &Store{
kvStore: kvStore,
}
return st, st.setup()
}

// View opens up a transaction that will not write to any data. Implementing interfaces
// should take care to ensure that all view transactions do not mutate any data.
func (s *Store) View(ctx context.Context, fn func(kv.Tx) error) error {
return s.kvStore.View(ctx, fn)
}

// Update opens up a transaction that will mutate data.
func (s *Store) Update(ctx context.Context, fn func(kv.Tx) error) error {
return s.kvStore.Update(ctx, fn)
}

func (s *Store) setup() error {
return s.Update(context.Background(), func(tx kv.Tx) error {
if _, err := tx.Bucket(userBucket); err != nil {
return err
}

if _, err := tx.Bucket(userIndex); err != nil {
return err
}

if _, err := tx.Bucket(urmBucket); err != nil {
return err
}
if _, err := tx.Bucket(organizationBucket); err != nil {
return err
}

if _, err := tx.Bucket(organizationIndex); err != nil {
return err
}

if _, err := tx.Bucket(bucketBucket); err != nil {
return err
}

if _, err := tx.Bucket(bucketIndex); err != nil {
return err
}

return nil
})
}
Loading

0 comments on commit 8e4fdce

Please sign in to comment.