diff --git a/command/flag/arguments.go b/command/flag/arguments.go index f4141c58085..2ede06676f1 100644 --- a/command/flag/arguments.go +++ b/command/flag/arguments.go @@ -324,8 +324,8 @@ type ServiceBroker struct { type ServiceBrokerArgs struct { ServiceBroker string `positional-arg-name:"SERVICE_BROKER" required:"true" description:"The service broker name"` Username string `positional-arg-name:"USERNAME" required:"true" description:"The username"` - Password string `positional-arg-name:"PASSWORD" required:"true" description:"The password"` - URL string `positional-arg-name:"URL" required:"true" description:"The URL of the service broker"` + PasswordOrURL string `positional-arg-name:"URL" required:"true" description:"The URL of the service broker"` + URL string `positional-arg-name:"URL" description:"The URL of the service broker"` } type RenameServiceBrokerArgs struct { diff --git a/command/v7/create_service_broker_command.go b/command/v7/create_service_broker_command.go index 0fbd44c5f69..4dc85d466f8 100644 --- a/command/v7/create_service_broker_command.go +++ b/command/v7/create_service_broker_command.go @@ -1,6 +1,9 @@ package v7 import ( + "os" + + "code.cloudfoundry.org/cli/command" "code.cloudfoundry.org/cli/command/flag" "code.cloudfoundry.org/cli/resources" "code.cloudfoundry.org/cli/util/configv3" @@ -9,10 +12,11 @@ import ( type CreateServiceBrokerCommand struct { BaseCommand - RequiredArgs flag.ServiceBrokerArgs `positional-args:"yes"` + PositionalArgs flag.ServiceBrokerArgs `positional-args:"yes"` SpaceScoped bool `long:"space-scoped" description:"Make the broker's service plans only visible within the targeted space"` - usage interface{} `usage:"CF_NAME create-service-broker SERVICE_BROKER USERNAME PASSWORD URL [--space-scoped]"` - relatedCommands interface{} `related_commands:"enable-service-access, service-brokers, target"` + usage any `usage:"CF_NAME create-service-broker SERVICE_BROKER USERNAME PASSWORD URL [--space-scoped]\n CF_NAME create-service-broker SERVICE_BROKER USERNAME URL [--space-scoped] (omit password to specify interactively or via environment variable)\n\nWARNING:\n Providing your password as a command line option is highly discouraged\n Your password may be visible to others and may be recorded in your shell history"` + relatedCommands any `related_commands:"enable-service-access, service-brokers, target"` + envPassword any `environmentName:"CF_BROKER_PASSWORD" environmentDescription:"Password associated with user. Overridden if PASSWORD argument is provided" environmentDefault:"password"` } func (cmd *CreateServiceBrokerCommand) Execute(args []string) error { @@ -21,6 +25,11 @@ func (cmd *CreateServiceBrokerCommand) Execute(args []string) error { return err } + brokerName, username, password, url, err := promptUserForBrokerPasswordIfRequired(cmd.PositionalArgs, cmd.UI) + if err != nil { + return err + } + user, err := cmd.Actor.GetCurrentUser() if err != nil { return err @@ -31,9 +40,9 @@ func (cmd *CreateServiceBrokerCommand) Execute(args []string) error { space = cmd.Config.TargetedSpace() cmd.UI.DisplayTextWithFlavor( "Creating service broker {{.ServiceBroker}} in org {{.Org}} / space {{.Space}} as {{.Username}}...", - map[string]interface{}{ + map[string]any{ "Username": user.Name, - "ServiceBroker": cmd.RequiredArgs.ServiceBroker, + "ServiceBroker": brokerName, "Org": cmd.Config.TargetedOrganizationName(), "Space": space.Name, }, @@ -41,19 +50,19 @@ func (cmd *CreateServiceBrokerCommand) Execute(args []string) error { } else { cmd.UI.DisplayTextWithFlavor( "Creating service broker {{.ServiceBroker}} as {{.Username}}...", - map[string]interface{}{ + map[string]any{ "Username": user.Name, - "ServiceBroker": cmd.RequiredArgs.ServiceBroker, + "ServiceBroker": brokerName, }, ) } warnings, err := cmd.Actor.CreateServiceBroker( resources.ServiceBroker{ - Name: cmd.RequiredArgs.ServiceBroker, - Username: cmd.RequiredArgs.Username, - Password: cmd.RequiredArgs.Password, - URL: cmd.RequiredArgs.URL, + Name: brokerName, + Username: username, + Password: password, + URL: url, SpaceGUID: space.GUID, }, ) @@ -65,3 +74,20 @@ func (cmd *CreateServiceBrokerCommand) Execute(args []string) error { cmd.UI.DisplayOK() return nil } + +func promptUserForBrokerPasswordIfRequired(args flag.ServiceBrokerArgs, ui command.UI) (string, string, string, string, error) { + if args.URL != "" { + return args.ServiceBroker, args.Username, args.PasswordOrURL, args.URL, nil + } + + if password, ok := os.LookupEnv("CF_BROKER_PASSWORD"); ok { + return args.ServiceBroker, args.Username, password, args.PasswordOrURL, nil + } + + password, err := ui.DisplayPasswordPrompt("Service Broker Password") + if err != nil { + return "", "", "", "", err + } + + return args.ServiceBroker, args.Username, password, args.PasswordOrURL, nil +} diff --git a/command/v7/create_service_broker_command_test.go b/command/v7/create_service_broker_command_test.go index f19175c3779..22e7bb95525 100644 --- a/command/v7/create_service_broker_command_test.go +++ b/command/v7/create_service_broker_command_test.go @@ -2,6 +2,8 @@ package v7_test import ( "errors" + "fmt" + "os" "code.cloudfoundry.org/cli/actor/v7action" "code.cloudfoundry.org/cli/command/commandfakes" @@ -15,6 +17,15 @@ import ( ) var _ = Describe("create-service-broker Command", func() { + const ( + binaryName = "cf-command" + user = "steve" + serviceBrokerName = "fake-service-broker-name" + username = "fake-username" + password = "fake-password" + url = "fake-url" + ) + var ( cmd *v7.CreateServiceBrokerCommand testUI *ui.UI @@ -22,7 +33,6 @@ var _ = Describe("create-service-broker Command", func() { fakeSharedActor *commandfakes.FakeSharedActor fakeActor *v7fakes.FakeActor input *Buffer - binaryName string executeErr error ) @@ -34,7 +44,6 @@ var _ = Describe("create-service-broker Command", func() { fakeActor = new(v7fakes.FakeActor) fakeActor.CreateServiceBrokerReturns(v7action.Warnings{"some default warning"}, nil) - binaryName = "faceman" fakeConfig.BinaryNameReturns(binaryName) cmd = &v7.CreateServiceBrokerCommand{ @@ -45,8 +54,6 @@ var _ = Describe("create-service-broker Command", func() { Actor: fakeActor, }, } - - setPositionalFlags(cmd, "service-broker-name", "username", "password", "https://example.org/super-broker") }) JustBeforeEach(func() { @@ -66,6 +73,7 @@ var _ = Describe("create-service-broker Command", func() { When("fetching the current user fails", func() { BeforeEach(func() { fakeActor.GetCurrentUserReturns(configv3.User{}, errors.New("an error occurred")) + setPositionalFlags(cmd, serviceBrokerName, username, password, url) }) It("return an error", func() { @@ -75,7 +83,8 @@ var _ = Describe("create-service-broker Command", func() { When("fetching the current user succeeds", func() { BeforeEach(func() { - fakeActor.GetCurrentUserReturns(configv3.User{Name: "steve"}, nil) + fakeActor.GetCurrentUserReturns(configv3.User{Name: user}, nil) + setPositionalFlags(cmd, serviceBrokerName, username, password, url) }) It("checks that there is a valid target", func() { @@ -86,7 +95,7 @@ var _ = Describe("create-service-broker Command", func() { }) It("displays a message with the username", func() { - Expect(testUI.Out).To(Say(`Creating service broker %s as %s\.\.\.`, "service-broker-name", "steve")) + Expect(testUI.Out).To(Say(`Creating service broker %s as %s\.\.\.`, serviceBrokerName, user)) }) It("passes the data to the actor layer", func() { @@ -94,10 +103,10 @@ var _ = Describe("create-service-broker Command", func() { model := fakeActor.CreateServiceBrokerArgsForCall(0) - Expect(model.Name).To(Equal("service-broker-name")) - Expect(model.Username).To(Equal("username")) - Expect(model.Password).To(Equal("password")) - Expect(model.URL).To(Equal("https://example.org/super-broker")) + Expect(model.Name).To(Equal(serviceBrokerName)) + Expect(model.Username).To(Equal(username)) + Expect(model.Password).To(Equal(password)) + Expect(model.URL).To(Equal(url)) Expect(model.SpaceGUID).To(Equal("")) }) @@ -122,13 +131,19 @@ var _ = Describe("create-service-broker Command", func() { }) When("creating a space scoped broker", func() { + const ( + orgName = "fake-org-name" + spaceName = "fake-space-name" + spaceGUID = "fake-space-guid" + ) + BeforeEach(func() { cmd.SpaceScoped = true fakeConfig.TargetedSpaceReturns(configv3.Space{ - Name: "fake-space-name", - GUID: "fake-space-guid", + Name: spaceName, + GUID: spaceGUID, }) - fakeConfig.TargetedOrganizationNameReturns("fake-org-name") + fakeConfig.TargetedOrganizationNameReturns(orgName) }) It("checks that a space is targeted", func() { @@ -139,15 +154,75 @@ var _ = Describe("create-service-broker Command", func() { }) It("displays the space name in the message", func() { - Expect(testUI.Out).To(Say(`Creating service broker %s in org %s / space %s as %s\.\.\.`, "service-broker-name", "fake-org-name", "fake-space-name", "steve")) + Expect(testUI.Out).To(Say(`Creating service broker %s in org %s / space %s as %s\.\.\.`, serviceBrokerName, orgName, spaceName, user)) }) It("looks up the space guid and passes it to the actor", func() { Expect(fakeActor.CreateServiceBrokerCallCount()).To(Equal(1)) model := fakeActor.CreateServiceBrokerArgsForCall(0) - Expect(model.SpaceGUID).To(Equal("fake-space-guid")) + Expect(model.SpaceGUID).To(Equal(spaceGUID)) }) }) }) + + When("password is provided as environment variable", func() { + const ( + varName = "CF_BROKER_PASSWORD" + varPassword = "var-password" + ) + + BeforeEach(func() { + setPositionalFlags(cmd, serviceBrokerName, username, url, "") + os.Setenv(varName, varPassword) + }) + + AfterEach(func() { + os.Unsetenv(varName) + }) + + It("passes the data to the actor layer", func() { + Expect(fakeActor.CreateServiceBrokerCallCount()).To(Equal(1)) + + model := fakeActor.CreateServiceBrokerArgsForCall(0) + + Expect(model.Name).To(Equal(serviceBrokerName)) + Expect(model.Username).To(Equal(username)) + Expect(model.Password).To(Equal(varPassword)) + Expect(model.URL).To(Equal(url)) + Expect(model.SpaceGUID).To(Equal("")) + }) + }) + + When("password is provided via prompt", func() { + const promptPassword = "prompt-password" + + BeforeEach(func() { + setPositionalFlags(cmd, serviceBrokerName, username, url, "") + + _, err := input.Write([]byte(fmt.Sprintf("%s\n", promptPassword))) + Expect(err).NotTo(HaveOccurred()) + }) + + It("prompts the user for credentials", func() { + Expect(testUI.Out).To(Say("Service Broker Password: ")) + }) + + It("does not echo the credentials", func() { + Expect(testUI.Out).NotTo(Say(promptPassword)) + Expect(testUI.Err).NotTo(Say(promptPassword)) + }) + + It("passes the data to the actor layer", func() { + Expect(fakeActor.CreateServiceBrokerCallCount()).To(Equal(1)) + + model := fakeActor.CreateServiceBrokerArgsForCall(0) + + Expect(model.Name).To(Equal(serviceBrokerName)) + Expect(model.Username).To(Equal(username)) + Expect(model.Password).To(Equal(promptPassword)) + Expect(model.URL).To(Equal(url)) + Expect(model.SpaceGUID).To(Equal("")) + }) + }) }) diff --git a/command/v7/create_user_provided_service_command.go b/command/v7/create_user_provided_service_command.go index c0cc5e5083b..fbe7a412bda 100644 --- a/command/v7/create_user_provided_service_command.go +++ b/command/v7/create_user_provided_service_command.go @@ -24,7 +24,7 @@ func (cmd CreateUserProvidedServiceCommand) Execute(args []string) error { return err } - if err := PromptUserForCredentialsIfRequired(&cmd.Credentials, cmd.UI); err != nil { + if err := promptUserForCredentialsIfRequired(&cmd.Credentials, cmd.UI); err != nil { return err } @@ -69,7 +69,7 @@ func (cmd CreateUserProvidedServiceCommand) displayMessage() error { return nil } -func PromptUserForCredentialsIfRequired(flag *flag.CredentialsOrJSON, ui command.UI) error { +func promptUserForCredentialsIfRequired(flag *flag.CredentialsOrJSON, ui command.UI) error { if len(flag.UserPromptCredentials) > 0 { flag.Value = make(map[string]interface{}) diff --git a/command/v7/update_service_broker_command.go b/command/v7/update_service_broker_command.go index 8380755d656..245d7c90310 100644 --- a/command/v7/update_service_broker_command.go +++ b/command/v7/update_service_broker_command.go @@ -8,9 +8,10 @@ import ( type UpdateServiceBrokerCommand struct { BaseCommand - RequiredArgs flag.ServiceBrokerArgs `positional-args:"yes"` - usage interface{} `usage:"CF_NAME update-service-broker SERVICE_BROKER USERNAME PASSWORD URL"` - relatedCommands interface{} `related_commands:"rename-service-broker, service-brokers"` + PositionalArgs flag.ServiceBrokerArgs `positional-args:"yes"` + usage any `usage:"CF_NAME update-service-broker SERVICE_BROKER USERNAME PASSWORD URL\n CF_NAME update-service-broker SERVICE_BROKER USERNAME URL (omit password to specify interactively or via environment variable)\n\nWARNING:\n Providing your password as a command line option is highly discouraged\n Your password may be visible to others and may be recorded in your shell history"` + relatedCommands any `related_commands:"rename-service-broker, service-brokers"` + envPassword any `environmentName:"CF_BROKER_PASSWORD" environmentDescription:"Password associated with user. Overridden if PASSWORD argument is provided" environmentDefault:"password"` } func (cmd UpdateServiceBrokerCommand) Execute(args []string) error { @@ -18,7 +19,12 @@ func (cmd UpdateServiceBrokerCommand) Execute(args []string) error { return err } - serviceBroker, warnings, err := cmd.Actor.GetServiceBrokerByName(cmd.RequiredArgs.ServiceBroker) + brokerName, username, password, url, err := promptUserForBrokerPasswordIfRequired(cmd.PositionalArgs, cmd.UI) + if err != nil { + return err + } + + serviceBroker, warnings, err := cmd.Actor.GetServiceBrokerByName(brokerName) cmd.UI.DisplayWarnings(warnings) if err != nil { return err @@ -31,18 +37,18 @@ func (cmd UpdateServiceBrokerCommand) Execute(args []string) error { cmd.UI.DisplayTextWithFlavor( "Updating service broker {{.ServiceBroker}} as {{.Username}}...", - map[string]interface{}{ + map[string]any{ "Username": user.Name, - "ServiceBroker": cmd.RequiredArgs.ServiceBroker, + "ServiceBroker": brokerName, }, ) warnings, err = cmd.Actor.UpdateServiceBroker( serviceBroker.GUID, resources.ServiceBroker{ - Username: cmd.RequiredArgs.Username, - Password: cmd.RequiredArgs.Password, - URL: cmd.RequiredArgs.URL, + Username: username, + Password: password, + URL: url, }, ) cmd.UI.DisplayWarnings(warnings) diff --git a/command/v7/update_service_broker_command_test.go b/command/v7/update_service_broker_command_test.go index d3a2b658bc4..f2915c4204c 100644 --- a/command/v7/update_service_broker_command_test.go +++ b/command/v7/update_service_broker_command_test.go @@ -1,6 +1,9 @@ package v7_test import ( + "fmt" + "os" + "code.cloudfoundry.org/cli/actor/actionerror" "code.cloudfoundry.org/cli/actor/v7action" "code.cloudfoundry.org/cli/cf/errors" @@ -29,13 +32,15 @@ var _ = Describe("update-service-broker command", func() { fakeUpdateServiceBrokerActor *v7fakes.FakeActor fakeSharedActor *commandfakes.FakeSharedActor fakeConfig *commandfakes.FakeConfig + input *Buffer testUI *ui.UI ) BeforeEach(func() { fakeUpdateServiceBrokerActor = &v7fakes.FakeActor{} fakeSharedActor = &commandfakes.FakeSharedActor{} - testUI = ui.NewTestUI(NewBuffer(), NewBuffer(), NewBuffer()) + input = NewBuffer() + testUI = ui.NewTestUI(input, NewBuffer(), NewBuffer()) fakeConfig = &commandfakes.FakeConfig{} cmd = &v7.UpdateServiceBrokerCommand{ BaseCommand: v7.BaseCommand{ @@ -45,8 +50,6 @@ var _ = Describe("update-service-broker command", func() { Config: fakeConfig, }, } - - setPositionalFlags(cmd, serviceBrokerName, username, password, url) }) When("logged in", func() { @@ -60,6 +63,8 @@ var _ = Describe("update-service-broker command", func() { ) fakeUpdateServiceBrokerActor.GetCurrentUserReturns(configv3.User{Name: "user"}, nil) + + setPositionalFlags(cmd, serviceBrokerName, username, password, url) }) It("succeeds", func() { @@ -123,6 +128,64 @@ var _ = Describe("update-service-broker command", func() { Expect(err).To(MatchError("no user found")) }) }) + + When("password is provided as environment variable", func() { + const ( + varName = "CF_BROKER_PASSWORD" + varPassword = "var-password" + ) + + BeforeEach(func() { + setPositionalFlags(cmd, serviceBrokerName, username, url, "") + os.Setenv(varName, varPassword) + + Expect(cmd.Execute(nil)).To(Succeed()) + }) + + AfterEach(func() { + os.Unsetenv(varName) + }) + + It("passes the data to the actor layer", func() { + Expect(fakeUpdateServiceBrokerActor.UpdateServiceBrokerCallCount()).To(Equal(1)) + serviceBrokerGUID, model := fakeUpdateServiceBrokerActor.UpdateServiceBrokerArgsForCall(0) + Expect(serviceBrokerGUID).To(Equal(guid)) + Expect(model.Username).To(Equal(username)) + Expect(model.Password).To(Equal(varPassword)) + Expect(model.URL).To(Equal(url)) + }) + }) + + When("password is provided via prompt", func() { + const promptPassword = "prompt-password" + + BeforeEach(func() { + setPositionalFlags(cmd, serviceBrokerName, username, url, "") + + _, err := input.Write([]byte(fmt.Sprintf("%s\n", promptPassword))) + Expect(err).NotTo(HaveOccurred()) + + Expect(cmd.Execute(nil)).To(Succeed()) + }) + + It("prompts the user for credentials", func() { + Expect(testUI.Out).To(Say("Service Broker Password: ")) + }) + + It("does not echo the credentials", func() { + Expect(testUI.Out).NotTo(Say(promptPassword)) + Expect(testUI.Err).NotTo(Say(promptPassword)) + }) + + It("passes the data to the actor layer", func() { + Expect(fakeUpdateServiceBrokerActor.UpdateServiceBrokerCallCount()).To(Equal(1)) + serviceBrokerGUID, model := fakeUpdateServiceBrokerActor.UpdateServiceBrokerArgsForCall(0) + Expect(serviceBrokerGUID).To(Equal(guid)) + Expect(model.Username).To(Equal(username)) + Expect(model.Password).To(Equal(promptPassword)) + Expect(model.URL).To(Equal(url)) + }) + }) }) When("not logged in", func() { diff --git a/command/v7/update_user_provided_service_command.go b/command/v7/update_user_provided_service_command.go index 71b9eb1a6e4..69184d166e9 100644 --- a/command/v7/update_user_provided_service_command.go +++ b/command/v7/update_user_provided_service_command.go @@ -25,7 +25,7 @@ func (cmd *UpdateUserProvidedServiceCommand) Execute(args []string) error { return err } - if err := PromptUserForCredentialsIfRequired(&cmd.Credentials, cmd.UI); err != nil { + if err := promptUserForCredentialsIfRequired(&cmd.Credentials, cmd.UI); err != nil { return err } diff --git a/integration/v7/isolated/create_service_broker_command_test.go b/integration/v7/isolated/create_service_broker_command_test.go index 7c5faf3e1e5..91dac36c09f 100644 --- a/integration/v7/isolated/create_service_broker_command_test.go +++ b/integration/v7/isolated/create_service_broker_command_test.go @@ -28,22 +28,9 @@ var _ = Describe("create-service-broker command", func() { When("--help flag is set", func() { It("displays command usage to output", func() { session := helpers.CF("create-service-broker", "--help") - Eventually(session).Should(Say("NAME:")) - Eventually(session).Should(Say("\\s+create-service-broker - Create a service broker")) - - Eventually(session).Should(Say("USAGE:")) - Eventually(session).Should(Say("\\s+cf create-service-broker SERVICE_BROKER USERNAME PASSWORD URL \\[--space-scoped\\]")) - - Eventually(session).Should(Say("ALIAS:")) - Eventually(session).Should(Say("\\s+csb")) - - Eventually(session).Should(Say("OPTIONS:")) - Eventually(session).Should(Say("\\s+--space-scoped Make the broker's service plans only visible within the targeted space")) - - Eventually(session).Should(Say("SEE ALSO:")) - Eventually(session).Should(Say("\\s+enable-service-access, service-brokers, target")) - Eventually(session).Should(Exit(0)) + + expectToRenderCreateServiceBrokerHelp(session) }) }) }) @@ -185,24 +172,36 @@ var _ = Describe("create-service-broker command", func() { When("no arguments are provided", func() { It("displays an error, naming each of the missing args and the help text", func() { session := helpers.CF("create-service-broker") - Eventually(session.Err).Should(Say("Incorrect Usage: the required arguments `SERVICE_BROKER`, `USERNAME`, `PASSWORD` and `URL` were not provided")) + Eventually(session).Should(Exit(1)) + + expectToRenderCreateServiceBrokerHelp(session) + }) + }) +}) - Eventually(session).Should(Say("NAME:")) - Eventually(session).Should(Say("\\s+create-service-broker - Create a service broker")) +func expectToRenderCreateServiceBrokerHelp(s *Session) { + Expect(s).To(SatisfyAll( + Say(`NAME:`), + Say(`\s+create-service-broker - Create a service broker`), - Eventually(session).Should(Say("USAGE:")) - Eventually(session).Should(Say("\\s+cf create-service-broker SERVICE_BROKER USERNAME PASSWORD URL \\[--space-scoped\\]")) + Say(`USAGE:`), + Say(`\s+cf create-service-broker SERVICE_BROKER USERNAME PASSWORD URL \[--space-scoped\]`), + Say(`\s+cf create-service-broker SERVICE_BROKER USERNAME URL \[--space-scoped\]`), - Eventually(session).Should(Say("ALIAS:")) - Eventually(session).Should(Say("\\s+csb")) + Say(`WARNING:`), + Say(`\s+Providing your password as a command line option is highly discouraged`), + Say(`\s+Your password may be visible to others and may be recorded in your shell history`), - Eventually(session).Should(Say("OPTIONS:")) - Eventually(session).Should(Say("\\s+--space-scoped Make the broker's service plans only visible within the targeted space")) + Say(`ALIAS:`), + Say(`\s+csb`), - Eventually(session).Should(Say("SEE ALSO:")) - Eventually(session).Should(Say("\\s+enable-service-access, service-brokers, target")) + Say(`OPTIONS:`), + Say(`\s+--space-scoped Make the broker's service plans only visible within the targeted space`), - Eventually(session).Should(Exit(1)) - }) - }) -}) + Say(`ENVIRONMENT:`), + Say(`\s+CF_BROKER_PASSWORD=password\s+Password associated with user. Overridden if PASSWORD argument is provided`), + + Say(`SEE ALSO:`), + Say(`\s+enable-service-access, service-brokers, target`), + )) +} diff --git a/integration/v7/isolated/update_service_broker_command_test.go b/integration/v7/isolated/update_service_broker_command_test.go index 46933da5992..0b0d654a5c3 100644 --- a/integration/v7/isolated/update_service_broker_command_test.go +++ b/integration/v7/isolated/update_service_broker_command_test.go @@ -141,10 +141,10 @@ var _ = Describe("update-service-broker command", func() { When("passing incorrect parameters", func() { It("prints an error message", func() { session := helpers.CF("update-service-broker", "b1") - - Eventually(session.Err).Should(Say("Incorrect Usage: the required arguments `USERNAME`, `PASSWORD` and `URL` were not provided")) - eventuallyRendersUpdateServiceBrokerHelp(session) Eventually(session).Should(Exit(1)) + + Expect(session.Err).To(Say("Incorrect Usage: the required arguments `USERNAME` and `URL` were not provided")) + expectToRenderUpdateServiceBrokerHelp(session) }) }) @@ -157,18 +157,26 @@ var _ = Describe("update-service-broker command", func() { When("passing --help", func() { It("displays command usage to output", func() { session := helpers.CF("update-service-broker", "--help") - - eventuallyRendersUpdateServiceBrokerHelp(session) Eventually(session).Should(Exit(0)) + + expectToRenderUpdateServiceBrokerHelp(session) }) }) }) -func eventuallyRendersUpdateServiceBrokerHelp(s *Session) { - Eventually(s).Should(Say("NAME:")) - Eventually(s).Should(Say("update-service-broker - Update a service broker")) - Eventually(s).Should(Say("USAGE:")) - Eventually(s).Should(Say("cf update-service-broker SERVICE_BROKER USERNAME PASSWORD URL")) - Eventually(s).Should(Say("SEE ALSO:")) - Eventually(s).Should(Say("rename-service-broker, service-brokers")) +func expectToRenderUpdateServiceBrokerHelp(s *Session) { + Expect(s).To(SatisfyAll( + Say("NAME:"), + Say("update-service-broker - Update a service broker"), + Say("USAGE:"), + Say("cf update-service-broker SERVICE_BROKER USERNAME PASSWORD URL"), + Say("cf update-service-broker SERVICE_BROKER USERNAME URL"), + Say(`WARNING:`), + Say(`\s+Providing your password as a command line option is highly discouraged`), + Say(`\s+Your password may be visible to others and may be recorded in your shell history`), + Say(`ENVIRONMENT:`), + Say(`\s+CF_BROKER_PASSWORD=password\s+Password associated with user. Overridden if PASSWORD argument is provided`), + Say("SEE ALSO:"), + Say("rename-service-broker, service-brokers"), + )) }