-
Notifications
You must be signed in to change notification settings - Fork 4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
In the case of an ECS Service runningon EC2 capacity, pointing a Load Balancer to the Service involves updating the SecurityGroups of the capacity associated to the Cluster (to allow traffic from the Load Balancer). If these resources are in different stacks, this is liable to create cyclic references: Service points to Cluster, Security Groups point to Load Balancer, cyclic references arise from the way these resources are typically colocated. This changes makes it so the ingress/egress rules will be created in the same stack as the Service (which points to both Cluster and LB), hence making sure there are no cycles. Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
- Loading branch information
1 parent
6e195e0
commit eb3c517
Showing
3 changed files
with
145 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
import { expect, haveResource } from '@aws-cdk/assert'; | ||
import * as ec2 from '@aws-cdk/aws-ec2'; | ||
import * as elbv2 from '@aws-cdk/aws-elasticloadbalancingv2'; | ||
import { App, Stack } from '@aws-cdk/core'; | ||
import { Test } from 'nodeunit'; | ||
import * as ecs from '../../lib'; | ||
|
||
// Test various cross-stack Cluster/Service/ALB scenario's | ||
|
||
let app: App; | ||
let stack1: Stack; | ||
let stack2: Stack; | ||
let cluster: ecs.Cluster; | ||
let service: ecs.Ec2Service; | ||
|
||
export = { | ||
"setUp"(cb: () => void) { | ||
app = new App(); | ||
|
||
stack1 = new Stack(app, 'Stack1'); | ||
const vpc = new ec2.Vpc(stack1, 'Vpc'); | ||
cluster = new ecs.Cluster(stack1, 'Cluster', { | ||
vpc, | ||
capacity: { instanceType: new ec2.InstanceType('t2.micro'), } | ||
}); | ||
|
||
stack2 = new Stack(app, 'Stack2'); | ||
const taskDefinition = new ecs.Ec2TaskDefinition(stack2, 'TD'); | ||
const container = taskDefinition.addContainer('Main', { | ||
image: ecs.ContainerImage.fromRegistry('asdf'), | ||
memoryLimitMiB: 512 | ||
}); | ||
container.addPortMappings({ containerPort: 8000 }); | ||
|
||
service = new ecs.Ec2Service(stack2, 'Service', { | ||
cluster, | ||
taskDefinition, | ||
}); | ||
|
||
cb(); | ||
}, | ||
|
||
"ALB next to Service"(test: Test) { | ||
// WHEN | ||
const lb = new elbv2.ApplicationLoadBalancer(stack2, "ALB", { vpc: cluster.vpc }); | ||
const listener = lb.addListener("listener", { port: 80 }); | ||
listener.addTargets("target", { | ||
port: 80, | ||
targets: [service] | ||
}); | ||
|
||
// THEN: it shouldn't throw due to cyclic dependencies | ||
expect(stack2).to(haveResource('AWS::ECS::Service')); | ||
|
||
expectIngress(stack2); | ||
|
||
test.done(); | ||
}, | ||
|
||
"ALB next to Cluster"(test: Test) { | ||
// WHEN | ||
const lb = new elbv2.ApplicationLoadBalancer(stack1, "ALB", { vpc: cluster.vpc }); | ||
const listener = lb.addListener("listener", { port: 80 }); | ||
listener.addTargets("target", { | ||
port: 80, | ||
targets: [service] | ||
}); | ||
|
||
// THEN: it shouldn't throw due to cyclic dependencies | ||
expect(stack2).to(haveResource('AWS::ECS::Service')); | ||
expectIngress(stack2); | ||
|
||
test.done(); | ||
}, | ||
|
||
"ALB in its own stack"(test: Test) { | ||
// WHEN | ||
const stack3 = new Stack(app, 'Stack3'); | ||
const lb = new elbv2.ApplicationLoadBalancer(stack3, "ALB", { vpc: cluster.vpc }); | ||
const listener = lb.addListener("listener", { port: 80 }); | ||
listener.addTargets("target", { | ||
port: 80, | ||
targets: [service] | ||
}); | ||
|
||
// THEN: it shouldn't throw due to cyclic dependencies | ||
expect(stack2).to(haveResource('AWS::ECS::Service')); | ||
expectIngress(stack2); | ||
|
||
test.done(); | ||
}, | ||
}; | ||
|
||
function expectIngress(stack: Stack) { | ||
expect(stack).to(haveResource('AWS::EC2::SecurityGroupIngress', { | ||
FromPort: 32768, | ||
ToPort: 65535, | ||
GroupId: { "Fn::ImportValue": "Stack1:ExportsOutputFnGetAttClusterDefaultAutoScalingGroupInstanceSecurityGroup1D15236AGroupIdEAB9C5E1" }, | ||
})); | ||
} |