cfndsl 0.4.4 → 0.5.0.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. checksums.yaml +5 -13
  2. data/.rubocop.yml +23 -0
  3. data/Gemfile +4 -0
  4. data/Rakefile +19 -17
  5. data/bin/cfndsl +20 -20
  6. data/cfndsl.gemspec +16 -15
  7. data/lib/cfndsl.rb +62 -68
  8. data/lib/cfndsl/aws/cloud_formation_template.rb +16 -0
  9. data/lib/cfndsl/aws/types.rb +12 -0
  10. data/lib/cfndsl/{aws_types.yaml → aws/types.yaml} +0 -0
  11. data/lib/cfndsl/{Conditions.rb → conditions.rb} +5 -7
  12. data/lib/cfndsl/creation_policy.rb +21 -0
  13. data/lib/cfndsl/errors.rb +29 -0
  14. data/lib/cfndsl/generate_types.rb +154 -0
  15. data/lib/cfndsl/jsonable.rb +214 -0
  16. data/lib/cfndsl/mappings.rb +23 -0
  17. data/lib/cfndsl/metadata.rb +16 -0
  18. data/lib/cfndsl/module.rb +52 -51
  19. data/lib/cfndsl/names.rb +5 -5
  20. data/lib/cfndsl/orchestration_template.rb +173 -0
  21. data/lib/cfndsl/os/heat_template.rb +16 -0
  22. data/lib/cfndsl/os/types.rb +12 -0
  23. data/lib/cfndsl/{os_types.yaml → os/types.yaml} +11 -11
  24. data/lib/cfndsl/{Outputs.rb → outputs.rb} +3 -4
  25. data/lib/cfndsl/{Parameters.rb → parameters.rb} +12 -13
  26. data/lib/cfndsl/plurals.rb +34 -0
  27. data/lib/cfndsl/properties.rb +21 -0
  28. data/lib/cfndsl/rake_task.rb +9 -7
  29. data/lib/cfndsl/ref_check.rb +44 -0
  30. data/lib/cfndsl/{Resources.rb → resources.rb} +13 -15
  31. data/lib/cfndsl/types.rb +151 -0
  32. data/lib/cfndsl/update_policy.rb +25 -0
  33. data/lib/cfndsl/version.rb +1 -1
  34. data/sample/autoscale.rb +152 -158
  35. data/sample/autoscale2.rb +151 -155
  36. data/sample/circular.rb +30 -33
  37. data/sample/codedeploy.rb +35 -36
  38. data/sample/config_service.rb +120 -0
  39. data/sample/ecs.rb +39 -39
  40. data/sample/iam_policies.rb +82 -0
  41. data/sample/lambda.rb +20 -24
  42. data/sample/s3.rb +11 -11
  43. data/sample/t1.rb +7 -9
  44. data/sample/vpc_example.rb +50 -0
  45. data/sample/vpc_with_vpn_example.rb +97 -0
  46. data/spec/cfndsl_spec.rb +22 -11
  47. data/spec/fixtures/heattest.rb +13 -14
  48. data/spec/fixtures/test.rb +56 -53
  49. metadata +36 -30
  50. data/lib/cfndsl/CloudFormationTemplate.rb +0 -267
  51. data/lib/cfndsl/CreationPolicy.rb +0 -25
  52. data/lib/cfndsl/Errors.rb +0 -31
  53. data/lib/cfndsl/JSONable.rb +0 -235
  54. data/lib/cfndsl/Mappings.rb +0 -25
  55. data/lib/cfndsl/Metadata.rb +0 -22
  56. data/lib/cfndsl/Plurals.rb +0 -35
  57. data/lib/cfndsl/Properties.rb +0 -25
  58. data/lib/cfndsl/RefCheck.rb +0 -48
  59. data/lib/cfndsl/Types.rb +0 -309
  60. data/lib/cfndsl/UpdatePolicy.rb +0 -29
  61. data/sample/config-service.rb +0 -119
  62. data/sample/iam-policies.rb +0 -82
  63. data/sample/vpc-example.rb +0 -51
  64. 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 "2010-09-09"
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 %Q/
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("InstanceType") {
28
- Description "Type of EC2 instance to launch"
29
- Type "String"
30
- Default "m1.small"
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( "WebServerPort") {
34
- Description "The TCP port for the Web Server"
35
- Type "String"
36
- Default "8888"
37
- }
38
- Parameter("KeyName") {
39
- Description "The EC2 Key Pair to allow SSH access to the instances"
40
- Type "String"
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("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
- })
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
- [ "t1.micro", "m1.large", "m1.xlarge", "m2.xlarge",
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] = { "Arch" => "64" }
64
+ architectures[arch] = { 'Arch' => '64' }
67
65
  end
68
66
 
69
- [ "m1.small", "c1.medium"
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] = { "Arch" => "32" }
70
+ architectures[arch] = { 'Arch' => '32' }
74
71
  end
75
-
76
- Mapping("AWSInstanceType2Arch", architectures )
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
- # "AWSInstanceType2Arch" : {
81
- # "m2.4xlarge" : { "Arch" : "64" },
82
- # "c1.xlarge" : { "Arch" : "64" },
83
- # "c1.medium" : { "Arch" : "32" },
84
- # "m1.xlarge" : { "Arch" : "64" },
85
- # "m1.large" : { "Arch" : "64" },
86
- # "t1.micro" : { "Arch" : "64" },
87
- # "m1.small" : { "Arch" : "32" },
88
- # "m2.2xlarge" : { "Arch" : "64" },
89
- # "m2.xlarge" : { "Arch" : "64" },
90
- # "cc1.4xlarge" : { "Arch" : "64" }
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("WebServerGroup") {
96
- Type "AWS::AutoScaling::AutoScalingGroup"
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("AvailabilityZones", FnGetAZs("") )
97
+ Property('AvailabilityZones', FnGetAZs(''))
102
98
  # will generate JSON that includes
103
- # { "Fn::GetAZs : "" }
99
+ # { 'Fn::GetAZs : '' }
104
100
  # as the value of the AvailabilityZones property for the
105
- # "WebServerGroup" reqource.
101
+ # 'WebServerGroup' reqource.
106
102
 
107
103
  # The same works for references
108
- Property("LaunchConfigurationName", Ref( "LaunchConfig") )
109
- Property("MinSize", "1")
110
- Property("MaxSize", "3")
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("LoadBalancerNames", [ Ref( "ElasticLoadBalancer") ] )
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( :LaunchConfig ) {
121
- Type "AWS::AutoScaling::LaunchConfiguration"
122
-
123
- Property("KeyName", Ref("KeyName") )
124
- Property( "ImageId",
125
- FnFindInMap( "AWSRegionArch2AMI", Ref("AWS::Region"),
126
- FnFindInMap( "AWSInstanceType2Arch", Ref("InstanceType"),"Arch")))
127
- Property("UserData", FnBase64( Ref("WebServerPort")))
128
- Property("SecurityGroups", [ Ref("InstanceSecurityGroup")])
129
- Property("InstanceType", Ref("InstanceType") )
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( "WebServerScaleUpPolicy" ) {
134
- Type "AWS::AutoScaling::ScalingPolicy"
135
- Property("AdjustmentType", "ChangeInCapacity")
136
- Property("AutoScalingGroupName", Ref( "WebServerGroup") )
137
- Property("Cooldown", "60")
138
- Property("ScalingAdjustment", "1")
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 "Resource", we are
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("CPUAlarmHigh") {
162
- Type "AWS::CloudWatch::Alarm"
163
- Property("AlarmDescription", "Scale-up if CPU > 90% for 10 minutes")
164
- Property("Threshold", "90")
165
- Property("AlarmActions", [ Ref("WebServerScaleUpPolicy" ) ])
166
- Property("ComparisonOperator", "GreaterThanThreshold")
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("CPUAlarmLow") {
171
- Type "AWS::CloudWatch::Alarm"
172
- Property("AlarmDescription", "Scale-down if CPU < 70% for 10 minutes")
173
- Property("Threshold", "70")
174
- Property("AlarmActions", [ Ref("WebServerScaleDownPolicy" ) ])
175
- Property("ComparisonOperator", "LessThanThreshold")
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("MetricName", "CPUUtilization")
186
- Property("Namespace", "AWS/EC2")
187
- Property("Statistic", "Average")
188
- Property("Period", "300")
189
- Property("EvaluationPeriods", "2")
190
- Property("Dimensions", [
191
- {
192
- "Name" => "AutoScalingGroupName",
193
- "Value" => Ref("WebServerGroup" )
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( "ElasticLoadBalancer" ) {
202
- Type "AWS::ElasticLoadBalancing::LoadBalancer"
203
- Property( "AvailabilityZones", FnGetAZs(""))
204
- Property( "Listeners" , [ {
205
- "LoadBalancerPort" => "80",
206
- "InstancePort" => Ref( "WebServerPort" ),
207
- "Protocol" => "HTTP"
208
- } ] )
209
- Property( "HealthCheck" , {
210
- # FnFormat replaces %0, %1, etc with passed in parameters
211
- # Note that it renders to a call to Fn::Join in the json.
212
- "Target" => FnFormat("HTTP:%0/", Ref( "WebServerPort" ) ),
213
- "HealthyThreshold" => "3",
214
- "UnhealthyThreshold" => "5",
215
- "Interval" => "30",
216
- "Timeout" => "5"
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 "2010-09-09"
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 %Q/
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("InstanceType") {
28
- Description "Type of EC2 instance to launch"
29
- Type "String"
30
- Default "m1.small"
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( "WebServerPort") {
34
- Description "The TCP port for the Web Server"
35
- Type "String"
36
- Default "8888"
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
- # The same kind of thing for parameters works for mappings,
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("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
- })
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
- [ "t1.micro", "m1.large", "m1.xlarge", "m2.xlarge",
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] = { "Arch" => "64" }
63
+ architectures[arch] = { 'Arch' => '64' }
67
64
  end
68
65
 
69
- [ "m1.small", "c1.medium"
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] = { "Arch" => "32" }
69
+ architectures[arch] = { 'Arch' => '32' }
74
70
  end
75
-
76
- Mapping("AWSInstanceType2Arch", architectures )
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
- # "AWSInstanceType2Arch" : {
81
- # "m2.4xlarge" : { "Arch" : "64" },
82
- # "c1.xlarge" : { "Arch" : "64" },
83
- # "c1.medium" : { "Arch" : "32" },
84
- # "m1.xlarge" : { "Arch" : "64" },
85
- # "m1.large" : { "Arch" : "64" },
86
- # "t1.micro" : { "Arch" : "64" },
87
- # "m1.small" : { "Arch" : "32" },
88
- # "m2.2xlarge" : { "Arch" : "64" },
89
- # "m2.xlarge" : { "Arch" : "64" },
90
- # "cc1.4xlarge" : { "Arch" : "64" }
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("WebServerGroup") {
95
- UpdatePolicy("AutoScalingRollingUpdate", {
96
- "MinInstancesInService" => "1",
97
- "MaxBatchSize" => "1",
98
- "PauseTime" => "PT15M"
99
- })
100
- AvailabilityZones FnGetAZs("")
101
- LaunchConfigurationName Ref("LaunchConfig")
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( "ElasticLoadBalancer" )
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( :LaunchConfig ) {
110
- KeyName Ref("KeyName")
111
- ImageId FnFindInMap( "AWSRegionArch2AMI",
112
- Ref("AWS::Region"),
113
- FnFindInMap( "AWSInstanceType2Arch", Ref("InstanceType"),"Arch") )
114
-
115
- UserData FnBase64( Ref("WebServerPort"))
116
- SecurityGroup Ref("InstanceSecurityGroup")
117
- InstanceType Ref("InstanceType")
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( "WebServerScaleUpPolicy" ) {
122
- Type "AWS::AutoScaling::ScalingPolicy"
123
- Property("AdjustmentType", "ChangeInCapacity")
124
- Property("AutoScalingGroupName", Ref( "WebServerGroup") )
125
- Property("Cooldown", "60")
126
- Property("ScalingAdjustment", "1")
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 "Resource", we are
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("CPUAlarmHigh") {
150
- Type "AWS::CloudWatch::Alarm"
151
- Property("AlarmDescription", "Scale-up if CPU > 90% for 10 minutes")
152
- Property("Threshold", "90")
153
- Property("AlarmActions", [ Ref("WebServerScaleUpPolicy" ) ])
154
- Property("ComparisonOperator", "GreaterThanThreshold")
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("CPUAlarmLow") {
159
- Type "AWS::CloudWatch::Alarm"
160
- Property("AlarmDescription", "Scale-down if CPU < 70% for 10 minutes")
161
- Property("Threshold", "70")
162
- Property("AlarmActions", [ Ref("WebServerScaleDownPolicy" ) ])
163
- Property("ComparisonOperator", "LessThanThreshold")
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("MetricName", "CPUUtilization")
174
- Property("Namespace", "AWS/EC2")
175
- Property("Statistic", "Average")
176
- Property("Period", "300")
177
- Property("EvaluationPeriods", "2")
178
- Property("Dimensions", [
179
- {
180
- "Name" => "AutoScalingGroupName",
181
- "Value" => Ref("WebServerGroup" )
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( "ElasticLoadBalancer" ) {
190
- Type "AWS::ElasticLoadBalancing::LoadBalancer"
191
- Property( "AvailabilityZones", FnGetAZs(""))
192
- Property( "Listeners" , [ {
193
- "LoadBalancerPort" => "80",
194
- "InstancePort" => Ref( "WebServerPort" ),
195
- "Protocol" => "HTTP"
196
- } ] )
197
- Property( "HealthCheck" , {
198
- # FnFormat replaces %0, %1, etc with passed in parameters
199
- # Note that it renders to a call to Fn::Join in the json.
200
- "Target" => FnFormat("HTTP:%0/", Ref( "WebServerPort" ) ),
201
- "HealthyThreshold" => "3",
202
- "UnhealthyThreshold" => "5",
203
- "Interval" => "30",
204
- "Timeout" => "5"
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