diff --git a/cmd/juju/commands/switch.go b/cmd/juju/commands/switch.go index cbfbb7a490d..ac844c18fc8 100644 --- a/cmd/juju/commands/switch.go +++ b/cmd/juju/commands/switch.go @@ -11,6 +11,7 @@ import ( "github.com/juju/errors" jujucmd "github.com/juju/juju/cmd" + "github.com/juju/juju/cmd/juju/common" "github.com/juju/juju/cmd/modelcmd" "github.com/juju/juju/juju/osenv" "github.com/juju/juju/jujuclient" @@ -37,8 +38,8 @@ var usageSummary = ` Selects or identifies the current controller and model.`[1:] var usageDetails = ` -When used without an argument, the command shows the current controller -and its active model. +When used without an argument, the command shows the current controller +and its active model. When a single argument without a colon is provided juju first looks for a controller by that name and switches to it, and if it's not found it tries to switch to a model within current controller. mycontroller: switches to @@ -55,7 +56,7 @@ Examples: juju switch mycontroller: juju switch :mymodel -See also: +See also: controllers models show-controller` @@ -92,7 +93,7 @@ func (c *switchCommand) Run(ctx *cmd.Context) (resultErr error) { return errors.Trace(err) } if currentName == "" { - return errors.New("no currently specified model") + return common.MissingModelNameError("switch") } fmt.Fprintf(ctx.Stdout, "%s\n", currentName) return nil diff --git a/cmd/juju/commands/switch_test.go b/cmd/juju/commands/switch_test.go index 30ade26474f..18f9694fdba 100644 --- a/cmd/juju/commands/switch_test.go +++ b/cmd/juju/commands/switch_test.go @@ -13,6 +13,7 @@ import ( jc "github.com/juju/testing/checkers" gc "gopkg.in/check.v1" + "github.com/juju/juju/cmd/juju/common" "github.com/juju/juju/cmd/modelcmd" _ "github.com/juju/juju/juju" "github.com/juju/juju/jujuclient" @@ -56,7 +57,7 @@ func (s *SwitchSimpleSuite) run(c *gc.C, args ...string) (*cmd.Context, error) { func (s *SwitchSimpleSuite) TestNoArgs(c *gc.C) { _, err := s.run(c) - c.Assert(err, gc.ErrorMatches, "no currently specified model") + c.Assert(err, gc.ErrorMatches, common.MissingModelNameError("switch").Error()) } func (s *SwitchSimpleSuite) TestNoArgsCurrentController(c *gc.C) { diff --git a/cmd/juju/common/errors.go b/cmd/juju/common/errors.go index e29ea4a1070..32cb048f281 100644 --- a/cmd/juju/common/errors.go +++ b/cmd/juju/common/errors.go @@ -58,3 +58,15 @@ func (e *TermsRequiredError) UserErr() error { return errors.Wrap(e, errors.Errorf(`Declined: some terms require agreement. Try: "juju agree %s"`, terms)) } + +const missingModelNameMessage = ` +juju: no model name was passed. See "juju %[1]s --help". + +Did you mean: + juju %[1]s ` + +// MissingModelNameError returns an error stating that the model name is missing +// and provides a better UX experience to the user. +func MissingModelNameError(cmdName string) error { + return errors.Errorf(missingModelNameMessage[1:], cmdName) +} diff --git a/cmd/juju/controller/addmodel.go b/cmd/juju/controller/addmodel.go index d847dbd80bb..f8e09b2b1b3 100644 --- a/cmd/juju/controller/addmodel.go +++ b/cmd/juju/controller/addmodel.go @@ -66,25 +66,25 @@ type addModelCommand struct { const addModelHelpDoc = ` Adding a model is typically done in order to run a specific workload. -To add a model, you must specify a model name. Model names can be duplicated -across controllers but must be unique per user for any given controller. -In other words, Alice and Bob can each have their own model called "secret" but +To add a model, you must specify a model name. Model names can be duplicated +across controllers but must be unique per user for any given controller. +In other words, Alice and Bob can each have their own model called "secret" but Alice can have only one model called "secret" in a controller. -Model names may only contain lowercase letters, digits and hyphens, and +Model names may only contain lowercase letters, digits and hyphens, and may not start with a hyphen. To add a model, Juju requires a credential: * if you have a default (or just one) credential defined at client (i.e. in credentials.yaml), then juju will use that; - * if you have no default (and multiple) credentials defined at the client, + * if you have no default (and multiple) credentials defined at the client, then you must specify one using --credential; - * as the admin user you can omit the credential, + * as the admin user you can omit the credential, and the credential used to bootstrap will be used. -To add a credential for add-model, use one of the "juju add-credential" or -"juju autoload-credentials" commands. These will add credentials -to the Juju client, which "juju add-model" will upload to the controller +To add a credential for add-model, use one of the "juju add-credential" or +"juju autoload-credentials" commands. These will add credentials +to the Juju client, which "juju add-model" will upload to the controller as necessary. You may also supply model-specific configuration as well as a @@ -94,7 +94,7 @@ are the ones used to create any future resources within the model. If no cloud/region is specified, then the model will be deployed to the same cloud/region as the controller model. If a region is specified without a cloud qualifier, then it is assumed to be in the same cloud -as the controller model. +as the controller model. Examples: @@ -124,7 +124,7 @@ func (c *addModelCommand) SetFlags(f *gnuflag.FlagSet) { func (c *addModelCommand) Init(args []string) error { if len(args) == 0 { - return errors.New("model name is required") + return common.MissingModelNameError("add-model") } c.Name, args = args[0], args[1:] diff --git a/cmd/juju/controller/addmodel_test.go b/cmd/juju/controller/addmodel_test.go index cd335a4d384..611508482d7 100644 --- a/cmd/juju/controller/addmodel_test.go +++ b/cmd/juju/controller/addmodel_test.go @@ -23,6 +23,7 @@ import ( "github.com/juju/juju/api/base" "github.com/juju/juju/apiserver/params" "github.com/juju/juju/cloud" + "github.com/juju/juju/cmd/juju/common" "github.com/juju/juju/cmd/juju/controller" "github.com/juju/juju/core/model" "github.com/juju/juju/environs" @@ -134,7 +135,7 @@ func (s *AddModelSuite) TestInit(c *gc.C) { values map[string]interface{} }{ { - err: "model name is required", + err: common.MissingModelNameError("add-model").Error(), }, { args: []string{"new-model"}, name: "new-model",