Skip to content

Commit cac601e

Browse files
authored
Support ecs quicksync force new deployment config (#6336)
* Support ecs quicksync force new deployment config Signed-off-by: khanhtc1202 <[email protected]> * Use const for medadata key Signed-off-by: khanhtc1202 <[email protected]> --------- Signed-off-by: khanhtc1202 <[email protected]>
1 parent 1db6e9b commit cac601e

File tree

6 files changed

+35
-10
lines changed

6 files changed

+35
-10
lines changed

pkg/app/piped/executor/ecs/deploy.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ package ecs
1616

1717
import (
1818
"context"
19+
"strconv"
1920

2021
"github.com/aws/aws-sdk-go-v2/service/ecs/types"
2122

@@ -109,7 +110,12 @@ func (e *deployExecutor) ensureSync(ctx context.Context) model.StageStatus {
109110
}
110111

111112
recreate := e.appCfg.QuickSync.Recreate
112-
if !sync(ctx, &e.Input, e.platformProviderName, e.platformProviderCfg, recreate, taskDefinition, servicedefinition, primary) {
113+
forceNewDeployment := e.appCfg.QuickSync.ForceNewDeployment
114+
115+
// Store force new deployment flag to metadata store.
116+
e.Input.MetadataStore.Shared().Put(ctx, forceNewDeploymentKey, strconv.FormatBool(forceNewDeployment))
117+
118+
if !sync(ctx, &e.Input, e.platformProviderName, e.platformProviderCfg, recreate, forceNewDeployment, taskDefinition, servicedefinition, primary) {
113119
return model.StageStatus_STAGE_FAILURE
114120
}
115121

pkg/app/piped/executor/ecs/ecs.go

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ const (
4141
canaryScaleMetadataKey = "canary-scale"
4242
currentListenersKey = "current-listeners"
4343
canaryTargetGroupArnKey = "canary-target-group-arn"
44+
// Force new deployment flag metadata key.
45+
forceNewDeploymentKey = "force-new-deployment"
4446
)
4547

4648
type registerer interface {
@@ -147,15 +149,15 @@ func applyTaskDefinition(ctx context.Context, cli provider.Client, taskDefinitio
147149
return td, nil
148150
}
149151

150-
func applyServiceDefinition(ctx context.Context, cli provider.Client, serviceDefinition types.Service) (*types.Service, error) {
152+
func applyServiceDefinition(ctx context.Context, cli provider.Client, serviceDefinition types.Service, forceNewDeployment bool) (*types.Service, error) {
151153
found, err := cli.ServiceExists(ctx, *serviceDefinition.ClusterArn, *serviceDefinition.ServiceName)
152154
if err != nil {
153155
return nil, fmt.Errorf("unable to validate service name %s: %w", *serviceDefinition.ServiceName, err)
154156
}
155157

156158
var service *types.Service
157159
if found {
158-
service, err = cli.UpdateService(ctx, serviceDefinition)
160+
service, err = cli.UpdateService(ctx, serviceDefinition, forceNewDeployment)
159161
if err != nil {
160162
return nil, fmt.Errorf("failed to update ECS service %s: %w", *serviceDefinition.ServiceName, err)
161163
}
@@ -291,7 +293,7 @@ func createPrimaryTaskSet(ctx context.Context, client provider.Client, service t
291293
return nil
292294
}
293295

294-
func sync(ctx context.Context, in *executor.Input, platformProviderName string, platformProviderCfg *config.PlatformProviderECSConfig, recreate bool, taskDefinition types.TaskDefinition, serviceDefinition types.Service, targetGroup *types.LoadBalancer) bool {
296+
func sync(ctx context.Context, in *executor.Input, platformProviderName string, platformProviderCfg *config.PlatformProviderECSConfig, recreate bool, forceNewDeployment bool, taskDefinition types.TaskDefinition, serviceDefinition types.Service, targetGroup *types.LoadBalancer) bool {
295297
client, err := provider.DefaultRegistry().Client(platformProviderName, platformProviderCfg, in.Logger)
296298
if err != nil {
297299
in.LogPersister.Errorf("Unable to create ECS client for the provider %s: %v", platformProviderName, err)
@@ -306,7 +308,7 @@ func sync(ctx context.Context, in *executor.Input, platformProviderName string,
306308
}
307309

308310
in.LogPersister.Infof("Start applying the ECS service definition")
309-
service, err := applyServiceDefinition(ctx, client, serviceDefinition)
311+
service, err := applyServiceDefinition(ctx, client, serviceDefinition, forceNewDeployment)
310312
if err != nil {
311313
in.LogPersister.Errorf("Failed to apply service %s: %v", *serviceDefinition.ServiceName, err)
312314
return false
@@ -330,7 +332,7 @@ func sync(ctx context.Context, in *executor.Input, platformProviderName string,
330332
// Scale up the service tasks count back to its desired.
331333
in.LogPersister.Infof("Scale up ECS desired tasks count back to %d", cnt)
332334
service.DesiredCount = cnt
333-
if _, err = client.UpdateService(ctx, *service); err != nil {
335+
if _, err = client.UpdateService(ctx, *service, forceNewDeployment); err != nil {
334336
in.LogPersister.Errorf("Failed to turning back service tasks: %v", err)
335337
return false
336338
}
@@ -367,7 +369,11 @@ func rollout(ctx context.Context, in *executor.Input, platformProviderName strin
367369
}
368370

369371
in.LogPersister.Infof("Start applying the ECS service definition")
370-
service, err := applyServiceDefinition(ctx, client, serviceDefinition)
372+
373+
// forceNewDeployment is false since this configuration only available for QuickSync strategy.
374+
forceNewDeployment := false
375+
376+
service, err := applyServiceDefinition(ctx, client, serviceDefinition, forceNewDeployment)
371377
if err != nil {
372378
in.LogPersister.Errorf("Failed to apply service %s: %v", *serviceDefinition.ServiceName, err)
373379
return false

pkg/app/piped/executor/ecs/rollback.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,15 @@ func rollback(ctx context.Context, in *executor.Input, platformProviderName stri
111111
return false
112112
}
113113

114+
// Retrieve force new deployment flag from metadata store.
115+
forceNewDeployment := false
116+
val, ok := in.MetadataStore.Shared().Get(forceNewDeploymentKey)
117+
if ok && val == "true" {
118+
forceNewDeployment = true
119+
}
120+
114121
// Rollback ECS service configuration to previous state including commit-hash of the tag.
115-
service, err := applyServiceDefinition(ctx, client, serviceDefinition)
122+
service, err := applyServiceDefinition(ctx, client, serviceDefinition, forceNewDeployment)
116123
if err != nil {
117124
in.LogPersister.Errorf("Unable to rollback ECS service %s configuration to previous stage: %v", *serviceDefinition.ServiceName, err)
118125
return false

pkg/app/piped/platformprovider/ecs/client.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,13 +144,14 @@ func (c *client) PruneServiceTasks(ctx context.Context, service types.Service) e
144144
return nil
145145
}
146146

147-
func (c *client) UpdateService(ctx context.Context, service types.Service) (*types.Service, error) {
147+
func (c *client) UpdateService(ctx context.Context, service types.Service, forceNewDeployment bool) (*types.Service, error) {
148148
if service.LaunchType != "" && service.CapacityProviderStrategy != nil {
149149
return nil, fmt.Errorf("failed to update ECS service %s: launch type and capacity provider strategy cannot be specified together", *service.ServiceName)
150150
}
151151
input := &ecs.UpdateServiceInput{
152152
Cluster: service.ClusterArn,
153153
Service: service.ServiceName,
154+
ForceNewDeployment: forceNewDeployment,
154155
EnableExecuteCommand: aws.Bool(service.EnableExecuteCommand),
155156
PlacementStrategy: service.PlacementStrategy,
156157
// TODO: Support update other properties of service.

pkg/app/piped/platformprovider/ecs/ecs.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ type ECS interface {
4545
ListClusters(ctx context.Context) ([]string, error)
4646
ServiceExists(ctx context.Context, clusterName string, servicesName string) (bool, error)
4747
CreateService(ctx context.Context, service types.Service) (*types.Service, error)
48-
UpdateService(ctx context.Context, service types.Service) (*types.Service, error)
48+
UpdateService(ctx context.Context, service types.Service, forceNewDeployment bool) (*types.Service, error)
4949
PruneServiceTasks(ctx context.Context, service types.Service) error
5050
WaitServiceStable(ctx context.Context, service types.Service) error
5151
GetServices(ctx context.Context, clusterName string) ([]*types.Service, error)

pkg/config/application_ecs.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,11 @@ type ECSSyncStageOptions struct {
109109
// If this is set, the application may be unavailable for a short of time during the deployment.
110110
// Default is false.
111111
Recreate bool `json:"recreate"`
112+
// Whether to force a new deployment or not.
113+
// If this is set, the new service deployment will be forced to start even if the service is already in a desired state.
114+
// This is useful when you want to update the service configuration.
115+
// Default is false.
116+
ForceNewDeployment bool `json:"forceNewDeployment"`
112117
}
113118

114119
// ECSCanaryRolloutStageOptions contains all configurable values for a ECS_CANARY_ROLLOUT stage.

0 commit comments

Comments
 (0)