Skip to content

Commit

Permalink
Canary Deployment Changes (#3051)
Browse files Browse the repository at this point in the history
Introduce canary strategy on all the commands

Co-authored-by: João Pereira <joaod@vmware.com>
  • Loading branch information
gururajsh and joaopapereira committed Aug 7, 2024
1 parent 7cf2e17 commit dceca07
Show file tree
Hide file tree
Showing 52 changed files with 2,894 additions and 1,471 deletions.
17 changes: 11 additions & 6 deletions actor/v7action/application.go
Original file line number Diff line number Diff line change
Expand Up @@ -298,9 +298,9 @@ func (actor Actor) PollStart(app resources.Application, noWait bool, handleInsta
}
}

// PollStartForRolling polls a deploying application's processes until some are started. It does the same thing as PollStart, except it accounts for rolling deployments and whether
// PollStartForDeployment polls a deploying application's processes until some are started. It does the same thing as PollStart, except it accounts for rolling/canary deployments and whether
// they have failed or been canceled during polling.
func (actor Actor) PollStartForRolling(app resources.Application, deploymentGUID string, noWait bool, handleInstanceDetails func(string)) (Warnings, error) {
func (actor Actor) PollStartForDeployment(app resources.Application, deploymentGUID string, noWait bool, handleInstanceDetails func(string)) (Warnings, error) {
var (
deployment resources.Deployment
processes []resources.Process
Expand All @@ -321,7 +321,7 @@ func (actor Actor) PollStartForRolling(app resources.Application, deploymentGUID
}
return allWarnings, actionerror.StartupTimeoutError{Name: app.Name}
case <-timer.C():
if !isDeployed(deployment) {
if !isDeployProcessed(deployment) {
ccDeployment, warnings, err := actor.getDeployment(deploymentGUID)
allWarnings = append(allWarnings, warnings...)
if err != nil {
Expand All @@ -335,7 +335,7 @@ func (actor Actor) PollStartForRolling(app resources.Application, deploymentGUID
}
}

if noWait || isDeployed(deployment) {
if noWait || isDeployProcessed(deployment) {
stopPolling, warnings, err := actor.PollProcesses(processes, handleInstanceDetails)
allWarnings = append(allWarnings, warnings...)
if stopPolling || err != nil {
Expand All @@ -348,7 +348,12 @@ func (actor Actor) PollStartForRolling(app resources.Application, deploymentGUID
}
}

func isDeployed(d resources.Deployment) bool {
func isDeployProcessed(d resources.Deployment) bool {
if d.Strategy == constant.DeploymentStrategyCanary {
return d.StatusValue == constant.DeploymentStatusValueActive && d.StatusReason == constant.DeploymentStatusReasonPaused ||
d.StatusValue == constant.DeploymentStatusValueFinalized && d.StatusReason == constant.DeploymentStatusReasonDeployed
}

return d.StatusValue == constant.DeploymentStatusValueFinalized && d.StatusReason == constant.DeploymentStatusReasonDeployed
}

Expand Down Expand Up @@ -439,7 +444,7 @@ func (actor Actor) getProcesses(deployment resources.Deployment, appGUID string,

// if the deployment is deployed we know web are all running and PollProcesses will see those as stable
// so just getting all processes is equivalent to just getting non-web ones and polling those
if isDeployed(deployment) {
if isDeployProcessed(deployment) {
processes, warnings, err := actor.CloudControllerClient.GetApplicationProcesses(appGUID)
if err != nil {
return processes, Warnings(warnings), err
Expand Down
136 changes: 136 additions & 0 deletions actor/v7action/application_summary_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -574,6 +574,142 @@ 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 strategy is canary", func() {
When("the deployment is paused", func() {
BeforeEach(func() {
fakeCloudControllerClient.GetDeploymentsReturns(
[]resources.Deployment{
{
GUID: "some-deployment-guid",
Strategy: "canary",
StatusValue: "ACTIVE",
StatusReason: "PAUSED",
},
},
nil,
nil,
)
})
It("returns the deployment information", func() {
Expect(summary.Deployment).To(Equal(resources.Deployment{
GUID: "some-deployment-guid",
Strategy: "canary",
StatusValue: "ACTIVE",
StatusReason: "PAUSED",
}))
})
})
})
})

When("the deployment is not active", 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 Down
Loading

0 comments on commit dceca07

Please sign in to comment.