Permalink
Fetching contributors…
Cannot retrieve contributors at this time
285 lines (274 sloc) 8.64 KB
Description: "Ufo ECS stack <%= @pretty_service_name %>"
Parameters:
# required
Vpc:
Description: Existing vpc id
Type: AWS::EC2::VPC::Id
ElbSubnets:
Description: Existing subnet ids for ELB
Type: List<AWS::EC2::Subnet::Id>
EcsSubnets:
Description: Existing subnet ids for ECS
Type: List<AWS::EC2::Subnet::Id>
EcsSecurityGroups:
Description: Existing ecs security group ids
Type: String
Default: ''
ElbSecurityGroups:
Description: Existing elb security group ids. List with commas.
Type: String
Default: ''
ElbTargetGroup:
Description: Existing target group
Type: String
Default: '' # when blank the automatically created TargetGroup is used
CreateElb:
Description: Create elb
Type: String
Default: true
EcsDesiredCount:
Description: Ecs desired count
Type: String
Default: 1
EcsTaskDefinition:
Description: Ecs task definition arn
Type: String
# Using to keep state
ElbEipIds:
Description: ELB EIP Allocation ids to use for network load balancer
Type: String
Default: ''
EcsSchedulingStrategy:
Description: The scheduling strategy to use for the service
Type: String
Default: 'REPLICA'
Conditions:
CreateElbIsTrue: !Equals [ !Ref CreateElb, true ]
ElbTargetGroupIsBlank: !Equals [ !Ref ElbTargetGroup, '' ]
CreateTargetGroupIsTrue: !And
- !Condition CreateElbIsTrue
- !Condition ElbTargetGroupIsBlank
ElbSecurityGroupsIsBlank: !Equals [ !Ref ElbSecurityGroups, '' ]
EcsSecurityGroupsIsBlank: !Equals [ !Ref EcsSecurityGroups, '' ]
EcsDesiredCountIsBlank: !Equals [ !Ref EcsDesiredCount, '' ]
Resources:
Elb:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
Condition: CreateElbIsTrue
Properties:
<% if ENV['UFO_FORCE_ELB'] -%>
# Error: SetSubnets is not supported for load balancers of type 'network'
# Happens: When changing subnets for an ELB
# Solution: Rename the ELB to force a replacement of it
<% random = (0...3).map { (65 + rand(26)).chr }.join.downcase %>
Name: <%= "#{@pretty_service_name}-#{random}" %>
<% end -%>
Type: <%= @elb_type %>
Tags:
- Key: Name
Value: <%= @pretty_service_name %>
<% if @elb_type == "application" -%>
# Add additional extra security groups if parameters set
SecurityGroups: !Split
- ','
- !If
- ElbSecurityGroupsIsBlank
- !Ref ElbSecurityGroup
- !Join [',', [!Ref ElbSecurityGroups, !Ref ElbSecurityGroup]]
<% end -%>
<% if @elb_type == "network" && @subnet_mappings && !@subnet_mappings.empty? -%>
SubnetMappings:
<% @subnet_mappings.each do |allocation_id, subnet_id| -%>
- AllocationId: <%= allocation_id %>
SubnetId: <%= subnet_id %>
<% end -%>
<% else -%>
Subnets: !Ref ElbSubnets
<% end -%>
<%= custom_properties(:Elb) %>
TargetGroup:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
Condition: CreateTargetGroupIsTrue
Properties:
VpcId: !Ref Vpc
Tags:
- Key: Name
Value: <%= @pretty_service_name %>
<% if ENV['UFO_FORCE_TARGET_GROUP'] -%>
# When adding and removing EIPs
# Error: TargetGroup cannot be associated with more than one load balancer
# Solution: https://forums.aws.amazon.com/thread.jspa?threadID=254544
Name: !Join
- '-'
- - <%= @pretty_service_name %>
- !Select [ 2, !Split [ '-', !GetAtt Elb.LoadBalancerName]]
<% end -%>
Protocol: <%= @default_target_group_protocol %>
<% if @container[:network_mode] == "awsvpc" -%>
TargetType: ip
<% end -%>
<% if @elb_type == "network" && @network_mode == "awsvpc" -%>
# target groups with network load balancers need to check the container
# port dirtectly and will be using
HealthCheckPort: <%= @container[:port] %>
<% end -%>
<%= custom_properties(:TargetGroup) %>
Listener:
Type: AWS::ElasticLoadBalancingV2::Listener
Condition: CreateElbIsTrue
Properties:
DefaultActions:
- Type: forward
TargetGroupArn:
!If [ElbTargetGroupIsBlank, !Ref TargetGroup, !Ref ElbTargetGroup]
LoadBalancerArn: !Ref Elb
Protocol: <%= @default_listener_protocol %>
<%= custom_properties(:Listener) %>
<% if @create_listener_ssl -%>
ListenerSsl:
Type: AWS::ElasticLoadBalancingV2::Listener
Condition: CreateElbIsTrue
Properties:
DefaultActions:
- Type: forward
TargetGroupArn:
!If [ElbTargetGroupIsBlank, !Ref TargetGroup, !Ref ElbTargetGroup]
LoadBalancerArn: !Ref Elb
Protocol: <%= @default_listener_ssl_protocol %>
<%= custom_properties(:ListenerSsl) %>
<% end -%>
<% if @elb_type == "application" -%>
ElbSecurityGroup:
Type: AWS::EC2::SecurityGroup
Condition: CreateElbIsTrue
Properties:
GroupDescription: Allow http to client host
VpcId: !Ref Vpc
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: '<%= cfn[:listener][:port] %>'
ToPort: '<%= cfn[:listener][:port] %>'
CidrIp: 0.0.0.0/0
<% if @create_listener_ssl -%>
- IpProtocol: tcp
FromPort: '<%= cfn[:listener_ssl][:port] %>'
ToPort: '<%= cfn[:listener_ssl][:port] %>'
CidrIp: 0.0.0.0/0
<% end -%>
SecurityGroupEgress:
- IpProtocol: tcp
FromPort: '0'
ToPort: '65535'
CidrIp: 0.0.0.0/0
Tags:
- Key: Name
Value: <%= @pretty_service_name %>-elb
<%= custom_properties(:ElbSecurityGroup) %>
<% end -%>
Ecs:
Type: AWS::ECS::Service
<% if @create_elb -%>
DependsOn: Listener
<% end -%>
Properties:
Cluster: <%= @cluster %>
DesiredCount: !If
- EcsDesiredCountIsBlank
- !Ref AWS::NoValue
- !Ref EcsDesiredCount
TaskDefinition: !Ref EcsTaskDefinition
<% if pretty_name? -%>
ServiceName: <%= @pretty_service_name %>
<% end -%>
<% if @container[:fargate] -%>
LaunchType: FARGATE
<% end -%>
<% if @container[:network_mode] == "awsvpc" -%>
NetworkConfiguration:
AwsvpcConfiguration:
Subnets: !Ref EcsSubnets # required
SecurityGroups: !Split
- ','
- !If
- EcsSecurityGroupsIsBlank
- !Ref EcsSecurityGroup
- !Join [',', [!Ref EcsSecurityGroups, !Ref EcsSecurityGroup]]
<% if @container[:fargate] -%>
AssignPublicIp: ENABLED # Works with fargate but doesnt seem to work with non-fargate
<% end -%>
<% end -%>
# Default to port 80 to get template to validate. For worker processes
# there is no actual port used.
LoadBalancers: !If
- CreateTargetGroupIsTrue
- - ContainerName: <%= @container[:name] %>
ContainerPort: <%= @container[:port] || 80 %>
TargetGroupArn: !Ref TargetGroup
- !If
- ElbTargetGroupIsBlank
- []
- - ContainerName: <%= @container[:name] %>
ContainerPort: <%= @container[:port] || 80 %>
TargetGroupArn: !Ref ElbTargetGroup
SchedulingStrategy: !Ref EcsSchedulingStrategy
<%= custom_properties(:Ecs) %>
EcsSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Allow http to client host
VpcId: !Ref Vpc
<% if @elb_type == "network" -%>
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: '<%= @container[:port] %>'
ToPort: '<%= @container[:port] %>'
CidrIp: 0.0.0.0/0
Description: docker ephemeral port range for network elb
<% end -%>
# Outbound access: instance needs access to internet to pull down image
# or else get CannotPullContainerError
SecurityGroupEgress:
- IpProtocol: tcp
FromPort: '0'
ToPort: '65535'
CidrIp: 0.0.0.0/0
Description: outbound traffic
Tags:
- Key: Name
Value: <%= @pretty_service_name %>
<%= custom_properties(:EcsSecurityGroup) %>
<% if @elb_type == "application" -%>
# Allow all traffic from ELB SG to ECS SG
EcsSecurityGroupRule:
Type: AWS::EC2::SecurityGroupIngress
Condition: CreateElbIsTrue
Properties:
IpProtocol: tcp
FromPort: '0'
ToPort: '65535'
SourceSecurityGroupId: !GetAtt ElbSecurityGroup.GroupId
GroupId: !GetAtt EcsSecurityGroup.GroupId
Description: application elb access to ecs
<%= custom_properties(:EcsSecurityGroupRule) %>
<% end -%>
<% if @create_route53 -%>
Dns:
Type: AWS::Route53::RecordSet
Properties:
Comment: cname to load balancer
Type: CNAME
TTL: '60' # ttl has special casing
ResourceRecords:
- !GetAtt Elb.DNSName
<%= custom_properties(:Dns) %>
<% end -%>
Outputs:
ElbDns:
Description: Elb Dns
Condition: CreateElbIsTrue
Value: !GetAtt Elb.DNSName
<% if @create_route53 -%>
Route53Dns:
Description: Route53 Dns
Value: !Ref Dns
<% end -%>