Merge pull request #16537 from influxdata/cli_update_password
feat(cmd/influx): update password in clipull/16553/head
commit
540e785eb4
|
@ -44,6 +44,7 @@
|
||||||
1. [16509](https://github.com/influxdata/influxdb/pull/16509): Add support for applying an influx package via a public facing URL
|
1. [16509](https://github.com/influxdata/influxdb/pull/16509): Add support for applying an influx package via a public facing URL
|
||||||
1. [16511](https://github.com/influxdata/influxdb/pull/16511): Add jsonnet support for influx packages
|
1. [16511](https://github.com/influxdata/influxdb/pull/16511): Add jsonnet support for influx packages
|
||||||
1. [14782](https://github.com/influxdata/influxdb/pull/16336): Add view page for Check
|
1. [14782](https://github.com/influxdata/influxdb/pull/16336): Add view page for Check
|
||||||
|
1. [16537](https://github.com/influxdata/influxdb/pull/16537): Add update password for CLI
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
|
@ -68,6 +69,7 @@
|
||||||
1. [16491](https://github.com/influxdata/influxdb/pull/16491): Add missing env vals to influx cli usage and fixes precedence of flag/env var priority
|
1. [16491](https://github.com/influxdata/influxdb/pull/16491): Add missing env vals to influx cli usage and fixes precedence of flag/env var priority
|
||||||
|
|
||||||
### UI Improvements
|
### UI Improvements
|
||||||
|
|
||||||
1. [16444](https://github.com/influxdata/influxdb/pull/16444): Add honeybadger reporting to create checks
|
1. [16444](https://github.com/influxdata/influxdb/pull/16444): Add honeybadger reporting to create checks
|
||||||
|
|
||||||
## v2.0.0-alpha.21 [2019-12-13]
|
## v2.0.0-alpha.21 [2019-12-13]
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
"io/ioutil"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/influxdata/influxdb"
|
"github.com/influxdata/influxdb"
|
||||||
|
@ -102,7 +103,7 @@ func TestCmdBucket(t *testing.T) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
builder := newCmdBucketBuilder(fakeSVCFn(svc), out(new(bytes.Buffer)))
|
builder := newCmdBucketBuilder(fakeSVCFn(svc), out(ioutil.Discard))
|
||||||
cmd := builder.cmdCreate()
|
cmd := builder.cmdCreate()
|
||||||
cmd.RunE = builder.cmdCreateRunEFn
|
cmd.RunE = builder.cmdCreateRunEFn
|
||||||
return cmd
|
return cmd
|
||||||
|
@ -151,7 +152,7 @@ func TestCmdBucket(t *testing.T) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
builder := newCmdBucketBuilder(fakeSVCFn(svc), out(new(bytes.Buffer)))
|
builder := newCmdBucketBuilder(fakeSVCFn(svc), out(ioutil.Discard))
|
||||||
cmd := builder.cmdDelete()
|
cmd := builder.cmdDelete()
|
||||||
cmd.RunE = builder.cmdDeleteRunEFn
|
cmd.RunE = builder.cmdDeleteRunEFn
|
||||||
return cmd
|
return cmd
|
||||||
|
@ -258,7 +259,7 @@ func TestCmdBucket(t *testing.T) {
|
||||||
return nil, 0, nil
|
return nil, 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
builder := newCmdBucketBuilder(fakeSVCFn(svc), in(new(bytes.Buffer)), out(new(bytes.Buffer)))
|
builder := newCmdBucketBuilder(fakeSVCFn(svc), in(new(bytes.Buffer)), out(ioutil.Discard))
|
||||||
cmd := builder.cmdFind()
|
cmd := builder.cmdFind()
|
||||||
cmd.RunE = builder.cmdFindRunEFn
|
cmd.RunE = builder.cmdFindRunEFn
|
||||||
return cmd, calls
|
return cmd, calls
|
||||||
|
@ -352,7 +353,7 @@ func TestCmdBucket(t *testing.T) {
|
||||||
return &influxdb.Bucket{}, nil
|
return &influxdb.Bucket{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
builder := newCmdBucketBuilder(fakeSVCFn(svc), out(new(bytes.Buffer)))
|
builder := newCmdBucketBuilder(fakeSVCFn(svc), out(ioutil.Discard))
|
||||||
cmd := builder.cmdUpdate()
|
cmd := builder.cmdUpdate()
|
||||||
cmd.RunE = builder.cmdUpdateRunEFn
|
cmd.RunE = builder.cmdUpdateRunEFn
|
||||||
return cmd
|
return cmd
|
||||||
|
|
|
@ -128,7 +128,7 @@ func influxCmd(opts ...genericCLIOptFn) *cobra.Command {
|
||||||
cmdREPL(),
|
cmdREPL(),
|
||||||
cmdSetup(),
|
cmdSetup(),
|
||||||
cmdTask(),
|
cmdTask(),
|
||||||
cmdUser(),
|
cmdUser(runEWrapper),
|
||||||
cmdWrite(),
|
cmdWrite(),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
@ -63,7 +64,7 @@ func TestCmdOrg(t *testing.T) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
builder := newCmdOrgBuilder(fakeOrgSVCFn(svc), out(new(bytes.Buffer)))
|
builder := newCmdOrgBuilder(fakeOrgSVCFn(svc), out(ioutil.Discard))
|
||||||
cmd := builder.cmdCreate()
|
cmd := builder.cmdCreate()
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
@ -109,7 +110,7 @@ func TestCmdOrg(t *testing.T) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
builder := newCmdOrgBuilder(fakeOrgSVCFn(svc), out(new(bytes.Buffer)))
|
builder := newCmdOrgBuilder(fakeOrgSVCFn(svc), out(ioutil.Discard))
|
||||||
cmd := builder.cmdDelete()
|
cmd := builder.cmdDelete()
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
@ -181,7 +182,7 @@ func TestCmdOrg(t *testing.T) {
|
||||||
return nil, 0, nil
|
return nil, 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
builder := newCmdOrgBuilder(fakeOrgSVCFn(svc), in(new(bytes.Buffer)), out(new(bytes.Buffer)))
|
builder := newCmdOrgBuilder(fakeOrgSVCFn(svc), in(new(bytes.Buffer)), out(ioutil.Discard))
|
||||||
cmd := builder.cmdFind()
|
cmd := builder.cmdFind()
|
||||||
return cmd, calls
|
return cmd, calls
|
||||||
}
|
}
|
||||||
|
@ -268,7 +269,7 @@ func TestCmdOrg(t *testing.T) {
|
||||||
return &influxdb.Organization{}, nil
|
return &influxdb.Organization{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
builder := newCmdOrgBuilder(fakeOrgSVCFn(svc), out(new(bytes.Buffer)))
|
builder := newCmdOrgBuilder(fakeOrgSVCFn(svc), out(ioutil.Discard))
|
||||||
cmd := builder.cmdUpdate()
|
cmd := builder.cmdUpdate()
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
@ -366,7 +367,7 @@ func TestCmdOrg(t *testing.T) {
|
||||||
return &influxdb.Organization{ID: 1}, nil
|
return &influxdb.Organization{ID: 1}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
builder := newCmdOrgBuilder(fakeOrgSVCFn(svc), in(new(bytes.Buffer)), out(new(bytes.Buffer)))
|
builder := newCmdOrgBuilder(fakeOrgSVCFn(svc), in(new(bytes.Buffer)), out(ioutil.Discard))
|
||||||
cmd := builder.cmdMemberList()
|
cmd := builder.cmdMemberList()
|
||||||
return cmd, calls
|
return cmd, calls
|
||||||
}
|
}
|
||||||
|
@ -394,7 +395,7 @@ func TestCmdOrg(t *testing.T) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
builder := newCmdOrgBuilder(fakeOrgUrmSVCsFn(svc, urmSVC), in(new(bytes.Buffer)), out(new(bytes.Buffer)))
|
builder := newCmdOrgBuilder(fakeOrgUrmSVCsFn(svc, urmSVC), in(new(bytes.Buffer)), out(ioutil.Discard))
|
||||||
cmd := builder.cmdMemberAdd()
|
cmd := builder.cmdMemberAdd()
|
||||||
return cmd, calls
|
return cmd, calls
|
||||||
}
|
}
|
||||||
|
@ -457,7 +458,7 @@ func TestCmdOrg(t *testing.T) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
builder := newCmdOrgBuilder(fakeOrgUrmSVCsFn(svc, urmSVC), in(new(bytes.Buffer)), out(new(bytes.Buffer)))
|
builder := newCmdOrgBuilder(fakeOrgUrmSVCsFn(svc, urmSVC), in(new(bytes.Buffer)), out(ioutil.Discard))
|
||||||
cmd := builder.cmdMemberRemove()
|
cmd := builder.cmdMemberRemove()
|
||||||
return cmd, calls
|
return cmd, calls
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,7 +88,7 @@ func setupF(cmd *cobra.Command, args []string) error {
|
||||||
return fmt.Errorf("failed to write token to path %q: %v", dPath, err)
|
return fmt.Errorf("failed to write token to path %q: %v", dPath, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println(promptWithColor("Your token has been stored in "+dPath+".", colorCyan))
|
fmt.Println(string(promptWithColor("Your token has been stored in "+dPath+".", colorCyan)))
|
||||||
|
|
||||||
w := internal.NewTabWriter(os.Stdout)
|
w := internal.NewTabWriter(os.Stdout)
|
||||||
w.WriteHeaders(
|
w.WriteHeaders(
|
||||||
|
@ -144,7 +144,7 @@ func interactive() (req *platform.OnboardingRequest, err error) {
|
||||||
Reader: os.Stdin,
|
Reader: os.Stdin,
|
||||||
}
|
}
|
||||||
req = new(platform.OnboardingRequest)
|
req = new(platform.OnboardingRequest)
|
||||||
fmt.Println(promptWithColor(`Welcome to InfluxDB 2.0!`, colorYellow))
|
fmt.Println(string(promptWithColor(`Welcome to InfluxDB 2.0!`, colorYellow)))
|
||||||
if setupFlags.username != "" {
|
if setupFlags.username != "" {
|
||||||
req.User = setupFlags.username
|
req.User = setupFlags.username
|
||||||
} else {
|
} else {
|
||||||
|
@ -153,7 +153,7 @@ func interactive() (req *platform.OnboardingRequest, err error) {
|
||||||
if setupFlags.password != "" {
|
if setupFlags.password != "" {
|
||||||
req.Password = setupFlags.password
|
req.Password = setupFlags.password
|
||||||
} else {
|
} else {
|
||||||
req.Password = getPassword(ui)
|
req.Password = getPassword(ui, false)
|
||||||
}
|
}
|
||||||
if setupFlags.token != "" {
|
if setupFlags.token != "" {
|
||||||
req.Token = setupFlags.token
|
req.Token = setupFlags.token
|
||||||
|
@ -200,8 +200,9 @@ var (
|
||||||
keyReset = []byte{keyEscape, '[', '0', 'm'}
|
keyReset = []byte{keyEscape, '[', '0', 'm'}
|
||||||
)
|
)
|
||||||
|
|
||||||
func promptWithColor(s string, color []byte) string {
|
func promptWithColor(s string, color []byte) []byte {
|
||||||
return string(color) + s + string(keyReset)
|
bb := append(color, []byte(s)...)
|
||||||
|
return append(bb, keyReset...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getConfirm(ui *input.UI, or *platform.OnboardingRequest) bool {
|
func getConfirm(ui *input.UI, or *platform.OnboardingRequest) bool {
|
||||||
|
@ -211,14 +212,14 @@ func getConfirm(ui *input.UI, or *platform.OnboardingRequest) bool {
|
||||||
if or.RetentionPeriod > 0 {
|
if or.RetentionPeriod > 0 {
|
||||||
rp = fmt.Sprintf("%d hrs", or.RetentionPeriod)
|
rp = fmt.Sprintf("%d hrs", or.RetentionPeriod)
|
||||||
}
|
}
|
||||||
fmt.Print(promptWithColor(fmt.Sprintf(`
|
ui.Writer.Write(promptWithColor(fmt.Sprintf(`
|
||||||
You have entered:
|
You have entered:
|
||||||
Username: %s
|
Username: %s
|
||||||
Organization: %s
|
Organization: %s
|
||||||
Bucket: %s
|
Bucket: %s
|
||||||
Retention Period: %s
|
Retention Period: %s
|
||||||
`, or.User, or.Org, or.Bucket, rp), colorCyan))
|
`, or.User, or.Org, or.Bucket, rp), colorCyan))
|
||||||
result, err := ui.Ask(prompt, &input.Options{
|
result, err := ui.Ask(string(prompt), &input.Options{
|
||||||
HideOrder: true,
|
HideOrder: true,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -240,15 +241,20 @@ var (
|
||||||
errPasswordIsTooShort = fmt.Errorf("passwords is too short")
|
errPasswordIsTooShort = fmt.Errorf("passwords is too short")
|
||||||
)
|
)
|
||||||
|
|
||||||
func getPassword(ui *input.UI) (password string) {
|
func getPassword(ui *input.UI, showNew bool) (password string) {
|
||||||
|
newStr := ""
|
||||||
|
if showNew {
|
||||||
|
newStr = " new"
|
||||||
|
}
|
||||||
var err error
|
var err error
|
||||||
enterPasswd:
|
enterPasswd:
|
||||||
query := promptWithColor("Please type your password", colorCyan)
|
query := string(promptWithColor("Please type your"+newStr+" password", colorCyan))
|
||||||
for {
|
for {
|
||||||
password, err = ui.Ask(query, &input.Options{
|
password, err = ui.Ask(query, &input.Options{
|
||||||
Required: true,
|
Required: true,
|
||||||
HideOrder: true,
|
HideOrder: true,
|
||||||
Hide: true,
|
Hide: true,
|
||||||
|
Mask: false,
|
||||||
ValidateFunc: func(s string) error {
|
ValidateFunc: func(s string) error {
|
||||||
if len(s) < 8 {
|
if len(s) < 8 {
|
||||||
return errPasswordIsTooShort
|
return errPasswordIsTooShort
|
||||||
|
@ -260,7 +266,7 @@ enterPasswd:
|
||||||
case input.ErrInterrupted:
|
case input.ErrInterrupted:
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
case errPasswordIsTooShort:
|
case errPasswordIsTooShort:
|
||||||
fmt.Println(promptWithColor("Password too short - minimum length is 8 characters!", colorRed))
|
ui.Writer.Write(promptWithColor("Password too short - minimum length is 8 characters!", colorRed))
|
||||||
goto enterPasswd
|
goto enterPasswd
|
||||||
default:
|
default:
|
||||||
if password = strings.TrimSpace(password); password == "" {
|
if password = strings.TrimSpace(password); password == "" {
|
||||||
|
@ -269,7 +275,7 @@ enterPasswd:
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
query = promptWithColor("Please type your password again", colorCyan)
|
query = string(promptWithColor("Please type your"+newStr+" password again", colorCyan))
|
||||||
for {
|
for {
|
||||||
_, err = ui.Ask(query, &input.Options{
|
_, err = ui.Ask(query, &input.Options{
|
||||||
Required: true,
|
Required: true,
|
||||||
|
@ -288,7 +294,7 @@ enterPasswd:
|
||||||
case nil:
|
case nil:
|
||||||
// Nothing.
|
// Nothing.
|
||||||
default:
|
default:
|
||||||
fmt.Println(promptWithColor("Passwords do not match!", colorRed))
|
ui.Writer.Write(promptWithColor("Passwords do not match!\n", colorRed))
|
||||||
goto enterPasswd
|
goto enterPasswd
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
|
@ -305,7 +311,7 @@ func getInput(ui *input.UI, prompt, defaultValue string) string {
|
||||||
option.Default = defaultValue
|
option.Default = defaultValue
|
||||||
option.HideDefault = true
|
option.HideDefault = true
|
||||||
}
|
}
|
||||||
prompt = promptWithColor(prompt, colorCyan)
|
prompt = string(promptWithColor(prompt, colorCyan))
|
||||||
for {
|
for {
|
||||||
line, err := ui.Ask(prompt, option)
|
line, err := ui.Ask(prompt, option)
|
||||||
switch err {
|
switch err {
|
||||||
|
|
|
@ -3,50 +3,96 @@ package main
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
platform "github.com/influxdata/influxdb"
|
"github.com/influxdata/influxdb"
|
||||||
"github.com/influxdata/influxdb/cmd/influx/internal"
|
"github.com/influxdata/influxdb/cmd/influx/internal"
|
||||||
"github.com/influxdata/influxdb/http"
|
"github.com/influxdata/influxdb/http"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
input "github.com/tcnksm/go-input"
|
||||||
)
|
)
|
||||||
|
|
||||||
func cmdUser() *cobra.Command {
|
type userSVCsFn func() (
|
||||||
cmd := &cobra.Command{
|
cmdUserDeps,
|
||||||
Use: "user",
|
error,
|
||||||
Short: "User management commands",
|
)
|
||||||
Run: seeHelp,
|
|
||||||
|
type cmdUserDeps struct {
|
||||||
|
userSVC influxdb.UserService
|
||||||
|
orgSvc influxdb.OrganizationService
|
||||||
|
passSVC influxdb.PasswordsService
|
||||||
|
urmSVC influxdb.UserResourceMappingService
|
||||||
|
getPassFn func(*input.UI, bool) string
|
||||||
|
}
|
||||||
|
|
||||||
|
func cmdUser(opts ...genericCLIOptFn) *cobra.Command {
|
||||||
|
return newCmdUserBuilder(newUserSVC, opts...).cmd()
|
||||||
|
}
|
||||||
|
|
||||||
|
type cmdUserBuilder struct {
|
||||||
|
genericCLIOpts
|
||||||
|
|
||||||
|
svcFn userSVCsFn
|
||||||
|
|
||||||
|
id string
|
||||||
|
name string
|
||||||
|
password string
|
||||||
|
org organization
|
||||||
|
}
|
||||||
|
|
||||||
|
func newCmdUserBuilder(svcsFn userSVCsFn, opts ...genericCLIOptFn) *cmdUserBuilder {
|
||||||
|
opt := genericCLIOpts{
|
||||||
|
in: os.Stdin,
|
||||||
|
w: os.Stdout,
|
||||||
}
|
}
|
||||||
|
for _, o := range opts {
|
||||||
|
o(&opt)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &cmdUserBuilder{
|
||||||
|
genericCLIOpts: opt,
|
||||||
|
svcFn: svcsFn,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *cmdUserBuilder) cmd() *cobra.Command {
|
||||||
|
cmd := b.newCmd("user", nil)
|
||||||
|
cmd.Short = "User management commands"
|
||||||
|
cmd.Run = seeHelp
|
||||||
cmd.AddCommand(
|
cmd.AddCommand(
|
||||||
userCreateCmd(),
|
b.cmdCreate(),
|
||||||
userDeleteCmd(),
|
b.cmdDelete(),
|
||||||
userFindCmd(),
|
b.cmdFind(),
|
||||||
userUpdateCmd(),
|
b.cmdUpdate(),
|
||||||
|
b.cmdPassword(),
|
||||||
)
|
)
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
var userUpdateFlags struct {
|
func (b *cmdUserBuilder) cmdPassword() *cobra.Command {
|
||||||
id string
|
cmd := b.newCmd("password", b.cmdPasswordRunEFn)
|
||||||
name string
|
cmd.Short = "Update user password"
|
||||||
|
|
||||||
|
cmd.Flags().StringVarP(&b.id, "id", "i", "", "The user ID")
|
||||||
|
cmd.Flags().StringVarP(&b.name, "name", "n", "", "The user name")
|
||||||
|
|
||||||
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func userUpdateCmd() *cobra.Command {
|
func (b *cmdUserBuilder) cmdUpdate() *cobra.Command {
|
||||||
cmd := &cobra.Command{
|
cmd := b.newCmd("update", b.cmdUpdateRunEFn)
|
||||||
Use: "update",
|
cmd.Short = "Update user"
|
||||||
Short: "Update user",
|
|
||||||
RunE: wrapCheckSetup(userUpdateF),
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd.Flags().StringVarP(&userUpdateFlags.id, "id", "i", "", "The user ID (required)")
|
cmd.Flags().StringVarP(&b.id, "id", "i", "", "The user ID (required)")
|
||||||
cmd.Flags().StringVarP(&userUpdateFlags.name, "name", "n", "", "The user name")
|
cmd.Flags().StringVarP(&b.name, "name", "n", "", "The user name")
|
||||||
cmd.MarkFlagRequired("id")
|
cmd.MarkFlagRequired("id")
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func newUserService() (platform.UserService, error) {
|
func newUserService() (influxdb.UserService, error) {
|
||||||
if flags.local {
|
if flags.local {
|
||||||
return newLocalKVService()
|
return newLocalKVService()
|
||||||
}
|
}
|
||||||
|
@ -60,28 +106,85 @@ func newUserService() (platform.UserService, error) {
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func userUpdateF(cmd *cobra.Command, args []string) error {
|
func newUserSVC() (
|
||||||
s, err := newUserService()
|
cmdUserDeps,
|
||||||
|
error) {
|
||||||
|
httpClient, err := newHTTPClient()
|
||||||
|
if err != nil {
|
||||||
|
return cmdUserDeps{}, err
|
||||||
|
}
|
||||||
|
userSvc := &http.UserService{Client: httpClient}
|
||||||
|
orgSvc := &http.OrganizationService{Client: httpClient}
|
||||||
|
passSvc := &http.PasswordService{Client: httpClient}
|
||||||
|
urmSvc := &http.UserResourceMappingService{Client: httpClient}
|
||||||
|
getPassFn := getPassword
|
||||||
|
|
||||||
|
return cmdUserDeps{
|
||||||
|
userSVC: userSvc,
|
||||||
|
orgSvc: orgSvc,
|
||||||
|
passSVC: passSvc,
|
||||||
|
urmSVC: urmSvc,
|
||||||
|
getPassFn: getPassFn,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *cmdUserBuilder) cmdPasswordRunEFn(cmd *cobra.Command, args []string) error {
|
||||||
|
ctx := context.Background()
|
||||||
|
dep, err := b.svcFn()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var id platform.ID
|
filter := influxdb.UserFilter{}
|
||||||
if err := id.DecodeFromString(userUpdateFlags.id); err != nil {
|
if b.name != "" {
|
||||||
|
filter.Name = &b.name
|
||||||
|
}
|
||||||
|
if b.id != "" {
|
||||||
|
id, err := influxdb.IDFromString(b.id)
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
filter.ID = id
|
||||||
update := platform.UserUpdate{}
|
|
||||||
if userUpdateFlags.name != "" {
|
|
||||||
update.Name = &userUpdateFlags.name
|
|
||||||
}
|
}
|
||||||
|
u, err := dep.userSVC.FindUser(ctx, filter)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
ui := &input.UI{
|
||||||
|
Writer: b.genericCLIOpts.w,
|
||||||
|
Reader: b.genericCLIOpts.in,
|
||||||
|
}
|
||||||
|
password := dep.getPassFn(ui, true)
|
||||||
|
|
||||||
user, err := s.UpdateUser(context.Background(), id, update)
|
if err = dep.passSVC.SetPassword(ctx, u.ID, password); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Fprintln(b.w, "Your password has been successfully updated.")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *cmdUserBuilder) cmdUpdateRunEFn(cmd *cobra.Command, args []string) error {
|
||||||
|
dep, err := b.svcFn()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
w := internal.NewTabWriter(os.Stdout)
|
var id influxdb.ID
|
||||||
|
if err := id.DecodeFromString(b.id); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
update := influxdb.UserUpdate{}
|
||||||
|
if b.name != "" {
|
||||||
|
update.Name = &b.name
|
||||||
|
}
|
||||||
|
|
||||||
|
user, err := dep.userSVC.UpdateUser(context.Background(), id, update)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
w := internal.NewTabWriter(b.w)
|
||||||
w.WriteHeaders(
|
w.WriteHeaders(
|
||||||
"ID",
|
"ID",
|
||||||
"Name",
|
"Name",
|
||||||
|
@ -95,42 +198,43 @@ func userUpdateF(cmd *cobra.Command, args []string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var userCreateFlags struct {
|
func (b *cmdUserBuilder) cmdCreate() *cobra.Command {
|
||||||
name string
|
cmd := b.newCmd("create", b.cmdCreateRunEFn)
|
||||||
password string
|
cmd.Short = "Create user"
|
||||||
org organization
|
|
||||||
}
|
|
||||||
|
|
||||||
func userCreateCmd() *cobra.Command {
|
opts := flagOpts{
|
||||||
cmd := &cobra.Command{
|
{
|
||||||
Use: "create",
|
DestP: &b.name,
|
||||||
Short: "Create user",
|
Flag: "name",
|
||||||
RunE: wrapCheckSetup(userCreateF),
|
Short: 'n',
|
||||||
|
Desc: "The user name (required)",
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
opts.mustRegister(cmd)
|
||||||
|
|
||||||
userCreateFlags.org.register(cmd, false)
|
cmd.Flags().StringVarP(&b.password, "password", "p", "", "The user password")
|
||||||
cmd.Flags().StringVarP(&userCreateFlags.name, "name", "n", "", "The user name (required)")
|
b.org.register(cmd, false)
|
||||||
cmd.MarkFlagRequired("name")
|
|
||||||
cmd.Flags().StringVarP(&userCreateFlags.password, "password", "p", "", "The user password")
|
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func userCreateF(cmd *cobra.Command, args []string) error {
|
func (b *cmdUserBuilder) cmdCreateRunEFn(*cobra.Command, []string) error {
|
||||||
if err := userCreateFlags.org.validOrgFlags(); err != nil {
|
ctx := context.Background()
|
||||||
|
if err := b.org.validOrgFlags(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
s, err := newUserService()
|
dep, err := b.svcFn()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
user := &platform.User{
|
user := &influxdb.User{
|
||||||
Name: userCreateFlags.name,
|
Name: b.name,
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := s.CreateUser(context.Background(), user); err != nil {
|
if err := dep.userSVC.CreateUser(ctx, user); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,7 +247,7 @@ func userCreateF(cmd *cobra.Command, args []string) error {
|
||||||
for i, h := range headers {
|
for i, h := range headers {
|
||||||
m[h] = vals[i]
|
m[h] = vals[i]
|
||||||
}
|
}
|
||||||
w := internal.NewTabWriter(os.Stdout)
|
w := internal.NewTabWriter(b.w)
|
||||||
w.WriteHeaders(headers...)
|
w.WriteHeaders(headers...)
|
||||||
w.Write(m)
|
w.Write(m)
|
||||||
w.Flush()
|
w.Flush()
|
||||||
|
@ -151,17 +255,12 @@ func userCreateF(cmd *cobra.Command, args []string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
orgSVC, err := newOrganizationService()
|
orgID, err := b.org.getID(dep.orgSvc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
orgID, err := userCreateFlags.org.getID(orgSVC)
|
pass := b.password
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
pass := userCreateFlags.password
|
|
||||||
if orgID == 0 && pass == "" {
|
if orgID == 0 && pass == "" {
|
||||||
return writeOutput([]string{"ID", "Name"}, user.ID.String(), user.Name)
|
return writeOutput([]string{"ID", "Name"}, user.ID.String(), user.Name)
|
||||||
}
|
}
|
||||||
|
@ -170,77 +269,57 @@ func userCreateF(cmd *cobra.Command, args []string) error {
|
||||||
return errors.New("an org id is required when providing a user password")
|
return errors.New("an org id is required when providing a user password")
|
||||||
}
|
}
|
||||||
|
|
||||||
c, err := newHTTPClient()
|
err = dep.urmSVC.CreateUserResourceMapping(context.Background(), &influxdb.UserResourceMapping{
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
userResMapSVC := &http.UserResourceMappingService{
|
|
||||||
Client: c,
|
|
||||||
}
|
|
||||||
|
|
||||||
err = userResMapSVC.CreateUserResourceMapping(context.Background(), &platform.UserResourceMapping{
|
|
||||||
UserID: user.ID,
|
UserID: user.ID,
|
||||||
UserType: platform.Member,
|
UserType: influxdb.Member,
|
||||||
ResourceType: platform.OrgsResourceType,
|
ResourceType: influxdb.OrgsResourceType,
|
||||||
ResourceID: orgID,
|
ResourceID: orgID,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
passSVC := &http.PasswordService{Client: c}
|
if err := dep.passSVC.SetPassword(ctx, user.ID, pass); err != nil {
|
||||||
|
|
||||||
ctx := context.Background()
|
|
||||||
if err := passSVC.SetPassword(ctx, user.ID, pass); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return writeOutput([]string{"ID", "Name", "Organization ID"}, user.ID.String(), user.Name, orgID.String())
|
return writeOutput([]string{"ID", "Name", "Organization ID"}, user.ID.String(), user.Name, orgID.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
var userFindFlags struct {
|
func (b *cmdUserBuilder) cmdFind() *cobra.Command {
|
||||||
id string
|
cmd := b.newCmd("find", b.cmdFindRunEFn)
|
||||||
name string
|
cmd.Short = "Find user"
|
||||||
}
|
|
||||||
|
|
||||||
func userFindCmd() *cobra.Command {
|
cmd.Flags().StringVarP(&b.id, "id", "i", "", "The user ID")
|
||||||
cmd := &cobra.Command{
|
cmd.Flags().StringVarP(&b.name, "name", "n", "", "The user name")
|
||||||
Use: "find",
|
|
||||||
Short: "Find user",
|
|
||||||
RunE: wrapCheckSetup(userFindF),
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd.Flags().StringVarP(&userFindFlags.id, "id", "i", "", "The user ID")
|
|
||||||
cmd.Flags().StringVarP(&userFindFlags.name, "name", "n", "", "The user name")
|
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func userFindF(cmd *cobra.Command, args []string) error {
|
func (b *cmdUserBuilder) cmdFindRunEFn(*cobra.Command, []string) error {
|
||||||
s, err := newUserService()
|
dep, err := b.svcFn()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
filter := platform.UserFilter{}
|
filter := influxdb.UserFilter{}
|
||||||
if userFindFlags.name != "" {
|
if b.name != "" {
|
||||||
filter.Name = &userFindFlags.name
|
filter.Name = &b.name
|
||||||
}
|
}
|
||||||
if userFindFlags.id != "" {
|
if b.id != "" {
|
||||||
id, err := platform.IDFromString(userFindFlags.id)
|
id, err := influxdb.IDFromString(b.id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
filter.ID = id
|
filter.ID = id
|
||||||
}
|
}
|
||||||
|
|
||||||
users, _, err := s.FindUsers(context.Background(), filter)
|
users, _, err := dep.userSVC.FindUsers(context.Background(), filter)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
w := internal.NewTabWriter(os.Stdout)
|
w := internal.NewTabWriter(b.w)
|
||||||
w.WriteHeaders(
|
w.WriteHeaders(
|
||||||
"ID",
|
"ID",
|
||||||
"Name",
|
"Name",
|
||||||
|
@ -256,45 +335,38 @@ func userFindF(cmd *cobra.Command, args []string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var userDeleteFlags struct {
|
func (b *cmdUserBuilder) cmdDelete() *cobra.Command {
|
||||||
id string
|
cmd := b.newCmd("delete", b.cmdDeleteRunEFn)
|
||||||
}
|
cmd.Short = "Delete user"
|
||||||
|
|
||||||
func userDeleteCmd() *cobra.Command {
|
cmd.Flags().StringVarP(&b.id, "id", "i", "", "The user ID (required)")
|
||||||
cmd := &cobra.Command{
|
|
||||||
Use: "delete",
|
|
||||||
Short: "Delete user",
|
|
||||||
RunE: wrapCheckSetup(userDeleteF),
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd.Flags().StringVarP(&userDeleteFlags.id, "id", "i", "", "The user ID (required)")
|
|
||||||
cmd.MarkFlagRequired("id")
|
cmd.MarkFlagRequired("id")
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func userDeleteF(cmd *cobra.Command, args []string) error {
|
func (b *cmdUserBuilder) cmdDeleteRunEFn(cmd *cobra.Command, args []string) error {
|
||||||
s, err := newUserService()
|
dep, err := b.svcFn()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var id platform.ID
|
var id influxdb.ID
|
||||||
if err := id.DecodeFromString(userDeleteFlags.id); err != nil {
|
if err := id.DecodeFromString(b.id); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
u, err := s.FindUserByID(ctx, id)
|
u, err := dep.userSVC.FindUserByID(ctx, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := s.DeleteUser(ctx, id); err != nil {
|
if err := dep.userSVC.DeleteUser(ctx, id); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
w := internal.NewTabWriter(os.Stdout)
|
w := internal.NewTabWriter(b.w)
|
||||||
w.WriteHeaders(
|
w.WriteHeaders(
|
||||||
"ID",
|
"ID",
|
||||||
"Name",
|
"Name",
|
||||||
|
|
|
@ -0,0 +1,399 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/influxdata/influxdb"
|
||||||
|
platform "github.com/influxdata/influxdb"
|
||||||
|
"github.com/influxdata/influxdb/mock"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
input "github.com/tcnksm/go-input"
|
||||||
|
)
|
||||||
|
|
||||||
|
func newCMDUserDeps(
|
||||||
|
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, *platform.UserResourceMapping) error {
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
},
|
||||||
|
getPassFn: getPassFn,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCmdUser(t *testing.T) {
|
||||||
|
setViperOptions()
|
||||||
|
|
||||||
|
type userResult struct {
|
||||||
|
user influxdb.User
|
||||||
|
password string
|
||||||
|
}
|
||||||
|
|
||||||
|
fakeSVCFn := func(dep cmdUserDeps) userSVCsFn {
|
||||||
|
return func() (
|
||||||
|
cmdUserDeps,
|
||||||
|
error) {
|
||||||
|
return dep, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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_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) *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
|
||||||
|
}
|
||||||
|
|
||||||
|
builder := newCmdUserBuilder(fakeSVCFn(newCMDUserDeps(svc, passSVC, nil)), out(ioutil.Discard))
|
||||||
|
cmd := builder.cmdCreate()
|
||||||
|
cmd.RunE = builder.cmdCreateRunEFn
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
fn := func(t *testing.T) {
|
||||||
|
defer addEnvVars(t, tt.envVars)()
|
||||||
|
cmd := cmdFn(tt.expected)
|
||||||
|
cmd.LocalFlags().Parse(tt.flags)
|
||||||
|
err := cmd.Execute()
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
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) *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
|
||||||
|
}
|
||||||
|
|
||||||
|
builder := newCmdUserBuilder(fakeSVCFn(newCMDUserDeps(svc, nil, nil)), out(ioutil.Discard))
|
||||||
|
cmd := builder.cmdDelete()
|
||||||
|
cmd.RunE = builder.cmdDeleteRunEFn
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
fn := func(t *testing.T) {
|
||||||
|
cmd := cmdFn(tt.expectedID)
|
||||||
|
idFlag := tt.flag + tt.expectedID.String()
|
||||||
|
cmd.LocalFlags().Parse([]string{idFlag})
|
||||||
|
require.NoError(t, cmd.Execute())
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Run(tt.name, fn)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("find", func(t *testing.T) {
|
||||||
|
type called struct {
|
||||||
|
name string
|
||||||
|
id influxdb.ID
|
||||||
|
}
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
expected called
|
||||||
|
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},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
cmdFn := func() (*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
|
||||||
|
}
|
||||||
|
|
||||||
|
builder := newCmdUserBuilder(fakeSVCFn(newCMDUserDeps(svc, nil, nil)), in(new(bytes.Buffer)), out(ioutil.Discard))
|
||||||
|
cmd := builder.cmdFind()
|
||||||
|
cmd.RunE = builder.cmdFindRunEFn
|
||||||
|
return cmd, calls
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
fn := func(t *testing.T) {
|
||||||
|
cmd, calls := cmdFn()
|
||||||
|
cmd.LocalFlags().Parse(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) *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
|
||||||
|
}
|
||||||
|
|
||||||
|
builder := newCmdUserBuilder(fakeSVCFn(newCMDUserDeps(svc, nil, nil)), out(ioutil.Discard))
|
||||||
|
cmd := builder.cmdUpdate()
|
||||||
|
cmd.RunE = builder.cmdUpdateRunEFn
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
fn := func(t *testing.T) {
|
||||||
|
cmd := cmdFn(tt.expected)
|
||||||
|
cmd.LocalFlags().Parse(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) *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
|
||||||
|
}
|
||||||
|
builder := newCmdUserBuilder(fakeSVCFn(newCMDUserDeps(svc, passSVC, getPassFn)),
|
||||||
|
out(ioutil.Discard))
|
||||||
|
cmd := builder.cmdPassword()
|
||||||
|
cmd.RunE = builder.cmdPasswordRunEFn
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
fn := func(t *testing.T) {
|
||||||
|
cmd := cmdFn(tt.expected)
|
||||||
|
cmd.LocalFlags().Parse(tt.flags)
|
||||||
|
require.NoError(t, cmd.Execute())
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Run(tt.name, fn)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
Loading…
Reference in New Issue