influxdb/cmd/influx/organization_test.go

591 lines
15 KiB
Go

package main
import (
"bytes"
"context"
"fmt"
"io/ioutil"
"reflect"
"testing"
"github.com/stretchr/testify/assert"
"github.com/influxdata/influxdb/v2"
"github.com/influxdata/influxdb/v2/mock"
"github.com/spf13/cobra"
"github.com/stretchr/testify/require"
)
func TestCmdOrg(t *testing.T) {
fakeOrgSVCFn := func(svc influxdb.OrganizationService) orgSVCFn {
return func() (influxdb.OrganizationService, influxdb.UserResourceMappingService, influxdb.UserService, error) {
return svc, mock.NewUserResourceMappingService(), mock.NewUserService(), nil
}
}
fakeOrgUrmSVCsFn := func(svc influxdb.OrganizationService, urmSVC influxdb.UserResourceMappingService) orgSVCFn {
return func() (influxdb.OrganizationService, influxdb.UserResourceMappingService, influxdb.UserService, error) {
return svc, urmSVC, mock.NewUserService(), nil
}
}
t.Run("create", func(t *testing.T) {
tests := []struct {
name string
expected influxdb.Organization
flags []string
}{
{
name: "all",
flags: []string{"--name=new name", "--description=desc"},
expected: influxdb.Organization{
Name: "new name",
Description: "desc",
},
},
{
name: "shorts",
flags: []string{"-n=new name", "-d=desc"},
expected: influxdb.Organization{
Name: "new name",
Description: "desc",
},
},
}
cmdFn := func(expectedOrg influxdb.Organization) func(*globalFlags, genericCLIOpts) *cobra.Command {
svc := mock.NewOrganizationService()
svc.CreateOrganizationF = func(ctx context.Context, org *influxdb.Organization) error {
if expectedOrg != *org {
return fmt.Errorf("unexpected org;\n\twant= %+v\n\tgot= %+v", expectedOrg, *org)
}
return nil
}
return func(_ *globalFlags, opt genericCLIOpts) *cobra.Command {
builder := newCmdOrgBuilder(fakeOrgSVCFn(svc), opt)
return builder.cmd()
}
}
for _, tt := range tests {
fn := func(t *testing.T) {
builder := newInfluxCmdBuilder(
in(new(bytes.Buffer)),
out(ioutil.Discard),
)
cmd := builder.cmd(cmdFn(tt.expected))
cmd.SetArgs(append([]string{"org", "create"}, tt.flags...))
require.NoError(t, cmd.Execute())
}
t.Run(tt.name, fn)
}
})
t.Run("delete", func(t *testing.T) {
tests := []struct {
name string
expectedID influxdb.ID
flag string
}{
{
name: "id",
expectedID: influxdb.ID(1),
flag: "--id=",
},
{
name: "shorts",
expectedID: influxdb.ID(1),
flag: "-i=",
},
}
cmdFn := func(expectedID influxdb.ID) func(*globalFlags, genericCLIOpts) *cobra.Command {
svc := mock.NewOrganizationService()
svc.FindOrganizationByIDF = func(ctx context.Context, id influxdb.ID) (*influxdb.Organization, error) {
return &influxdb.Organization{ID: id}, nil
}
svc.DeleteOrganizationF = func(ctx context.Context, id influxdb.ID) error {
if expectedID != id {
return fmt.Errorf("unexpected id:\n\twant= %s\n\tgot= %s", expectedID, id)
}
return nil
}
return func(g *globalFlags, opt genericCLIOpts) *cobra.Command {
builder := newCmdOrgBuilder(fakeOrgSVCFn(svc), opt)
return builder.cmd()
}
}
for _, tt := range tests {
fn := func(t *testing.T) {
builder := newInfluxCmdBuilder(
in(new(bytes.Buffer)),
out(ioutil.Discard),
)
cmd := builder.cmd(cmdFn(tt.expectedID))
idFlag := tt.flag + tt.expectedID.String()
cmd.SetArgs([]string{"org", "find", idFlag})
require.NoError(t, cmd.Execute())
}
t.Run(tt.name, fn)
}
})
t.Run("list", func(t *testing.T) {
type called struct {
name string
id influxdb.ID
}
tests := []struct {
name string
expected called
flags []string
command string
envVars map[string]string
}{
{
name: "org id",
flags: []string{"--id=" + influxdb.ID(3).String()},
envVars: envVarsZeroMap,
expected: called{id: 3},
},
{
name: "name",
flags: []string{"--name=name1"},
envVars: envVarsZeroMap,
expected: called{name: "name1"},
},
{
name: "shorts",
flags: []string{
"-n=name1",
"-i=" + influxdb.ID(1).String(),
},
envVars: envVarsZeroMap,
expected: called{name: "name1", id: 1},
},
{
name: "env vars",
envVars: map[string]string{
"INFLUX_ORG_ID": influxdb.ID(1).String(),
"INFLUX_ORG": "name1",
},
flags: []string{"-i=" + influxdb.ID(1).String()},
expected: called{name: "name1", id: 1},
},
{
name: "ls alias",
command: "ls",
flags: []string{"--name=name1"},
envVars: envVarsZeroMap,
expected: called{name: "name1"},
},
{
name: "find alias",
command: "find",
flags: []string{"--name=name1"},
envVars: envVarsZeroMap,
expected: called{name: "name1"},
},
}
cmdFn := func() (func(*globalFlags, genericCLIOpts) *cobra.Command, *called) {
calls := new(called)
svc := mock.NewOrganizationService()
svc.FindOrganizationsF = func(ctx context.Context, f influxdb.OrganizationFilter, opt ...influxdb.FindOptions) ([]*influxdb.Organization, int, error) {
if f.ID != nil {
calls.id = *f.ID
}
if f.Name != nil {
calls.name = *f.Name
}
return nil, 0, nil
}
return func(g *globalFlags, opt genericCLIOpts) *cobra.Command {
builder := newCmdOrgBuilder(fakeOrgSVCFn(svc), opt)
return builder.cmd()
}, calls
}
for _, tt := range tests {
fn := func(t *testing.T) {
defer addEnvVars(t, tt.envVars)()
builder := newInfluxCmdBuilder(
in(new(bytes.Buffer)),
out(ioutil.Discard),
)
cmdFn, calls := cmdFn()
cmd := builder.cmd(cmdFn)
if tt.command == "" {
tt.command = "list"
}
cmd.SetArgs(append([]string{"org", tt.command}, tt.flags...))
require.NoError(t, cmd.Execute())
assert.Equal(t, tt.expected, *calls)
}
t.Run(tt.name, fn)
}
})
t.Run("update", func(t *testing.T) {
tests := []struct {
name string
expected influxdb.OrganizationUpdate
flags []string
envVars map[string]string
}{
{
name: "basic just name",
flags: []string{
"--id=" + influxdb.ID(3).String(),
"--name=new name",
},
expected: influxdb.OrganizationUpdate{
Name: strPtr("new name"),
},
},
{
name: "with all fields",
flags: []string{
"--id=" + influxdb.ID(3).String(),
"--name=new name",
"--description=desc",
},
expected: influxdb.OrganizationUpdate{
Name: strPtr("new name"),
Description: strPtr("desc"),
},
},
{
name: "shorts",
flags: []string{
"-i=" + influxdb.ID(3).String(),
"-n=new name",
"-d=desc",
},
expected: influxdb.OrganizationUpdate{
Name: strPtr("new name"),
Description: strPtr("desc"),
},
},
{
name: "env var",
envVars: map[string]string{
"INFLUX_ORG": "new name",
"INFLUX_ORG_ID": influxdb.ID(3).String(),
"INFLUX_ORG_DESCRIPTION": "desc",
},
expected: influxdb.OrganizationUpdate{
Name: strPtr("new name"),
Description: strPtr("desc"),
},
},
}
cmdFn := func(expectedUpdate influxdb.OrganizationUpdate) func(*globalFlags, genericCLIOpts) *cobra.Command {
svc := mock.NewOrganizationService()
svc.UpdateOrganizationF = func(ctx context.Context, id influxdb.ID, upd influxdb.OrganizationUpdate) (*influxdb.Organization, error) {
if id != 3 {
return nil, fmt.Errorf("unexpecte id:\n\twant= %s\n\tgot= %s", influxdb.ID(3), id)
}
if !reflect.DeepEqual(expectedUpdate, upd) {
return nil, fmt.Errorf("unexpected bucket update;\n\twant= %+v\n\tgot= %+v", expectedUpdate, upd)
}
return &influxdb.Organization{}, nil
}
return func(g *globalFlags, opt genericCLIOpts) *cobra.Command {
builder := newCmdOrgBuilder(fakeOrgSVCFn(svc), opt)
return builder.cmd()
}
}
for _, tt := range tests {
fn := func(t *testing.T) {
defer addEnvVars(t, tt.envVars)()
builder := newInfluxCmdBuilder(
in(new(bytes.Buffer)),
out(ioutil.Discard),
)
cmd := builder.cmd(cmdFn(tt.expected))
cmd.SetArgs(append([]string{"org", "update"}, tt.flags...))
require.NoError(t, cmd.Execute())
}
t.Run(tt.name, fn)
}
})
t.Run("members", func(t *testing.T) {
type (
called struct {
name string
id influxdb.ID
memberID influxdb.ID
}
testCase struct {
name string
expected called
memberFlags []string
envVars map[string]string
}
)
testMemberFn := func(t *testing.T, cmdName string, cmdFn func() (func(*globalFlags, genericCLIOpts) *cobra.Command, *called), testCases ...testCase) {
for _, tt := range testCases {
fn := func(t *testing.T) {
envVars := tt.envVars
if len(envVars) == 0 {
envVars = envVarsZeroMap
}
defer addEnvVars(t, envVars)()
outBuf := new(bytes.Buffer)
defer func() {
if t.Failed() && outBuf.Len() > 0 {
t.Log(outBuf.String())
}
}()
builder := newInfluxCmdBuilder(
in(new(bytes.Buffer)),
out(outBuf),
)
nestedCmd, calls := cmdFn()
cmd := builder.cmd(nestedCmd)
cmd.SetArgs(append([]string{"org", "members", cmdName}, tt.memberFlags...))
require.NoError(t, cmd.Execute())
assert.Equal(t, tt.expected, *calls)
}
t.Run(tt.name, fn)
}
}
t.Run("list", func(t *testing.T) {
tests := []testCase{
{
name: "org id",
memberFlags: []string{"--id=" + influxdb.ID(3).String()},
envVars: envVarsZeroMap,
expected: called{id: 3},
},
{
name: "org id short",
memberFlags: []string{"-i=" + influxdb.ID(3).String()},
envVars: envVarsZeroMap,
expected: called{id: 3},
},
{
name: "org id env var",
envVars: map[string]string{
"INFLUX_ORG": "",
"INFLUX_ORG_ID": influxdb.ID(3).String(),
},
expected: called{id: 3},
},
{
name: "name",
memberFlags: []string{"--name=name1"},
envVars: envVarsZeroMap,
expected: called{name: "name1"},
},
{
name: "name short",
memberFlags: []string{"-n=name1"},
envVars: envVarsZeroMap,
expected: called{name: "name1"},
},
{
name: "name env var",
envVars: map[string]string{"INFLUX_ORG": "name1"},
expected: called{name: "name1"},
},
}
cmdFn := func() (func(*globalFlags, genericCLIOpts) *cobra.Command, *called) {
calls := new(called)
svc := mock.NewOrganizationService()
svc.FindOrganizationF = func(ctx context.Context, f influxdb.OrganizationFilter) (*influxdb.Organization, error) {
if f.ID != nil {
calls.id = *f.ID
}
if f.Name != nil {
calls.name = *f.Name
}
return &influxdb.Organization{ID: 1}, nil
}
return func(g *globalFlags, opt genericCLIOpts) *cobra.Command {
builder := newCmdOrgBuilder(fakeOrgSVCFn(svc), opt)
return builder.cmd()
}, calls
}
testMemberFn(t, "list", cmdFn, tests...)
testMemberFn(t, "ls", cmdFn, tests[0:1]...)
testMemberFn(t, "find", cmdFn, tests[0:1]...)
})
t.Run("add", func(t *testing.T) {
cmdFn := func() (func(*globalFlags, genericCLIOpts) *cobra.Command, *called) {
calls := new(called)
svc := mock.NewOrganizationService()
svc.FindOrganizationF = func(ctx context.Context, f influxdb.OrganizationFilter) (*influxdb.Organization, error) {
if f.ID != nil {
calls.id = *f.ID
}
if f.Name != nil {
calls.name = *f.Name
}
return &influxdb.Organization{ID: 1}, nil
}
urmSVC := mock.NewUserResourceMappingService()
urmSVC.CreateMappingFn = func(ctx context.Context, m *influxdb.UserResourceMapping) error {
calls.memberID = m.UserID
return nil
}
return func(g *globalFlags, opt genericCLIOpts) *cobra.Command {
builder := newCmdOrgBuilder(fakeOrgUrmSVCsFn(svc, urmSVC), opt)
return builder.cmd()
}, calls
}
addTests := []testCase{
{
name: "org id",
memberFlags: []string{
"--id=" + influxdb.ID(3).String(),
"--member=" + influxdb.ID(4).String(),
},
envVars: envVarsZeroMap,
expected: called{id: 3, memberID: 4},
},
{
name: "org id shorts",
memberFlags: []string{
"-i=" + influxdb.ID(3).String(),
"-m=" + influxdb.ID(4).String(),
},
envVars: envVarsZeroMap,
expected: called{id: 3, memberID: 4},
},
{
name: "org name",
memberFlags: []string{
"--name=name1",
"--member=" + influxdb.ID(4).String(),
},
envVars: envVarsZeroMap,
expected: called{name: "name1", memberID: 4},
},
{
name: "org name shorts",
memberFlags: []string{
"-n=name1",
"-m=" + influxdb.ID(4).String(),
},
envVars: envVarsZeroMap,
expected: called{name: "name1", memberID: 4},
},
}
testMemberFn(t, "add", cmdFn, addTests...)
})
t.Run("remove", func(t *testing.T) {
cmdFn := func() (func(*globalFlags, genericCLIOpts) *cobra.Command, *called) {
calls := new(called)
svc := mock.NewOrganizationService()
svc.FindOrganizationF = func(ctx context.Context, f influxdb.OrganizationFilter) (*influxdb.Organization, error) {
if f.ID != nil {
calls.id = *f.ID
}
if f.Name != nil {
calls.name = *f.Name
}
return &influxdb.Organization{ID: 1}, nil
}
urmSVC := mock.NewUserResourceMappingService()
urmSVC.DeleteMappingFn = func(ctx context.Context, resourceID, userID influxdb.ID) error {
calls.memberID = userID
return nil
}
return func(g *globalFlags, opt genericCLIOpts) *cobra.Command {
builder := newCmdOrgBuilder(fakeOrgUrmSVCsFn(svc, urmSVC), opt)
return builder.cmd()
}, calls
}
addTests := []testCase{
{
name: "org id",
memberFlags: []string{
"--id=" + influxdb.ID(3).String(),
"--member=" + influxdb.ID(4).String(),
},
envVars: envVarsZeroMap,
expected: called{id: 3, memberID: 4},
},
{
name: "org id shorts",
memberFlags: []string{
"-i=" + influxdb.ID(3).String(),
"-m=" + influxdb.ID(4).String(),
},
envVars: envVarsZeroMap,
expected: called{id: 3, memberID: 4},
},
{
name: "org name",
memberFlags: []string{
"--name=name1",
"--member=" + influxdb.ID(4).String(),
},
envVars: envVarsZeroMap,
expected: called{name: "name1", memberID: 4},
},
{
name: "org name shorts",
memberFlags: []string{
"-n=name1",
"-m=" + influxdb.ID(4).String(),
},
envVars: envVarsZeroMap,
expected: called{name: "name1", memberID: 4},
},
}
testMemberFn(t, "remove", cmdFn, addTests...)
})
})
}
var envVarsZeroMap = map[string]string{
"INFLUX_ORG_ID": "",
"INFLUX_ORG": "",
}