Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(ECS): enable selection of listener rules #4668

Merged
Merged
15 changes: 15 additions & 0 deletions pkg/app/piped/executor/ecs/ecs.go
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,21 @@ func routing(ctx context.Context, in *executor.Input, platformProviderName strin
return false
}

currListenerRuleArns, err := client.GetListenerRuleArns(ctx, currListenerArns)
if err != nil {
in.LogPersister.Errorf("Failed to get current active listener rule: %v", err)
return false
}

if len(currListenerRuleArns) > 0 {
if err := client.ModifyRules(ctx, currListenerRuleArns, routingTrafficCfg); err != nil {
in.LogPersister.Errorf("Failed to routing traffic to PRIMARY/CANARY variants: %v", err)
return false
}
khanhtc1202 marked this conversation as resolved.
Show resolved Hide resolved

return true
}

if err := client.ModifyListeners(ctx, currListenerArns, routingTrafficCfg); err != nil {
in.LogPersister.Errorf("Failed to routing traffic to PRIMARY/CANARY variants: %v", err)
return false
Expand Down
17 changes: 16 additions & 1 deletion pkg/app/piped/executor/ecs/rollback.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,8 +158,23 @@ func rollback(ctx context.Context, in *executor.Input, platformProviderName stri
return false
}

currListenerRuleArns, err := client.GetListenerRuleArns(ctx, currListenerArns)
if err != nil {
in.LogPersister.Errorf("Failed to get current active listener rule: %v", err)
return false
}

if len(currListenerRuleArns) > 0 {
if err := client.ModifyRules(ctx, currListenerRuleArns, routingTrafficCfg); err != nil {
in.LogPersister.Errorf("Failed to routing traffic to PRIMARY/CANARY variants: %v", err)
return false
}
khanhtc1202 marked this conversation as resolved.
Show resolved Hide resolved

return true
}

if err := client.ModifyListeners(ctx, currListenerArns, routingTrafficCfg); err != nil {
in.LogPersister.Errorf("Failed to routing traffic to PRIMARY variant: %v", err)
in.LogPersister.Errorf("Failed to routing traffic to PRIMARY/CANARY variants: %v", err)
return false
}
}
Expand Down
117 changes: 105 additions & 12 deletions pkg/app/piped/platformprovider/ecs/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"context"
"errors"
"fmt"
"strings"
"time"

"github.com/aws/aws-sdk-go-v2/aws"
Expand Down Expand Up @@ -417,6 +418,30 @@
return arns, nil
}

func (c *client) GetListenerRuleArns(ctx context.Context, listenerArns []string) ([]string, error) {
var ruleArns []string

// Fetch all rules by listeners
for _, listenerArn := range listenerArns {
input := &elasticloadbalancingv2.DescribeRulesInput{
ListenerArn: aws.String(listenerArn),
}
output, err := c.elbClient.DescribeRules(ctx, input)
if err != nil {
return nil, err
}
for _, rule := range output.Rules {
ruleArns = append(ruleArns, *rule.RuleArn)
}

Check warning on line 435 in pkg/app/piped/platformprovider/ecs/client.go

View check run for this annotation

Codecov / codecov/patch

pkg/app/piped/platformprovider/ecs/client.go#L421-L435

Added lines #L421 - L435 were not covered by tests
}

if len(ruleArns) == 0 {
return nil, platformprovider.ErrNotFound
}

Check warning on line 440 in pkg/app/piped/platformprovider/ecs/client.go

View check run for this annotation

Codecov / codecov/patch

pkg/app/piped/platformprovider/ecs/client.go#L438-L440

Added lines #L438 - L440 were not covered by tests

return ruleArns, nil

Check warning on line 442 in pkg/app/piped/platformprovider/ecs/client.go

View check run for this annotation

Codecov / codecov/patch

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

Added line #L442 was not covered by tests
}

