cfndsl 0.4.4 → 0.5.0.pre
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -13
- data/.rubocop.yml +23 -0
- data/Gemfile +4 -0
- data/Rakefile +19 -17
- data/bin/cfndsl +20 -20
- data/cfndsl.gemspec +16 -15
- data/lib/cfndsl.rb +62 -68
- data/lib/cfndsl/aws/cloud_formation_template.rb +16 -0
- data/lib/cfndsl/aws/types.rb +12 -0
- data/lib/cfndsl/{aws_types.yaml → aws/types.yaml} +0 -0
- data/lib/cfndsl/{Conditions.rb → conditions.rb} +5 -7
- data/lib/cfndsl/creation_policy.rb +21 -0
- data/lib/cfndsl/errors.rb +29 -0
- data/lib/cfndsl/generate_types.rb +154 -0
- data/lib/cfndsl/jsonable.rb +214 -0
- data/lib/cfndsl/mappings.rb +23 -0
- data/lib/cfndsl/metadata.rb +16 -0
- data/lib/cfndsl/module.rb +52 -51
- data/lib/cfndsl/names.rb +5 -5
- data/lib/cfndsl/orchestration_template.rb +173 -0
- data/lib/cfndsl/os/heat_template.rb +16 -0
- data/lib/cfndsl/os/types.rb +12 -0
- data/lib/cfndsl/{os_types.yaml → os/types.yaml} +11 -11
- data/lib/cfndsl/{Outputs.rb → outputs.rb} +3 -4
- data/lib/cfndsl/{Parameters.rb → parameters.rb} +12 -13
- data/lib/cfndsl/plurals.rb +34 -0
- data/lib/cfndsl/properties.rb +21 -0
- data/lib/cfndsl/rake_task.rb +9 -7
- data/lib/cfndsl/ref_check.rb +44 -0
- data/lib/cfndsl/{Resources.rb → resources.rb} +13 -15
- data/lib/cfndsl/types.rb +151 -0
- data/lib/cfndsl/update_policy.rb +25 -0
- data/lib/cfndsl/version.rb +1 -1
- data/sample/autoscale.rb +152 -158
- data/sample/autoscale2.rb +151 -155
- data/sample/circular.rb +30 -33
- data/sample/codedeploy.rb +35 -36
- data/sample/config_service.rb +120 -0
- data/sample/ecs.rb +39 -39
- data/sample/iam_policies.rb +82 -0
- data/sample/lambda.rb +20 -24
- data/sample/s3.rb +11 -11
- data/sample/t1.rb +7 -9
- data/sample/vpc_example.rb +50 -0
- data/sample/vpc_with_vpn_example.rb +97 -0
- data/spec/cfndsl_spec.rb +22 -11
- data/spec/fixtures/heattest.rb +13 -14
- data/spec/fixtures/test.rb +56 -53
- metadata +36 -30
- data/lib/cfndsl/CloudFormationTemplate.rb +0 -267
- data/lib/cfndsl/CreationPolicy.rb +0 -25
- data/lib/cfndsl/Errors.rb +0 -31
- data/lib/cfndsl/JSONable.rb +0 -235
- data/lib/cfndsl/Mappings.rb +0 -25
- data/lib/cfndsl/Metadata.rb +0 -22
- data/lib/cfndsl/Plurals.rb +0 -35
- data/lib/cfndsl/Properties.rb +0 -25
- data/lib/cfndsl/RefCheck.rb +0 -48
- data/lib/cfndsl/Types.rb +0 -309
- data/lib/cfndsl/UpdatePolicy.rb +0 -29
- data/sample/config-service.rb +0 -119
- data/sample/iam-policies.rb +0 -82
- data/sample/vpc-example.rb +0 -51
- data/sample/vpc-with-vpn-example.rb +0 -97
data/sample/autoscale.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
|
2
2
|
# We start things off by calling the CloudFormation function.
|
3
|
-
CloudFormation
|
3
|
+
CloudFormation do
|
4
4
|
# Declare the template format version
|
5
|
-
AWSTemplateFormatVersion
|
5
|
+
AWSTemplateFormatVersion '2010-09-09'
|
6
6
|
|
7
7
|
# As the DSL is really ruby, we get all of the different
|
8
8
|
# ways to quote strings that come with ruby.
|
9
|
-
Description
|
9
|
+
Description %/
|
10
10
|
Create a multi-az, load balanced, Auto Scaled sample web site. The
|
11
11
|
Auto Scaling trigger is based on the CPU utilization of the web
|
12
12
|
servers. The AMI is chosen based on the region in which the stack is
|
@@ -24,220 +24,214 @@ a stack from this template.
|
|
24
24
|
# We can declare Parameters anywhere in the CloudFormation
|
25
25
|
# block - these will get rolled up into the Parameters container
|
26
26
|
# in the output.
|
27
|
-
Parameter(
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
27
|
+
Parameter('InstanceType') do
|
28
|
+
Description 'Type of EC2 instance to launch'
|
29
|
+
Type 'String'
|
30
|
+
Default 'm1.small'
|
31
|
+
end
|
32
32
|
|
33
|
-
Parameter(
|
34
|
-
Description
|
35
|
-
Type
|
36
|
-
Default
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
33
|
+
Parameter('WebServerPort') do
|
34
|
+
Description 'The TCP port for the Web Server'
|
35
|
+
Type 'String'
|
36
|
+
Default '8888'
|
37
|
+
end
|
38
|
+
|
39
|
+
Parameter('KeyName') do
|
40
|
+
Description 'The EC2 Key Pair to allow SSH access to the instances'
|
41
|
+
Type 'String'
|
42
|
+
end
|
42
43
|
|
43
|
-
# The same kind of thing for parameters works for mappings,
|
44
|
+
# The same kind of thing for parameters works for mappings,
|
44
45
|
# except that there is not a special object declared for mappings,
|
45
46
|
# so we just have to build a hash of hashes which will be turned
|
46
47
|
# directly into json.
|
47
48
|
|
48
|
-
Mapping(
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
49
|
+
Mapping('AWSRegionArch2AMI',
|
50
|
+
'us-east-1' => { '32' => 'ami-6411e20d', '64' => 'ami-7a11e213' },
|
51
|
+
'us-west-1' => { '32' => 'ami-c9c7978c', '64' => 'ami-cfc7978a' },
|
52
|
+
'eu-west-1' => { '32' => 'ami-37c2f643', '64' => 'ami-31c2f645' },
|
53
|
+
'ap-southeast-1' => { '32' => 'ami-66f28c34', '64' => 'ami-60f28c32' },
|
54
|
+
'ap-northeast-1' => { '32' => 'ami-9c03a89d', '64' => 'ami-a003a8a1' }
|
55
|
+
)
|
56
56
|
|
57
57
|
# We can also write arbitrary ruby code
|
58
58
|
|
59
59
|
# Here we build up a ruby hash
|
60
60
|
architectures = {}
|
61
|
-
[
|
62
|
-
"m2.2xlarge", "m2.4xlarge", "c1.xlarge", "cc1.4xlarge"
|
63
|
-
].each do |arch|
|
61
|
+
['t1.micro', 'm1.large', 'm1.xlarge', 'm2.xlarge', 'm2.2xlarge', 'm2.4xlarge', 'c1.xlarge', 'cc1.4xlarge'].each do |arch|
|
64
62
|
# Iterate through the 64 bit machines to build a mapping for
|
65
63
|
# 64 bit architecture
|
66
|
-
architectures[arch] = {
|
64
|
+
architectures[arch] = { 'Arch' => '64' }
|
67
65
|
end
|
68
66
|
|
69
|
-
[
|
70
|
-
].each do |arch|
|
67
|
+
['m1.small', 'c1.medium'].each do |arch|
|
71
68
|
# iterate throught he 32 bit machine to build a mapping for
|
72
69
|
# 32 bit architectures
|
73
|
-
architectures[arch] = {
|
70
|
+
architectures[arch] = { 'Arch' => '32' }
|
74
71
|
end
|
75
|
-
|
76
|
-
Mapping(
|
72
|
+
|
73
|
+
Mapping('AWSInstanceType2Arch', architectures)
|
77
74
|
# This will add a mapping entry equivalent to the following to the
|
78
75
|
# template:
|
79
76
|
#
|
80
|
-
#
|
81
|
-
#
|
82
|
-
#
|
83
|
-
#
|
84
|
-
#
|
85
|
-
#
|
86
|
-
#
|
87
|
-
#
|
88
|
-
#
|
89
|
-
#
|
90
|
-
#
|
77
|
+
# 'AWSInstanceType2Arch' : {
|
78
|
+
# 'm2.4xlarge' : { 'Arch' : '64' },
|
79
|
+
# 'c1.xlarge' : { 'Arch' : '64' },
|
80
|
+
# 'c1.medium' : { 'Arch' : '32' },
|
81
|
+
# 'm1.xlarge' : { 'Arch' : '64' },
|
82
|
+
# 'm1.large' : { 'Arch' : '64' },
|
83
|
+
# 't1.micro' : { 'Arch' : '64' },
|
84
|
+
# 'm1.small' : { 'Arch' : '32' },
|
85
|
+
# 'm2.2xlarge' : { 'Arch' : '64' },
|
86
|
+
# 'm2.xlarge' : { 'Arch' : '64' },
|
87
|
+
# 'cc1.4xlarge' : { 'Arch' : '64' }
|
91
88
|
# }
|
92
89
|
|
93
|
-
|
94
90
|
# Resources work similar to Parameters
|
95
|
-
Resource(
|
96
|
-
Type
|
91
|
+
Resource('WebServerGroup') do
|
92
|
+
Type 'AWS::AutoScaling::AutoScalingGroup'
|
97
93
|
|
98
94
|
# To call aws template defined functions, call them like
|
99
95
|
# functios (leaving out the double colons). For example
|
100
96
|
# the following:
|
101
|
-
Property(
|
97
|
+
Property('AvailabilityZones', FnGetAZs(''))
|
102
98
|
# will generate JSON that includes
|
103
|
-
# {
|
99
|
+
# { 'Fn::GetAZs : '' }
|
104
100
|
# as the value of the AvailabilityZones property for the
|
105
|
-
#
|
101
|
+
# 'WebServerGroup' reqource.
|
106
102
|
|
107
103
|
# The same works for references
|
108
|
-
Property(
|
109
|
-
Property(
|
110
|
-
Property(
|
104
|
+
Property('LaunchConfigurationName', Ref('LaunchConfig'))
|
105
|
+
Property('MinSize', '1')
|
106
|
+
Property('MaxSize', '3')
|
111
107
|
|
112
|
-
# If you need to set a property value to a JSON array in
|
108
|
+
# If you need to set a property value to a JSON array in
|
113
109
|
# the template, you can just use a ruby array in the DSL.
|
114
|
-
Property(
|
115
|
-
|
116
|
-
}
|
110
|
+
Property('LoadBalancerNames', [Ref('ElasticLoadBalancer')])
|
111
|
+
end
|
117
112
|
|
118
113
|
# You can use either strings or symbols for
|
119
114
|
# Resource/Parameter/Mapping/Output names
|
120
|
-
Resource(
|
121
|
-
Type
|
122
|
-
|
123
|
-
Property(
|
124
|
-
Property(
|
125
|
-
|
126
|
-
|
127
|
-
Property(
|
128
|
-
Property(
|
129
|
-
Property(
|
130
|
-
|
115
|
+
Resource(:LaunchConfig) do
|
116
|
+
Type 'AWS::AutoScaling::LaunchConfiguration'
|
117
|
+
|
118
|
+
Property('KeyName', Ref('KeyName'))
|
119
|
+
Property('ImageId',
|
120
|
+
FnFindInMap('AWSRegionArch2AMI', Ref('AWS::Region'),
|
121
|
+
FnFindInMap('AWSInstanceType2Arch', Ref('InstanceType'), 'Arch')))
|
122
|
+
Property('UserData', FnBase64(Ref('WebServerPort')))
|
123
|
+
Property('SecurityGroups', [Ref('InstanceSecurityGroup')])
|
124
|
+
Property('InstanceType', Ref('InstanceType'))
|
125
|
+
end
|
131
126
|
|
127
|
+
Resource('WebServerScaleUpPolicy') do
|
128
|
+
Type 'AWS::AutoScaling::ScalingPolicy'
|
129
|
+
Property('AdjustmentType', 'ChangeInCapacity')
|
130
|
+
Property('AutoScalingGroupName', Ref('WebServerGroup'))
|
131
|
+
Property('Cooldown', '60')
|
132
|
+
Property('ScalingAdjustment', '1')
|
133
|
+
end
|
132
134
|
|
133
|
-
Resource(
|
134
|
-
Type
|
135
|
-
Property(
|
136
|
-
Property(
|
137
|
-
Property(
|
138
|
-
Property(
|
139
|
-
|
140
|
-
|
141
|
-
Resource("WebServerScaleDownPolicy") {
|
142
|
-
Type "AWS::AutoScaling::ScalingPolicy"
|
143
|
-
Property("AdjustmentType", "ChangeInCapacity")
|
144
|
-
Property("AutoScalingGroupName", Ref( "WebServerGroup" ))
|
145
|
-
Property("Cooldown", "60")
|
146
|
-
Property("ScalingAdjustment", "-1")
|
147
|
-
}
|
148
|
-
|
135
|
+
Resource('WebServerScaleDownPolicy') do
|
136
|
+
Type 'AWS::AutoScaling::ScalingPolicy'
|
137
|
+
Property('AdjustmentType', 'ChangeInCapacity')
|
138
|
+
Property('AutoScalingGroupName', Ref('WebServerGroup'))
|
139
|
+
Property('Cooldown', '60')
|
140
|
+
Property('ScalingAdjustment', '-1')
|
141
|
+
end
|
149
142
|
|
150
143
|
# You can use ruby language constructs to keep from repeating
|
151
144
|
# yourself
|
152
145
|
|
153
146
|
# declare an aray - we are going to use it to collect some
|
154
147
|
# resources that we create
|
155
|
-
alarms = []
|
148
|
+
alarms = []
|
156
149
|
|
157
|
-
# When we declare a resource with
|
150
|
+
# When we declare a resource with 'Resource', we are
|
158
151
|
# actually calling a method on CfnDsl::CloudFormationTemplate
|
159
152
|
# that sets up the resource, and then returns it. We can use
|
160
153
|
# the return value for other means.
|
161
|
-
alarms.push Resource(
|
162
|
-
Type
|
163
|
-
Property(
|
164
|
-
Property(
|
165
|
-
Property(
|
166
|
-
Property(
|
154
|
+
alarms.push Resource('CPUAlarmHigh') {
|
155
|
+
Type 'AWS::CloudWatch::Alarm'
|
156
|
+
Property('AlarmDescription', 'Scale-up if CPU > 90% for 10 minutes')
|
157
|
+
Property('Threshold', '90')
|
158
|
+
Property('AlarmActions', [Ref('WebServerScaleUpPolicy')])
|
159
|
+
Property('ComparisonOperator', 'GreaterThanThreshold')
|
167
160
|
}
|
168
161
|
|
169
162
|
# Declare a second alarm resource and add it to our list
|
170
|
-
alarms.push Resource(
|
171
|
-
Type
|
172
|
-
Property(
|
173
|
-
Property(
|
174
|
-
Property(
|
175
|
-
Property(
|
163
|
+
alarms.push Resource('CPUAlarmLow') {
|
164
|
+
Type 'AWS::CloudWatch::Alarm'
|
165
|
+
Property('AlarmDescription', 'Scale-down if CPU < 70% for 10 minutes')
|
166
|
+
Property('Threshold', '70')
|
167
|
+
Property('AlarmActions', [Ref('WebServerScaleDownPolicy')])
|
168
|
+
Property('ComparisonOperator', 'LessThanThreshold')
|
176
169
|
}
|
177
170
|
|
178
171
|
# Ok, the alarms that we previously declared actually share a bunch
|
179
172
|
# of property declarations. Here we iterate through the alarms and
|
180
|
-
# call declare on each one, passing in a code block. This works the
|
181
|
-
# same as the declarations placed in the code blocks that went along
|
173
|
+
# call declare on each one, passing in a code block. This works the
|
174
|
+
# same as the declarations placed in the code blocks that went along
|
182
175
|
# with the call to Resource that was used to create the resouce above.
|
183
176
|
alarms.each do |alarm|
|
184
|
-
alarm.declare
|
185
|
-
Property(
|
186
|
-
Property(
|
187
|
-
Property(
|
188
|
-
Property(
|
189
|
-
Property(
|
190
|
-
Property(
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
}
|
177
|
+
alarm.declare do
|
178
|
+
Property('MetricName', 'CPUUtilization')
|
179
|
+
Property('Namespace', 'AWS/EC2')
|
180
|
+
Property('Statistic', 'Average')
|
181
|
+
Property('Period', '300')
|
182
|
+
Property('EvaluationPeriods', '2')
|
183
|
+
Property('Dimensions',
|
184
|
+
[
|
185
|
+
{
|
186
|
+
'Name' => 'AutoScalingGroupName',
|
187
|
+
'Value' => Ref('WebServerGroup')
|
188
|
+
}])
|
189
|
+
end
|
198
190
|
end
|
199
191
|
|
192
|
+
Resource('ElasticLoadBalancer') do
|
193
|
+
Type 'AWS::ElasticLoadBalancing::LoadBalancer'
|
194
|
+
Property('AvailabilityZones', FnGetAZs(''))
|
195
|
+
Property('Listeners',
|
196
|
+
[
|
197
|
+
{
|
198
|
+
'LoadBalancerPort' => '80',
|
199
|
+
'InstancePort' => Ref('WebServerPort'),
|
200
|
+
'Protocol' => 'HTTP'
|
201
|
+
}])
|
202
|
+
Property('HealthCheck',
|
203
|
+
# FnFormat replaces %0, %1, etc with passed in parameters
|
204
|
+
# Note that it renders to a call to Fn::Join in the json.
|
205
|
+
'Target' => FnFormat('HTTP:%0/', Ref('WebServerPort')),
|
206
|
+
'HealthyThreshold' => '3',
|
207
|
+
'UnhealthyThreshold' => '5',
|
208
|
+
'Interval' => '30',
|
209
|
+
'Timeout' => '5'
|
210
|
+
)
|
211
|
+
end
|
200
212
|
|
201
|
-
Resource(
|
202
|
-
Type
|
203
|
-
Property(
|
204
|
-
Property(
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
Resource("InstanceSecurityGroup" ) {
|
221
|
-
Type "AWS::EC2::SecurityGroup"
|
222
|
-
Property("GroupDescription" , "Enable SSH access and HTTP access on the inbound port")
|
223
|
-
Property("SecurityGroupIngress", [ {
|
224
|
-
"IpProtocol" => "tcp",
|
225
|
-
"FromPort" => "22",
|
226
|
-
"ToPort" => "22",
|
227
|
-
"CidrIp" => "0.0.0.0/0"
|
228
|
-
},
|
229
|
-
{
|
230
|
-
"IpProtocol" => "tcp",
|
231
|
-
"FromPort" => Ref( "WebServerPort" ),
|
232
|
-
"ToPort" => Ref( "WebServerPort" ),
|
233
|
-
"SourceSecurityGroupOwnerId" => FnGetAtt("ElasticLoadBalancer", "SourceSecurityGroup.OwnerAlias"),
|
234
|
-
"SourceSecurityGroupName" => FnGetAtt("ElasticLoadBalancer", "SourceSecurityGroup.GroupName")
|
235
|
-
} ])
|
236
|
-
}
|
237
|
-
|
238
|
-
Output( "URL" ) {
|
239
|
-
Description "The URL of the website"
|
240
|
-
Value FnJoin( "", [ "http://", FnGetAtt( "ElasticLoadBalancer", "DNSName" ) ] )
|
241
|
-
}
|
213
|
+
Resource('InstanceSecurityGroup') do
|
214
|
+
Type 'AWS::EC2::SecurityGroup'
|
215
|
+
Property('GroupDescription', 'Enable SSH access and HTTP access on the inbound port')
|
216
|
+
Property('SecurityGroupIngress',
|
217
|
+
[
|
218
|
+
{
|
219
|
+
'IpProtocol' => 'tcp',
|
220
|
+
'FromPort' => '22',
|
221
|
+
'ToPort' => '22',
|
222
|
+
'CidrIp' => '0.0.0.0/0'
|
223
|
+
},
|
224
|
+
{
|
225
|
+
'IpProtocol' => 'tcp',
|
226
|
+
'FromPort' => Ref('WebServerPort'),
|
227
|
+
'ToPort' => Ref('WebServerPort'),
|
228
|
+
'SourceSecurityGroupOwnerId' => FnGetAtt('ElasticLoadBalancer', 'SourceSecurityGroup.OwnerAlias'),
|
229
|
+
'SourceSecurityGroupName' => FnGetAtt('ElasticLoadBalancer', 'SourceSecurityGroup.GroupName')
|
230
|
+
}])
|
231
|
+
end
|
242
232
|
|
243
|
-
|
233
|
+
Output('URL') do
|
234
|
+
Description 'The URL of the website'
|
235
|
+
Value FnJoin('', ['http://', FnGetAtt('ElasticLoadBalancer', 'DNSName')])
|
236
|
+
end
|
237
|
+
end
|
data/sample/autoscale2.rb
CHANGED
@@ -1,12 +1,11 @@
|
|
1
|
-
|
2
1
|
# We start things off by calling the CloudFormation function.
|
3
|
-
CloudFormation
|
2
|
+
CloudFormation do
|
4
3
|
# Declare the template format version
|
5
|
-
AWSTemplateFormatVersion
|
4
|
+
AWSTemplateFormatVersion '2010-09-09'
|
6
5
|
|
7
6
|
# As the DSL is really ruby, we get all of the different
|
8
7
|
# ways to quote strings that come with ruby.
|
9
|
-
Description
|
8
|
+
Description %/
|
10
9
|
Create a multi-az, load balanced, Auto Scaled sample web site. The
|
11
10
|
Auto Scaling trigger is based on the CPU utilization of the web
|
12
11
|
servers. The AMI is chosen based on the region in which the stack is
|
@@ -24,208 +23,205 @@ a stack from this template.
|
|
24
23
|
# We can declare Parameters anywhere in the CloudFormation
|
25
24
|
# block - these will get rolled up into the Parameters container
|
26
25
|
# in the output.
|
27
|
-
Parameter(
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
26
|
+
Parameter('InstanceType') do
|
27
|
+
Description 'Type of EC2 instance to launch'
|
28
|
+
Type 'String'
|
29
|
+
Default 'm1.small'
|
30
|
+
end
|
32
31
|
|
33
|
-
Parameter(
|
34
|
-
Description
|
35
|
-
Type
|
36
|
-
Default
|
37
|
-
|
38
|
-
Parameter("KeyName") {
|
39
|
-
Description "The EC2 Key Pair to allow SSH access to the instances"
|
40
|
-
Type "String"
|
41
|
-
}
|
32
|
+
Parameter('WebServerPort') do
|
33
|
+
Description 'The TCP port for the Web Server'
|
34
|
+
Type 'String'
|
35
|
+
Default '8888'
|
36
|
+
end
|
42
37
|
|
43
|
-
|
38
|
+
Parameter('KeyName') do
|
39
|
+
Description 'The EC2 Key Pair to allow SSH access to the instances'
|
40
|
+
Type 'String'
|
41
|
+
end
|
42
|
+
|
43
|
+
# The same kind of thing for parameters works for mappings,
|
44
44
|
# except that there is not a special object declared for mappings,
|
45
45
|
# so we just have to build a hash of hashes which will be turned
|
46
46
|
# directly into json.
|
47
47
|
|
48
|
-
Mapping(
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
48
|
+
Mapping('AWSRegionArch2AMI',
|
49
|
+
'us-east-1' => { '32' => 'ami-6411e20d', '64' => 'ami-7a11e213' },
|
50
|
+
'us-west-1' => { '32' => 'ami-c9c7978c', '64' => 'ami-cfc7978a' },
|
51
|
+
'eu-west-1' => { '32' => 'ami-37c2f643', '64' => 'ami-31c2f645' },
|
52
|
+
'ap-southeast-1' => { '32' => 'ami-66f28c34', '64' => 'ami-60f28c32' },
|
53
|
+
'ap-northeast-1' => { '32' => 'ami-9c03a89d', '64' => 'ami-a003a8a1' }
|
54
|
+
)
|
56
55
|
|
57
56
|
# We can also write arbitrary ruby code
|
58
57
|
|
59
58
|
# Here we build up a ruby hash
|
60
59
|
architectures = {}
|
61
|
-
[
|
62
|
-
"m2.2xlarge", "m2.4xlarge", "c1.xlarge", "cc1.4xlarge"
|
63
|
-
].each do |arch|
|
60
|
+
['t1.micro', 'm1.large', 'm1.xlarge', 'm2.xlarge', 'm2.2xlarge', 'm2.4xlarge', 'c1.xlarge', 'cc1.4xlarge'].each do |arch|
|
64
61
|
# Iterate through the 64 bit machines to build a mapping for
|
65
62
|
# 64 bit architecture
|
66
|
-
architectures[arch] = {
|
63
|
+
architectures[arch] = { 'Arch' => '64' }
|
67
64
|
end
|
68
65
|
|
69
|
-
[
|
70
|
-
].each do |arch|
|
66
|
+
['m1.small', 'c1.medium'].each do |arch|
|
71
67
|
# iterate throught he 32 bit machine to build a mapping for
|
72
68
|
# 32 bit architectures
|
73
|
-
architectures[arch] = {
|
69
|
+
architectures[arch] = { 'Arch' => '32' }
|
74
70
|
end
|
75
|
-
|
76
|
-
Mapping(
|
71
|
+
|
72
|
+
Mapping('AWSInstanceType2Arch', architectures)
|
77
73
|
# This will add a mapping entry equivalent to the following to the
|
78
74
|
# template:
|
79
75
|
#
|
80
|
-
#
|
81
|
-
#
|
82
|
-
#
|
83
|
-
#
|
84
|
-
#
|
85
|
-
#
|
86
|
-
#
|
87
|
-
#
|
88
|
-
#
|
89
|
-
#
|
90
|
-
#
|
76
|
+
# 'AWSInstanceType2Arch' : {
|
77
|
+
# 'm2.4xlarge' : { 'Arch' : '64' },
|
78
|
+
# 'c1.xlarge' : { 'Arch' : '64' },
|
79
|
+
# 'c1.medium' : { 'Arch' : '32' },
|
80
|
+
# 'm1.xlarge' : { 'Arch' : '64' },
|
81
|
+
# 'm1.large' : { 'Arch' : '64' },
|
82
|
+
# 't1.micro' : { 'Arch' : '64' },
|
83
|
+
# 'm1.small' : { 'Arch' : '32' },
|
84
|
+
# 'm2.2xlarge' : { 'Arch' : '64' },
|
85
|
+
# 'm2.xlarge' : { 'Arch' : '64' },
|
86
|
+
# 'cc1.4xlarge' : { 'Arch' : '64' }
|
91
87
|
# }
|
92
88
|
|
93
89
|
# Resources work similar to Parameters
|
94
|
-
AutoScalingGroup(
|
95
|
-
UpdatePolicy(
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
AvailabilityZones FnGetAZs(
|
101
|
-
LaunchConfigurationName Ref(
|
90
|
+
AutoScalingGroup('WebServerGroup') do
|
91
|
+
UpdatePolicy('AutoScalingRollingUpdate',
|
92
|
+
'MinInstancesInService' => '1',
|
93
|
+
'MaxBatchSize' => '1',
|
94
|
+
'PauseTime' => 'PT15M'
|
95
|
+
)
|
96
|
+
AvailabilityZones FnGetAZs('')
|
97
|
+
LaunchConfigurationName Ref('LaunchConfig')
|
102
98
|
MinSize 1
|
103
99
|
MaxSize 3
|
104
|
-
LoadBalancerNames Ref(
|
105
|
-
|
100
|
+
LoadBalancerNames Ref('ElasticLoadBalancer')
|
101
|
+
end
|
106
102
|
|
107
103
|
# You can use either strings or symbols for
|
108
104
|
# Resource/Parameter/Mapping/Output names
|
109
|
-
LaunchConfiguration(
|
110
|
-
KeyName Ref(
|
111
|
-
ImageId FnFindInMap(
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
UserData FnBase64(
|
116
|
-
SecurityGroup Ref(
|
117
|
-
InstanceType Ref(
|
118
|
-
|
105
|
+
LaunchConfiguration(:LaunchConfig) do
|
106
|
+
KeyName Ref('KeyName')
|
107
|
+
ImageId FnFindInMap('AWSRegionArch2AMI',
|
108
|
+
Ref('AWS::Region'),
|
109
|
+
FnFindInMap('AWSInstanceType2Arch', Ref('InstanceType'), 'Arch'))
|
110
|
+
|
111
|
+
UserData FnBase64(Ref('WebServerPort'))
|
112
|
+
SecurityGroup Ref('InstanceSecurityGroup')
|
113
|
+
InstanceType Ref('InstanceType')
|
114
|
+
end
|
119
115
|
|
116
|
+
Resource('WebServerScaleUpPolicy') do
|
117
|
+
Type 'AWS::AutoScaling::ScalingPolicy'
|
118
|
+
Property('AdjustmentType', 'ChangeInCapacity')
|
119
|
+
Property('AutoScalingGroupName', Ref('WebServerGroup'))
|
120
|
+
Property('Cooldown', '60')
|
121
|
+
Property('ScalingAdjustment', '1')
|
122
|
+
end
|
120
123
|
|
121
|
-
Resource(
|
122
|
-
Type
|
123
|
-
Property(
|
124
|
-
Property(
|
125
|
-
Property(
|
126
|
-
Property(
|
127
|
-
|
128
|
-
|
129
|
-
Resource("WebServerScaleDownPolicy") {
|
130
|
-
Type "AWS::AutoScaling::ScalingPolicy"
|
131
|
-
Property("AdjustmentType", "ChangeInCapacity")
|
132
|
-
Property("AutoScalingGroupName", Ref( "WebServerGroup" ))
|
133
|
-
Property("Cooldown", "60")
|
134
|
-
Property("ScalingAdjustment", "-1")
|
135
|
-
}
|
136
|
-
|
124
|
+
Resource('WebServerScaleDownPolicy') do
|
125
|
+
Type 'AWS::AutoScaling::ScalingPolicy'
|
126
|
+
Property('AdjustmentType', 'ChangeInCapacity')
|
127
|
+
Property('AutoScalingGroupName', Ref('WebServerGroup'))
|
128
|
+
Property('Cooldown', '60')
|
129
|
+
Property('ScalingAdjustment', '-1')
|
130
|
+
end
|
137
131
|
|
138
132
|
# You can use ruby language constructs to keep from repeating
|
139
133
|
# yourself
|
140
134
|
|
141
135
|
# declare an aray - we are going to use it to collect some
|
142
136
|
# resources that we create
|
143
|
-
alarms = []
|
137
|
+
alarms = []
|
144
138
|
|
145
|
-
# When we declare a resource with
|
139
|
+
# When we declare a resource with 'Resource', we are
|
146
140
|
# actually calling a method on CfnDsl::CloudFormationTemplate
|
147
141
|
# that sets up the resource, and then returns it. We can use
|
148
142
|
# the return value for other means.
|
149
|
-
alarms.push Resource(
|
150
|
-
Type
|
151
|
-
Property(
|
152
|
-
Property(
|
153
|
-
Property(
|
154
|
-
Property(
|
143
|
+
alarms.push Resource('CPUAlarmHigh') {
|
144
|
+
Type 'AWS::CloudWatch::Alarm'
|
145
|
+
Property('AlarmDescription', 'Scale-up if CPU > 90% for 10 minutes')
|
146
|
+
Property('Threshold', '90')
|
147
|
+
Property('AlarmActions', [Ref('WebServerScaleUpPolicy')])
|
148
|
+
Property('ComparisonOperator', 'GreaterThanThreshold')
|
155
149
|
}
|
156
150
|
|
157
151
|
# Declare a second alarm resource and add it to our list
|
158
|
-
alarms.push Resource(
|
159
|
-
Type
|
160
|
-
Property(
|
161
|
-
Property(
|
162
|
-
Property(
|
163
|
-
Property(
|
152
|
+
alarms.push Resource('CPUAlarmLow') {
|
153
|
+
Type 'AWS::CloudWatch::Alarm'
|
154
|
+
Property('AlarmDescription', 'Scale-down if CPU < 70% for 10 minutes')
|
155
|
+
Property('Threshold', '70')
|
156
|
+
Property('AlarmActions', [Ref('WebServerScaleDownPolicy')])
|
157
|
+
Property('ComparisonOperator', 'LessThanThreshold')
|
164
158
|
}
|
165
159
|
|
166
160
|
# Ok, the alarms that we previously declared actually share a bunch
|
167
161
|
# of property declarations. Here we iterate through the alarms and
|
168
|
-
# call declare on each one, passing in a code block. This works the
|
169
|
-
# same as the declarations placed in the code blocks that went along
|
162
|
+
# call declare on each one, passing in a code block. This works the
|
163
|
+
# same as the declarations placed in the code blocks that went along
|
170
164
|
# with the call to Resource that was used to create the resouce above.
|
171
165
|
alarms.each do |alarm|
|
172
|
-
alarm.declare
|
173
|
-
Property(
|
174
|
-
Property(
|
175
|
-
Property(
|
176
|
-
Property(
|
177
|
-
Property(
|
178
|
-
Property(
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
166
|
+
alarm.declare do
|
167
|
+
Property('MetricName', 'CPUUtilization')
|
168
|
+
Property('Namespace', 'AWS/EC2')
|
169
|
+
Property('Statistic', 'Average')
|
170
|
+
Property('Period', '300')
|
171
|
+
Property('EvaluationPeriods', '2')
|
172
|
+
Property('Dimensions',
|
173
|
+
[
|
174
|
+
{
|
175
|
+
'Name' => 'AutoScalingGroupName',
|
176
|
+
'Value' => Ref('WebServerGroup')
|
177
|
+
}
|
178
|
+
])
|
179
|
+
end
|
186
180
|
end
|
187
181
|
|
182
|
+
Resource('ElasticLoadBalancer') do
|
183
|
+
Type 'AWS::ElasticLoadBalancing::LoadBalancer'
|
184
|
+
Property('AvailabilityZones', FnGetAZs(''))
|
185
|
+
Property('Listeners',
|
186
|
+
[
|
187
|
+
{
|
188
|
+
'LoadBalancerPort' => '80',
|
189
|
+
'InstancePort' => Ref('WebServerPort'),
|
190
|
+
'Protocol' => 'HTTP'
|
191
|
+
}])
|
192
|
+
Property('HealthCheck',
|
193
|
+
# FnFormat replaces %0, %1, etc with passed in parameters
|
194
|
+
# Note that it renders to a call to Fn::Join in the json.
|
195
|
+
'Target' => FnFormat('HTTP:%0/', Ref('WebServerPort')),
|
196
|
+
'HealthyThreshold' => '3',
|
197
|
+
'UnhealthyThreshold' => '5',
|
198
|
+
'Interval' => '30',
|
199
|
+
'Timeout' => '5'
|
200
|
+
)
|
201
|
+
end
|
188
202
|
|
189
|
-
Resource(
|
190
|
-
Type
|
191
|
-
Property(
|
192
|
-
Property(
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
Resource("InstanceSecurityGroup" ) {
|
209
|
-
Type "AWS::EC2::SecurityGroup"
|
210
|
-
Property("GroupDescription" , "Enable SSH access and HTTP access on the inbound port")
|
211
|
-
Property("SecurityGroupIngress", [ {
|
212
|
-
"IpProtocol" => "tcp",
|
213
|
-
"FromPort" => "22",
|
214
|
-
"ToPort" => "22",
|
215
|
-
"CidrIp" => "0.0.0.0/0"
|
216
|
-
},
|
217
|
-
{
|
218
|
-
"IpProtocol" => "tcp",
|
219
|
-
"FromPort" => Ref( "WebServerPort" ),
|
220
|
-
"ToPort" => Ref( "WebServerPort" ),
|
221
|
-
"SourceSecurityGroupOwnerId" => FnGetAtt("ElasticLoadBalancer", "SourceSecurityGroup.OwnerAlias"),
|
222
|
-
"SourceSecurityGroupName" => FnGetAtt("ElasticLoadBalancer", "SourceSecurityGroup.GroupName")
|
223
|
-
} ])
|
224
|
-
}
|
225
|
-
|
226
|
-
Output( "URL" ) {
|
227
|
-
Description "The URL of the website"
|
228
|
-
Value FnJoin( "", [ "http://", FnGetAtt( "ElasticLoadBalancer", "DNSName" ) ] )
|
229
|
-
}
|
203
|
+
Resource('InstanceSecurityGroup') do
|
204
|
+
Type 'AWS::EC2::SecurityGroup'
|
205
|
+
Property('GroupDescription', 'Enable SSH access and HTTP access on the inbound port')
|
206
|
+
Property('SecurityGroupIngress',
|
207
|
+
[
|
208
|
+
{
|
209
|
+
'IpProtocol' => 'tcp',
|
210
|
+
'FromPort' => '22',
|
211
|
+
'ToPort' => '22',
|
212
|
+
'CidrIp' => '0.0.0.0/0'
|
213
|
+
},
|
214
|
+
{
|
215
|
+
'IpProtocol' => 'tcp',
|
216
|
+
'FromPort' => Ref('WebServerPort'),
|
217
|
+
'ToPort' => Ref('WebServerPort'),
|
218
|
+
'SourceSecurityGroupOwnerId' => FnGetAtt('ElasticLoadBalancer', 'SourceSecurityGroup.OwnerAlias'),
|
219
|
+
'SourceSecurityGroupName' => FnGetAtt('ElasticLoadBalancer', 'SourceSecurityGroup.GroupName')
|
220
|
+
}])
|
221
|
+
end
|
230
222
|
|
231
|
-
|
223
|
+
Output('URL') do
|
224
|
+
Description 'The URL of the website'
|
225
|
+
Value FnJoin('', ['http://', FnGetAtt('ElasticLoadBalancer', 'DNSName')])
|
226
|
+
end
|
227
|
+
end
|