influxdb/cmd/influx/user_test.go

448 lines
10 KiB
Go

package main
import (
"bytes"
"context"
"fmt"
"io/ioutil"
"reflect"
"testing"
"github.com/influxdata/influxdb/v2"
"github.com/influxdata/influxdb/v2/mock"
"github.com/spf13/cobra"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
input "github.com/tcnksm/go-input"
)
func TestCmdUser(t *testing.T) {
type userResult struct {
user influxdb.User
password string
}
fakeSVCFn := func(dep cmdUserDeps) userSVCsFn {
return func() (cmdUserDeps, error) {
return dep, nil
}
}
newCMDUserDeps := func(
userSVC influxdb.UserService,
passSVC influxdb.PasswordsService,
getPassFn func(*input.UI, bool) string,
) cmdUserDeps {
return cmdUserDeps{
userSVC: userSVC,
orgSvc: &mock.OrganizationService{
FindOrganizationF: func(ctx context.Context, filter influxdb.OrganizationFilter) (*influxdb.Organization, error) {
return &influxdb.Organization{ID: influxdb.ID(9000), Name: "influxdata"}, nil
},
},
passSVC: passSVC,
urmSVC: &mock.UserResourceMappingService{
CreateMappingFn: func(context.Context, *influxdb.UserResourceMapping) error {
return nil
},
},
getPassFn: getPassFn,
}
}
t.Run("create", func(t *testing.T) {
tests := []struct {
name string
expected userResult
flags []string
envVars map[string]string
}{
{
name: "basic just name",
flags: []string{"--name=new name", "--org=org name"},
expected: userResult{
user: influxdb.User{
Name: "new name",
},
},
},
{
name: "with password",
flags: []string{
"--name=new name",
"--password=pass1",
"--org=org name",
},
expected: userResult{
user: influxdb.User{
Name: "new name",
},
password: "pass1",
},
},
{
name: "with password and env",
flags: []string{
"--name=new name",
"--password=pass1",
},
envVars: map[string]string{
"INFLUX_ORG": "",
"INFLUX_ORG_ID": influxdb.ID(1).String(),
},
expected: userResult{
user: influxdb.User{
Name: "new name",
},
password: "pass1",
},
},
{
name: "shorts",
flags: []string{
"-n=new name",
"-o=org name",
},
expected: userResult{
user: influxdb.User{
Name: "new name",
},
},
},
}
cmdFn := func(expected userResult) func(*globalFlags, genericCLIOpts) *cobra.Command {
svc := mock.NewUserService()
svc.CreateUserFn = func(ctx context.Context, User *influxdb.User) error {
if expected.user != *User {
return fmt.Errorf("unexpected User;\n\twant= %+v\n\tgot= %+v", expected, *User)
}
return nil
}
passSVC := mock.NewPasswordsService()
passSVC.SetPasswordFn = func(ctx context.Context, id influxdb.ID, password string) error {
if expected.password != password {
return fmt.Errorf("unexpected password;\n\twant= %+v\n\tgot= %+v", expected.password, password)
}
return nil
}
return func(g *globalFlags, opt genericCLIOpts) *cobra.Command {
builder := newCmdUserBuilder(fakeSVCFn(newCMDUserDeps(svc, passSVC, nil)), g, 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{"user", "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: "long 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.NewUserService()
svc.FindUserByIDFn = func(ctx context.Context, id influxdb.ID) (*influxdb.User, error) {
return &influxdb.User{ID: id}, nil
}
svc.DeleteUserFn = 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 := newCmdUserBuilder(fakeSVCFn(newCMDUserDeps(svc, nil, nil)), g, 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{"user", "delete", 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
command string
flags []string
}{
{
name: "id",
flags: []string{
"--id=" + influxdb.ID(2).String(),
},
expected: called{
id: 2,
},
},
{
name: "name",
flags: []string{"--name=name1"},
expected: called{name: "name1"},
},
{
name: "shorts",
flags: []string{
"-n=name1",
"-i=" + influxdb.ID(1).String(),
},
expected: called{name: "name1", id: 1},
},
{
name: "ls alias",
command: "ls",
flags: []string{
"--id=" + influxdb.ID(2).String(),
},
expected: called{
id: 2,
},
},
{
name: "find alias",
command: "find",
flags: []string{
"--id=" + influxdb.ID(2).String(),
},
expected: called{
id: 2,
},
},
}
cmdFn := func() (func(*globalFlags, genericCLIOpts) *cobra.Command, *called) {
calls := new(called)
svc := mock.NewUserService()
svc.FindUsersFn = func(ctx context.Context, f influxdb.UserFilter, opt ...influxdb.FindOptions) ([]*influxdb.User, 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 := newCmdUserBuilder(fakeSVCFn(newCMDUserDeps(svc, nil, nil)), g, opt)
return builder.cmd()
}, calls
}
for _, tt := range tests {
fn := func(t *testing.T) {
builder := newInfluxCmdBuilder(
in(new(bytes.Buffer)),
out(ioutil.Discard),
)
nestedCmdFn, calls := cmdFn()
cmd := builder.cmd(nestedCmdFn)
if tt.command == "" {
tt.command = "list"
}
cmd.SetArgs(append([]string{"user", 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.UserUpdate
flags []string
}{
{
name: "basic just name",
flags: []string{
"--id=" + influxdb.ID(3).String(),
"--name=new name",
},
expected: influxdb.UserUpdate{
Name: strPtr("new name"),
},
},
{
name: "with all fields",
flags: []string{
"--id=" + influxdb.ID(3).String(),
"--name=new name",
},
expected: influxdb.UserUpdate{
Name: strPtr("new name"),
},
},
{
name: "shorts",
flags: []string{
"-i=" + influxdb.ID(3).String(),
"-n=new name",
},
expected: influxdb.UserUpdate{
Name: strPtr("new name"),
},
},
}
cmdFn := func(expectedUpdate influxdb.UserUpdate) func(*globalFlags, genericCLIOpts) *cobra.Command {
svc := mock.NewUserService()
svc.UpdateUserFn = func(ctx context.Context, id influxdb.ID, upd influxdb.UserUpdate) (*influxdb.User, 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 User update;\n\twant= %+v\n\tgot= %+v", expectedUpdate, upd)
}
return &influxdb.User{}, nil
}
return func(g *globalFlags, opt genericCLIOpts) *cobra.Command {
builder := newCmdUserBuilder(fakeSVCFn(newCMDUserDeps(svc, nil, nil)), g, 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{"user", "update"}, tt.flags...))
require.NoError(t, cmd.Execute())
}
t.Run(tt.name, fn)
}
})
t.Run("password", func(t *testing.T) {
tests := []struct {
name string
expected string
flags []string
}{
{
name: "basic id",
flags: []string{
"--id=" + influxdb.ID(3).String(),
},
expected: "pass1",
},
{
name: "shorts",
flags: []string{
"-i=" + influxdb.ID(3).String(),
"-n=new name",
},
expected: "pass1",
},
}
cmdFn := func(expected string) func(*globalFlags, genericCLIOpts) *cobra.Command {
svc := mock.NewUserService()
svc.FindUserFn = func(ctx context.Context, f influxdb.UserFilter) (*influxdb.User, error) {
usr := new(influxdb.User)
if id := f.ID; id != nil {
usr.ID = *id
}
if name := f.Name; name != nil {
usr.Name = *name
}
return usr, nil
}
passSVC := mock.NewPasswordsService()
passSVC.SetPasswordFn = func(ctx context.Context, id influxdb.ID, pass string) error {
if pass != expected {
return fmt.Errorf("unexpecte id:\n\twant= %s\n\tgot= %s", pass, expected)
}
return nil
}
getPassFn := func(*input.UI, bool) string {
return expected
}
return func(g *globalFlags, opt genericCLIOpts) *cobra.Command {
builder := newCmdUserBuilder(fakeSVCFn(newCMDUserDeps(svc, passSVC, getPassFn)), g, 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{"user", "password"}, tt.flags...))
require.NoError(t, cmd.Execute())
}
t.Run(tt.name, fn)
}
})
}