Repository: nats-io/nsc
Pull request #43 (2018-12-08 22:50:17)

[FIX-40] fixed selection of user on interactive mode
wrapped MaxNArgs from cobra to enable tests to be debugged


Patch:
diff --git a/cmd/addaccount.go b/cmd/addaccount.go
index 8bed303..6a91d23 100644
--- a/cmd/addaccount.go
+++ b/cmd/addaccount.go
@@ -29,7 +29,7 @@ func CreateAddAccountCmd() *cobra.Command {
 	cmd := &cobra.Command{
 		Use:          "account",
 		Short:        "Add an account",
-		Args:         cobra.MaximumNArgs(0),
+		Args:         MaxArgs(0),
 		SilenceUsage: true,
 
 		RunE: func(cmd *cobra.Command, args []string) error {
diff --git a/cmd/addcluster.go b/cmd/addcluster.go
index 557e3ea..274530b 100644
--- a/cmd/addcluster.go
+++ b/cmd/addcluster.go
@@ -29,7 +29,7 @@ func createAddClusterCmd() *cobra.Command {
 	cmd := &cobra.Command{
 		Use:          "cluster",
 		Short:        "Add a cluster (operator only)",
-		Args:         cobra.MaximumNArgs(0),
+		Args:         MaxArgs(0),
 		Example:      `nsc add cluster --name mycluster --trusted-accounts actkey1,actkey2 --trusted-operators opkey1,opkey2`,
 		SilenceUsage: true,
 		RunE: func(cmd *cobra.Command, args []string) error {
diff --git a/cmd/addexport.go b/cmd/addexport.go
index 5c23502..73cfcb7 100644
--- a/cmd/addexport.go
+++ b/cmd/addexport.go
@@ -30,7 +30,7 @@ func createAddExportCmd() *cobra.Command {
 	cmd := &cobra.Command{
 		Use:   "export",
 		Short: "Add an export",
-		Args:  cobra.MaximumNArgs(0),
+		Args:  MaxArgs(0),
 		Example: `nsc add export -i
 nsc add export --subject "a.b.c.>"
 nsc add export --service --subject a.b
diff --git a/cmd/addimport.go b/cmd/addimport.go
index 1b4fe31..d532b6a 100644
--- a/cmd/addimport.go
+++ b/cmd/addimport.go
@@ -33,7 +33,7 @@ func createAddImportCmd() *cobra.Command {
 	cmd := &cobra.Command{
 		Use:          "import",
 		Short:        "Add an import",
-		Args:         cobra.MaximumNArgs(0),
+		Args:         MaxArgs(0),
 		Example:      params.longHelp(),
 		SilenceUsage: true,
 		RunE: func(cmd *cobra.Command, args []string) error {
diff --git a/cmd/addserver.go b/cmd/addserver.go
index 449bd5c..cbd2d11 100644
--- a/cmd/addserver.go
+++ b/cmd/addserver.go
@@ -30,7 +30,7 @@ func createAddServerCmd() *cobra.Command {
 	cmd := &cobra.Command{
 		Use:          "server",
 		Short:        "Add a server to a cluster (operator only)",
-		Args:         cobra.MaximumNArgs(0),
+		Args:         MaxArgs(0),
 		SilenceUsage: true,
 		Example:      `nsc add server -i`,
 		RunE: func(cmd *cobra.Command, args []string) error {
diff --git a/cmd/adduser.go b/cmd/adduser.go
index 0edc4bc..31f08c1 100644
--- a/cmd/adduser.go
+++ b/cmd/adduser.go
@@ -30,7 +30,7 @@ func CreateAddUserCmd() *cobra.Command {
 	cmd := &cobra.Command{
 		Use:          "user",
 		Short:        "Add an user to the account",
-		Args:         cobra.MaximumNArgs(0),
+		Args:         MaxArgs(0),
 		SilenceUsage: true,
 		Example: `nsc add user -i
 nsc add user --name u --deny-pubsub "bar.>"
diff --git a/cmd/common.go b/cmd/common.go
index 40b3f0d..5d6603f 100644
--- a/cmd/common.go
+++ b/cmd/common.go
@@ -29,6 +29,8 @@ import (
 	"strings"
 	"time"
 
+	"github.com/spf13/cobra"
+
 	"github.com/dustin/go-humanize"
 	"github.com/mitchellh/go-homedir"
 	"github.com/nats-io/nkeys"
@@ -354,3 +356,11 @@ func AbbrevHomePaths(fp string) string {
 	}
 	return fp
 }
+
+func MaxArgs(max int) cobra.PositionalArgs {
+	// if we are running in a test, remove the limit
+	if strings.Contains(strings.Join(os.Args, " "), "-test.v") {
+		return nil
+	}
+	return cobra.MaximumNArgs(max)
+}
diff --git a/cmd/deleteexport.go b/cmd/deleteexport.go
index 94221d2..696697b 100644
--- a/cmd/deleteexport.go
+++ b/cmd/deleteexport.go
@@ -29,7 +29,7 @@ func createDeleteExportCmd() *cobra.Command {
 	cmd := &cobra.Command{
 		Use:          "export",
 		Short:        "Delete an export",
-		Args:         cobra.MaximumNArgs(0),
+		Args:         MaxArgs(0),
 		SilenceUsage: true,
 		RunE: func(cmd *cobra.Command, args []string) error {
 			if err := RunAction(cmd, args, &params); err != nil {
diff --git a/cmd/deleteimport.go b/cmd/deleteimport.go
index b84e8a4..c44612d 100644
--- a/cmd/deleteimport.go
+++ b/cmd/deleteimport.go
@@ -29,7 +29,7 @@ func createDeleteImportCmd() *cobra.Command {
 	cmd := &cobra.Command{
 		Use:   "import",
 		Short: "Delete an import",
-		Args:  cobra.MaximumNArgs(0),
+		Args:  MaxArgs(0),
 		Example: `nsc delete import -i
 nsc delete import -s "bar.>"`,
 		SilenceUsage: true,
diff --git a/cmd/describeaccount.go b/cmd/describeaccount.go
index 0cdc4a7..7f4c797 100644
--- a/cmd/describeaccount.go
+++ b/cmd/describeaccount.go
@@ -28,7 +28,7 @@ func createDescribeAccountCmd() *cobra.Command {
 	cmd := &cobra.Command{
 		Use:          "account",
 		Short:        "Describes an account",
-		Args:         cobra.MaximumNArgs(0),
+		Args:         MaxArgs(0),
 		SilenceUsage: true,
 		RunE: func(cmd *cobra.Command, args []string) error {
 			if err := RunAction(cmd, args, &params); err != nil {
diff --git a/cmd/describecluster.go b/cmd/describecluster.go
index 6f427e5..e13fb84 100644
--- a/cmd/describecluster.go
+++ b/cmd/describecluster.go
@@ -28,7 +28,7 @@ func createDescribeClusterCmd() *cobra.Command {
 	cmd := &cobra.Command{
 		Use:          "cluster",
 		Short:        "Describes a cluster",
-		Args:         cobra.MaximumNArgs(0),
+		Args:         MaxArgs(0),
 		SilenceUsage: true,
 		RunE: func(cmd *cobra.Command, args []string) error {
 			if err := RunAction(cmd, args, &params); err != nil {
diff --git a/cmd/describejwt.go b/cmd/describejwt.go
index 77cc3e5..643785a 100644
--- a/cmd/describejwt.go
+++ b/cmd/describejwt.go
@@ -30,7 +30,7 @@ func createDescribeJwtCmd() *cobra.Command {
 	var cmd = &cobra.Command{
 		Use:          "jwt",
 		Short:        "Describe a jwt file",
-		Args:         cobra.MaximumNArgs(0),
+		Args:         MaxArgs(0),
 		Example:      `nsc describe -f pathorurl`,
 		SilenceUsage: true,
 		RunE: func(cmd *cobra.Command, args []string) error {
diff --git a/cmd/describeoperator.go b/cmd/describeoperator.go
index eab1f1e..51db536 100644
--- a/cmd/describeoperator.go
+++ b/cmd/describeoperator.go
@@ -29,7 +29,7 @@ func createDescribeOperatorCmd() *cobra.Command {
 	cmd := &cobra.Command{
 		Use:          "operator",
 		Short:        "Describes the operator",
-		Args:         cobra.MaximumNArgs(0),
+		Args:         MaxArgs(0),
 		SilenceUsage: true,
 		RunE: func(cmd *cobra.Command, args []string) error {
 			if err := RunMaybeStorelessAction(cmd, args, &params); err != nil {
diff --git a/cmd/describeserver.go b/cmd/describeserver.go
index aeefb74..c0ad66e 100644
--- a/cmd/describeserver.go
+++ b/cmd/describeserver.go
@@ -28,7 +28,7 @@ func createDescribeServerCmd() *cobra.Command {
 	cmd := &cobra.Command{
 		Use:          "server",
 		Short:        "Describes a server",
-		Args:         cobra.MaximumNArgs(0),
+		Args:         MaxArgs(0),
 		SilenceUsage: true,
 		RunE: func(cmd *cobra.Command, args []string) error {
 			if err := RunAction(cmd, args, &params); err != nil {
diff --git a/cmd/describeuser.go b/cmd/describeuser.go
index 8e6952b..df99647 100644
--- a/cmd/describeuser.go
+++ b/cmd/describeuser.go
@@ -28,7 +28,7 @@ func createDescribeUserCmd() *cobra.Command {
 	cmd := &cobra.Command{
 		Use:          "user",
 		Short:        "Describes an user",
-		Args:         cobra.MaximumNArgs(0),
+		Args:         MaxArgs(0),
 		SilenceUsage: true,
 		RunE: func(cmd *cobra.Command, args []string) error {
 			if err := RunAction(cmd, args, &params); err != nil {
diff --git a/cmd/editaccount.go b/cmd/editaccount.go
index 4879ed7..a52b662 100644
--- a/cmd/editaccount.go
+++ b/cmd/editaccount.go
@@ -29,7 +29,7 @@ func createEditAccount() *cobra.Command {
 	cmd := &cobra.Command{
 		Use:          "account",
 		Short:        "Edit an account",
-		Args:         cobra.MaximumNArgs(0),
+		Args:         MaxArgs(0),
 		SilenceUsage: true,
 		RunE: func(cmd *cobra.Command, args []string) error {
 			if err := RunAction(cmd, args, &params); err != nil {
diff --git a/cmd/editcluster.go b/cmd/editcluster.go
index 40c02aa..bdc0705 100644
--- a/cmd/editcluster.go
+++ b/cmd/editcluster.go
@@ -29,7 +29,7 @@ func createEditClusterCmd() *cobra.Command {
 	cmd := &cobra.Command{
 		Use:          "cluster",
 		Short:        "Edit a cluster",
-		Args:         cobra.MaximumNArgs(0),
+		Args:         MaxArgs(0),
 		SilenceUsage: true,
 		RunE: func(cmd *cobra.Command, args []string) error {
 			if err := RunAction(cmd, args, &params); err != nil {
diff --git a/cmd/editserver.go b/cmd/editserver.go
index 4b695ab..3c71acd 100644
--- a/cmd/editserver.go
+++ b/cmd/editserver.go
@@ -30,7 +30,7 @@ func createEditServerCmd() *cobra.Command {
 	cmd := &cobra.Command{
 		Use:          "server",
 		Short:        "Edit a server",
-		Args:         cobra.MaximumNArgs(0),
+		Args:         MaxArgs(0),
 		SilenceUsage: true,
 		RunE: func(cmd *cobra.Command, args []string) error {
 			if err := RunAction(cmd, args, &params); err != nil {
diff --git a/cmd/edituser.go b/cmd/edituser.go
index e5572d7..871517c 100644
--- a/cmd/edituser.go
+++ b/cmd/edituser.go
@@ -31,7 +31,7 @@ func createEditUserCmd() *cobra.Command {
 	cmd := &cobra.Command{
 		Use:          "user",
 		Short:        "Edit an user",
-		Args:         cobra.MaximumNArgs(0),
+		Args:         MaxArgs(0),
 		SilenceUsage: true,
 		RunE: func(cmd *cobra.Command, args []string) error {
 			if err := RunAction(cmd, args, &params); err != nil {
diff --git a/cmd/env.go b/cmd/env.go
index 66e4ef4..4096b7a 100644
--- a/cmd/env.go
+++ b/cmd/env.go
@@ -36,7 +36,7 @@ func createEnvCmd() *cobra.Command {
 	cmd := &cobra.Command{
 		Use:           "env",
 		Short:         fmt.Sprintf("Prints and manage the %s environment", GetToolName()),
-		Args:          cobra.MaximumNArgs(0),
+		Args:          MaxArgs(0),
 		SilenceErrors: false,
 		SilenceUsage:  false,
 		Example:       "env",
diff --git a/cmd/generateactivation.go b/cmd/generateactivation.go
index f3e0853..c9f5025 100644
--- a/cmd/generateactivation.go
+++ b/cmd/generateactivation.go
@@ -30,7 +30,7 @@ func createGenerateActivationCmd() *cobra.Command {
 	cmd := &cobra.Command{
 		Use:          "activation",
 		Short:        "Generate an export activation jwt token",
-		Args:         cobra.MaximumNArgs(0),
+		Args:         MaxArgs(0),
 		SilenceUsage: true,
 		RunE: func(cmd *cobra.Command, args []string) error {
 			if err := RunAction(cmd, args, &params); err != nil {
diff --git a/cmd/generateconfig.go b/cmd/generateconfig.go
index cae771c..c9c1967 100644
--- a/cmd/generateconfig.go
+++ b/cmd/generateconfig.go
@@ -28,7 +28,7 @@ func createGenerateConfigCmd() *cobra.Command {
 	cmd := &cobra.Command{
 		Use:          "config",
 		Short:        "Generate a config file for an user",
-		Args:         cobra.MaximumNArgs(0),
+		Args:         MaxArgs(0),
 		SilenceUsage: true,
 		Example:      `nsc generate config --account a --user u`,
 		RunE: func(cmd *cobra.Command, args []string) error {
@@ -83,15 +83,12 @@ func (p *GenerateConfigParams) SetDefaults(ctx ActionCtx) error {
 
 func (p *GenerateConfigParams) PreInteractive(ctx ActionCtx) error {
 	var err error
-
 	if err = p.AccountContextParams.Edit(ctx); err != nil {
 		return err
 	}
-	if p.user == "" {
-		p.user, err = ctx.StoreCtx().PickUser(p.AccountContextParams.Name)
-		if err != nil {
-			return err
-		}
+	p.user, err = ctx.StoreCtx().PickUser(p.AccountContextParams.Name)
+	if err != nil {
+		return err
 	}
 	return nil
 }
@@ -111,7 +108,7 @@ func (p *GenerateConfigParams) Validate(ctx ActionCtx) error {
 		return fmt.Errorf("account is required")
 	}
 	if p.user == "" {
-		return fmt.Errorf("name is required")
+		return fmt.Errorf("user is required")
 	}
 
 	p.entityKP, err = ctx.StoreCtx().KeyStore.GetUserKey(p.AccountContextParams.Name, p.user)
@@ -120,7 +117,7 @@ func (p *GenerateConfigParams) Validate(ctx ActionCtx) error {
 	}
 
 	if !ctx.StoreCtx().Store.Has(store.Accounts, p.AccountContextParams.Name, store.Users, store.JwtName(p.user)) {
-		return fmt.Errorf("user %q not found", p.user)
+		return fmt.Errorf("user %q not found in %q", p.user, p.AccountContextParams.Name)
 	}
 
 	p.entityJwt, err = ctx.StoreCtx().Store.Read(store.Accounts, p.AccountContextParams.Name, store.Users, store.JwtName(p.user))
diff --git a/cmd/generateoperatorconfig.go b/cmd/generateoperatorconfig.go
index 744477c..9f9fadf 100644
--- a/cmd/generateoperatorconfig.go
+++ b/cmd/generateoperatorconfig.go
@@ -29,7 +29,7 @@ func createGenerateOperatorConfigCmd() *cobra.Command {
 	cmd := &cobra.Command{
 		Use:          "operator",
 		Short:        "Generate an operator config",
-		Args:         cobra.MaximumNArgs(0),
+		Args:         MaxArgs(0),
 		SilenceUsage: true,
 		Example:      `nsc generate operator --n a`,
 		RunE: func(cmd *cobra.Command, args []string) error {
diff --git a/cmd/init.go b/cmd/init.go
index f35bab5..b687040 100644
--- a/cmd/init.go
+++ b/cmd/init.go
@@ -31,7 +31,7 @@ func CreateInitCmd() *cobra.Command {
 	cmd := &cobra.Command{
 		Use:   "init",
 		Short: "Init a configuration directory",
-		Args:  cobra.MaximumNArgs(0),
+		Args:  MaxArgs(0),
 		Example: `init --name operatorname
 init --interactive
 `,
diff --git a/cmd/list.go b/cmd/list.go
index 6195da5..e62df02 100644
--- a/cmd/list.go
+++ b/cmd/list.go
@@ -52,7 +52,7 @@ func createListOperatorsCmd() *cobra.Command {
 	cmd := &cobra.Command{
 		Use:   "operators",
 		Short: "List operators",
-		Args:  cobra.MaximumNArgs(0),
+		Args:  MaxArgs(0),
 		RunE: func(cmd *cobra.Command, args []string) error {
 			config := GetConfig()
 			if config.StoreRoot == "" {
@@ -97,7 +97,7 @@ func createListAccountsCmd() *cobra.Command {
 	cmd := &cobra.Command{
 		Use:   "accounts",
 		Short: "List accounts",
-		Args:  cobra.MaximumNArgs(0),
+		Args:  MaxArgs(0),
 		RunE: func(cmd *cobra.Command, args []string) error {
 			config := GetConfig()
 			if config.StoreRoot == "" {
@@ -143,7 +143,7 @@ func createListUsersCmd() *cobra.Command {
 	cmd := &cobra.Command{
 		Use:   "users",
 		Short: "List users",
-		Args:  cobra.MaximumNArgs(0),
+		Args:  MaxArgs(0),
 		RunE: func(cmd *cobra.Command, args []string) error {
 			config := GetConfig()
 			if config.StoreRoot == "" {
@@ -191,7 +191,7 @@ func createListClustersCmd() *cobra.Command {
 	cmd := &cobra.Command{
 		Use:   "clusters",
 		Short: "List clusters",
-		Args:  cobra.MaximumNArgs(0),
+		Args:  MaxArgs(0),
 		RunE: func(cmd *cobra.Command, args []string) error {
 			config := GetConfig()
 			if config.StoreRoot == "" {
@@ -238,7 +238,7 @@ func createListServersCmd() *cobra.Command {
 	cmd := &cobra.Command{
 		Use:   "servers",
 		Short: "List servers",
-		Args:  cobra.MaximumNArgs(0),
+		Args:  MaxArgs(0),
 		RunE: func(cmd *cobra.Command, args []string) error {
 			config := GetConfig()
 			if config.StoreRoot == "" {
diff --git a/cmd/update.go b/cmd/update.go
index 3e5a024..f1c7777 100644
--- a/cmd/update.go
+++ b/cmd/update.go
@@ -35,7 +35,7 @@ update --release-notes
 `,
 		Use:   "update",
 		Short: "Update this tool to latest version",
-		Args:  cobra.MaximumNArgs(0),
+		Args:  MaxArgs(0),
 		RunE: func(cmd *cobra.Command, args []string) error {
 			v := semver.MustParse(GetRootCmd().Version)
 


Test patch:
diff --git a/cmd/generateconfig_test.go b/cmd/generateconfig_test.go
index f0d5186..5574685 100644
--- a/cmd/generateconfig_test.go
+++ b/cmd/generateconfig_test.go
@@ -16,8 +16,11 @@
 package cmd
 
 import (
+	"os"
 	"testing"
 
+	"github.com/nats-io/jwt"
+
 	"github.com/nats-io/nsc/cmd/store"
 	"github.com/stretchr/testify/require"
 )
@@ -93,7 +96,7 @@ func TestGenerateConfig_MultipleUsers(t *testing.T) {
 
 	_, _, err = ExecuteCmd(createGenerateConfigCmd())
 	require.Error(t, err)
-	require.Equal(t, "name is required", err.Error())
+	require.Equal(t, "user is required", err.Error())
 
 	stdout, _, err := ExecuteCmd(createGenerateConfigCmd(), "--account", "A", "--user", "u")
 	require.NoError(t, err)
@@ -121,3 +124,58 @@ func TestGenerateConfig_Interactive(t *testing.T) {
 	require.Contains(t, stdout, string(accountJwt))
 	require.Contains(t, stdout, seed)
 }
+
+func TestGenerateConfig_HonorsAccount(t *testing.T) {
+	ts := NewTestStore(t, "operator")
+	defer ts.Done(t)
+
+	ts.AddAccount(t, "A")
+	ts.AddUser(t, "A", "au")
+	ts.AddAccount(t, "B")
+	ts.AddUser(t, "B", "bu")
+
+	stdout, _, err := ExecuteCmd(createGenerateConfigCmd(), "--account", "A")
+	require.NoError(t, err)
+	userToken, _ := ExtractToken(stdout)
+
+	uc, err := jwt.DecodeUserClaims(userToken)
+	require.NoError(t, err)
+	require.Equal(t, "au", uc.Name)
+
+	stdout, _, err = ExecuteCmd(createGenerateConfigCmd(), "--account", "B")
+	require.NoError(t, err)
+	userToken, _ = ExtractToken(stdout)
+
+	uc, err = jwt.DecodeUserClaims(userToken)
+	require.NoError(t, err)
+	require.Equal(t, "bu", uc.Name)
+}
+
+func TestGenerateConfig_InteractiveHonorsAccount(t *testing.T) {
+	ts := NewTestStore(t, "operator")
+	defer ts.Done(t)
+
+	ts.AddAccount(t, "A")
+	ts.AddUser(t, "A", "au")
+	ts.AddAccount(t, "B")
+	ts.AddUser(t, "B", "bu")
+
+	t.Log(os.Args[0])
+
+	inputs := []interface{}{0}
+	stdout, _, err := ExecuteInteractiveCmd(createGenerateConfigCmd(), inputs)
+	require.NoError(t, err)
+	userToken, _ := ExtractToken(stdout)
+
+	uc, err := jwt.DecodeUserClaims(userToken)
+	require.NoError(t, err)
+	require.Equal(t, "au", uc.Name)
+
+	//stdout, _, err = ExecuteCmd(createGenerateConfigCmd(), "--account", "B")
+	//require.NoError(t, err)
+	//userToken, _ = ExtractToken(stdout)
+	//
+	//uc, err = jwt.DecodeUserClaims(userToken)
+	//require.NoError(t, err)
+	//require.Equal(t, "bu", uc.Name)
+}