705 lines
21 KiB
Go
705 lines
21 KiB
Go
package tests
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"io"
|
|
"net/http"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/influxdata/flux/csv"
|
|
"github.com/influxdata/influxdb/v2"
|
|
"github.com/influxdata/influxdb/v2/authorization"
|
|
influxhttp "github.com/influxdata/influxdb/v2/http"
|
|
"github.com/influxdata/influxdb/v2/kit/platform"
|
|
"github.com/influxdata/influxdb/v2/pkg/httpc"
|
|
"github.com/influxdata/influxdb/v2/tenant"
|
|
)
|
|
|
|
type ClientConfig struct {
|
|
UserID platform.ID
|
|
OrgID platform.ID
|
|
BucketID platform.ID
|
|
DocumentsNamespace string
|
|
|
|
// If Session is provided, Token is ignored.
|
|
Token string
|
|
Session *influxdb.Session
|
|
}
|
|
|
|
// Client provides an API for writing, querying, and interacting with
|
|
// resources like authorizations, buckets, and organizations.
|
|
type Client struct {
|
|
Client *httpc.Client
|
|
*influxhttp.Service
|
|
|
|
*authorization.AuthorizationClientService
|
|
*tenant.BucketClientService
|
|
*tenant.OrgClientService
|
|
*tenant.UserClientService
|
|
|
|
ClientConfig
|
|
}
|
|
|
|
// NewClient initialises a new Client which is ready to write points to the HTTP write endpoint.
|
|
func NewClient(endpoint string, config ClientConfig) (*Client, error) {
|
|
opts := make([]httpc.ClientOptFn, 0)
|
|
if config.Session != nil {
|
|
config.Token = ""
|
|
opts = append(opts, httpc.WithSessionCookie(config.Session.Key))
|
|
}
|
|
hc, err := influxhttp.NewHTTPClient(endpoint, config.Token, false, opts...)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
svc, err := influxhttp.NewService(hc, endpoint, config.Token)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &Client{
|
|
Client: hc,
|
|
Service: svc,
|
|
AuthorizationClientService: &authorization.AuthorizationClientService{Client: hc},
|
|
BucketClientService: &tenant.BucketClientService{Client: hc},
|
|
OrgClientService: &tenant.OrgClientService{Client: hc},
|
|
UserClientService: &tenant.UserClientService{Client: hc},
|
|
ClientConfig: config,
|
|
}, nil
|
|
}
|
|
|
|
// Open opens the client
|
|
func (c *Client) Open() error { return nil }
|
|
|
|
// Close closes the client
|
|
func (c *Client) Close() error { return nil }
|
|
|
|
// MustWriteBatch calls WriteBatch, panicking if an error is encountered.
|
|
func (c *Client) MustWriteBatch(points string) {
|
|
if err := c.WriteBatch(points); err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
|
|
// WriteBatch writes the current batch of points to the HTTP endpoint.
|
|
func (c *Client) WriteBatch(points string) error {
|
|
return c.WriteService.WriteTo(
|
|
context.Background(),
|
|
influxdb.BucketFilter{
|
|
ID: &c.BucketID,
|
|
OrganizationID: &c.OrgID,
|
|
},
|
|
strings.NewReader(points),
|
|
)
|
|
}
|
|
|
|
// Query returns the CSV response from a flux query to the HTTP API.
|
|
//
|
|
// This also remove all the \r to make it easier to write tests.
|
|
func (c *Client) QueryFlux(org, query string) (string, error) {
|
|
var csv string
|
|
csvResp := func(resp *http.Response) error {
|
|
body, err := io.ReadAll(resp.Body)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
// remove the \r to simplify testing against a body of CSV.
|
|
body = bytes.ReplaceAll(body, []byte("\r"), nil)
|
|
csv = string(body)
|
|
return nil
|
|
}
|
|
|
|
qr := QueryRequestBody(query)
|
|
err := c.Client.PostJSON(qr, fluxPath).
|
|
QueryParams([2]string{"org", org}).
|
|
Accept("text/csv").
|
|
RespFn(csvResp).
|
|
StatusFn(httpc.StatusIn(http.StatusOK)).
|
|
Do(context.Background())
|
|
|
|
return csv, err
|
|
}
|
|
|
|
const (
|
|
fluxPath = "/api/v2/query"
|
|
// This is the only namespace for documents present after init.
|
|
DefaultDocumentsNamespace = "templates"
|
|
)
|
|
|
|
// QueryRequestBody creates a body for a flux query using common CSV output params.
|
|
// Headers are included, but, annotations are not.
|
|
func QueryRequestBody(flux string) *influxhttp.QueryRequest {
|
|
header := true
|
|
return &influxhttp.QueryRequest{
|
|
Type: "flux",
|
|
Query: flux,
|
|
Dialect: influxhttp.QueryDialect{
|
|
Header: &header,
|
|
Delimiter: ",",
|
|
CommentPrefix: "#",
|
|
DateTimeFormat: "RFC3339",
|
|
Annotations: csv.DefaultEncoderConfig().Annotations,
|
|
},
|
|
}
|
|
}
|
|
|
|
// MustCreateAuth creates an auth or is a fatal error.
|
|
// Used in tests where the content of the bucket does not matter.
|
|
//
|
|
// This authorization token is an operator token for the default
|
|
// organization for the default user.
|
|
func (c *Client) MustCreateAuth(t *testing.T) platform.ID {
|
|
t.Helper()
|
|
|
|
perms := influxdb.OperPermissions()
|
|
auth := &influxdb.Authorization{
|
|
OrgID: c.OrgID,
|
|
UserID: c.UserID,
|
|
Permissions: perms,
|
|
}
|
|
err := c.CreateAuthorization(context.Background(), auth)
|
|
if err != nil {
|
|
t.Fatalf("unable to create auth: %v", err)
|
|
}
|
|
return auth.ID
|
|
}
|
|
|
|
// MustCreateBucket creates a bucket or is a fatal error.
|
|
// Used in tests where the content of the bucket does not matter.
|
|
func (c *Client) MustCreateBucket(t *testing.T) platform.ID {
|
|
t.Helper()
|
|
|
|
bucket := &influxdb.Bucket{OrgID: c.OrgID, Name: "n1"}
|
|
err := c.CreateBucket(context.Background(), bucket)
|
|
if err != nil {
|
|
t.Fatalf("unable to create bucket: %v", err)
|
|
}
|
|
return bucket.ID
|
|
}
|
|
|
|
// MustCreateOrg creates an org or is a fatal error.
|
|
// Used in tests where the content of the org does not matter.
|
|
func (c *Client) MustCreateOrg(t *testing.T) platform.ID {
|
|
t.Helper()
|
|
|
|
org := &influxdb.Organization{Name: "n1"}
|
|
err := c.CreateOrganization(context.Background(), org)
|
|
if err != nil {
|
|
t.Fatalf("unable to create org: %v", err)
|
|
}
|
|
return org.ID
|
|
}
|
|
|
|
// MustCreateLabel creates a label or is a fatal error.
|
|
// Used in tests where the content of the label does not matter.
|
|
func (c *Client) MustCreateLabel(t *testing.T) platform.ID {
|
|
t.Helper()
|
|
|
|
l := &influxdb.Label{OrgID: c.OrgID, Name: "n1"}
|
|
err := c.CreateLabel(context.Background(), l)
|
|
if err != nil {
|
|
t.Fatalf("unable to create label: %v", err)
|
|
}
|
|
return l.ID
|
|
}
|
|
|
|
// MustCreateCheck creates a check or is a fatal error.
|
|
// Used in tests where the content of the check does not matter.
|
|
func (c *Client) MustCreateCheck(t *testing.T) platform.ID {
|
|
t.Helper()
|
|
|
|
chk, err := c.CreateCheck(context.Background(), MockCheck("c", c.OrgID, c.UserID))
|
|
if err != nil {
|
|
t.Fatalf("unable to create check: %v", err)
|
|
}
|
|
return chk.ID
|
|
}
|
|
|
|
// MustCreateTelegraf creates a telegraf config or is a fatal error.
|
|
// Used in tests where the content of the telegraf config does not matter.
|
|
func (c *Client) MustCreateTelegraf(t *testing.T) platform.ID {
|
|
t.Helper()
|
|
|
|
tc := &influxdb.TelegrafConfig{
|
|
OrgID: c.OrgID,
|
|
Name: "n1",
|
|
Description: "d1",
|
|
Config: "[[howdy]]",
|
|
}
|
|
unused := platform.ID(1) /* this id is not used in the API */
|
|
err := c.CreateTelegrafConfig(context.Background(), tc, unused)
|
|
if err != nil {
|
|
t.Fatalf("unable to create telegraf config: %v", err)
|
|
}
|
|
return tc.ID
|
|
}
|
|
|
|
// MustCreateUser creates a user or is a fatal error.
|
|
// Used in tests where the content of the user does not matter.
|
|
func (c *Client) MustCreateUser(t *testing.T) platform.ID {
|
|
t.Helper()
|
|
|
|
u := &influxdb.User{Name: "n1"}
|
|
err := c.CreateUser(context.Background(), u)
|
|
if err != nil {
|
|
t.Fatalf("unable to create user: %v", err)
|
|
}
|
|
return u.ID
|
|
}
|
|
|
|
// MustCreateVariable creates a variable or is a fatal error.
|
|
// Used in tests where the content of the variable does not matter.
|
|
func (c *Client) MustCreateVariable(t *testing.T) platform.ID {
|
|
t.Helper()
|
|
|
|
v := &influxdb.Variable{
|
|
OrganizationID: c.OrgID,
|
|
Name: "n1",
|
|
Arguments: &influxdb.VariableArguments{
|
|
Type: "constant",
|
|
Values: influxdb.VariableConstantValues{"v1", "v2"},
|
|
},
|
|
}
|
|
err := c.CreateVariable(context.Background(), v)
|
|
if err != nil {
|
|
t.Fatalf("unable to create variable: %v", err)
|
|
}
|
|
return v.ID
|
|
}
|
|
|
|
// MustCreateNotificationEndpoint creates a notification endpoint or is a fatal error.
|
|
// Used in tests where the content of the notification endpoint does not matter.
|
|
func (c *Client) MustCreateNotificationEndpoint(t *testing.T) platform.ID {
|
|
t.Helper()
|
|
|
|
ne := ValidNotificationEndpoint(c.OrgID)
|
|
err := c.CreateNotificationEndpoint(context.Background(), ne, c.UserID)
|
|
if err != nil {
|
|
t.Fatalf("unable to create notification endpoint: %v", err)
|
|
}
|
|
return ne.GetID()
|
|
}
|
|
|
|
// MustCreateNotificationRule creates a Notification Rule or is a fatal error
|
|
// Used in tests where the content of the notification rule does not matter
|
|
func (c *Client) MustCreateNotificationRule(t *testing.T) platform.ID {
|
|
t.Helper()
|
|
ctx := context.Background()
|
|
|
|
ne := ValidCustomNotificationEndpoint(c.OrgID, time.Now().String())
|
|
err := c.CreateNotificationEndpoint(ctx, ne, c.UserID)
|
|
if err != nil {
|
|
t.Fatalf("unable to create notification endpoint: %v", err)
|
|
}
|
|
endpointID := ne.GetID()
|
|
r := ValidNotificationRule(c.OrgID, endpointID)
|
|
rc := influxdb.NotificationRuleCreate{NotificationRule: r, Status: influxdb.Active}
|
|
|
|
err = c.CreateNotificationRule(ctx, rc, c.UserID)
|
|
if err != nil {
|
|
t.Fatalf("unable to create notification rule: %v", err)
|
|
}
|
|
|
|
// we don't need this endpoint, so delete it to be compatible with other tests
|
|
_, _, err = c.DeleteNotificationEndpoint(ctx, endpointID)
|
|
if err != nil {
|
|
t.Fatalf("unable to delete notification endpoint: %v", err)
|
|
}
|
|
|
|
return r.GetID()
|
|
}
|
|
|
|
// MustCreateDBRPMapping creates a DBRP Mapping or is a fatal error.
|
|
// Used in tests where the content of the mapping does not matter.
|
|
// The created mapping points to the user's default bucket.
|
|
func (c *Client) MustCreateDBRPMapping(t *testing.T) platform.ID {
|
|
t.Helper()
|
|
ctx := context.Background()
|
|
|
|
m := &influxdb.DBRPMapping{
|
|
Database: "db",
|
|
RetentionPolicy: "rp",
|
|
OrganizationID: c.OrgID,
|
|
BucketID: c.BucketID,
|
|
}
|
|
if err := c.DBRPMappingService.Create(ctx, m); err != nil {
|
|
t.Fatalf("unable to create DBRP mapping: %v", err)
|
|
}
|
|
return m.ID
|
|
}
|
|
|
|
// MustCreateResource will create a generic resource via the API.
|
|
// Used in tests where the content of the resource does not matter.
|
|
//
|
|
// // Create one of each org resource
|
|
// for _, r := range influxdb.OrgResourceTypes {
|
|
// client.MustCreateResource(t, r)
|
|
// }
|
|
//
|
|
//
|
|
// // Create a variable:
|
|
// id := client.MustCreateResource(t, influxdb.VariablesResourceType)
|
|
// defer client.MustDeleteResource(t, influxdb.VariablesResourceType, id)
|
|
func (c *Client) MustCreateResource(t *testing.T, r influxdb.ResourceType) platform.ID {
|
|
t.Helper()
|
|
|
|
switch r {
|
|
case influxdb.AuthorizationsResourceType: // 0
|
|
return c.MustCreateAuth(t)
|
|
case influxdb.BucketsResourceType: // 1
|
|
return c.MustCreateBucket(t)
|
|
case influxdb.OrgsResourceType: // 3
|
|
return c.MustCreateOrg(t)
|
|
case influxdb.SourcesResourceType: // 4
|
|
t.Skip("I think sources are going to be removed right?")
|
|
case influxdb.TasksResourceType: // 5
|
|
t.Skip("Task go client is not yet created")
|
|
case influxdb.TelegrafsResourceType: // 6
|
|
return c.MustCreateTelegraf(t)
|
|
case influxdb.UsersResourceType: // 7
|
|
return c.MustCreateUser(t)
|
|
case influxdb.VariablesResourceType: // 8
|
|
return c.MustCreateVariable(t)
|
|
case influxdb.ScraperResourceType: // 9
|
|
t.Skip("Scraper go client is not yet created")
|
|
case influxdb.SecretsResourceType: // 10
|
|
t.Skip("Secrets go client is not yet created")
|
|
case influxdb.LabelsResourceType: // 11
|
|
return c.MustCreateLabel(t)
|
|
case influxdb.ViewsResourceType: // 12
|
|
t.Skip("Are views still a thing?")
|
|
case influxdb.NotificationRuleResourceType: // 14
|
|
return c.MustCreateNotificationRule(t)
|
|
case influxdb.NotificationEndpointResourceType: // 15
|
|
return c.MustCreateNotificationEndpoint(t)
|
|
case influxdb.ChecksResourceType: // 16
|
|
return c.MustCreateCheck(t)
|
|
case influxdb.DBRPResourceType: // 17
|
|
return c.MustCreateDBRPMapping(t)
|
|
}
|
|
return 0
|
|
}
|
|
|
|
// DeleteResource will remove a resource using the API.
|
|
func (c *Client) DeleteResource(t *testing.T, r influxdb.ResourceType, id platform.ID) error {
|
|
t.Helper()
|
|
|
|
ctx := context.Background()
|
|
switch r {
|
|
case influxdb.AuthorizationsResourceType: // 0
|
|
return c.DeleteAuthorization(ctx, id)
|
|
case influxdb.BucketsResourceType: // 1
|
|
return c.DeleteBucket(context.Background(), id)
|
|
case influxdb.OrgsResourceType: // 3
|
|
return c.DeleteOrganization(ctx, id)
|
|
case influxdb.SourcesResourceType: // 4
|
|
t.Skip("I think sources are going to be removed right?")
|
|
case influxdb.TasksResourceType: // 5
|
|
t.Skip("Task go client is not yet created")
|
|
case influxdb.TelegrafsResourceType: // 6
|
|
return c.DeleteTelegrafConfig(ctx, id)
|
|
case influxdb.UsersResourceType: // 7
|
|
return c.DeleteUser(ctx, id)
|
|
case influxdb.VariablesResourceType: // 8
|
|
return c.DeleteVariable(ctx, id)
|
|
case influxdb.ScraperResourceType: // 9
|
|
t.Skip("Scraper go client is not yet created")
|
|
case influxdb.SecretsResourceType: // 10
|
|
t.Skip("Secrets go client is not yet created")
|
|
case influxdb.LabelsResourceType: // 11
|
|
return c.DeleteLabel(ctx, id)
|
|
case influxdb.ViewsResourceType: // 12
|
|
t.Skip("Are views still a thing?")
|
|
case influxdb.NotificationRuleResourceType: // 14
|
|
return c.DeleteNotificationRule(ctx, id)
|
|
case influxdb.NotificationEndpointResourceType: // 15
|
|
// Ignore the other results as suggested by goDoc.
|
|
_, _, err := c.DeleteNotificationEndpoint(ctx, id)
|
|
return err
|
|
case influxdb.ChecksResourceType: // 16
|
|
return c.DeleteCheck(ctx, id)
|
|
case influxdb.DBRPResourceType: // 17
|
|
return c.DBRPMappingService.Delete(ctx, c.OrgID, id)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// MustDeleteResource requires no error when deleting a resource.
|
|
func (c *Client) MustDeleteResource(t *testing.T, r influxdb.ResourceType, id platform.ID) {
|
|
t.Helper()
|
|
|
|
if err := c.DeleteResource(t, r, id); err != nil {
|
|
t.Fatalf("unable to delete resource %v %v: %v", r, id, err)
|
|
}
|
|
}
|
|
|
|
// FindAll returns all the IDs of a specific resource type.
|
|
func (c *Client) FindAll(t *testing.T, r influxdb.ResourceType) ([]platform.ID, error) {
|
|
t.Helper()
|
|
|
|
var ids []platform.ID
|
|
ctx := context.Background()
|
|
switch r {
|
|
case influxdb.AuthorizationsResourceType: // 0
|
|
rs, _, err := c.FindAuthorizations(ctx, influxdb.AuthorizationFilter{})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
for _, r := range rs {
|
|
ids = append(ids, r.ID)
|
|
}
|
|
case influxdb.BucketsResourceType: // 1
|
|
rs, _, err := c.FindBuckets(ctx, influxdb.BucketFilter{})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
for _, r := range rs {
|
|
ids = append(ids, r.ID)
|
|
}
|
|
case influxdb.OrgsResourceType: // 3
|
|
rs, _, err := c.FindOrganizations(ctx, influxdb.OrganizationFilter{})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
for _, r := range rs {
|
|
ids = append(ids, r.ID)
|
|
}
|
|
case influxdb.SourcesResourceType: // 4
|
|
t.Skip("I think sources are going to be removed right?")
|
|
case influxdb.TasksResourceType: // 5
|
|
t.Skip("Task go client is not yet created")
|
|
case influxdb.TelegrafsResourceType: // 6
|
|
rs, _, err := c.FindTelegrafConfigs(ctx, influxdb.TelegrafConfigFilter{})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
for _, r := range rs {
|
|
ids = append(ids, r.ID)
|
|
}
|
|
case influxdb.UsersResourceType: // 7
|
|
rs, _, err := c.FindUsers(ctx, influxdb.UserFilter{})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
for _, r := range rs {
|
|
ids = append(ids, r.ID)
|
|
}
|
|
case influxdb.VariablesResourceType: // 8
|
|
rs, err := c.FindVariables(ctx, influxdb.VariableFilter{})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
for _, r := range rs {
|
|
ids = append(ids, r.ID)
|
|
}
|
|
case influxdb.ScraperResourceType: // 9
|
|
t.Skip("Scraper go client is not yet created")
|
|
case influxdb.SecretsResourceType: // 10
|
|
t.Skip("Secrets go client is not yet created")
|
|
case influxdb.LabelsResourceType: // 11
|
|
rs, err := c.FindLabels(ctx, influxdb.LabelFilter{})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
for _, r := range rs {
|
|
ids = append(ids, r.ID)
|
|
}
|
|
case influxdb.ViewsResourceType: // 12
|
|
t.Skip("Are views still a thing?")
|
|
case influxdb.NotificationRuleResourceType: // 14
|
|
rs, _, err := c.FindNotificationRules(ctx, influxdb.NotificationRuleFilter{OrgID: &c.OrgID})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
for _, r := range rs {
|
|
ids = append(ids, r.GetID())
|
|
}
|
|
return ids, nil
|
|
case influxdb.NotificationEndpointResourceType: // 15
|
|
rs, _, err := c.FindNotificationEndpoints(ctx, influxdb.NotificationEndpointFilter{OrgID: &c.OrgID})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
for _, r := range rs {
|
|
ids = append(ids, r.GetID())
|
|
}
|
|
case influxdb.ChecksResourceType: // 16
|
|
rs, _, err := c.FindChecks(ctx, influxdb.CheckFilter{})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
for _, r := range rs {
|
|
ids = append(ids, r.ID)
|
|
}
|
|
case influxdb.DBRPResourceType: // 17
|
|
rs, _, err := c.DBRPMappingService.FindMany(ctx, influxdb.DBRPMappingFilter{OrgID: &c.OrgID})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
for _, r := range rs {
|
|
ids = append(ids, r.ID)
|
|
}
|
|
}
|
|
return ids, nil
|
|
}
|
|
|
|
// MustFindAll returns all the IDs of a specific resource type; any error
|
|
// is fatal.
|
|
func (c *Client) MustFindAll(t *testing.T, r influxdb.ResourceType) []platform.ID {
|
|
t.Helper()
|
|
|
|
ids, err := c.FindAll(t, r)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error finding resources %v: %v", r, err)
|
|
}
|
|
return ids
|
|
}
|
|
|
|
func (c *Client) AddURM(u platform.ID, typ influxdb.UserType, r influxdb.ResourceType, id platform.ID) error {
|
|
access := &influxdb.UserResourceMapping{
|
|
UserID: u,
|
|
UserType: typ,
|
|
MappingType: influxdb.UserMappingType,
|
|
ResourceType: r,
|
|
ResourceID: id,
|
|
}
|
|
|
|
return c.CreateUserResourceMapping(
|
|
context.Background(),
|
|
access,
|
|
)
|
|
}
|
|
|
|
// AddOwner associates the user as owner of the resource.
|
|
func (c *Client) AddOwner(user platform.ID, r influxdb.ResourceType, id platform.ID) error {
|
|
return c.AddURM(user, influxdb.Owner, r, id)
|
|
}
|
|
|
|
// MustAddOwner requires that the user is associated with the resource
|
|
// or the test will be stopped fatally.
|
|
func (c *Client) MustAddOwner(t *testing.T, user platform.ID, r influxdb.ResourceType, id platform.ID) {
|
|
t.Helper()
|
|
|
|
if err := c.AddOwner(user, r, id); err != nil {
|
|
t.Fatalf("unexpected error adding owner %v to %v: %v", user, id, err)
|
|
}
|
|
}
|
|
|
|
// AddMember associates the user as member of the resource.
|
|
func (c *Client) AddMember(user platform.ID, r influxdb.ResourceType, id platform.ID) error {
|
|
return c.AddURM(user, influxdb.Member, r, id)
|
|
}
|
|
|
|
// MustAddMember requires that the user is associated with the resource
|
|
// or the test will be stopped fatally.
|
|
func (c *Client) MustAddMember(t *testing.T, user platform.ID, r influxdb.ResourceType, id platform.ID) {
|
|
t.Helper()
|
|
|
|
if err := c.AddMember(user, r, id); err != nil {
|
|
t.Fatalf("unexpected error adding member %v to %v", user, id)
|
|
}
|
|
}
|
|
|
|
// RemoveURM removes association of the user to the resource.
|
|
// Interestingly the URM service does not make difference on the user type.
|
|
// I.e. removing an URM from a user to a resource, will delete every URM of every type
|
|
// from that user to that resource.
|
|
// Or, put in another way, there can only be one resource mapping from a user to a
|
|
// resource at a time: either you are a member, or an owner (in that case you are a member too).
|
|
func (c *Client) RemoveURM(user, id platform.ID) error {
|
|
return c.DeleteUserResourceMapping(context.Background(), id, user)
|
|
}
|
|
|
|
// RemoveSpecificURM gets around a client issue where deletes doesn't have enough context to remove a urm from
|
|
// a specific resource type
|
|
func (c *Client) RemoveSpecificURM(rt influxdb.ResourceType, ut influxdb.UserType, user, id platform.ID) error {
|
|
return c.SpecificURMSvc(rt, ut).DeleteUserResourceMapping(context.Background(), id, user)
|
|
}
|
|
|
|
// MustRemoveURM requires that the user is removed as owner/member from the resource.
|
|
func (c *Client) MustRemoveURM(t *testing.T, user, id platform.ID) {
|
|
t.Helper()
|
|
|
|
if err := c.RemoveURM(user, id); err != nil {
|
|
t.Fatalf("unexpected error removing org/resource mapping: %v", err)
|
|
}
|
|
}
|
|
|
|
// CreateLabelMapping creates a label mapping for label `l` to the resource with `id`.
|
|
func (c *Client) CreateLabelMapping(l platform.ID, r influxdb.ResourceType, id platform.ID) error {
|
|
mapping := &influxdb.LabelMapping{
|
|
LabelID: l,
|
|
ResourceType: r,
|
|
ResourceID: id,
|
|
}
|
|
return c.LabelService.CreateLabelMapping(
|
|
context.Background(),
|
|
mapping,
|
|
)
|
|
}
|
|
|
|
// MustCreateLabelMapping requires that the label is associated with the resource
|
|
// or the test will be stopped fatally.
|
|
func (c *Client) MustCreateLabelMapping(t *testing.T, l platform.ID, r influxdb.ResourceType, id platform.ID) {
|
|
t.Helper()
|
|
|
|
if err := c.CreateLabelMapping(l, r, id); err != nil {
|
|
t.Fatalf("unexpected error attaching label %v to %v: %v", l, id, err)
|
|
}
|
|
}
|
|
|
|
// FindLabelMappings finds the labels for the specified resource.
|
|
func (c *Client) FindLabelMappings(r influxdb.ResourceType, id platform.ID) ([]platform.ID, error) {
|
|
filter := influxdb.LabelMappingFilter{
|
|
ResourceType: r,
|
|
ResourceID: id,
|
|
}
|
|
ls, err := c.LabelService.FindResourceLabels(
|
|
context.Background(),
|
|
filter,
|
|
)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var ids []platform.ID
|
|
for _, r := range ls {
|
|
ids = append(ids, r.ID)
|
|
}
|
|
return ids, nil
|
|
}
|
|
|
|
// MustFindLabelMappings makes the test fail if an error is found.
|
|
func (c *Client) MustFindLabelMappings(t *testing.T, r influxdb.ResourceType, id platform.ID) []platform.ID {
|
|
t.Helper()
|
|
|
|
ls, err := c.FindLabelMappings(r, id)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error finding label mappings: %v", err)
|
|
}
|
|
return ls
|
|
}
|
|
|
|
// DeleteLabelMapping deletes the label for the specified resource.
|
|
func (c *Client) DeleteLabelMapping(l platform.ID, r influxdb.ResourceType, id platform.ID) error {
|
|
m := &influxdb.LabelMapping{
|
|
ResourceType: r,
|
|
ResourceID: id,
|
|
LabelID: l,
|
|
}
|
|
return c.LabelService.DeleteLabelMapping(
|
|
context.Background(),
|
|
m,
|
|
)
|
|
}
|
|
|
|
// MustDeleteLabelMapping makes the test fail if an error is found.
|
|
func (c *Client) MustDeleteLabelMapping(t *testing.T, l platform.ID, r influxdb.ResourceType, id platform.ID) {
|
|
t.Helper()
|
|
|
|
if err := c.DeleteLabelMapping(l, r, id); err != nil {
|
|
t.Fatalf("unexpected error deleting label %v from %v", l, id)
|
|
}
|
|
}
|