diff --git a/command/v7/rollback_command.go b/command/v7/rollback_command.go index f01205837f..26a53efdf0 100644 --- a/command/v7/rollback_command.go +++ b/command/v7/rollback_command.go @@ -8,6 +8,7 @@ import ( "code.cloudfoundry.org/cli/cf/errors" "code.cloudfoundry.org/cli/command" "code.cloudfoundry.org/cli/command/flag" + "code.cloudfoundry.org/cli/command/translatableerror" "code.cloudfoundry.org/cli/command/v7/shared" ) @@ -19,6 +20,7 @@ type RollbackCommand struct { Version flag.Revision `long:"version" required:"true" description:"Roll back to the specified revision"` relatedCommands interface{} `related_commands:"revisions"` usage interface{} `usage:"CF_NAME rollback APP_NAME [--version VERSION] [-f]"` + MaxInFlight int `long:"max-in-flight" default:"-1" description:"Defines the maximum number of instances that will be actively being rolled back."` LogCacheClient sharedaction.LogCacheClient Stager shared.AppStager @@ -49,6 +51,11 @@ func (cmd RollbackCommand) Execute(args []string) error { return err } + err = cmd.ValidateFlags() + if err != nil { + return err + } + app, warnings, err := cmd.Actor.GetApplicationByNameAndSpace(cmd.RequiredArgs.AppName, cmd.Config.TargetedSpace().GUID) cmd.UI.DisplayWarnings(warnings) if err != nil { @@ -71,10 +78,6 @@ func (cmd RollbackCommand) Execute(args []string) error { return err } - if err != nil { - return err - } - // TODO Localization? if !cmd.Force { cmd.UI.DisplayTextWithFlavor("Rolling '{{.AppName}}' back to revision '{{.TargetRevision}}' will create a new revision. The new revision will use the settings from revision '{{.TargetRevision}}'.", map[string]interface{}{ @@ -107,9 +110,10 @@ func (cmd RollbackCommand) Execute(args []string) error { }) opts := shared.AppStartOpts{ - Strategy: constant.DeploymentStrategyRolling, - NoWait: false, - AppAction: constant.ApplicationRollingBack, + AppAction: constant.ApplicationRollingBack, + MaxInFlight: cmd.MaxInFlight, + NoWait: false, + Strategy: constant.DeploymentStrategyRolling, } startAppErr := cmd.Stager.StartApp(app, cmd.Config.TargetedSpace(), cmd.Config.TargetedOrganization(), revision.GUID, opts) @@ -121,3 +125,12 @@ func (cmd RollbackCommand) Execute(args []string) error { return nil } + +func (cmd RollbackCommand) ValidateFlags() error { + switch { + case cmd.MaxInFlight < 1: + return translatableerror.IncorrectUsageError{Message: "--max-in-flight must be greater than or equal to 1"} + } + + return nil +} diff --git a/command/v7/rollback_command_test.go b/command/v7/rollback_command_test.go index 59f1a6bec3..b644bf30f0 100644 --- a/command/v7/rollback_command_test.go +++ b/command/v7/rollback_command_test.go @@ -8,6 +8,7 @@ import ( "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant" "code.cloudfoundry.org/cli/command/commandfakes" "code.cloudfoundry.org/cli/command/flag" + "code.cloudfoundry.org/cli/command/translatableerror" v7 "code.cloudfoundry.org/cli/command/v7" "code.cloudfoundry.org/cli/command/v7/shared/sharedfakes" "code.cloudfoundry.org/cli/command/v7/v7fakes" @@ -76,6 +77,7 @@ var _ = Describe("rollback Command", func() { }, Stager: fakeAppStager, } + cmd.MaxInFlight = 5 }) JustBeforeEach(func() { @@ -219,6 +221,8 @@ var _ = Describe("rollback Command", func() { Expect(application.GUID).To(Equal("123")) Expect(revisionGUID).To(Equal("some-1-guid")) Expect(opts.AppAction).To(Equal(constant.ApplicationRollingBack)) + Expect(opts.Strategy).To(Equal(constant.DeploymentStrategyRolling)) + Expect(opts.MaxInFlight).To(Equal(5)) Expect(testUI.Out).To(Say("Rolling '%s' back to revision '1' will create a new revision. The new revision will use the settings from revision '1'.", app)) Expect(testUI.Out).To(Say("Are you sure you want to continue?")) @@ -265,4 +269,24 @@ var _ = Describe("rollback Command", func() { }) }) }) + + DescribeTable("ValidateFlags returns an error", + func(setup func(), expectedErr error) { + setup() + err := cmd.ValidateFlags() + if expectedErr == nil { + Expect(err).To(BeNil()) + } else { + Expect(err).To(MatchError(expectedErr)) + } + }, + + Entry("max-in-flight is smaller than 1", + func() { + cmd.MaxInFlight = 0 + }, + translatableerror.IncorrectUsageError{ + Message: "--max-in-flight must be greater than or equal to 1", + }), + ) }) diff --git a/integration/v7/isolated/rollback_command_test.go b/integration/v7/isolated/rollback_command_test.go index 7410f4d2b4..d5c5e4a5ce 100644 --- a/integration/v7/isolated/rollback_command_test.go +++ b/integration/v7/isolated/rollback_command_test.go @@ -36,6 +36,7 @@ var _ = Describe("rollback command", func() { Expect(session).To(Say("OPTIONS:")) Expect(session).To(Say("-f Force rollback without confirmation")) Expect(session).To(Say("--version Roll back to the specified revision")) + Expect(session).To(Say("--max-in-flight")) Expect(session).To(Say("SEE ALSO:")) Expect(session).To(Say("revisions")) }) @@ -112,7 +113,7 @@ applications: When("the -f flag is provided", func() { It("does not prompt the user, and just rolls back", func() { - session := helpers.CF("rollback", appName, "--version", "1", "-f") + session := helpers.CF("rollback", appName, "--version", "1", "-f", "--max-in-flight", "3") Eventually(session).Should(Exit(0)) Expect(session).To(HaveRollbackOutput(appName, orgName, spaceName, userName))