Skip to content

Commit

Permalink
Display deployment status
Browse files Browse the repository at this point in the history
Co-authored-by: Michael Chinigo <[email protected]>
  • Loading branch information
gururajsh and chinigo committed Jul 22, 2024
1 parent 7f10007 commit 8620013
Show file tree
Hide file tree
Showing 9 changed files with 265 additions and 5 deletions.
6 changes: 6 additions & 0 deletions .github/ops-files/replace-redis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
- type: replace
path: /instance_groups/name=api/jobs/name=redis?
value:
name: valkey
release: capi
1 change: 1 addition & 0 deletions .github/workflows/tests-integration-reusable.yml
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ jobs:
bosh -d cf manifest > /tmp/manifest.yml
bosh interpolate /tmp/manifest.yml \
-o .github/ops-files/use-cflinuxfs3.yml \
-o .github/ops-files/replace-redis.yml \
-o cf-deployment/operations/use-internal-lookup-for-route-services.yml \
-o cf-deployment/operations/add-persistent-isolation-segment-diego-cell.yml \
-o cli-ci/ci/infrastructure/operations/use-latest-capi.yml \
Expand Down
22 changes: 22 additions & 0 deletions actor/v7action/application_summary.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ type ApplicationSummary struct {
type DetailedApplicationSummary struct {
ApplicationSummary
CurrentDroplet resources.Droplet
Deployment resources.Deployment
}

func (a ApplicationSummary) GetIsolationSegmentName() (string, bool) {
Expand Down Expand Up @@ -120,6 +121,12 @@ func (actor Actor) GetDetailedAppSummary(appName, spaceGUID string, withObfuscat
return DetailedApplicationSummary{}, allWarnings, err
}

detailedSummary, warnings, err = actor.addDeployment(detailedSummary)
allWarnings = append(allWarnings, warnings...)
if err != nil {
return DetailedApplicationSummary{}, allWarnings, err
}

return detailedSummary, allWarnings, err
}

Expand Down Expand Up @@ -206,6 +213,21 @@ func (actor Actor) addDroplet(summary ApplicationSummary) (DetailedApplicationSu
}, allWarnings, nil
}

func (actor Actor) addDeployment(detailedSummary DetailedApplicationSummary) (DetailedApplicationSummary, Warnings, error) {
var allWarnings Warnings

deployment, warnings, err := actor.GetLatestActiveDeploymentForApp(detailedSummary.GUID)
allWarnings = append(allWarnings, warnings...)
if err != nil {
if _, ok := err.(actionerror.ActiveDeploymentNotFoundError); !ok {
return DetailedApplicationSummary{}, allWarnings, err
}
}

detailedSummary.Deployment = deployment
return detailedSummary, allWarnings, nil
}

func toAppGUIDs(apps []resources.Application) []string {
guids := make([]string, len(apps))

Expand Down
114 changes: 111 additions & 3 deletions actor/v7action/application_summary_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"errors"
"fmt"

"code.cloudfoundry.org/cli/actor/v7action"
. "code.cloudfoundry.org/cli/actor/v7action"
"code.cloudfoundry.org/cli/actor/v7action/v7actionfakes"
"code.cloudfoundry.org/cli/api/cloudcontroller/ccerror"
Expand Down Expand Up @@ -574,6 +573,115 @@ var _ = Describe("Application Summary Actions", func() {
)
})

When("getting application deployment succeeds", func() {
When("the deployment is active", func() {
When("the deployment strategy is rolling", func() {
When("the deployment is in progress", func() {
BeforeEach(func() {
fakeCloudControllerClient.GetDeploymentsReturns(
[]resources.Deployment{
{
GUID: "some-deployment-guid",
Strategy: "rolling",
StatusValue: "ACTIVE",
StatusReason: "DEPLOYING",
},
},
nil,
nil,
)
})
It("returns the deployment information", func() {
Expect(summary.Deployment).To(Equal(resources.Deployment{
GUID: "some-deployment-guid",
Strategy: "rolling",
StatusValue: "ACTIVE",
StatusReason: "DEPLOYING",
}))
})
})

When("the deployment is canceled", func() {
When("the deployment is in progress", func() {
BeforeEach(func() {
fakeCloudControllerClient.GetDeploymentsReturns(
[]resources.Deployment{
{
GUID: "some-deployment-guid",
Strategy: "rolling",
StatusValue: "ACTIVE",
StatusReason: "CANCELLING",
},
},
nil,
nil,
)
})
It("returns the deployment information", func() {
Expect(summary.Deployment).To(Equal(resources.Deployment{
GUID: "some-deployment-guid",
Strategy: "rolling",
StatusValue: "ACTIVE",
StatusReason: "CANCELLING",
}))
})
})
})
})
})

When("the deployment is finalized", func() {
BeforeEach(func() {
fakeCloudControllerClient.GetDeploymentsReturns(
[]resources.Deployment{
{
GUID: "",
Strategy: "",
StatusValue: "",
StatusReason: "",
},
},
nil,
nil,
)
})
It("returns no deployment information", func() {
Expect(summary.Deployment).To(Equal(resources.Deployment{
GUID: "",
Strategy: "",
StatusValue: "",
StatusReason: "",
}))
})
})
})

