diff --git a/actor/v7action/application.go b/actor/v7action/application.go index f22bff8903f..2f8428d5921 100644 --- a/actor/v7action/application.go +++ b/actor/v7action/application.go @@ -311,6 +311,11 @@ func (actor Actor) PollStartForRolling(app resources.Application, deploymentGUID for { select { case <-timeout: + warnings, err := actor.CancelDeployment(deploymentGUID) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return allWarnings, err + } return allWarnings, actionerror.StartupTimeoutError{Name: app.Name} case <-timer.C(): if !isDeployed(deployment) { diff --git a/actor/v7action/application_test.go b/actor/v7action/application_test.go index 01bb6862d49..2b5748db286 100644 --- a/actor/v7action/application_test.go +++ b/actor/v7action/application_test.go @@ -1160,9 +1160,13 @@ var _ = Describe("Application Actions", func() { ccv3.Warnings{"get-deployment-warning"}, nil, ) + fakeCloudControllerClient.CancelDeploymentReturns( + ccv3.Warnings{"cancel-deployment-warning"}, + nil, + ) }) - It("returns a timeout error and any warnings", func() { + It("returns a timeout error and any warnings and cancels the deployment", func() { // initial tick fakeClock.WaitForNWatchersAndIncrement(1*time.Millisecond, 2) @@ -1171,12 +1175,43 @@ var _ = Describe("Application Actions", func() { // timeout tick fakeClock.Increment(1 * time.Millisecond) + Eventually(fakeCloudControllerClient.CancelDeploymentCallCount).Should(Equal(1)) + // wait for func to finish Eventually(done).Should(Receive(BeTrue())) Expect(executeErr).To(MatchError(actionerror.StartupTimeoutError{})) - Expect(warnings).To(ConsistOf("get-deployment-warning")) + Expect(warnings).To(ConsistOf("get-deployment-warning", "cancel-deployment-warning")) + }) + + When("the cancel deployment fails", func() { + BeforeEach(func() { + fakeCloudControllerClient.CancelDeploymentReturns( + ccv3.Warnings{"cancel-deployment-warning"}, + errors.New("cancel-deployment-error"), + ) + }) + + It("returns a timeout error and any warnings and cancels the deployment", func() { + // initial tick + fakeClock.WaitForNWatchersAndIncrement(1*time.Millisecond, 2) + + Eventually(fakeCloudControllerClient.GetDeploymentCallCount).Should(Equal(1)) + + // timeout tick + fakeClock.Increment(1 * time.Millisecond) + + Eventually(fakeCloudControllerClient.CancelDeploymentCallCount).Should(Equal(1)) + + // wait for func to finish + Eventually(done).Should(Receive(BeTrue())) + + Expect(executeErr).To(MatchError("cancel-deployment-error")) + Expect(warnings).To(ConsistOf("get-deployment-warning", "cancel-deployment-warning")) + }) + }) + }) When("the processes dont become healthy", func() { diff --git a/integration/v7/push/rolling_push_test.go b/integration/v7/push/rolling_push_test.go index d8bc9ec56ba..1b4739e507c 100644 --- a/integration/v7/push/rolling_push_test.go +++ b/integration/v7/push/rolling_push_test.go @@ -1,6 +1,8 @@ package push import ( + "fmt" + "code.cloudfoundry.org/cli/integration/helpers" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" @@ -34,21 +36,21 @@ var _ = Describe("push with --strategy rolling", func() { PushCommandName, appName, "--strategy", "rolling", ) - Eventually(session).Should(Say(`Pushing app %s to org %s / space %s as %s\.\.\.`, appName, organization, space, userName)) - Eventually(session).Should(Say(`Packaging files to upload\.\.\.`)) - Eventually(session).Should(Say(`Uploading files\.\.\.`)) - Eventually(session).Should(Say(`100.00%`)) - Eventually(session).Should(Say(`Waiting for API to complete processing files\.\.\.`)) - Eventually(session).Should(Say(`Staging app and tracing logs\.\.\.`)) - Eventually(session).Should(Say(`Starting deployment for app %s\.\.\.`, appName)) - Eventually(session).Should(Say(`Waiting for app to deploy\.\.\.`)) - Eventually(session).Should(Say(`name:\s+%s`, appName)) - Eventually(session).Should(Say(`requested state:\s+started`)) - Eventually(session).Should(Say(`routes:\s+%s.%s`, appName, helpers.DefaultSharedDomain())) - Eventually(session).Should(Say(`type:\s+web`)) - Eventually(session).Should(Say(`start command:\s+%s`, helpers.StaticfileBuildpackStartCommand)) - Eventually(session).Should(Say(`#0\s+running`)) Eventually(session).Should(Exit(0)) + Expect(session).To(Say(`Pushing app %s to org %s / space %s as %s\.\.\.`, appName, organization, space, userName)) + Expect(session).To(Say(`Packaging files to upload\.\.\.`)) + Expect(session).To(Say(`Uploading files\.\.\.`)) + Expect(session).To(Say(`100.00%`)) + Expect(session).To(Say(`Waiting for API to complete processing files\.\.\.`)) + Expect(session).To(Say(`Staging app and tracing logs\.\.\.`)) + Expect(session).To(Say(`Starting deployment for app %s\.\.\.`, appName)) + Expect(session).To(Say(`Waiting for app to deploy\.\.\.`)) + Expect(session).To(Say(`name:\s+%s`, appName)) + Expect(session).To(Say(`requested state:\s+started`)) + Expect(session).To(Say(`routes:\s+%s.%s`, appName, helpers.DefaultSharedDomain())) + Expect(session).To(Say(`type:\s+web`)) + Expect(session).To(Say(`start command:\s+%s`, helpers.StaticfileBuildpackStartCommand)) + Expect(session).To(Say(`#0\s+running`)) }) }) }) @@ -100,19 +102,25 @@ var _ = Describe("push with --strategy rolling", func() { WorkingDirectory: appDir, EnvVars: map[string]string{"CF_STARTUP_TIMEOUT": "0.1"}, }, PushCommandName, appName, "--strategy", "rolling") - Eventually(session).Should(Say(`Pushing app %s to org %s / space %s as %s\.\.\.`, appName, organization, space, userName)) - Eventually(session).Should(Say(`Packaging files to upload\.\.\.`)) - Eventually(session).Should(Say(`Uploading files\.\.\.`)) - Eventually(session).Should(Say(`100.00%`)) - Eventually(session).Should(Say(`Waiting for API to complete processing files\.\.\.`)) - Eventually(session).Should(Say(`Staging app and tracing logs\.\.\.`)) - Eventually(session).Should(Say(`Starting deployment for app %s\.\.\.`, appName)) - Eventually(session).Should(Say(`Waiting for app to deploy\.\.\.`)) - Eventually(session).Should(Say(`FAILED`)) - Eventually(session.Err).Should(Say(`Start app timeout`)) - Eventually(session.Err).Should(Say(`TIP: Application must be listening on the right port\. Instead of hard coding the port, use the \$PORT environment variable\.`)) - Eventually(session.Err).Should(Say(`Use 'cf logs %s --recent' for more information`, appName)) Eventually(session).Should(Exit(1)) + Expect(session).To(Say(`Pushing app %s to org %s / space %s as %s\.\.\.`, appName, organization, space, userName)) + Expect(session).To(Say(`Packaging files to upload\.\.\.`)) + Expect(session).To(Say(`Uploading files\.\.\.`)) + Expect(session).To(Say(`100.00%`)) + Expect(session).To(Say(`Waiting for API to complete processing files\.\.\.`)) + Expect(session).To(Say(`Staging app and tracing logs\.\.\.`)) + Expect(session).To(Say(`Starting deployment for app %s\.\.\.`, appName)) + Expect(session).To(Say(`Waiting for app to deploy\.\.\.`)) + Expect(session).To(Say(`FAILED`)) + Expect(session.Err).To(Say(`Start app timeout`)) + Expect(session.Err).To(Say(`TIP: Application must be listening on the right port\. Instead of hard coding the port, use the \$PORT environment variable\.`)) + Expect(session.Err).To(Say(`Use 'cf logs %s --recent' for more information`, appName)) + appGUID := helpers.AppGUID(appName) + Eventually(func() *Buffer { + session_deployment := helpers.CF("curl", fmt.Sprintf("/v3/deployments?app_guids=%s", appGUID)) + Eventually(session_deployment).Should(Exit(0)) + return session_deployment.Out + }).Should(Say(`"reason":\s*"CANCELED"`)) }) }) })