rubycfn 0.5.2 → 0.5.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -1
- data/Gemfile.lock +2 -2
- data/README.md +5 -6
- data/lib/rubycfn/version.rb +1 -1
- data/templates/.gitignore +4 -0
- data/templates/.rubocop.yml +3 -0
- data/templates/README.md +1 -1
- data/templates/Rakefile +3 -4
- data/templates/config.yaml +3 -0
- data/templates/lib/aws_helper/compiler.rb +1 -1
- data/templates/lib/aws_helper/dependencies.rb +11 -3
- data/templates/lib/aws_helper/upload_stack.rb +3 -10
- data/templates/lib/core/applications.rb +117 -28
- data/templates/lib/core/dependencies.rb +3 -3
- data/templates/lib/core/deploy.rb +2 -2
- data/templates/lib/core/init.rb +60 -12
- data/templates/lib/main.rb +1 -1
- data/templates/lib/shared_concerns/global_variables.rb +1 -1
- data/templates/lib/shared_concerns/shared_methods.rb +2 -2
- data/templates/lib/stacks/ecs_stack/ecs_cluster.rb +276 -276
- data/templates/lib/stacks/ecs_stack/lifecycle_hook.rb +162 -160
- data/templates/lib/stacks/ecs_stack/load_balancer.rb +52 -50
- data/templates/lib/stacks/ecs_stack/main.rb +2 -0
- data/templates/lib/stacks/ecs_stack/rollback.rb +77 -0
- metadata +4 -3
- data/templates/bootstrap/dependency_stack.rb +0 -49
data/templates/lib/core/init.rb
CHANGED
@@ -30,7 +30,7 @@ def inject_dummy_resource(stack)
|
|
30
30
|
end
|
31
31
|
|
32
32
|
def read_domain_name
|
33
|
-
config = YAML.safe_load(File.read("config.yaml"))
|
33
|
+
config = YAML.safe_load(File.read("config.yaml"), [Symbol])
|
34
34
|
config["applications"] ||= {}
|
35
35
|
config["environments"] ||= {}
|
36
36
|
config["subnets"] ||= {}
|
@@ -60,16 +60,64 @@ subdomain, domain_name = read_domain_name
|
|
60
60
|
raise "ENVIRONMENT not set" unless ENV["ENVIRONMENT"]
|
61
61
|
warn "WARNING: domain_name not set in config.yaml... Route53 Hosted Zone will not be created" if domain_name.empty?
|
62
62
|
|
63
|
-
module DependencyStack
|
63
|
+
module Project<%= project_name %>DependencyStack
|
64
64
|
extend ActiveSupport::Concern
|
65
65
|
include Rubycfn
|
66
66
|
|
67
67
|
included do
|
68
|
-
|
68
|
+
description "<%= project_name %>#{ENV["ENVIRONMENT"].capitalize}Dependency Stack"
|
69
|
+
|
70
|
+
parameter :environment,
|
71
|
+
description: "Environment name",
|
72
|
+
type: "String"
|
73
|
+
|
74
|
+
parameter :domain_name,
|
75
|
+
description: "Domain name",
|
76
|
+
type: "String"
|
77
|
+
|
78
|
+
condition :has_environment,
|
79
|
+
[["", :environment.ref].fnequals].fnnot
|
80
|
+
|
81
|
+
condition :has_domain_name,
|
82
|
+
[["", :domain_name.ref].fnequals].fnnot
|
83
|
+
|
84
|
+
%i(
|
85
|
+
artifact_bucket
|
86
|
+
cloudformation_bucket
|
87
|
+
lambda_bucket
|
88
|
+
logging_bucket
|
89
|
+
).each do |bucket|
|
90
|
+
resource bucket,
|
91
|
+
deletion_policy: "Retain",
|
92
|
+
update_replace_policy: "Retain",
|
93
|
+
type: "AWS::S3::Bucket"
|
94
|
+
|
95
|
+
output bucket,
|
96
|
+
value: bucket.ref
|
97
|
+
end
|
98
|
+
|
99
|
+
resource :hosted_zone,
|
100
|
+
condition: "HasDomainName",
|
101
|
+
type: "AWS::Route53::HostedZone" do |r|
|
102
|
+
r.property(:hosted_zone_config) do
|
103
|
+
{
|
104
|
+
"Comment": ["Hosted zone for ", ["HasEnvironment", [:environment.ref, "."].fnjoin, ""].fnif, :domain_name.ref].fnjoin
|
105
|
+
}
|
106
|
+
end
|
107
|
+
r.property(:name) { [["HasEnvironment", [:environment.ref, "."].fnjoin, ""].fnif, :domain_name.ref].fnjoin }
|
108
|
+
end
|
109
|
+
|
110
|
+
output :hosted_zone_id,
|
111
|
+
condition: "HasDomainName",
|
112
|
+
value: :hosted_zone.ref
|
113
|
+
|
114
|
+
output :hosted_zone_name,
|
115
|
+
condition: "HasDomainName",
|
116
|
+
value: [["HasEnvironment", [:environment.ref, "."].fnjoin, ""].fnif, :domain_name.ref].fnjoin
|
69
117
|
end
|
70
118
|
end
|
71
119
|
|
72
|
-
stack = include DependencyStack # rubocop:disable Style/MixinUsage
|
120
|
+
stack = include Project<%= project_name %>DependencyStack # rubocop:disable Style/MixinUsage
|
73
121
|
template = stack.render_template
|
74
122
|
|
75
123
|
client = Aws::CloudFormation::Client.new
|
@@ -77,7 +125,7 @@ client = Aws::CloudFormation::Client.new
|
|
77
125
|
stack_exists = false
|
78
126
|
previous_statuses = []
|
79
127
|
80.times do
|
80
|
-
previous_events = get_prior_events(client, "DependencyStack")
|
128
|
+
previous_events = get_prior_events(client, "<%= project_name %>#{ENV["ENVIRONMENT"].capitalize}DependencyStack")
|
81
129
|
previous_statuses = previous_events.map(&:event_id)
|
82
130
|
stack_exists = previous_events.size.to_i.positive? ? true : false
|
83
131
|
break unless stack_exists
|
@@ -85,8 +133,8 @@ previous_statuses = []
|
|
85
133
|
events_last_deploy = get_events_last_deploy(previous_events)
|
86
134
|
last_event = events_last_deploy.shift
|
87
135
|
break if last_event \
|
88
|
-
&& (last_event.logical_resource_id == "DependencyStack") \
|
89
|
-
&& (last_event.stack_name == "DependencyStack") \
|
136
|
+
&& (last_event.logical_resource_id == "<%= project_name %>#{ENV["ENVIRONMENT"].capitalize}DependencyStack") \
|
137
|
+
&& (last_event.stack_name == "<%= project_name %>#{ENV["ENVIRONMENT"].capitalize}DependencyStack") \
|
90
138
|
&& (DEPLOYABLE_STATES.include? last_event.resource_status)
|
91
139
|
puts "Stack is currently in #{last_event.resource_status} mode. Waiting for it to finish..." if last_event
|
92
140
|
sleep 15
|
@@ -107,7 +155,7 @@ parameters = [
|
|
107
155
|
|
108
156
|
if stack_exists
|
109
157
|
client.update_stack(
|
110
|
-
stack_name: "DependencyStack",
|
158
|
+
stack_name: "<%= project_name %>#{ENV["ENVIRONMENT"].capitalize}DependencyStack",
|
111
159
|
template_body: template,
|
112
160
|
capabilities: %w(CAPABILITY_IAM CAPABILITY_NAMED_IAM),
|
113
161
|
parameters: parameters,
|
@@ -120,7 +168,7 @@ if stack_exists
|
|
120
168
|
)
|
121
169
|
else
|
122
170
|
client.create_stack(
|
123
|
-
stack_name: "DependencyStack",
|
171
|
+
stack_name: "<%= project_name %>#{ENV["ENVIRONMENT"].capitalize}DependencyStack",
|
124
172
|
template_body: template,
|
125
173
|
timeout_in_minutes: 60,
|
126
174
|
capabilities: %w(CAPABILITY_IAM CAPABILITY_NAMED_IAM),
|
@@ -140,7 +188,7 @@ shown_log_lines = {}
|
|
140
188
|
|
141
189
|
360.times do
|
142
190
|
resp = client.describe_stack_events(
|
143
|
-
stack_name: "DependencyStack"
|
191
|
+
stack_name: "<%= project_name %>#{ENV["ENVIRONMENT"].capitalize}DependencyStack"
|
144
192
|
)
|
145
193
|
resp.stack_events.to_a.reverse.each_with_index do |event, index|
|
146
194
|
next if previous_statuses.include? event.event_id
|
@@ -155,8 +203,8 @@ shown_log_lines = {}
|
|
155
203
|
"#{@resource_status.white} #{@resource_status_reason.to_s.red}"
|
156
204
|
puts log_line unless shown_log_lines[log_line]
|
157
205
|
shown_log_lines[log_line] = true
|
158
|
-
if (@stack_name == "DependencyStack") \
|
159
|
-
&& (@logical_resource_id == "DependencyStack") \
|
206
|
+
if (@stack_name == "<%= project_name %>#{ENV["ENVIRONMENT"].capitalize}DependencyStack") \
|
207
|
+
&& (@logical_resource_id == "<%= project_name %>#{ENV["ENVIRONMENT"].capitalize}DependencyStack") \
|
160
208
|
&& (END_STATES.include? @resource_status) \
|
161
209
|
&& (index + 1 == resp.stack_events.to_a.size)
|
162
210
|
@completed = true
|
data/templates/lib/main.rb
CHANGED
@@ -35,8 +35,8 @@ module Concerns
|
|
35
35
|
end
|
36
36
|
|
37
37
|
def generate_bootstrap_parameters
|
38
|
-
warn "WARNING: .env.dependencies does not exist. Run `rake dependencies` first!" unless File.file?(".env.dependencies")
|
39
|
-
filename = File.file?(".env.dependencies") && ".env.dependencies#{environment == "rspec" && ".rspec" || ""}" || ".env.dependencies.rspec"
|
38
|
+
warn "WARNING: .env.dependencies.#{ENV["ENVIRONMENT"]} does not exist. Run `rake dependencies` first!" unless File.file?(".env.dependencies.#{ENV["ENVIRONMENT"]}")
|
39
|
+
filename = File.file?(".env.dependencies.#{ENV["ENVIRONMENT"]}") && ".env.dependencies#{environment == "rspec" && ".rspec" || ".#{ENV["ENVIRONMENT"]}"}" || ".env.dependencies.rspec"
|
40
40
|
File.open(filename).read.each_line do |line|
|
41
41
|
line.strip!
|
42
42
|
param, _value = line.split("=")
|
@@ -22,323 +22,323 @@ module EcsStack
|
|
22
22
|
resource :ecs_cluster,
|
23
23
|
type: "AWS::ECS::Cluster"
|
24
24
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
25
|
+
unless infra_config["environments"][environment]["cluster_size"].nil? || infra_config["environments"][environment]["cluster_size"].to_i.zero?
|
26
|
+
resource :ecs_auto_scaling_group,
|
27
|
+
type: "AWS::AutoScaling::AutoScalingGroup" do |r|
|
28
|
+
r.property(:vpc_zone_identifier) { :subnets.ref.fnsplit(",") }
|
29
|
+
r.property(:launch_configuration_name) { :ecs_launch_configuration.ref }
|
30
|
+
r.property(:min_size) { cluster_size.to_i }
|
31
|
+
r.property(:max_size) { cluster_size.to_i + 1 }
|
32
|
+
r.property(:desired_capacity) { cluster_size.to_i }
|
33
|
+
r.property(:tags) do
|
34
|
+
[
|
35
|
+
{
|
36
|
+
"Key": "Name",
|
37
|
+
"Value": "#{environment} ECS host",
|
38
|
+
"PropagateAtLaunch": true
|
39
|
+
}
|
40
|
+
]
|
41
|
+
end
|
40
42
|
end
|
41
|
-
end
|
42
43
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
},
|
52
|
-
"commands": {
|
53
|
-
"01_add_instance_to_cluster": {
|
54
|
-
"command": "echo ECS_CLUSTER=${SfsEcsCluster} >> /etc/ecs/ecs.config".fnsub
|
44
|
+
resource :ecs_launch_configuration,
|
45
|
+
metadata: {
|
46
|
+
"AWS::CloudFormation::Init": {
|
47
|
+
"config": {
|
48
|
+
"packages": {
|
49
|
+
"yum": {
|
50
|
+
"collectd": []
|
51
|
+
}
|
55
52
|
},
|
56
|
-
"
|
57
|
-
"
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
"owner": "root",
|
64
|
-
"group": "root",
|
65
|
-
"content": "[main]\nstack=${AWS::StackId}\nregion=${AWS::Region}\n".fnsub
|
53
|
+
"commands": {
|
54
|
+
"01_add_instance_to_cluster": {
|
55
|
+
"command": "echo ECS_CLUSTER=${EcsCluster} >> /etc/ecs/ecs.config".fnsub
|
56
|
+
},
|
57
|
+
"02_enable_cloudwatch_agent": {
|
58
|
+
"command": "/opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -c ssm:${EcsCloudWatchParameter} -s".fnsub
|
59
|
+
}
|
66
60
|
},
|
67
|
-
"
|
68
|
-
"
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
"
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
61
|
+
"files": {
|
62
|
+
"/etc/cfn/cfn-hup.conf": {
|
63
|
+
"mode": 256,
|
64
|
+
"owner": "root",
|
65
|
+
"group": "root",
|
66
|
+
"content": "[main]\nstack=${AWS::StackId}\nregion=${AWS::Region}\n".fnsub
|
67
|
+
},
|
68
|
+
"/etc/cfn/hooks.d/cfn-auto-reloader.conf": {
|
69
|
+
"content": "[cfn-auto-reloader-hook]\ntriggers=post.update\npath=Resources.EcsLaunchConfiguration.Metadata.AWS::CloudFormation::Init\naction=/opt/aws/bin/cfn-init -v --region ${AWS::Region} --stack ${AWS::StackName} --resource EcsLaunchConfiguration\n".fnsub
|
70
|
+
}
|
71
|
+
},
|
72
|
+
"services": {
|
73
|
+
"sysvinit": {
|
74
|
+
"cfn-hup": {
|
75
|
+
"enabled": true,
|
76
|
+
"ensureRunning": true,
|
77
|
+
"files": [
|
78
|
+
"/etc/cfn/cfn-hup.conf",
|
79
|
+
"/etc/cfn/hooks.d/cfn-auto-reloader.conf"
|
80
|
+
]
|
81
|
+
}
|
80
82
|
}
|
81
83
|
}
|
82
84
|
}
|
83
85
|
}
|
84
|
-
}
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
86
|
+
},
|
87
|
+
type: "AWS::AutoScaling::LaunchConfiguration" do |r|
|
88
|
+
r.property(:image_id) { :ecs_ami.ref }
|
89
|
+
r.property(:instance_type) { cluster_instance_type }
|
90
|
+
r.property(:security_groups) do
|
91
|
+
[
|
92
|
+
:ecs_host_security_group.ref,
|
93
|
+
:load_balancer_security_group.ref # Not sure if necessary
|
94
|
+
]
|
95
|
+
end
|
96
|
+
r.property(:iam_instance_profile) { :ecs_instance_profile.ref }
|
97
|
+
r.property(:user_data) { "#!/bin/bash\nyum install -y https://s3.amazonaws.com/ec2-downloads-windows/SSMAgent/latest/linux_amd64/amazon-ssm-agent.rpm\nyum install -y https://s3.amazonaws.com/amazoncloudwatch-agent/amazon_linux/amd64/latest/amazon-cloudwatch-agent.rpm\nyum install -y aws-cfn-bootstrap hibagent \n/opt/aws/bin/cfn-init -v --region ${AWS::Region} --stack ${AWS::StackName} --resource EcsLaunchConfiguration\n/opt/aws/bin/cfn-signal -e $? --region ${AWS::Region} --stack ${AWS::StackName} --resource EcsAutoScalingGroup\n/usr/bin/enable-ec2-spot-hibernation\n".fnsub.fnbase64 }
|
95
98
|
end
|
96
|
-
r.property(:iam_instance_profile) { :ecs_instance_profile.ref }
|
97
|
-
r.property(:user_data) { "#!/bin/bash\nyum install -y https://s3.amazonaws.com/ec2-downloads-windows/SSMAgent/latest/linux_amd64/amazon-ssm-agent.rpm\nyum install -y https://s3.amazonaws.com/amazoncloudwatch-agent/amazon_linux/amd64/latest/amazon-cloudwatch-agent.rpm\nyum install -y aws-cfn-bootstrap hibagent \n/opt/aws/bin/cfn-init -v --region ${AWS::Region} --stack ${AWS::StackName} --resource EcsLaunchConfiguration\n/opt/aws/bin/cfn-signal -e $? --region ${AWS::Region} --stack ${AWS::StackName} --resource EcsAutoScalingGroup\n/usr/bin/enable-ec2-spot-hibernation\n".fnsub.fnbase64 }
|
98
|
-
end
|
99
99
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
100
|
+
ecs_ssm_parameter_value = {
|
101
|
+
"logs": {
|
102
|
+
"force_flush_interval": 5,
|
103
|
+
"logs_collected": {
|
104
|
+
"files": {
|
105
|
+
"collect_list": [
|
106
|
+
{
|
107
|
+
"file_path": "/var/log/messages",
|
108
|
+
"log_group_name": "${EcsCluster}-/var/log/messages",
|
109
|
+
"log_stream_name": "{instance_id}",
|
110
|
+
"timestamp_format": "%b %d %H:%M:%S"
|
111
|
+
},
|
112
|
+
{
|
113
|
+
"file_path": "/var/log/dmesg",
|
114
|
+
"log_group_name": "${EcsCluster}-/var/log/dmesg",
|
115
|
+
"log_stream_name": "{instance_id}"
|
116
|
+
},
|
117
|
+
{
|
118
|
+
"file_path": "/var/log/docker",
|
119
|
+
"log_group_name": "${EcsCluster}-/var/log/docker",
|
120
|
+
"log_stream_name": "{instance_id}",
|
121
|
+
"timestamp_format": "%Y-%m-%dT%H:%M:%S.%f"
|
122
|
+
},
|
123
|
+
{
|
124
|
+
"file_path": "/var/log/ecs/ecs-init.log",
|
125
|
+
"log_group_name": "${EcsCluster}-/var/log/ecs/ecs-init.log",
|
126
|
+
"log_stream_name": "{instance_id}",
|
127
|
+
"timestamp_format": "%Y-%m-%dT%H:%M:%SZ"
|
128
|
+
},
|
129
|
+
{
|
130
|
+
"file_path": "/var/log/ecs/ecs-agent.log.*",
|
131
|
+
"log_group_name": "${EcsCluster}-/var/log/ecs/ecs-agent.log",
|
132
|
+
"log_stream_name": "{instance_id}",
|
133
|
+
"timestamp_format": "%Y-%m-%dT%H:%M:%SZ"
|
134
|
+
},
|
135
|
+
{
|
136
|
+
"file_path": "/var/log/ecs/audit.log",
|
137
|
+
"log_group_name": "${EcsCluster}-/var/log/ecs/audit.log",
|
138
|
+
"log_stream_name": "{instance_id}",
|
139
|
+
"timestamp_format": "%Y-%m-%dT%H:%M:%SZ"
|
140
|
+
}
|
141
|
+
]
|
142
|
+
}
|
142
143
|
}
|
143
|
-
}
|
144
|
-
},
|
145
|
-
"metrics": {
|
146
|
-
"append_dimensions": {
|
147
|
-
"AutoScalingGroupName": "${!aws:AutoScalingGroupName}",
|
148
|
-
"InstanceId": "${!aws:InstanceId}",
|
149
|
-
"InstanceType": "${!aws:InstanceType}"
|
150
144
|
},
|
151
|
-
"
|
152
|
-
"
|
153
|
-
"
|
145
|
+
"metrics": {
|
146
|
+
"append_dimensions": {
|
147
|
+
"AutoScalingGroupName": "${!aws:AutoScalingGroupName}",
|
148
|
+
"InstanceId": "${!aws:InstanceId}",
|
149
|
+
"InstanceType": "${!aws:InstanceType}"
|
154
150
|
},
|
155
|
-
"
|
156
|
-
"
|
157
|
-
"
|
158
|
-
|
159
|
-
"
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
"
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
151
|
+
"metrics_collected": {
|
152
|
+
"collectd": {
|
153
|
+
"metrics_aggregation_interval": 60
|
154
|
+
},
|
155
|
+
"disk": {
|
156
|
+
"measurement": [
|
157
|
+
"used_percent"
|
158
|
+
],
|
159
|
+
"metrics_collection_interval": 60,
|
160
|
+
"resources": [
|
161
|
+
"/"
|
162
|
+
]
|
163
|
+
},
|
164
|
+
"mem": {
|
165
|
+
"measurement": [
|
166
|
+
"mem_used_percent"
|
167
|
+
],
|
168
|
+
"metrics_collection_interval": 60
|
169
|
+
},
|
170
|
+
"statsd": {
|
171
|
+
"metrics_aggregation_interval": 60,
|
172
|
+
"metrics_collection_interval": 10,
|
173
|
+
"service_address": ":8125"
|
174
|
+
}
|
174
175
|
}
|
175
176
|
}
|
176
177
|
}
|
177
|
-
}
|
178
178
|
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
end
|
186
|
-
|
187
|
-
resource :ecs_host_security_group,
|
188
|
-
type: "AWS::EC2::SecurityGroup" do |r|
|
189
|
-
r.property(:vpc_id) { :vpc.ref }
|
190
|
-
r.property(:group_description) { "Access to the ECS hosts and the tasks/containers that run on them" }
|
191
|
-
r.property(:security_group_ingress) do
|
192
|
-
[
|
193
|
-
{
|
194
|
-
"SourceSecurityGroupId": :load_balancer_security_group.ref,
|
195
|
-
"IpProtocol": -1
|
196
|
-
}
|
197
|
-
]
|
179
|
+
resource :ecs_cloud_watch_parameter,
|
180
|
+
type: "AWS::SSM::Parameter" do |r|
|
181
|
+
r.property(:description) { "ECS" }
|
182
|
+
r.property(:name) { "AmazonCloudWatch-${EcsCluster}-ECS".fnsub }
|
183
|
+
r.property(:type) { "String" }
|
184
|
+
r.property(:value) { JSON.pretty_generate(ecs_ssm_parameter_value).fnsub }
|
198
185
|
end
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
186
|
+
|
187
|
+
resource :ecs_host_security_group,
|
188
|
+
type: "AWS::EC2::SecurityGroup" do |r|
|
189
|
+
r.property(:vpc_id) { :vpc.ref }
|
190
|
+
r.property(:group_description) { "Access to the ECS hosts and the tasks/containers that run on them" }
|
191
|
+
r.property(:security_group_ingress) do
|
192
|
+
[
|
193
|
+
{
|
194
|
+
"SourceSecurityGroupId": :load_balancer_security_group.ref,
|
195
|
+
"IpProtocol": -1
|
196
|
+
}
|
197
|
+
]
|
198
|
+
end
|
199
|
+
r.property(:tags) do
|
200
|
+
[
|
201
|
+
{
|
202
|
+
"Key": "Name",
|
203
|
+
"Value": "#{environment}-ECS-Hosts"
|
204
|
+
}
|
205
|
+
]
|
206
|
+
end
|
206
207
|
end
|
207
|
-
end
|
208
208
|
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
209
|
+
resource :load_balancer_security_group,
|
210
|
+
type: "AWS::EC2::SecurityGroup" do |r|
|
211
|
+
r.property(:vpc_id) { :vpc.ref }
|
212
|
+
r.property(:group_description) { "Access to the load balancer that sits in front of ECS" }
|
213
|
+
r.property(:security_group_ingress) do
|
214
|
+
[
|
215
|
+
{
|
216
|
+
"CidrIp": "0.0.0.0/0",
|
217
|
+
"IpProtocol": -1
|
218
|
+
}
|
219
|
+
]
|
220
|
+
end
|
221
|
+
r.property(:tags) do
|
222
|
+
[
|
223
|
+
{
|
224
|
+
"Key": "Name",
|
225
|
+
"Value": "#{environment}-ECS-LoadBalancers"
|
226
|
+
}
|
227
|
+
]
|
228
|
+
end
|
220
229
|
end
|
221
|
-
|
222
|
-
|
230
|
+
|
231
|
+
ecs_role_assume_role_policy_document = {
|
232
|
+
"Statement": [
|
223
233
|
{
|
224
|
-
"
|
225
|
-
"
|
234
|
+
"Action": "sts:AssumeRole",
|
235
|
+
"Effect": "Allow",
|
236
|
+
"Principal": {
|
237
|
+
"Service": "ec2.amazonaws.com"
|
238
|
+
}
|
226
239
|
}
|
227
240
|
]
|
228
|
-
|
229
|
-
end
|
241
|
+
}
|
230
242
|
|
231
|
-
|
232
|
-
|
233
|
-
{
|
234
|
-
"Action": "sts:AssumeRole",
|
243
|
+
ecs_role_policy_document = {
|
244
|
+
"Statement": [{
|
235
245
|
"Effect": "Allow",
|
236
|
-
"
|
237
|
-
"
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
"
|
250
|
-
|
251
|
-
|
252
|
-
"ecs:StartTelemetrySession",
|
253
|
-
"ecs:Submit*",
|
254
|
-
"ecr:BatchCheckLayerAvailability",
|
255
|
-
"ecr:BatchGetImage",
|
256
|
-
"ecr:GetDownloadUrlForLayer",
|
257
|
-
"ecr:GetAuthorizationToken"
|
258
|
-
],
|
259
|
-
"Resource": "*"
|
260
|
-
}]
|
261
|
-
}
|
246
|
+
"Action": [
|
247
|
+
"ecs:CreateCluster",
|
248
|
+
"ecs:DeregisterContainerInstance",
|
249
|
+
"ecs:DiscoverPollEndpoint",
|
250
|
+
"ecs:Poll",
|
251
|
+
"ecs:RegisterContainerInstance",
|
252
|
+
"ecs:StartTelemetrySession",
|
253
|
+
"ecs:Submit*",
|
254
|
+
"ecr:BatchCheckLayerAvailability",
|
255
|
+
"ecr:BatchGetImage",
|
256
|
+
"ecr:GetDownloadUrlForLayer",
|
257
|
+
"ecr:GetAuthorizationToken"
|
258
|
+
],
|
259
|
+
"Resource": "*"
|
260
|
+
}]
|
261
|
+
}
|
262
262
|
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
263
|
+
resource :ecs_role,
|
264
|
+
type: "AWS::IAM::Role" do |r|
|
265
|
+
r.property(:path) { "/" }
|
266
|
+
r.property(:role_name) { "#{environment}-ECSRole-${AWS::Region}".fnsub }
|
267
|
+
r.property(:assume_role_policy_document) { JSON.pretty_generate(ecs_role_assume_role_policy_document) }
|
268
|
+
r.property(:managed_policy_arns) do
|
269
|
+
[
|
270
|
+
"arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforSSM",
|
271
|
+
"arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy",
|
272
|
+
"arn:aws:iam::aws:policy/service-role/AmazonEC2ContainerServiceforEC2Role"
|
273
|
+
]
|
274
|
+
end
|
275
|
+
r.property(:policies) do
|
276
|
+
[
|
277
|
+
{
|
278
|
+
"PolicyName": "ecs-service",
|
279
|
+
"PolicyDocument": JSON.pretty_generate(ecs_role_policy_document)
|
280
|
+
}
|
281
|
+
]
|
282
|
+
end
|
282
283
|
end
|
283
|
-
end
|
284
284
|
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
285
|
+
resource :ecs_instance_profile,
|
286
|
+
type: "AWS::IAM::InstanceProfile" do |r|
|
287
|
+
r.property(:path) { "/" }
|
288
|
+
r.property(:roles) do
|
289
|
+
[
|
290
|
+
:ecs_role.ref
|
291
|
+
]
|
292
|
+
end
|
292
293
|
end
|
293
|
-
end
|
294
294
|
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
{
|
299
|
-
"Version": "2012-10-17",
|
300
|
-
"Statement": {
|
301
|
-
"Action": [
|
302
|
-
"sts:AssumeRole"
|
303
|
-
],
|
304
|
-
"Effect": "Allow",
|
305
|
-
"Principal": {
|
306
|
-
"Service": [
|
307
|
-
"application-autoscaling.amazonaws.com"
|
308
|
-
]
|
309
|
-
}
|
310
|
-
}
|
311
|
-
}
|
312
|
-
end
|
313
|
-
r.property(:path) { "/" }
|
314
|
-
r.property(:policies) do
|
315
|
-
[
|
295
|
+
resource :ecs_service_auto_scaling_role,
|
296
|
+
type: "AWS::IAM::Role" do |r|
|
297
|
+
r.property(:assume_role_policy_document) do
|
316
298
|
{
|
317
|
-
"
|
318
|
-
"
|
319
|
-
"
|
320
|
-
"
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
"
|
326
|
-
|
327
|
-
],
|
328
|
-
"Resource": "*"
|
299
|
+
"Version": "2012-10-17",
|
300
|
+
"Statement": {
|
301
|
+
"Action": [
|
302
|
+
"sts:AssumeRole"
|
303
|
+
],
|
304
|
+
"Effect": "Allow",
|
305
|
+
"Principal": {
|
306
|
+
"Service": [
|
307
|
+
"application-autoscaling.amazonaws.com"
|
308
|
+
]
|
329
309
|
}
|
330
310
|
}
|
331
311
|
}
|
332
|
-
|
312
|
+
end
|
313
|
+
r.property(:path) { "/" }
|
314
|
+
r.property(:policies) do
|
315
|
+
[
|
316
|
+
{
|
317
|
+
"PolicyName": "ecs-service-autoscaling",
|
318
|
+
"PolicyDocument": {
|
319
|
+
"Statement": {
|
320
|
+
"Effect": "Allow",
|
321
|
+
"Action": [
|
322
|
+
"application-autoscaling:*",
|
323
|
+
"cloudwatch:DescribeAlarms",
|
324
|
+
"cloudwatch:PutMetricAlarm",
|
325
|
+
"ecs:DescribeServices",
|
326
|
+
"ecs:UpdateService"
|
327
|
+
],
|
328
|
+
"Resource": "*"
|
329
|
+
}
|
330
|
+
}
|
331
|
+
}
|
332
|
+
]
|
333
|
+
end
|
333
334
|
end
|
335
|
+
output :ecs_auto_scaling_role_arn,
|
336
|
+
value: :ecs_service_auto_scaling_role.ref(:arn)
|
334
337
|
end
|
335
|
-
|
336
338
|
output :ecs_cluster,
|
337
339
|
value: :ecs_cluster.ref
|
338
340
|
output :ecs_cluster_arn,
|
339
341
|
value: :ecs_cluster.ref(:arn)
|
340
|
-
output :ecs_auto_scaling_role_arn,
|
341
|
-
value: :ecs_service_auto_scaling_role.ref(:arn)
|
342
342
|
end
|
343
343
|
end
|
344
344
|
end
|