cardtapp-cloudformation-ruby-dsl 0.0.1.pre.pre1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,274 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Copyright 2013-2014 Bazaarvoice, Inc.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require 'bundler/setup'
18
+ require 'cloudformation-ruby-dsl/cfntemplate'
19
+ require 'cloudformation-ruby-dsl/table'
20
+
21
+ # Note: this is only intended to demonstrate the cloudformation-ruby-dsl. It compiles
22
+ # and validates correctly, but won't produce a viable CloudFormation stack.
23
+
24
+ template do
25
+
26
+ # Metadata may be embedded into the stack, as per http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/metadata-section-structure.html
27
+ # The below definition produces CloudFormation interface metadata.
28
+ metadata 'AWS::CloudFormation::Interface', {
29
+ :ParameterGroups => [
30
+ {
31
+ :Label => { :default => 'Instance options' },
32
+ :Parameters => [ 'InstanceType', 'ImageId', 'KeyPairName' ]
33
+ },
34
+ {
35
+ :Label => { :default => 'Other options' },
36
+ :Parameters => [ 'Label', 'EmailAddress' ]
37
+ }
38
+ ],
39
+ :ParameterLabels => {
40
+ :EmailAddress => {
41
+ :default => "We value your privacy!"
42
+ }
43
+ }
44
+ }
45
+
46
+ parameter 'Label',
47
+ :Description => 'The label to apply to the servers.',
48
+ :Type => 'String',
49
+ :MinLength => '2',
50
+ :MaxLength => '25',
51
+ :AllowedPattern => '[_a-zA-Z0-9]*',
52
+ :ConstraintDescription => 'Maximum length of the Label parameter may not exceed 25 characters and may only contain letters, numbers and underscores.',
53
+ # The :Immutable attribute is a Ruby CFN extension. It affects the behavior of the '<template> update ...'
54
+ # operation in that a stack update may not change the values of parameters marked w/:Immutable => true.
55
+ :Immutable => true
56
+
57
+ parameter 'InstanceType',
58
+ :Description => 'EC2 instance type',
59
+ :Type => 'String',
60
+ :Default => 'm2.xlarge',
61
+ :AllowedValues => %w(t1.micro m1.small m1.medium m1.large m1.xlarge m2.xlarge m2.2xlarge m2.4xlarge c1.medium c1.xlarge),
62
+ :ConstraintDescription => 'Must be a valid EC2 instance type.'
63
+
64
+ parameter 'ImageId',
65
+ :Description => 'EC2 Image ID',
66
+ :Type => 'String',
67
+ :Default => 'ami-255bbc4c',
68
+ :AllowedPattern => 'ami-[a-f0-9]{8}',
69
+ :ConstraintDescription => 'Must be ami-XXXXXXXX (where X is a hexadecimal digit)'
70
+
71
+ parameter 'KeyPairName',
72
+ :Description => 'Name of KeyPair to use.',
73
+ :Type => 'String',
74
+ :MinLength => '1',
75
+ :MaxLength => '40',
76
+ :Default => parameters['Label']
77
+
78
+ parameter 'EmailAddress',
79
+ :Type => 'String',
80
+ :Description => 'Email address at which to send notification events.'
81
+
82
+ parameter 'BucketName',
83
+ :Type => 'String',
84
+ :Description => 'Name of the bucket to upload to.'
85
+
86
+ mapping 'InlineExampleMap',
87
+ :team1 => {
88
+ :name => 'test1',
89
+ :email => 'test1@example.com',
90
+ },
91
+ :team2 => {
92
+ :name => 'test2',
93
+ :email => 'test2@example.com',
94
+ }
95
+
96
+ # Generates mappings from external files with various formats.
97
+ mapping 'JsonExampleMap', 'maps/map.json'
98
+
99
+ mapping 'RubyExampleMap', 'maps/map.rb'
100
+
101
+ mapping 'YamlExampleMap', 'maps/map.yaml'
102
+
103
+ # Loads JSON mappings dynamically from example directory.
104
+ Dir.entries('maps/more_maps').each_with_index do |path, index|
105
+ next if path == "." or path == ".."
106
+ mapping "ExampleMap#{index - 1}", "maps/more_maps/#{path}"
107
+ end
108
+
109
+ # Selects all rows in the table which match the name/value pairs of the predicate object and returns a
110
+ # set of nested maps, where the key for the map at level n is the key at index n in the specified keys,
111
+ # except for the last key in the specified keys which is used to determine the value of the leaf-level map.
112
+ text = Table.load 'maps/table.txt'
113
+ mapping 'TableExampleMap',
114
+ text.get_map({ :column0 => 'foo' }, :column1, :column2, :column3)
115
+
116
+ # Shows how to create a table useful for looking up subnets that correspond to a particular env/region for eg. vpc placement.
117
+ vpc = Table.load 'maps/vpc.txt'
118
+ mapping 'TableExampleMultimap',
119
+ vpc.get_multimap({ :visibility => 'private', :zone => ['a', 'c'] }, :env, :region, :subnet)
120
+
121
+ # Shows how to use a table for iterative processing.
122
+ domains = Table.load 'maps/domains.txt'
123
+ domains.get_multihash(:purpose, {:product => 'demo', :alias => 'true'}, :prefix, :target, :alias_hosted_zone_id).each_pair do |key, value|
124
+ resource key+'Route53RecordSet', :Type => 'AWS::Route53::RecordSet', :Properties => {
125
+ :Comment => '',
126
+ :HostedZoneName => 'bazaarvoice.com',
127
+ :Name => value[:prefix]+'.bazaarvoice.com',
128
+ :Type => 'A',
129
+ :AliasTarget => {
130
+ :DNSName => value[:target],
131
+ :HostedZoneId => value[:alias_hosted_zone_id]
132
+ }
133
+ }
134
+ end
135
+
136
+
137
+ # The tag type is a DSL extension; it is not a property of actual CloudFormation templates.
138
+ # These tags are excised from the template and used to generate a series of --tag arguments
139
+ # which are passed to CloudFormation when a stack is created.
140
+ # They do not ultimately appear in the expanded CloudFormation template.
141
+ # The diff subcommand will compare tags with the running stack and identify any changes,
142
+ # but a stack update will do the diff and throw an error on any immutable tags update attempt.
143
+ # The tags are propagated to all resources created by the stack, including the stack itself.
144
+ # If a resource has its own tag with the same name as CF's it's not overwritten.
145
+ #
146
+ # Amazon has set the following restrictions on CloudFormation tags:
147
+ # => limit 10
148
+ # CloudFormation tags declaration examples:
149
+
150
+ tag 'My:New:Tag',
151
+ :Value => 'ImmutableTagValue',
152
+ :Immutable => true
153
+
154
+ tag :MyOtherTag,
155
+ :Value => 'My Value With Spaces'
156
+
157
+ tag(:"tag:name", :Value => 'tag_value', :Immutable => true)
158
+
159
+ # Following format is deprecated and not advised. Please declare CloudFormation tags as described above.
160
+ tag :TagName => 'tag_value' # It's immutable.
161
+
162
+ resource 'SecurityGroup', :Type => 'AWS::EC2::SecurityGroup', :Properties => {
163
+ :GroupDescription => 'Lets any vpc traffic in.',
164
+ :SecurityGroupIngress => {:IpProtocol => '-1', :FromPort => '0', :ToPort => '65535', :CidrIp => "10.0.0.0/8"}
165
+ }
166
+
167
+ resource "ASG", :Type => 'AWS::AutoScaling::AutoScalingGroup', :Properties => {
168
+ :AvailabilityZones => 'us-east-1',
169
+ :HealthCheckType => 'EC2',
170
+ :LaunchConfigurationName => ref('LaunchConfig'),
171
+ :MinSize => 1,
172
+ :MaxSize => 5,
173
+ :NotificationConfiguration => {
174
+ :TopicARN => ref('EmailSNSTopic'),
175
+ :NotificationTypes => %w(autoscaling:EC2_INSTANCE_LAUNCH autoscaling:EC2_INSTANCE_LAUNCH_ERROR autoscaling:EC2_INSTANCE_TERMINATE autoscaling:EC2_INSTANCE_TERMINATE_ERROR),
176
+ },
177
+ :Tags => [
178
+ {
179
+ :Key => 'Name',
180
+ # Grabs a value in an external map file.
181
+ :Value => find_in_map('TableExampleMap', 'corge', 'grault'),
182
+ :PropagateAtLaunch => 'true',
183
+ },
184
+ {
185
+ :Key => 'Label',
186
+ :Value => parameters['Label'],
187
+ :PropagateAtLaunch => 'true',
188
+ }
189
+ ],
190
+ }
191
+
192
+ resource 'EmailSNSTopic', :Type => 'AWS::SNS::Topic', :Properties => {
193
+ :Subscription => [
194
+ {
195
+ :Endpoint => ref('EmailAddress'),
196
+ :Protocol => 'email',
197
+ },
198
+ ],
199
+ }
200
+
201
+ resource 'WaitConditionHandle', :Type => 'AWS::CloudFormation::WaitConditionHandle', :Properties => {}
202
+
203
+ resource 'WaitCondition', :Type => 'AWS::CloudFormation::WaitCondition', :DependsOn => 'ASG', :Properties => {
204
+ :Handle => ref('WaitConditionHandle'),
205
+ :Timeout => 1200,
206
+ :Count => "1"
207
+ }
208
+
209
+ resource 'LaunchConfig', :Type => 'AWS::AutoScaling::LaunchConfiguration', :Properties => {
210
+ :ImageId => parameters['ImageId'],
211
+ :KeyName => ref('KeyPairName'),
212
+ :IamInstanceProfile => ref('InstanceProfile'),
213
+ :InstanceType => ref('InstanceType'),
214
+ :InstanceMonitoring => 'false',
215
+ :SecurityGroups => [ref('SecurityGroup')],
216
+ :BlockDeviceMappings => [
217
+ {:DeviceName => '/dev/sdb', :VirtualName => 'ephemeral0'},
218
+ {:DeviceName => '/dev/sdc', :VirtualName => 'ephemeral1'},
219
+ {:DeviceName => '/dev/sdd', :VirtualName => 'ephemeral2'},
220
+ {:DeviceName => '/dev/sde', :VirtualName => 'ephemeral3'},
221
+ ],
222
+ # Loads an external userdata script with an interpolated argument.
223
+ :UserData => base64(interpolate(file('userdata.sh'), time: Time.now)),
224
+ }
225
+
226
+ resource 'InstanceProfile', :Type => 'AWS::IAM::InstanceProfile', :Properties => {
227
+ # use cfn intrinsic conditional to choose the 2nd value because the expression evaluates to false
228
+ :Path => fn_if(equal(3, 0), '/unselected/', '/'),
229
+ :Roles => [ ref('InstanceRole') ],
230
+ }
231
+
232
+ resource 'InstanceRole', :Type => 'AWS::IAM::Role', :Properties => {
233
+ :AssumeRolePolicyDocument => {
234
+ :Statement => [
235
+ {
236
+ :Effect => 'Allow',
237
+ :Principal => { :Service => [ 'ec2.amazonaws.com' ] },
238
+ :Action => [ 'sts:AssumeRole' ],
239
+ },
240
+ ],
241
+ },
242
+ :Path => '/',
243
+ }
244
+
245
+ # Use sub to set bucket names for an S3 Policy.
246
+ resource 'ManagedPolicy', :Type => "AWS::IAM::ManagedPolicy", :Properties => {
247
+ :Description => 'Access policy for S3 Buckets',
248
+ :PolicyDocument => {
249
+ :Version => "2012-10-17",
250
+ :Statement => [
251
+ {
252
+ :Action => ["s3:ListBucket"],
253
+ :Effect => "Allow",
254
+ :Resource => [
255
+ sub("arn:aws:s3:::${BucketName}"),
256
+ sub("arn:aws:s3:::${BaseName}${Hash}", {:BaseName => 'Bucket', :Hash => '3bsd73w'}),
257
+ ]
258
+ }
259
+ ]
260
+ }
261
+ }
262
+
263
+ # add conditions that can be used elsewhere in the template
264
+ condition 'myCondition', fn_and(equal("one", "two"), not_equal("three", "four"))
265
+
266
+ output 'EmailSNSTopicARN',
267
+ :Value => ref('EmailSNSTopic'),
268
+ :Description => 'ARN of SNS Topic used to send emails on events.'
269
+
270
+ output 'MappingLookup',
271
+ :Value => find_in_map('TableExampleMap', 'corge', 'grault'),
272
+ :Description => 'An example map lookup.'
273
+
274
+ end.exec!
@@ -0,0 +1,4 @@
1
+ purpose product prefix target alias alias_hosted_zone_id has_origin_domain origin_target
2
+ CDN demo code dabc123.cloudfront.net true Z2FDTNDATAQYW2 false
3
+ Assets demo assets ddef456.cloudfront.net true Z2FDTNDATAQYW2 false
4
+ API demo api prod-api false false prod-api-origin.whatever.net.
@@ -0,0 +1,9 @@
1
+ {
2
+ "Mappings": {
3
+ "JsonExampleMap": {
4
+ "foo": "bar"
5
+ }
6
+ }
7
+
8
+ }
9
+
@@ -0,0 +1,5 @@
1
+ {
2
+ 'Mappings' => {
3
+ 'RubyExampleMap' => { 'baz' => 'blah' }
4
+ }
5
+ }
@@ -0,0 +1,5 @@
1
+ ---
2
+ Mappings:
3
+ YamlExampleMap:
4
+ foo:
5
+ bar: yo
@@ -0,0 +1,8 @@
1
+ {
2
+ "Mappings": {
3
+ "ExampleMap1": {
4
+ "gregory": "smith"
5
+ }
6
+ }
7
+
8
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "Mappings": {
3
+ "ExampleMap2": {
4
+ "smith": "john"
5
+ }
6
+ }
7
+
8
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "Mappings": {
3
+ "ExampleMap3": {
4
+ "john": "gregory"
5
+ }
6
+ }
7
+
8
+ }
@@ -0,0 +1,5 @@
1
+ column0 column1 column2 column3 column4
2
+ foo baz qux quux
3
+ foo corge grault garply
4
+ bar waldo fred
5
+ bar plugh xyzzy thud
@@ -0,0 +1,25 @@
1
+ env region zone visibility subnet
2
+ qa us-east-1 a public subnet-aaaa
3
+ qa us-east-1 a private subnet-bbbb
4
+ qa us-east-1 b public subnet-cccc
5
+ qa us-east-1 b private subnet-dddd
6
+ qa us-east-1 c public subnet-eeee
7
+ qa us-east-1 c private subnet-ffff
8
+ qa eu-west-1 a public subnet-gggg
9
+ qa eu-west-1 a private subnet-hhhh
10
+ qa eu-west-1 b public subnet-iiii
11
+ qa eu-west-1 b private subnet-jjjj
12
+ qa eu-west-1 c public subnet-kkkk
13
+ qa eu-west-1 c private subnet-llll
14
+ prod us-east-1 a public subnet-mmmm
15
+ prod us-east-1 a private subnet-nnnn
16
+ prod us-east-1 b public subnet-oooo
17
+ prod us-east-1 b private subnet-pppp
18
+ prod us-east-1 c public subnet-qqqq
19
+ prod us-east-1 c private subnet-rrrr
20
+ prod eu-west-1 a public subnet-ssss
21
+ prod eu-west-1 a private subnet-tttt
22
+ prod eu-west-1 b public subnet-uuuu
23
+ prod eu-west-1 b private subnet-vvvv
24
+ prod eu-west-1 c public subnet-wwww
25
+ prod eu-west-1 c private subnet-xxxx
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env ruby
2
+ require 'bundler/setup'
3
+ require 'cloudformation-ruby-dsl/cfntemplate'
4
+
5
+ tmpl = template do
6
+ @stack_name = 'hello-bucket-example'
7
+
8
+ parameter 'Label',
9
+ :Description => 'The label to apply to the bucket.',
10
+ :Type => 'String',
11
+ :Default => 'cfnrdsl',
12
+ :UsePreviousValue => true
13
+
14
+ resource "HelloBucket",
15
+ :Type => 'AWS::S3::Bucket',
16
+ :Properties => {
17
+ :BucketName => ref('Label')
18
+ }
19
+ end
20
+
21
+ tmpl.exec!
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env bash
2
+ echo "put initialization script here"
3
+ echo "the time is {{ locals[:time] }}"
4
+ echo "the aws region is {{ ref('AWS::Region') }}"
@@ -0,0 +1,5 @@
1
+ Several people were instrumental in building this project during its incubation stage. Because the process of open sourcing involved squashing the repository to remove confidential information, some of their contributions have been lost from the history that Github displays.
2
+
3
+ - [Shawn Smith](https://github.com/shawnsmith): initial implementation
4
+ - [Nathaniel Eliot](https://github.com/temujin9): converted from raw library to gem, refactored table code, cleaned and prepared code for open sourcing
5
+ - [Jona Fenocchi](http://github.com/jonaf): added support for CloudFormation tags