-
Notifications
You must be signed in to change notification settings - Fork 330
Fix bring-your-own-alb for plugin/ecs #4457
Conversation
Prior to this, our docs claimed we allowed users to bring their own alb listeners: https://developer.hashicorp.com/waypoint/plugins/aws-ecs#alb-listener_arn But in practice, they would get this error: ``` $ waypoint deploy » Deploying hello-app... ✓ Running deploy v22 ✓ Deployment resources created ✓ Discovered service subnets ✓ Discovered alb subnets ✓ Using external security group hello-app-inbound ✓ Using internal security group hello-app-inbound-internal ✓ Using existing log group waypoint-logs ✓ Using existing execution IAM role "ecr-hello-app" ✓ Registered Task definition: waypoint-hello-app ✓ Using existing ECS cluster waypoint ✓ Created target group hello-app-01GQNGJSKZ557FNN7JPG7 ✓ Modified ALB Listener to introduce target group ✓ Created ECS Service hello-app-01GQNGJSKZ557FNN7JPG7 » Performing operation locally ✓ Finished building report for ecs deployment ✓ Determining status of ecs service hello-app-01GQNGJSKZ557FNN7JPG7 ✓ Found existing ECS cluster: waypoint⚠️ 1 cluster READY, 1 service READY, 1 task MISSING⚠️ Waypoint detected that the current deployment is not ready, however your application might be available or still starting up. » Releasing... » Performing operation locally ✓ Running release v17 ! ValidationError: A load balancer ARN must be specified status code: 400, request id: f6328bdb-0616-484e-8654-140b8c2c1ca9 ``` Waypoint hcl contents: ``` project = "hello-app" app "hello-app" { build { use "pack" {} registry { use "aws-ecr" { region = "us-east-1" repository = "waypoint-example" tag = "latest" } } } deploy { use "aws-ecs" { region = "us-east-1" memory = "512" alb { listener_arn = "arn:aws:elasticloadbalancing:us-east-1:863953081260:listener/app/waypoint-ecs-hello-app/3cdb806e2340b21e/1c2034ee6148da78" subnets = ["subnet-0bd08267365065f8e","subnet-04ff6753f3ba35e49","subnet-02c9aaa7732de7eb7","subnet-047d5841370712b24","subnet-086d533750a535ea5","subnet-0f8dd2e1826266538"] } } } } ``` This change brings us in line with our docs.
var listener *elbv2.Listener | ||
for _, l := range listeners.Listeners { | ||
if *l.Port == int64(externalIngressPort) { | ||
listener = l | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Previously, we were always plucking the first listener from the ALB. Now, we make sure to modify the one that corresponds to our port of interest.
This is important if someone brings an ALB that already has a listener on another port that's unrelated to this waypoint app.
|
||
if !newListener { | ||
if listener != nil { | ||
s.Update("Modifying existing ALB Listener to introduce target group") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was no UI output previously! Now it reports progress to users.
@@ -51,107 +62,90 @@ func (r *Releaser) Release( | |||
} | |||
elbsrv := elbv2.New(sess) | |||
|
|||
dlb, err := elbsrv.DescribeLoadBalancers(&elbv2.DescribeLoadBalancersInput{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here's a part of the old bug - if the user specified a listener in the deploy config, we would always try to describe the load balancer here. The deploy plugin didn't set the load balancer arn, so target.LoadBalancerArn
would be empty string and we'd get a 400.
} else { | ||
log.Info("load-balancer defined", "dns-name", *lb.DNSName) | ||
|
||
lo, err := elbsrv.CreateListener(&elbv2.CreateListenerInput{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this would ever happen - the deploy plugin was already creating a listener if necessary. Now we're relying on that, and only modifying the listener here.
I'm honestly not sure about this use-case, but it's existing behavior and i'm not going to fight it here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks great - I think users will definitely take advantage of using an existing ALB (managed with Terraform)! I appreciate the well-commented changes - it helped me better understand what the platform and releaser plugins are intended to do in the first place.
if err != nil { | ||
return status.Errorf(codes.Internal, "failed to create listener: %s", err) | ||
} | ||
if alb == nil || alb.Arn == "" { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
❓ I see that this if block already existed, but how is it enforced that the ALB is created before the listener is created? In the resource manager I can see that the ALB listener is sequentially after the ALB itself - is that what ensures that it is done first?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Argmapper magic! This resourceAlbListenerCreate
function takes an *Resource_Alb
as input, and goes into the argmapper soup along with the resourceAlbCreate
function that provides it. Argmapper figures out the right order to invoke the whole string of resource functions.
|
||
_, err := elbsrv.ModifyListenerWithContext(ctx, &elbv2.ModifyListenerInput{ | ||
ListenerArn: listener.ListenerArn, | ||
// Setting these on every deployment so that we pick up any potential changes |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice!
Co-authored-by: Joe <83741749+paladin-devops@users.noreply.github.com>
And properly using the load_balancer_arn field
The cert is a property of the listener, not the ALB, so it's OK for both of these to be set.
@@ -1054,7 +1054,7 @@ func (p *Platform) resourceAlbListenerCreate( | |||
} | |||
log.Info("load-balancer defined", "dns-name", alb.DnsName) | |||
|
|||
s.Update("Looking for listeners for ALB %q", alb.Name) | |||
s.Update("Looking for listeners for ALB %q", alb.Arn) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The name might not be defined if the user specified an arn.
Fixes #4456
Replaces #4457
What changed
load_balancer_arn
to the ecs plugin's deploy config. If specified, waypoint will use this alb rather than creating it's own.listener_arn
field from same configMotivation
Prior to this, to use an existing alb (and prevent waypoint from creating a new one), you would specify a
listener_arn
in the ecs deployment config. In practice, that was broken (see the above issue)This approach wan't ideal anyway. Waypoint needs to modify the listener on every deployment, so if someone were to create the listener through terraform and wire the output into waypoint, that terraform would also try to change the default listener on the rule away from waypoint's deployment on every run.
Waypoint should own the listener, but can inherit an existing ALB.
Backwards-compat
While removing a field is generally a breaking change, because the field was broken anyway (see issue), I can't see how anyone could have been depending on it.
How do I test this?
I'd recommend starting with https://github.com/hashicorp/waypoint-examples/tree/main/aws/aws-ecs/nodejs. Run a few
waypoint deploy
's while observing the aws alb, and notice how the default rule moves traffic to the most recent target group on every release.To test bring-your-own-alb, you can copy the arn and subnets of the alb waypoint created in the above testing into your deploy config
Example:
Run a few more releases, and observe the same successful behavior.
Other fixes in this PR