When("getting application deployment fails", func() {
BeforeEach(func() {
fakeCloudControllerClient.GetDeploymentsReturns(
nil,
ccv3.Warnings{"get-deployments-warning"},
errors.New("some-error"),
)
})

It("returns the warnings and error", func() {
Expect(executeErr).To(MatchError("some-error"))
Expect(warnings).To(ConsistOf(
"get-apps-warning",
"get-app-processes-warning",
"get-process-by-type-warning",
"get-process-sidecars-warning",
"get-process-instances-warning",
"get-process-by-type-warning",
"get-process-sidecars-warning",
"get-process-instances-warning",
"get-app-droplet-warning",
"get-deployments-warning",
))
})
})

When("getting application routes succeeds", func() {
BeforeEach(func() {
fakeCloudControllerClient.GetApplicationRoutesReturns(
Expand All @@ -589,7 +697,7 @@ var _ = Describe("Application Summary Actions", func() {
It("returns the summary and warnings with droplet information", func() {
Expect(executeErr).ToNot(HaveOccurred())
Expect(summary).To(Equal(DetailedApplicationSummary{
ApplicationSummary: v7action.ApplicationSummary{
ApplicationSummary: ApplicationSummary{
Application: resources.Application{
Name: "some-app-name",
GUID: "some-app-guid",
Expand Down Expand Up @@ -733,7 +841,7 @@ var _ = Describe("Application Summary Actions", func() {
It("returns the summary and warnings without droplet information", func() {
Expect(executeErr).ToNot(HaveOccurred())
Expect(summary).To(Equal(DetailedApplicationSummary{
ApplicationSummary: v7action.ApplicationSummary{
ApplicationSummary: ApplicationSummary{
Application: resources.Application{
Name: "some-app-name",
GUID: "some-app-guid",
Expand Down
6 changes: 6 additions & 0 deletions api/cloudcontroller/ccv3/constant/deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ const (
type DeploymentStatusReason string

const (
// DeploymentStatusReasonDeploying means the deployment is in state 'DEPLOYING'
DeploymentStatusReasonDeploying DeploymentStatusReason = "DEPLOYING"

// DeploymentCanceled means the deployment is in state 'CANCELING'
DeploymentStatusReasonCanceling DeploymentStatusReason = "CANCELING"

// DeploymentStatusReasonDeployed means the deployment's status.value is
// 'DEPLOYED'
DeploymentStatusReasonDeployed DeploymentStatusReason = "DEPLOYED"
Expand Down
8 changes: 8 additions & 0 deletions command/v7/shared/app_summary_displayer.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import (
"code.cloudfoundry.org/cli/resources"
"code.cloudfoundry.org/cli/util/ui"
log "github.com/sirupsen/logrus"
"golang.org/x/text/cases"
"golang.org/x/text/language"
)

type AppSummaryDisplayer struct {
Expand Down Expand Up @@ -156,6 +158,12 @@ func (display AppSummaryDisplayer) displayProcessTable(summary v7action.Detailed
}
display.displayAppInstancesTable(process)
}

if summary.Deployment.StatusValue == constant.DeploymentStatusValueActive {
display.UI.DisplayText(fmt.Sprintf("%s deployment currently %s",
cases.Title(language.English, cases.NoLower).String(string(summary.Deployment.Strategy)),
summary.Deployment.StatusReason))
}
}

func (display AppSummaryDisplayer) getCreatedTime(summary v7action.DetailedApplicationSummary) string {
Expand Down
57 changes: 57 additions & 0 deletions command/v7/shared/app_summary_displayer_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package shared_test

import (
"fmt"
"time"

"code.cloudfoundry.org/cli/actor/v7action"
Expand All @@ -13,6 +14,8 @@ import (
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
. "github.com/onsi/gomega/gbytes"
"golang.org/x/text/cases"
"golang.org/x/text/language"
)

var _ = Describe("app summary displayer", func() {
Expand Down Expand Up @@ -691,5 +694,59 @@ var _ = Describe("app summary displayer", func() {
Expect(testUI.Out).To(Say(`some-buildpack`))
})
})

When("there is an active deployment", func() {
When("the deployment strategy is rolling", func() {
When("the deployment is in progress", func() {
BeforeEach(func() {
summary = v7action.DetailedApplicationSummary{
Deployment: resources.Deployment{
Strategy: constant.DeploymentStrategyRolling,
StatusValue: constant.DeploymentStatusValueActive,
StatusReason: constant.DeploymentStatusReasonDeploying,
},
}
})

It("displays the message", func() {
Expect(testUI.Out).To(Say("Rolling deployment currently DEPLOYING"))
})
})

When("the deployment is cancelled", func() {
BeforeEach(func() {
summary = v7action.DetailedApplicationSummary{
Deployment: resources.Deployment{
Strategy: constant.DeploymentStrategyRolling,
StatusValue: constant.DeploymentStatusValueActive,
StatusReason: constant.DeploymentStatusReasonCanceling,
},
}
})

It("displays the message", func() {
Expect(testUI.Out).To(Say("Rolling deployment currently CANCELING"))
})
})
})
})

When("there is no active deployment", func() {
BeforeEach(func() {
summary = v7action.DetailedApplicationSummary{
Deployment: resources.Deployment{
Strategy: "",
StatusValue: "",
StatusReason: "",
},
}
})

It("does not display deployment info", func() {
Expect(testUI.Out).NotTo(Say(fmt.Sprintf("%s deployment currently %s",
cases.Title(language.English, cases.NoLower).String(string(summary.Deployment.Strategy)),
summary.Deployment.StatusReason)))
})
})
})
})
48 changes: 48 additions & 0 deletions integration/v7/isolated/app_command_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"os"
"path"
"path/filepath"
"time"

. "code.cloudfoundry.org/cli/cf/util/testhelpers/matchers"
"code.cloudfoundry.org/cli/integration/helpers"
Expand Down Expand Up @@ -253,6 +254,53 @@ applications:
Eventually(session).Should(Exit(0))
})
})

When("there is an active deployment", func() {
BeforeEach(func() {
helpers.WithHelloWorldApp(func(appDir string) {
Eventually(helpers.CF("push", appName, "-p", appDir, "-b", "staticfile_buildpack")).Should(Exit(0))
})
})

When("the deployment strategy is rolling", func() {
When("the deployment is in progress", func() {
It("displays the message", func() {
session := helpers.CF("restart", appName, "--strategy", "rolling")

session1 := helpers.CF("app", appName)
Eventually(session1).Should(Say("Rolling deployment currently DEPLOYING"))
Eventually(session).Should(Exit(0))
Eventually(session1).Should(Exit(0))
})
})
When("the deployment is cancelled", func() {
It("displays the message", func() {
helpers.CF("restart", appName, "--strategy", "rolling")
time.Sleep(3 * time.Second)
session1 := helpers.CF("cancel-deployment", appName)
Eventually(session1).Should(Exit(0))

session2 := helpers.CF("app", appName)
Eventually(session2).Should(Say("Rolling deployment currently CANCELING"))
Eventually(session2).Should(Exit(0))
})
})
})
})

When("there is no active deployment", func() {
BeforeEach(func() {
helpers.WithHelloWorldApp(func(appDir string) {
Eventually(helpers.CF("push", appName, "-p", appDir, "-b", "staticfile_buildpack")).Should(Exit(0))
})
})

It("doesn not display the message", func() {
session := helpers.CF("app", appName)
Eventually(session).Should(Exit(0))
Eventually(session).ShouldNot(Say(`\w+ deployment currently \w+`))
})
})
})

Describe("version independent display", func() {
Expand Down
Loading

0 comments on commit 8620013

Please sign in to comment.