Repository: nats-io/nsc
Pull request #34 (2018-12-07 18:12:04)

Fix for commands that specify --account or --cluster 
Regardless of the current setting for default account/cluster, handle the
--account/--cluster flags correctly.

Adding an account or cluster will now set that account/cluster as a default
as reported by `nsc env`. Commands that specify an `--account/cluster` will
use the value transiently.


Patch:
diff --git a/cmd/accountcontextparams.go b/cmd/accountcontextparams.go
index 75220d6..3c3a3c5 100644
--- a/cmd/accountcontextparams.go
+++ b/cmd/accountcontextparams.go
@@ -29,17 +29,22 @@ func (p *AccountContextParams) BindFlags(cmd *cobra.Command) {
 	cmd.Flags().StringVarP(&p.Name, "account", "a", "", "account name")
 }
 
-func (p *AccountContextParams) SetDefaults(ctx ActionCtx) {
+func (p *AccountContextParams) SetDefaults(ctx ActionCtx) error {
 	config := GetConfig()
-	if p.Name == "" {
-		p.Name = config.Account
-	}
-	if p.Name != "" && ctx.StoreCtx().Account.Name == "" {
+	if p.Name != "" {
+		err := config.SetAccountTemp(p.Name)
+		if err != nil {
+			return err
+		}
 		ctx.StoreCtx().Account.Name = p.Name
+		return nil
+	} else {
+		if config.Account != "" {
+			ctx.StoreCtx().Account.Name = config.Account
+			p.Name = config.Account
+		}
 	}
-	if ctx.StoreCtx().Account.Name != "" && p.Name == "" {
-		p.Name = ctx.StoreCtx().Account.Name
-	}
+	return nil
 }
 
 func (p *AccountContextParams) Edit(ctx ActionCtx) error {
diff --git a/cmd/addaccount.go b/cmd/addaccount.go
index 4cf3fb1..8bed303 100644
--- a/cmd/addaccount.go
+++ b/cmd/addaccount.go
@@ -122,7 +122,9 @@ func (p *AddAccountParams) Run(ctx ActionCtx) error {
 	if err := p.Entity.GenerateClaim(p.signerKP, ctx); err != nil {
 		return err
 	}
-	return nil
+
+	// if we added an account - make this the current account
+	return GetConfig().SetAccount(p.Entity.name)
 }
 
 func (p *AddAccountParams) editAccount(c interface{}, ctx ActionCtx) error {
diff --git a/cmd/addcluster.go b/cmd/addcluster.go
index 93852d0..557e3ea 100644
--- a/cmd/addcluster.go
+++ b/cmd/addcluster.go
@@ -149,7 +149,8 @@ func (p *AddClusterParams) Run(ctx ActionCtx) error {
 		return err
 	}
 
-	return nil
+	// if we added an cluster - make this the current cluster
+	return GetConfig().SetCluster(p.Entity.name)
 }
 
 func (p *AddClusterParams) editClusterClaim(c interface{}, ctx ActionCtx) error {
diff --git a/cmd/clustercontextparams.go b/cmd/clustercontextparams.go
index a5bc0e7..5950212 100644
--- a/cmd/clustercontextparams.go
+++ b/cmd/clustercontextparams.go
@@ -29,17 +29,21 @@ func (p *ClusterContextParams) BindFlags(cmd *cobra.Command) {
 	cmd.Flags().StringVarP(&p.Name, "cluster", "c", "", "cluster name")
 }
 
-func (p *ClusterContextParams) SetDefaults(ctx ActionCtx) {
+func (p *ClusterContextParams) SetDefaults(ctx ActionCtx) error {
 	config := GetConfig()
-	if p.Name == "" {
-		p.Name = config.Cluster
-	}
-	if p.Name != "" && ctx.StoreCtx().Cluster.Name == "" {
-		ctx.StoreCtx().Cluster.Name = p.Name
-	}
-	if ctx.StoreCtx().Cluster.Name != "" && p.Name == "" {
-		p.Name = ctx.StoreCtx().Cluster.Name
+	if p.Name != "" {
+		err := config.SetClusterTemp(p.Name)
+		if err != nil {
+			return err
+		}
+		ctx.StoreCtx().Cluster.Name = config.Cluster
+	} else {
+		if config.Cluster != "" {
+			ctx.StoreCtx().Cluster.Name = config.Cluster
+			p.Name = config.Cluster
+		}
 	}
+	return nil
 }
 
 func (p *ClusterContextParams) Edit(ctx ActionCtx) error {
diff --git a/cmd/contextconfig.go b/cmd/contextconfig.go
index dc3f1e0..6e9f78e 100644
--- a/cmd/contextconfig.go
+++ b/cmd/contextconfig.go
@@ -112,27 +112,54 @@ func (c *ContextConfig) ListOperators() []string {
 }
 
 func (c *ContextConfig) SetOperator(operator string) error {
-	for _, v := range c.ListOperators() {
-		if v == operator {
-			c.Operator = operator
-			return nil
+	ok := true
+	if operator != "" {
+		ok = false
+		for _, v := range c.ListOperators() {
+			if v == operator {
+				ok = true
+				break
+			}
 		}
 	}
-	return fmt.Errorf("operator %q not in %q", operator, c.StoreRoot)
+	if !ok {
+		return fmt.Errorf("operator %q not in %q", operator, c.StoreRoot)
+	}
+
+	c.Operator = operator
+	return GetConfig().Save()
 }
 
 func (c *ContextConfig) SetAccount(account string) error {
-	if err := c.hasSubContainer(store.Accounts, account); err != nil {
+	if err := c.SetAccountTemp(account); err != nil {
 		return err
 	}
+	return GetConfig().Save()
+}
+
+func (c *ContextConfig) SetAccountTemp(account string) error {
+	if account != "" {
+		if err := c.hasSubContainer(store.Accounts, account); err != nil {
+			return err
+		}
+	}
 	c.Account = account
 	return nil
 }
 
 func (c *ContextConfig) SetCluster(cluster string) error {
-	if err := c.hasSubContainer(store.Clusters, cluster); err != nil {
+	if err := c.SetClusterTemp(cluster); err != nil {
 		return err
 	}
+	return GetConfig().Save()
+}
+
+func (c *ContextConfig) SetClusterTemp(cluster string) error {
+	if cluster != "" {
+		if err := c.hasSubContainer(store.Clusters, cluster); err != nil {
+			return err
+		}
+	}
 	c.Cluster = cluster
 	return nil
 }
diff --git a/cmd/defaults.go b/cmd/defaults.go
index 9dedc66..f3f8925 100644
--- a/cmd/defaults.go
+++ b/cmd/defaults.go
@@ -116,6 +116,7 @@ func (d *ToolConfig) load() error {
 }
 
 func (d *ToolConfig) Save() error {
+	d.SetDefaults()
 	return WriteJson(d.configFile(), d)
 }
 
diff --git a/cmd/env.go b/cmd/env.go
index 89d3c85..66e4ef4 100644
--- a/cmd/env.go
+++ b/cmd/env.go
@@ -41,7 +41,7 @@ func createEnvCmd() *cobra.Command {
 		SilenceUsage:  false,
 		Example:       "env",
 		RunE: func(cmd *cobra.Command, args []string) error {
-			_ = params.Run()
+			_ = params.Run(cmd)
 			params.PrintEnv(cmd)
 			return nil
 		},
@@ -66,7 +66,7 @@ type SetContextParams struct {
 	Cluster   string
 }
 
-func (p *SetContextParams) Run() error {
+func (p *SetContextParams) Run(cmd *cobra.Command) error {
 	if *p == (SetContextParams{}) {
 		// no edits
 		return nil
diff --git a/cmd/store/store.go b/cmd/store/store.go
index ed4659b..e12e254 100644
--- a/cmd/store/store.go
+++ b/cmd/store/store.go
@@ -635,25 +635,24 @@ func (ctx *Context) PickAccount(name string) (string, error) {
 		name = ctx.Account.Name
 	}
 
-	if name == "" {
-		accounts, err := ctx.Store.ListSubContainers(Accounts)
+	accounts, err := ctx.Store.ListSubContainers(Accounts)
+	if err != nil {
+		return "", err
+	}
+	if len(accounts) == 0 {
+		return "", fmt.Errorf("no accounts defined - add one first")
+	}
+	if len(accounts) == 1 {
+		name = accounts[0]
+	}
+	if len(accounts) > 1 {
+		i, err := cli.PromptChoices("select account", accounts)
 		if err != nil {
 			return "", err
 		}
-		if len(accounts) == 0 {
-			return "", fmt.Errorf("no accounts defined - add one first")
-		}
-		if len(accounts) == 1 {
-			name = accounts[0]
-		}
-		if len(accounts) > 1 {
-			i, err := cli.PromptChoices("select account", accounts)
-			if err != nil {
-				return "", err
-			}
-			name = accounts[i]
-		}
+		name = accounts[i]
 	}
+
 	// allow downstream use of context to have account
 	ctx.Account.Name = name
 
@@ -759,25 +758,24 @@ func (ctx *Context) PickCluster(name string) (string, error) {
 		name = ctx.Cluster.Name
 	}
 
-	if name == "" {
-		clusters, err := ctx.Store.ListSubContainers(Clusters)
+	clusters, err := ctx.Store.ListSubContainers(Clusters)
+	if err != nil {
+		return "", err
+	}
+	if len(clusters) == 0 {
+		return "", fmt.Errorf("no clusters defined - add one first")
+	}
+	if len(clusters) == 1 {
+		name = clusters[0]
+	}
+	if len(clusters) > 1 {
+		i, err := cli.PromptChoices("select cluster", clusters)
 		if err != nil {
 			return "", err
 		}
-		if len(clusters) == 0 {
-			return "", fmt.Errorf("no clusters defined - add one first")
-		}
-		if len(clusters) == 1 {
-			name = clusters[0]
-		}
-		if len(clusters) > 1 {
-			i, err := cli.PromptChoices("select cluster", clusters)
-			if err != nil {
-				return "", err
-			}
-			name = clusters[i]
-		}
+		name = clusters[i]
 	}
+
 	// allow downstream use of context to have cluster
 	ctx.Cluster.Name = name
 


Test patch:
diff --git a/cmd/addexport_test.go b/cmd/addexport_test.go
index 4a29cd0..23fb876 100644
--- a/cmd/addexport_test.go
+++ b/cmd/addexport_test.go
@@ -115,9 +115,14 @@ func Test_AddExportAccountNameRequired(t *testing.T) {
 	ts.AddAccount(t, "A")
 	ts.AddAccount(t, "B")
 
-	_, _, err := ExecuteCmd(createAddExportCmd(), "--subject", "aaaa")
-	require.Error(t, err)
-	require.Equal(t, "an account is required", err.Error())
+	_, _, err := ExecuteCmd(createAddExportCmd(), "--subject", "bbbb")
+	require.NoError(t, err)
+
+	ac, err := ts.Store.ReadAccountClaim("B")
+	require.NoError(t, err)
+	require.NotNil(t, ac)
+	require.Len(t, ac.Exports, 1)
+	require.Equal(t, "bbbb", ac.Exports[0].Name)
 }
 
 func TestAddExportInteractive(t *testing.T) {
diff --git a/cmd/addimport_test.go b/cmd/addimport_test.go
index caf5659..ba47a42 100644
--- a/cmd/addimport_test.go
+++ b/cmd/addimport_test.go
@@ -40,7 +40,6 @@ func Test_AddImport(t *testing.T) {
 	require.NoError(t, Write(fp, []byte(token)))
 
 	tests := CmdTests{
-		{createAddImportCmd(), []string{"add", "import"}, nil, []string{"an account is required"}, true},
 		{createAddImportCmd(), []string{"add", "import", "--account", "B"}, nil, []string{"token is required"}, true},
 		{createAddImportCmd(), []string{"add", "import", "--account", "B", "--token", fp}, nil, []string{"added stream import"}, false},
 	}
@@ -48,6 +47,15 @@ func Test_AddImport(t *testing.T) {
 	tests.Run(t, "root", "add")
 }
 
+func Test_AddImportNoDefaultAccount(t *testing.T) {
+	ts := NewTestStore(t, "test")
+	defer ts.Done(t)
+
+	ts.AddAccount(t, "A")
+	ts.AddAccount(t, "B")
+
+}
+
 func Test_AddImportSelfImportsRejected(t *testing.T) {
 	ts := NewTestStore(t, "test")
 	defer ts.Done(t)
diff --git a/cmd/adduser_test.go b/cmd/adduser_test.go
index eab9da2..0e690a8 100644
--- a/cmd/adduser_test.go
+++ b/cmd/adduser_test.go
@@ -120,3 +120,25 @@ func Test_AddUserOperatorLessStore(t *testing.T) {
 
 	validateAddUserClaims(t, ts)
 }
+
+func Test_AddUser_Account(t *testing.T) {
+	ts := NewTestStore(t, "test")
+	defer ts.Done(t)
+
+	_, _, err := ExecuteCmd(CreateAddAccountCmd(), "--name", "A", "--start", "2018-01-01", "--expiry", "2050-01-01")
+	require.NoError(t, err)
+
+	_, _, err = ExecuteCmd(CreateAddAccountCmd(), "--name", "B", "--start", "2018-01-01", "--expiry", "2050-01-01")
+	require.NoError(t, err)
+
+	config := GetConfig()
+	err = config.SetAccount("A")
+	require.NoError(t, err)
+
+	_, _, err = ExecuteCmd(CreateAddUserCmd(), "--name", "bb", "--account", "B")
+	require.NoError(t, err)
+
+	u, err := ts.Store.ReadUserClaim("B", "bb")
+	require.NoError(t, err)
+	require.NotNil(t, u)
+}
diff --git a/cmd/clustercontextparams_test.go b/cmd/clustercontextparams_test.go
index 1de386a..3a32d6d 100644
--- a/cmd/clustercontextparams_test.go
+++ b/cmd/clustercontextparams_test.go
@@ -62,7 +62,7 @@ func TestCCP_DefaultsMultipleNone(t *testing.T) {
 
 	ccp := ClusterContextParams{}
 	ccp.SetDefaults(ctx)
-	require.Equal(t, "", ccp.Name)
+	require.Equal(t, "bar", ccp.Name)
 }
 
 func TestCCP_DefaultsPath(t *testing.T) {
@@ -77,7 +77,7 @@ func TestCCP_DefaultsPath(t *testing.T) {
 
 	ccp := ClusterContextParams{}
 	ccp.SetDefaults(ctx)
-	require.Equal(t, "", ccp.Name)
+	require.Equal(t, "bar", ccp.Name)
 }
 
 func TestCCP_Edit(t *testing.T) {
@@ -95,7 +95,7 @@ func TestCCP_Edit(t *testing.T) {
 
 	ccp := ClusterContextParams{}
 	ccp.SetDefaults(ctx)
-	require.Equal(t, "", ccp.Name)
+	require.Equal(t, "baz", ccp.Name)
 
 	require.NoError(t, ccp.Edit(ctx))
 	require.Contains(t, []string{"foo", "bar", "baz"}, ccp.Name)
diff --git a/cmd/contextconfig_test.go b/cmd/contextconfig_test.go
index 3ae7d2d..e83e09e 100644
--- a/cmd/contextconfig_test.go
+++ b/cmd/contextconfig_test.go
@@ -97,7 +97,7 @@ func TestContextConfig_SetEptyOperator(t *testing.T) {
 	c, err := NewContextConfig(storesDir)
 	require.NoError(t, err)
 	err = c.SetOperator("")
-	require.Error(t, err)
+	require.NoError(t, err)
 }
 
 func TestContextConfig_Account(t *testing.T) {
@@ -167,7 +167,7 @@ func TestContextConfig_SetEmptyAccount(t *testing.T) {
 	require.NoError(t, err)
 
 	err = c.SetAccount("")
-	require.Error(t, err)
+	require.NoError(t, err)
 }
 
 func TestContextConfig_LoadCluster(t *testing.T) {
@@ -238,7 +238,7 @@ func TestContextConfig_SetEmptyCluster(t *testing.T) {
 	require.NoError(t, err)
 
 	err = c.SetCluster("")
-	require.Error(t, err)
+	require.NoError(t, err)
 }
 
 func TestContextConfig_ListOperators(t *testing.T) {
diff --git a/cmd/deleteexport_test.go b/cmd/deleteexport_test.go
index ed65a6e..3d90098 100644
--- a/cmd/deleteexport_test.go
+++ b/cmd/deleteexport_test.go
@@ -31,7 +31,6 @@ func Test_DeleteExport(t *testing.T) {
 	ts.AddExport(t, "B", jwt.Service, "bar", true)
 
 	tests := CmdTests{
-		{createDeleteExportCmd(), []string{"delete", "export"}, nil, []string{"account is required"}, true},
 		{createDeleteExportCmd(), []string{"delete", "export", "--account", "A"}, nil, []string{"subject is required"}, true},
 		{createDeleteExportCmd(), []string{"delete", "export", "--account", "A", "--subject", "a"}, nil, []string{"no export matching \"a\" found"}, true},
 		{createDeleteExportCmd(), []string{"delete", "export", "--account", "A", "--subject", "foo"}, nil, []string{"deleted export of \"foo\""}, false},
@@ -41,6 +40,18 @@ func Test_DeleteExport(t *testing.T) {
 	tests.Run(t, "root", "delete")
 }
 
+func Test_DeleteExportAccountRequired(t *testing.T) {
+	ts := NewTestStore(t, "add_server")
+	defer ts.Done(t)
+
+	ts.AddExport(t, "A", jwt.Stream, "foo", true)
+	ts.AddExport(t, "B", jwt.Service, "bar", true)
+	GetConfig().SetAccount("")
+	_, _, err := ExecuteCmd(createDeleteExportCmd(), "--subject", "foo")
+	require.Error(t, err)
+	require.Contains(t, err.Error(), "account is required")
+}
+
 func Test_DeleteExportInteractive(t *testing.T) {
 	ts := NewTestStoreWithOperator(t, "test", nil)
 	defer ts.Done(t)
diff --git a/cmd/deleteimport_test.go b/cmd/deleteimport_test.go
index 301ed95..ee40ac3 100644
--- a/cmd/deleteimport_test.go
+++ b/cmd/deleteimport_test.go
@@ -35,7 +35,6 @@ func Test_DeleteImport(t *testing.T) {
 	ts.AddImport(t, "A", "bar", "B")
 
 	tests := CmdTests{
-		{createDeleteImportCmd(), []string{"delete", "import"}, nil, []string{"account is required"}, true},
 		{createDeleteImportCmd(), []string{"delete", "import", "--account", "A"}, nil, []string{"account \"A\" doesn't have imports"}, true},
 		{createDeleteImportCmd(), []string{"delete", "import", "--account", "B"}, nil, []string{"subject is required"}, true},
 		{createDeleteImportCmd(), []string{"delete", "import", "--account", "B", "--subject", "baz"}, nil, []string{"no import matching \"baz\" found"}, true},
@@ -45,6 +44,21 @@ func Test_DeleteImport(t *testing.T) {
 	tests.Run(t, "root", "delete")
 }
 
+func Test_DeleteImportAccountRequired(t *testing.T) {
+	ts := NewTestStore(t, "delete import")
+	defer ts.Done(t)
+
+	ts.AddAccount(t, "A")
+	ts.AddExport(t, "A", jwt.Stream, "foo", false)
+	ts.AddAccount(t, "B")
+	ts.AddImport(t, "A", "foo", "B")
+
+	GetConfig().SetAccount("")
+	_, _, err := ExecuteCmd(createDeleteImportCmd(), "--subject", "A")
+	require.Error(t, err)
+	require.Contains(t, err.Error(), "account is required")
+}
+
 func Test_DeleteImportInteractive(t *testing.T) {
 	ts := NewTestStoreWithOperator(t, "test", nil)
 	defer ts.Done(t)
diff --git a/cmd/describeaccount_test.go b/cmd/describeaccount_test.go
index a95a599..a0078d9 100644
--- a/cmd/describeaccount_test.go
+++ b/cmd/describeaccount_test.go
@@ -50,9 +50,23 @@ func TestDescribeAccount_Multiple(t *testing.T) {
 	ts.AddAccount(t, "A")
 	ts.AddAccount(t, "B")
 
-	_, stderr, err := ExecuteCmd(createDescribeAccountCmd())
+	out, _, err := ExecuteCmd(createDescribeAccountCmd())
+	require.NoError(t, err)
+	out = StripTableDecorations(out)
+	require.Contains(t, out, "Name B")
+}
+
+func TestDescribeAccount_MultipleAccountRequired(t *testing.T) {
+	ts := NewTestStore(t, "operator")
+	defer ts.Done(t)
+
+	ts.AddAccount(t, "A")
+	ts.AddAccount(t, "B")
+	GetConfig().SetAccount("")
+
+	_, _, err := ExecuteCmd(createDescribeAccountCmd())
 	require.Error(t, err)
-	require.Contains(t, stderr, "an account is required")
+	require.Contains(t, err.Error(), "account is required")
 }
 
 func TestDescribeAccount_MultipleWithContext(t *testing.T) {
diff --git a/cmd/describecluster_test.go b/cmd/describecluster_test.go
index 666991a..c364a4d 100644
--- a/cmd/describecluster_test.go
+++ b/cmd/describecluster_test.go
@@ -47,9 +47,22 @@ func TestDescribeCluster_Multiple(t *testing.T) {
 	ts.AddCluster(t, "A")
 	ts.AddCluster(t, "B")
 
-	_, stderr, err := ExecuteCmd(createDescribeClusterCmd())
+	out, _, err := ExecuteCmd(createDescribeClusterCmd())
+	require.NoError(t, err)
+	require.Contains(t, StripTableDecorations(out), "Name B")
+}
+
+func TestDescribeCluster_MultipleAccountRequired(t *testing.T) {
+	ts := NewTestStore(t, "operator")
+	defer ts.Done(t)
+
+	ts.AddCluster(t, "A")
+	ts.AddCluster(t, "B")
+	GetConfig().SetCluster("")
+
+	_, _, err := ExecuteCmd(createDescribeClusterCmd())
 	require.Error(t, err)
-	require.Contains(t, stderr, "a cluster is required")
+	require.Contains(t, err.Error(), "cluster is required")
 }
 
 func TestDescribeCluster_MultipleWithContext(t *testing.T) {
diff --git a/cmd/editaccount_test.go b/cmd/editaccount_test.go
index dd7ee0a..c4f7cf4 100644
--- a/cmd/editaccount_test.go
+++ b/cmd/editaccount_test.go
@@ -30,13 +30,24 @@ func Test_EditAccount(t *testing.T) {
 
 	tests := CmdTests{
 		{createEditAccount(), []string{"edit", "account"}, nil, []string{"specify an edit option"}, true},
-		{createEditAccount(), []string{"edit", "account", "--tag", "A"}, nil, []string{"an account is required"}, true},
 		{createEditAccount(), []string{"edit", "account", "--tag", "A", "--account", "A"}, nil, []string{"edited account \"A\""}, false},
 	}
 
 	tests.Run(t, "root", "edit")
 }
 
+func Test_EditAccountRequired(t *testing.T) {
+	ts := NewTestStore(t, "edit account")
+	defer ts.Done(t)
+
+	ts.AddAccount(t, "A")
+	ts.AddAccount(t, "B")
+	require.NoError(t, GetConfig().SetAccount(""))
+	_, _, err := ExecuteCmd(createEditAccount(), "--tag", "A")
+	require.Error(t, err)
+	require.Contains(t, "an account is required", err.Error())
+}
+
 func Test_EditAccount_Tag(t *testing.T) {
 	ts := NewTestStore(t, "edit account")
 	defer ts.Done(t)
diff --git a/cmd/editcluster_test.go b/cmd/editcluster_test.go
index 7fb12c3..805ec3b 100644
--- a/cmd/editcluster_test.go
+++ b/cmd/editcluster_test.go
@@ -30,13 +30,24 @@ func Test_EditCluster(t *testing.T) {
 
 	tests := CmdTests{
 		{createEditClusterCmd(), []string{"edit", "cluster"}, nil, []string{"specify an edit option"}, true},
-		{createEditClusterCmd(), []string{"edit", "cluster", "--tag", "A"}, nil, []string{"a cluster is required"}, true},
 		{createEditClusterCmd(), []string{"edit", "cluster", "--tag", "A", "--cluster", "A"}, nil, []string{"edited cluster \"A\""}, false},
 	}
 
 	tests.Run(t, "root", "edit")
 }
 
+func Test_EditClusterClusterRequired(t *testing.T) {
+	ts := NewTestStore(t, "edit cluster")
+	defer ts.Done(t)
+
+	ts.AddCluster(t, "A")
+	ts.AddCluster(t, "B")
+	GetConfig().SetCluster("")
+	_, _, err := ExecuteCmd(createEditClusterCmd(), "--tag", "A")
+	require.Error(t, err)
+	require.Contains(t, err.Error(), "cluster is required")
+}
+
 func Test_EditCluster_Tag(t *testing.T) {
 	ts := NewTestStore(t, "edit cluster")
 	defer ts.Done(t)
diff --git a/cmd/editserver_test.go b/cmd/editserver_test.go
index d94da0f..5958b63 100644
--- a/cmd/editserver_test.go
+++ b/cmd/editserver_test.go
@@ -31,7 +31,6 @@ func Test_EditServer(t *testing.T) {
 
 	tests := CmdTests{
 		{createEditServerCmd(), []string{"edit", "server"}, nil, []string{"specify an edit option"}, true},
-		{createEditServerCmd(), []string{"edit", "server", "--tag", "A"}, nil, []string{"a cluster is required"}, true},
 		{createEditServerCmd(), []string{"edit", "server", "--tag", "A", "--cluster", "A"}, nil, []string{"edited server \"a\""}, false},
 		{createEditServerCmd(), []string{"edit", "server", "--tag", "B", "--cluster", "B"}, nil, []string{"server name is required"}, true},
 		{createEditServerCmd(), []string{"edit", "server", "--tag", "B", "--cluster", "B", "--name", "bb"}, nil, []string{"edited server \"bb\""}, false},
@@ -40,6 +39,18 @@ func Test_EditServer(t *testing.T) {
 	tests.Run(t, "root", "edit")
 }
 
+func Test_EditServerClusterRequired(t *testing.T) {
+	ts := NewTestStore(t, "edit server")
+	defer ts.Done(t)
+	ts.AddServer(t, "A", "a")
+	ts.AddServer(t, "B", "b")
+	GetConfig().SetCluster("")
+
+	_, _, err := ExecuteCmd(createEditServerCmd(), "--tag", "A")
+	require.Error(t, err)
+	require.Contains(t, err.Error(), "cluster is required")
+}
+
 func Test_EditServer_Tag(t *testing.T) {
 	ts := NewTestStore(t, "edit server")
 	defer ts.Done(t)
diff --git a/cmd/edituser_test.go b/cmd/edituser_test.go
index a9655b4..340eeab 100644
--- a/cmd/edituser_test.go
+++ b/cmd/edituser_test.go
@@ -32,7 +32,6 @@ func Test_EditUser(t *testing.T) {
 
 	tests := CmdTests{
 		{createEditUserCmd(), []string{"edit", "user"}, nil, []string{"specify an edit option"}, true},
-		{createEditUserCmd(), []string{"edit", "user", "--tag", "A"}, nil, []string{"account is required"}, true},
 		{createEditUserCmd(), []string{"edit", "user", "--tag", "A", "--account", "A"}, nil, []string{"edited user \"a\""}, false},
 		{createEditUserCmd(), []string{"edit", "user", "--tag", "B", "--account", "B"}, nil, []string{"user name is required"}, true},
 		{createEditUserCmd(), []string{"edit", "user", "--tag", "B", "--account", "B", "--name", "bb"}, nil, []string{"edited user \"bb\""}, false},
@@ -41,6 +40,18 @@ func Test_EditUser(t *testing.T) {
 	tests.Run(t, "root", "edit")
 }
 
+func Test_EditUserAccountRequired(t *testing.T) {
+	ts := NewTestStore(t, "edit user")
+	defer ts.Done(t)
+
+	ts.AddUser(t, "A", "a")
+	ts.AddUser(t, "B", "b")
+	GetConfig().SetAccount("")
+	_, _, err := ExecuteCmd(createEditUserCmd(), "--tag", "A")
+	require.Error(t, err)
+	require.Contains(t, err.Error(), "account is required")
+}
+
 func Test_EditUser_Tag(t *testing.T) {
 	ts := NewTestStore(t, "edit user")
 	defer ts.Done(t)
diff --git a/cmd/generateactivation_test.go b/cmd/generateactivation_test.go
index 74cdec5..2023417 100644
--- a/cmd/generateactivation_test.go
+++ b/cmd/generateactivation_test.go
@@ -55,7 +55,6 @@ func Test_GenerateActivationMultiple(t *testing.T) {
 	_, pub, _ := CreateAccountKey(t)
 
 	tests := CmdTests{
-		{createGenerateActivationCmd(), []string{"generate", "activation"}, nil, []string{"an account is required"}, true},
 		{createGenerateActivationCmd(), []string{"generate", "activation", "--account", "A"}, nil, []string{"a subject is required"}, true},
 		{createGenerateActivationCmd(), []string{"generate", "activation", "--account", "A", "--subject", "bar.>"}, nil, []string{"target-account cannot be empty"}, true},
 		{createGenerateActivationCmd(), []string{"generate", "activation", "--account", "A", "--subject", "bar.>", "--target-account", pub}, []string{"-----BEGIN NATS ACTIVATION JWT-----"}, nil, false},
@@ -64,6 +63,20 @@ func Test_GenerateActivationMultiple(t *testing.T) {
 	tests.Run(t, "root", "generate")
 }
 
+func Test_GenerateActivationMultipleAccountRequired(t *testing.T) {
+	ts := NewTestStore(t, "gen activation")
+	defer ts.Done(t)
+
+	ts.AddAccount(t, "A")
+	ts.AddExport(t, "A", jwt.Stream, "foo.>", false)
+	ts.AddExport(t, "A", jwt.Stream, "bar.>", false)
+	ts.AddAccount(t, "B")
+	GetConfig().SetAccount("")
+	_, _, err := ExecuteCmd(createGenerateActivationCmd())
+	require.Error(t, err)
+	require.Contains(t, err.Error(), "account is required")
+}
+
 func Test_GenerateActivationEmptyExports(t *testing.T) {
 	ts := NewTestStore(t, "gen activation")
 	defer ts.Done(t)
diff --git a/cmd/generateconfig_test.go b/cmd/generateconfig_test.go
index e5cddc8..f0d5186 100644
--- a/cmd/generateconfig_test.go
+++ b/cmd/generateconfig_test.go
@@ -45,8 +45,9 @@ func TestGenerateConfig_MultipleAccounts(t *testing.T) {
 	ts := NewTestStore(t, "operator")
 	defer ts.Done(t)
 
-	ts.AddAccount(t, "A")
 	ts.AddAccount(t, "B")
+	ts.AddUser(t, "B", "u")
+	ts.AddAccount(t, "A")
 	ts.AddUser(t, "A", "u")
 
 	accountJwt, err := ts.Store.Read(store.Accounts, "A", store.Users, "u.jwt")
@@ -55,16 +56,27 @@ func TestGenerateConfig_MultipleAccounts(t *testing.T) {
 	seed, err := ts.KeyStore.GetUserSeed("A", "u")
 	require.NoError(t, err)
 
-	_, _, err = ExecuteCmd(createGenerateConfigCmd())
-	require.Error(t, err)
-	require.Equal(t, "account is required", err.Error())
-
-	stdout, _, err := ExecuteCmd(createGenerateConfigCmd(), "--account", "A")
+	stdout, _, err := ExecuteCmd(createGenerateConfigCmd())
 	require.NoError(t, err)
 	require.Contains(t, stdout, string(accountJwt))
 	require.Contains(t, stdout, seed)
 }
 
+func TestGenerateConfig_MultipleAccountsAccountRequired(t *testing.T) {
+	ts := NewTestStore(t, "operator")
+	defer ts.Done(t)
+
+	ts.AddAccount(t, "A")
+	ts.AddAccount(t, "B")
+	ts.AddUser(t, "A", "u")
+	ts.AddUser(t, "B", "u")
+
+	GetConfig().SetAccount("")
+	_, _, err := ExecuteCmd(createGenerateConfigCmd())
+	require.Error(t, err)
+	require.Contains(t, err.Error(), "account is required")
+}
+
 func TestGenerateConfig_MultipleUsers(t *testing.T) {
 	ts := NewTestStore(t, "operator")
 	defer ts.Done(t)
diff --git a/cmd/util_test.go b/cmd/util_test.go
index 191d1ba..0add517 100644
--- a/cmd/util_test.go
+++ b/cmd/util_test.go
@@ -50,7 +50,8 @@ func NewTestStoreWithOperator(t *testing.T, operatorName string, operator nkeys.
 
 	ts.OperatorKey = operator
 	ts.Dir = MakeTempDir(t)
-	require.NoError(t, os.Setenv(t.Name(), filepath.Join(ts.Dir, "cli_home")))
+	require.NoError(t, os.Setenv(t.Name(), filepath.Join(ts.Dir, "toolprefs")))
+	initToolHome(t.Name())
 	// debug the test that created the store
 	_ = ioutil.WriteFile(filepath.Join(ts.Dir, "test.txt"), []byte(t.Name()), 0700)
 
@@ -61,6 +62,20 @@ func NewTestStoreWithOperator(t *testing.T, operatorName string, operator nkeys.
 	return &ts
 }
 
+func (ts *TestStore) Reload(t *testing.T) {
+	s, err := store.LoadStore(ts.Store.Dir)
+	require.NoError(t, err)
+	if ts.Store == nil {
+		ts.Store = s
+	}
+	ctx, err := ts.Store.GetContext()
+	require.NoError(t, err, "getting context")
+
+	ts.KeyStore = ctx.KeyStore
+
+	GetConfig().SetDefaults()
+}
+
 func (ts *TestStore) AddOperator(t *testing.T, operatorName string) *store.Store {
 	_, _, kp := CreateOperatorKey(t)
 	return ts.AddOperatorWithKey(t, operatorName, kp)