func (c *client) getLoadBalancerArn(ctx context.Context, targetGroupArn string) (string, error) {
input := &elasticloadbalancingv2.DescribeTargetGroupsInput{
TargetGroupArns: []string{targetGroupArn},
Expand All @@ -437,11 +462,21 @@
return fmt.Errorf("invalid listener configuration: requires 2 target groups")
}

modifyListener := func(ctx context.Context, listenerArn string) error {
input := &elasticloadbalancingv2.ModifyListenerInput{
ListenerArn: aws.String(listenerArn),
DefaultActions: []elbtypes.Action{
{
for _, listenerArn := range listenerArns {
// Describe the listener to get the current actions
describeListenersOutput, err := c.elbClient.DescribeListeners(ctx, &elasticloadbalancingv2.DescribeListenersInput{
ListenerArns: []string{listenerArn},
})
if err != nil {
return fmt.Errorf("error describing listener %s: %w", listenerArn, err)
}

Check warning on line 472 in pkg/app/piped/platformprovider/ecs/client.go

View check run for this annotation

Codecov / codecov/patch

pkg/app/piped/platformprovider/ecs/client.go#L465-L472

Added lines #L465 - L472 were not covered by tests

// Prepare the actions to be modified
var modifiedActions []elbtypes.Action
for _, action := range describeListenersOutput.Listeners[0].DefaultActions {
if action.Type == elbtypes.ActionTypeEnumForward {
// Modify only the forward action (new logic)
modifiedAction := elbtypes.Action{

Check warning on line 479 in pkg/app/piped/platformprovider/ecs/client.go

View check run for this annotation

Codecov / codecov/patch

pkg/app/piped/platformprovider/ecs/client.go#L475-L479

Added lines #L475 - L479 were not covered by tests
Type: elbtypes.ActionTypeEnumForward,
ForwardConfig: &elbtypes.ForwardActionConfig{
TargetGroups: []elbtypes.TargetGroupTuple{
Expand All @@ -455,16 +490,74 @@
},
},
},
},
},
}
modifiedActions = append(modifiedActions, modifiedAction)
} else {
// Keep other actions unchanged (new logic)
modifiedActions = append(modifiedActions, action)
}

Check warning on line 498 in pkg/app/piped/platformprovider/ecs/client.go

View check run for this annotation

Codecov / codecov/patch

pkg/app/piped/platformprovider/ecs/client.go#L493-L498

Added lines #L493 - L498 were not covered by tests
}
_, err := c.elbClient.ModifyListener(ctx, input)
return err

// Modify the listener
_, err = c.elbClient.ModifyListener(ctx, &elasticloadbalancingv2.ModifyListenerInput{
ListenerArn: aws.String(listenerArn),
DefaultActions: modifiedActions,
})
if err != nil {
return fmt.Errorf("error modifying listener %s: %w", listenerArn, err)
}

Check warning on line 508 in pkg/app/piped/platformprovider/ecs/client.go

View check run for this annotation

Codecov / codecov/patch

pkg/app/piped/platformprovider/ecs/client.go#L502-L508

Added lines #L502 - L508 were not covered by tests
}
return nil

Check warning on line 510 in pkg/app/piped/platformprovider/ecs/client.go

View check run for this annotation

Codecov / codecov/patch

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

Added line #L510 was not covered by tests
}

func (c *client) ModifyRules(ctx context.Context, listenerRuleArns []string, routingTrafficCfg RoutingTrafficConfig) error {
if len(routingTrafficCfg) != 2 {
return fmt.Errorf("invalid listener configuration: requires 2 target groups")

Check warning on line 515 in pkg/app/piped/platformprovider/ecs/client.go

View check run for this annotation

Codecov / codecov/patch

pkg/app/piped/platformprovider/ecs/client.go#L513-L515

Added lines #L513 - L515 were not covered by tests
}

for _, listener := range listenerArns {
if err := modifyListener(ctx, listener); err != nil {
return err
for _, ruleArn := range listenerRuleArns {
// Describe the rule to get current actions
describeRulesOutput, err := c.elbClient.DescribeRules(ctx, &elasticloadbalancingv2.DescribeRulesInput{
RuleArns: []string{ruleArn},
})
if err != nil {
return fmt.Errorf("error describing listener rule %v: %w", strings.Join(listenerRuleArns, ", "), err)
}

Check warning on line 525 in pkg/app/piped/platformprovider/ecs/client.go

View check run for this annotation

Codecov / codecov/patch

pkg/app/piped/platformprovider/ecs/client.go#L518-L525

Added lines #L518 - L525 were not covered by tests

// Prepare the actions to be modified
var modifiedActions []elbtypes.Action
for _, action := range describeRulesOutput.Rules[0].Actions {
if action.Type == elbtypes.ActionTypeEnumForward {
// Modify only the forward action (new logic)
modifiedAction := elbtypes.Action{
Type: elbtypes.ActionTypeEnumForward,
ForwardConfig: &elbtypes.ForwardActionConfig{
TargetGroups: []elbtypes.TargetGroupTuple{
{
TargetGroupArn: aws.String(routingTrafficCfg[0].TargetGroupArn),
Weight: aws.Int32(int32(routingTrafficCfg[0].Weight)),
},
{
TargetGroupArn: aws.String(routingTrafficCfg[1].TargetGroupArn),
Weight: aws.Int32(int32(routingTrafficCfg[1].Weight)),
},
},
},
}
modifiedActions = append(modifiedActions, modifiedAction)
} else {
// Keep other actions unchanged (new logic)
modifiedActions = append(modifiedActions, action)
}

Check warning on line 551 in pkg/app/piped/platformprovider/ecs/client.go

View check run for this annotation

Codecov / codecov/patch

pkg/app/piped/platformprovider/ecs/client.go#L528-L551

Added lines #L528 - L551 were not covered by tests
}

// Modify the rule with the new actions
_, err = c.elbClient.ModifyRule(ctx, &elasticloadbalancingv2.ModifyRuleInput{
RuleArn: aws.String(ruleArn),
Actions: modifiedActions,
})
if err != nil {
return fmt.Errorf("error modifying listener rule %s: %w", ruleArn, err)

Check warning on line 560 in pkg/app/piped/platformprovider/ecs/client.go

View check run for this annotation

Codecov / codecov/patch

pkg/app/piped/platformprovider/ecs/client.go#L555-L560

Added lines #L555 - L560 were not covered by tests
}
}
return nil
Expand Down
2 changes: 2 additions & 0 deletions pkg/app/piped/platformprovider/ecs/ecs.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,9 @@ type ECS interface {

type ELB interface {
GetListenerArns(ctx context.Context, targetGroup types.LoadBalancer) ([]string, error)
GetListenerRuleArns(ctx context.Context, listenerArns []string) ([]string, error)
ModifyListeners(ctx context.Context, listenerArns []string, routingTrafficCfg RoutingTrafficConfig) error
ModifyRules(ctx context.Context, listenerRuleArns []string, routingTrafficCfg RoutingTrafficConfig) error
khanhtc1202 marked this conversation as resolved.
Show resolved Hide resolved
}

// Registry holds a pool of aws client wrappers.
Expand Down