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

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 9e310b865545fc3d4ee18fe2a2aea573fd0d6bc22dabc56cfb7f6005745fd2c8
4
+ data.tar.gz: 8c02987d1d661411c09fc0f8d915bacbf303f4b807420d1fe09c32ccab5a91ad
5
+ SHA512:
6
+ metadata.gz: 0524a7f152ddc375dacdc5c8beb65027a0d7c9adc6869004c5ab41bd11cd52bc2dd14a4fb00ea35ac45055c2950df8f35d4b74daf4fd4a009c36ba50dbf7e6c3
7
+ data.tar.gz: 9f40c1be8e66ff6d068d7942fd0a72fa21e3163da9ad7e00223bd749486ecc4bb2391c8f72b52a88d0c67d444885a07ec6acbf775d95dc35d4479358069f07c9
data/.gitignore ADDED
@@ -0,0 +1,30 @@
1
+ *.swp
2
+ maestro.json
3
+ .rakeTasks
4
+ .DS_Store
5
+ target
6
+ *.iml
7
+ .idea/
8
+ *.swo
9
+ /manifests
10
+ /modules
11
+ cloudformation/expanded/
12
+ *.gem
13
+ *.rbc
14
+ .bundle
15
+ .config
16
+ .yardoc
17
+ Gemfile.lock
18
+ InstalledFiles
19
+ _yardoc
20
+ coverage
21
+ doc/
22
+ lib/bundler/man
23
+ pkg
24
+ rdoc
25
+ spec/reports
26
+ test/tmp
27
+ test/version_tmp
28
+ tmp
29
+ .rvmrc
30
+ /vendor/bundle
data/.travis.yml ADDED
@@ -0,0 +1,10 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9
4
+ - 2.0
5
+ - 2.1
6
+ - 2.2
7
+ - 2.3
8
+ script:
9
+ - rake clean
10
+ - rake build
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in cloudformation-ruby-dsl.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,13 @@
1
+ Copyright 2015 Bazaarvoice, Inc.
2
+  
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License.
5
+ You may obtain a copy of the License at
6
+  
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+  
9
+ Unless required by applicable law or agreed to in writing, software
10
+ distributed under the License is distributed on an "AS IS" BASIS,
11
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ See the License for the specific language governing permissions and
13
+ limitations under the License.
data/OWNERS ADDED
@@ -0,0 +1,3 @@
1
+ # Owners.
2
+
3
+ infrastructure-dev@bazaarvoice.com
@@ -0,0 +1,30 @@
1
+ ## Description
2
+ Describe the objective of this PR.
3
+
4
+ ## Steps to Test or Reproduce
5
+ Outline the steps to test or reproduce the PR here.
6
+ ```
7
+ Code that reproduces the behaviour of the PR/to be fixed by the PR
8
+ ```
9
+ ### Environment
10
+ Describe the environment the bug or feature can be observed in. This may include platform, ruby version, DSL info, etc.
11
+
12
+ ## Deploy Notes
13
+ If the change affects the way in which the gem is released, or requires a bump in version, note this here.
14
+
15
+ ## Related Issues and PRs
16
+
17
+ ### Issues
18
+ - [issue_link]()
19
+
20
+ ### PRs
21
+ - [pr1]()
22
+ - [pr2]()
23
+
24
+ ## Todos
25
+ - [x] Pull Request
26
+ - [ ] Tests
27
+ - [ ] Documentation
28
+
29
+ ## Request to Review
30
+ @jonaf/@temujin9
data/README.md ADDED
@@ -0,0 +1,128 @@
1
+ # cloudformation-ruby-dsl
2
+
3
+ A Ruby DSL and helper utilities for building CloudFormation templates dynamically.
4
+
5
+ Written by [Bazaarvoice](http://www.bazaarvoice.com): see [the contributors page](https://github.com/bazaarvoice/cloudformation-ruby-dsl/graphs/contributors) and [the initial contributions](https://github.com/bazaarvoice/cloudformation-ruby-dsl/blob/master/initial_contributions.md) for more details.
6
+
7
+ ## Motivation
8
+
9
+ CloudFormation templates often contain repeated stanzas, information which must be loaded from external sources, and other functionality that would be easier handled as code, instead of configuration.
10
+
11
+ Consider when a userdata script needs to be added to a CloudFormation template. Traditionally, you would re-write the script by hand in a valid JSON format. Using the DSL, you can specify the file containing the script and generate the correct information at runtime.
12
+
13
+ :UserData => base64(interpolate(file('userdata.sh')))
14
+
15
+ Additionally, CloudFormation templates are just massive JSON documents, making general readability and reusability an issue. The DSL allows not only a cleaner format (and comments!), but will also allow the same DSL template to be reused as needed.
16
+
17
+ ## Installation
18
+
19
+ Run `gem install cloudformation-ruby-dsl` to install system-wide.
20
+
21
+ To use in a specific project, add `gem 'cloudformation-ruby-dsl'` to your Gemfile, and then run `bundle`.
22
+
23
+ ## Releasing
24
+
25
+ See [Releasing](docs/Releasing.md).
26
+
27
+ ## Contributing
28
+
29
+ See [Contributing](docs/Contributing.md).
30
+
31
+ ## Usage
32
+
33
+ To convert existing JSON templates to use the DSL, run
34
+
35
+ cfntemplate-to-ruby [EXISTING_CFN] > [NEW_NAME.rb]
36
+
37
+ You may need to preface this with `bundle exec` if you installed via Bundler.
38
+
39
+ Make the resulting file executable (`chmod +x [NEW_NAME.rb]`). It can respond to the following subcommands (which are listed if you run without parameters):
40
+ - `expand`: output the JSON template to the command line (takes optional `--nopretty` to minimize the output)
41
+ - `diff`: compare an existing stack with your template. Produces following exit codes:
42
+ ```
43
+ 0 - no differences, nothing to update
44
+ 1 - stack does not exist, template Validation error
45
+ 2 - there are differences between an existing stack and your template
46
+ ```
47
+ - `validate`: run validation against the stack definition
48
+ - `create`: create a new stack from the output (takes optional `--s3-bucket` to upload the template to the specified S3 bucket prior to creating the stack)
49
+ - `update`: update an existing stack from the output (takes optional `--s3-bucket` to upload the template to the specified S3 bucket prior to creating the stack). Produces following exit codes:
50
+ ```
51
+ 0 - update finished successfully
52
+ 1 - no updates to perform, stack doesn't exist, unable to update immutable parameter or tag, AWS ServiceError exception
53
+ ```
54
+ - `cancel-update`: cancel updating a stack
55
+ - `delete`: delete a stack (with prompt)
56
+ - `describe`: get output of an existing stack and output it (takes optional `--nopretty` to minimize output)
57
+ - `describe-resource`: given two arguments: stack-name and logical-resource-id, get output from a stack concerning the specific resource (takes optional `--nopretty` to minimize output)
58
+ - `get-template`: get entire template output of an existing stack
59
+
60
+ Command line options similar to cloudformation commands, but parsed by the dsl.
61
+ - `--profile`
62
+ - `--stack-name`
63
+ - `--region`
64
+ - `--parameters`
65
+ - `--tag`
66
+
67
+ Any other parameters are passed directly onto cloudformation. (--disable-rollback for instance)
68
+
69
+ Using the ruby scripts:
70
+ ```
71
+ template.rb create --stack-name my_stack --parameters "BucketName=bucket-s3-static;SnsQueue=mysnsqueue"
72
+ ```
73
+
74
+ Below are the various functions currently available in the DSL. See [the example script](examples/cloudformation-ruby-script.rb) for more usage information.
75
+
76
+ ### DSL Statements
77
+
78
+ Add the named object to the appropriate collection.
79
+ - `parameter(name, options)` (may be marked :Immutable, which will raise error on a later change)
80
+ - `mapping(name, options)`
81
+ - `condition(name, conditions)`
82
+ - `resource(name, options)`
83
+ - `output(name, options)`
84
+ - `metadata(object)`
85
+
86
+ ### CloudFormation Function Calls
87
+
88
+ Invoke an intrinsic CloudFormation function.
89
+ - `base64(value)`
90
+ - `find_in_map(map, key, name)`
91
+ - `get_att(resource, attribute)`
92
+ - `get_azs(region)`
93
+ - `split(delim, string)`
94
+ - `join(delim, *list)`
95
+ - `select(index, list)`
96
+ - `ref(name)`
97
+ - `import_value(value)`
98
+ - `sub(sub_string)`
99
+ - `sub(sub_string, var_map)`
100
+
101
+ Intrinsic conditionals are also supported, with some syntactic sugar.
102
+ - `fn_not(condition)`
103
+ - `fn_or(*condition_list)`
104
+ - `fn_and(*condition_list)`
105
+ - `fn_if(condition, value_if_true, value_if_false)`
106
+ - `equal(lhsOperand, rhsOperand)`
107
+ - `not_equal(lhsOperand, rhsOperand)`
108
+
109
+ Reference a CloudFormation pseudo parameter.
110
+ - `aws_account_id()`
111
+ - `aws_notification_arns()`
112
+ - `aws_no_value()`
113
+ - `aws_region()`
114
+ - `aws_stack_id()`
115
+ - `aws_stack_name()`
116
+
117
+ ### Utility Functions
118
+
119
+ Additional capabilities for file inclusion, etc.
120
+ - `tag(tag_name, tag_options_hash)`: add tags to the stack, which are inherited by all resources in that stack. `tag_options_hash` includes `:Value=>value` and `:Immutable=>true` properties. `tag(tag_value_hash)` is deprecated and will be removed in a future version.
121
+ - `file(name)`: return the named file as a string, for further use
122
+ - `load_from_file(filename)`: load the named file by a given type; currently handles YAML, JSON, and Ruby
123
+ - `interpolate(string)`: embed CFN references into a string (`{{ref('Service')}}`) for later interpretation by the CFN engine
124
+ - `Table.load(filename)`: load a table from the listed file, which can then be turned into mappings (via `get_map`)
125
+
126
+ ### Default Region
127
+
128
+ The tool defaults to region `us-east-1`. To change this set either `EC2_REGION` or `AWS_DEFAULT_REGION` in your environment.
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ begin
4
+ require 'rspec/core/rake_task'
5
+ RSpec::Core::RakeTask.new(:spec)
6
+ rescue LoadError
7
+ end
8
+
9
+ task :default => :spec
@@ -0,0 +1,347 @@
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
+ unless RUBY_VERSION >= '1.9'
18
+ # Ruby 1.9 preserves order within Hash objects which avoid scrambling the template output.
19
+ $stderr.puts "This script requires ruby 1.9+. On OS/X use Homebrew to install ruby 1.9:"
20
+ $stderr.puts " brew install ruby"
21
+ exit(2)
22
+ end
23
+
24
+ require 'json'
25
+
26
+ def main(argv)
27
+ unless (argv & %w(-h --help -?)).empty?
28
+ $stderr.puts <<"EOF"
29
+ usage: #{$PROGRAM_NAME} [cloudformation-template.json] ...
30
+
31
+ Converts the specified CloudFormation JSON template or template fragment to
32
+ Ruby DSL syntax. Reads from stdin or from the specified json files. Note
33
+ that the input must be valid JSON.
34
+
35
+ Examples:
36
+
37
+ # Convert a JSON CloudFormation template to Ruby DSL syntax
38
+ #{$PROGRAM_NAME} my-template.json > my-template.rb
39
+ chmod +x my-template.rb
40
+
41
+ # Convert the JSON fragment in the clipboard to Ruby DSL syntax
42
+ pbpaste | #{$PROGRAM_NAME} | less
43
+
44
+ EOF
45
+ exit(2)
46
+ end
47
+ if argv.empty?
48
+ pprint(simplify(JSON.parse($stdin.read)))
49
+ else
50
+ argv.each do |filename|
51
+ pprint(simplify(JSON.parse(File.read(filename))))
52
+ end
53
+ end
54
+ # The user should make the resulting template executable w/chmod +x
55
+ end
56
+
57
+ class FnCall
58
+ attr_reader :name, :arguments, :multiline
59
+
60
+ def initialize(name, arguments, multiline = false)
61
+ @name = name
62
+ @arguments = arguments
63
+ @multiline = multiline
64
+ end
65
+
66
+ def to_s()
67
+ @name + "(" + @arguments.join(', ') + ")"
68
+ end
69
+ end
70
+
71
+ def pprint(val)
72
+ case detect_type(val)
73
+ when :template
74
+ pprint_cfn_template(val)
75
+ when :parameter
76
+ pprint_cfn_section 'parameter', 'TODO', val
77
+ when :resource
78
+ pprint_cfn_resource 'TODO', val
79
+ when :parameters
80
+ val.each { |k, v| pprint_cfn_section 'parameter', k, v }
81
+ when :resources
82
+ val.each { |k, v| pprint_cfn_resource k, v }
83
+ else
84
+ pprint_value(val, '')
85
+ end
86
+ end
87
+
88
+ # Attempt to figure out what fragment of the template we have. This is imprecise and can't
89
+ # detect Mappings and Outputs sections reliably, so it doesn't attempt to.
90
+ def detect_type(val)
91
+ if val.is_a?(Hash) && val['AWSTemplateFormatVersion']
92
+ :template
93
+ elsif val.is_a?(Hash) && /^(String|Number)$/ =~ val['Type']
94
+ :parameter
95
+ elsif val.is_a?(Hash) && val['Type']
96
+ :resource
97
+ elsif val.is_a?(Hash) && val.values.all? { |v| detect_type(v) == :parameter }
98
+ :parameters
99
+ elsif val.is_a?(Hash) && val.values.all? { |v| detect_type(v) == :resource }
100
+ :resources
101
+ end
102
+ end
103
+
104
+ def pprint_cfn_template(tpl)
105
+ puts "#!/usr/bin/env ruby"
106
+ puts
107
+ puts "require 'bundler/setup'"
108
+ puts "require 'cloudformation-ruby-dsl/cfntemplate'"
109
+ puts "require 'cloudformation-ruby-dsl/spotprice'"
110
+ puts "require 'cloudformation-ruby-dsl/table'"
111
+ puts
112
+ puts "template do"
113
+ puts
114
+ tpl.each do |section, v|
115
+ case section
116
+ when 'Metadata'
117
+ v.each { |name, options| pprint_cfn_section 'metadata', name, options }
118
+ when 'Parameters'
119
+ v.each { |name, options| pprint_cfn_section 'parameter', name, options }
120
+ when 'Mappings'
121
+ v.each { |name, options| pprint_cfn_section 'mapping', name, options }
122
+ when 'Resources'
123
+ v.each { |name, options| pprint_cfn_resource name, options }
124
+ when 'Conditions'
125
+ v.each { |name, options| pprint_cfn_section 'condition', name, options }
126
+ when 'Outputs'
127
+ v.each { |name, options| pprint_cfn_section 'output', name, options }
128
+ else
129
+ print " value #{fmt_key(section)} => "
130
+ pprint_value v, ' '
131
+ puts
132
+ puts
133
+ end
134
+ end
135
+ puts "end.exec!"
136
+ end
137
+
138
+ def pprint_cfn_section(section, name, options)
139
+ print " #{section} #{fmt_string(name)}"
140
+ indent = ' ' + (' ' * section.length) + ' '
141
+ options.each do |k, v|
142
+ puts ","
143
+ print indent, fmt_key(k), " => "
144
+ pprint_value v, indent
145
+ end
146
+ puts
147
+ puts
148
+ end
149
+
150
+ def pprint_cfn_resource(name, options)
151
+ print " resource #{fmt_string(name)}"
152
+ indent = ' '
153
+ options.each do |k, v|
154
+ unless k == 'Properties'
155
+ print ", #{fmt_key(k)} => #{fmt(v)}"
156
+ end
157
+ end
158
+ if options.key?('Properties')
159
+ print ", #{fmt_key('Properties')} => "
160
+ pprint_value options['Properties'], indent
161
+ end
162
+ puts
163
+ puts
164
+ end
165
+
166
+ def pprint_value(val, indent)
167
+ # Prefer to print the value on a single line if it's reasonable to do so
168
+ single_line = is_single_line(val) || is_single_line_hack(val)
169
+ if single_line && !is_multi_line_hack(val)
170
+ s = fmt(val)
171
+ if s.length < 120 || is_single_line_hack(val)
172
+ print s
173
+ return
174
+ end
175
+ end
176
+
177
+ # Print the value across multiple lines
178
+ if val.is_a?(Hash)
179
+ puts "{"
180
+ val.each do |k, v|
181
+ print "#{indent} #{fmt_key(k)} => "
182
+ pprint_value v, indent + ' '
183
+ puts ","
184
+ end
185
+ print "#{indent}}"
186
+
187
+ elsif val.is_a?(Array)
188
+ puts "["
189
+ val.each do |v|
190
+ print "#{indent} "
191
+ pprint_value v, indent + ' '
192
+ puts ","
193
+ end
194
+ print "#{indent}]"
195
+
196
+ elsif val.is_a?(FnCall) && val.multiline
197
+ print val.name, "("
198
+ args = val.arguments
199
+ sep = ''
200
+ sub_indent = indent + ' '
201
+ if val.name == 'join' && args.length > 1
202
+ pprint_value args[0], indent + ' '
203
+ args = args[1..-1]
204
+ sep = ','
205
+ sub_indent = indent + ' '
206
+ end
207
+ unless args.empty?
208
+ args.each do |v|
209
+ puts sep
210
+ print sub_indent
211
+ pprint_value v, sub_indent
212
+ sep = ','
213
+ end
214
+ if val.name == 'join' && args.length > 1
215
+ print ","
216
+ end
217
+ puts
218
+ print indent
219
+ end
220
+ print ")"
221
+
222
+ else
223
+ print fmt(val)
224
+ end
225
+ end
226
+
227
+ def is_single_line(val)
228
+ if val.is_a?(Hash)
229
+ is_single_line(val.values)
230
+ elsif val.is_a?(Array)
231
+ val.empty? ||
232
+ (val.length == 1 && is_single_line(val[0]) && !val[0].is_a?(Hash)) ||
233
+ val.all? { |v| v.is_a?(String) }
234
+ else
235
+ true
236
+ end
237
+ end
238
+
239
+ # Emo-specific hacks to force the desired output formatting
240
+ def is_single_line_hack(val)
241
+ is_array_of_strings_hack(val)
242
+ end
243
+
244
+ # Emo-specific hacks to force the desired output formatting
245
+ def is_multi_line_hack(val)
246
+ val.is_a?(Hash) && val['email']
247
+ end
248
+
249
+ # Emo-specific hacks to force the desired output formatting
250
+ def is_array_of_strings_hack(val)
251
+ val.is_a?(Array) && val.all? { |v| v.is_a?(String) } && val.grep(/\s/).empty? && (
252
+ val.include?('autoscaling:EC2_INSTANCE_LAUNCH') ||
253
+ val.include?('m1.small')
254
+ )
255
+ end
256
+
257
+ def fmt(val)
258
+ if val == {}
259
+ '{}'
260
+ elsif val == []
261
+ '[]'
262
+ elsif val.is_a?(Hash)
263
+ '{ ' + (val.map { |k,v| fmt_key(k) + ' => ' + fmt(v) }).join(', ') + ' }'
264
+ elsif val.is_a?(Array) && is_array_of_strings_hack(val)
265
+ '%w(' + val.join(' ') + ')'
266
+ elsif val.is_a?(Array)
267
+ '[ ' + (val.map { |v| fmt(v) }).join(', ') + ' ]'
268
+ elsif val.is_a?(FnCall) && val.arguments.empty?
269
+ val.name
270
+ elsif val.is_a?(FnCall)
271
+ val.name + '(' + (val.arguments.map { |v| fmt(v) }).join(', ') + ')'
272
+ elsif val.is_a?(String)
273
+ fmt_string(val)
274
+ elsif val == nil
275
+ 'null'
276
+ else
277
+ val.to_s # number, boolean
278
+ end
279
+ end
280
+
281
+ def fmt_key(s)
282
+ ':' + (/^[a-zA-Z_]\w+$/ =~ s ? s : fmt_string(s)) # returns a symbol like :Foo or :'us-east-1'
283
+ end
284
+
285
+ def fmt_string(s)
286
+ if /[^ -~]/ =~ s
287
+ s.dump # contains, non-ascii or control char, return double-quoted string
288
+ else
289
+ '\'' + s.gsub(/([\\'])/, '\\\\\1') + '\'' # return single-quoted string, escape \ and '
290
+ end
291
+ end
292
+
293
+ def many(val)
294
+ if val.is_a?(Array)
295
+ val
296
+ else
297
+ [ val ]
298
+ end
299
+ end
300
+
301
+ def simplify(val)
302
+ if val.is_a?(Hash)
303
+ val = Hash[val.map { |k,v| [k, simplify(v)] }]
304
+ if val.length != 1
305
+ val
306
+ else
307
+ k, v = val.entries[0]
308
+ # CloudFormation functions
309
+ case
310
+ when k == 'Fn::Base64'
311
+ FnCall.new 'base64', [v], true
312
+ when k == 'Fn::FindInMap'
313
+ FnCall.new 'find_in_map', v
314
+ when k == 'Fn::GetAtt'
315
+ FnCall.new 'get_att', v
316
+ when k == 'Fn::GetAZs'
317
+ FnCall.new 'get_azs', v != '' ? [v] : []
318
+ when k == 'Fn::Join'
319
+ FnCall.new 'join', [v[0]] + many(v[1]), true
320
+ when k == 'Fn::Select'
321
+ FnCall.new 'select', v
322
+ when k == 'Ref' && v == 'AWS::AccountId'
323
+ FnCall.new 'aws_account_id', []
324
+ when k == 'Ref' && v == 'AWS::NotificationARNs'
325
+ FnCall.new 'aws_notification_arns', []
326
+ when k == 'Ref' && v == 'AWS::NoValue'
327
+ FnCall.new 'aws_no_value', []
328
+ when k == 'Ref' && v == 'AWS::Region'
329
+ FnCall.new 'aws_region', []
330
+ when k == 'Ref' && v == 'AWS::StackId'
331
+ FnCall.new 'aws_stack_id', []
332
+ when k == 'Ref' && v == 'AWS::StackName'
333
+ FnCall.new 'aws_stack_name', []
334
+ when k == 'Ref'
335
+ FnCall.new 'ref', [v]
336
+ else
337
+ val
338
+ end
339
+ end
340
+ elsif val.is_a?(Array)
341
+ val.map { |v| simplify(v) }
342
+ else
343
+ val
344
+ end
345
+ end
346
+
347
+ main(ARGV)
@@ -0,0 +1,46 @@
1
+ # -*- encoding: utf-8 -*-
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
+ lib = File.expand_path('../lib', __FILE__)
18
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
19
+ require 'cloudformation-ruby-dsl/version'
20
+
21
+ Gem::Specification.new do |gem|
22
+ gem.name = "cardtapp-cloudformation-ruby-dsl"
23
+ gem.version = Cfn::Ruby::Dsl::VERSION
24
+ gem.authors = ["Shawn Smith", "Dave Barcelo", "Morgan Fletcher", "Csongor Gyuricza", "Igor Polishchuk", "Nathaniel Eliot", "Jona Fenocchi", "Tony Cui"]
25
+ gem.email = ["Shawn.Smith@bazaarvoice.com", "Dave.Barcelo@bazaarvoice.com", "Morgan.Fletcher@bazaarvoice.com", "Csongor.Gyuricza@bazaarvoice.com", "Igor.Polishchuk@bazaarvoice.com", "Nathaniel.Eliot@bazaarvoice.com", "Jona.Fenocchi@bazaarvoice.com", "Tony.Cui@bazaarvoice.com"]
26
+ gem.description = %q{Ruby DSL library that provides a wrapper around the CloudFormation.}
27
+ gem.summary = %q{Ruby DSL library that provides a wrapper around the CloudFormation. Written by [Bazaarvoice](http://www.bazaarvoice.com).}
28
+ gem.homepage = "http://github.com/bazaarvoice/cloudformation-ruby-dsl"
29
+
30
+ gem.files = `git ls-files`.split($/)
31
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
32
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
33
+ gem.require_paths = %w{lib bin}
34
+
35
+ gem.add_runtime_dependency 'detabulator'
36
+ gem.add_runtime_dependency 'json'
37
+ gem.add_runtime_dependency 'bundler'
38
+ gem.add_runtime_dependency 'aws-sdk-s3'
39
+ gem.add_runtime_dependency 'aws-sdk-cloudformation'
40
+ gem.add_runtime_dependency 'diffy'
41
+ gem.add_runtime_dependency 'highline'
42
+ gem.add_runtime_dependency 'rake'
43
+
44
+ gem.add_development_dependency 'rspec'
45
+ gem.add_development_dependency 'pry'
46
+ end
@@ -0,0 +1,22 @@
1
+ # Contributing
2
+
3
+ Thanks for your interest in contributing! Here are some things you should know.
4
+
5
+ ## Getting started
6
+
7
+ To get started:
8
+
9
+ - fork this project on github
10
+ - create a new branch named after the change you want to make; i.e., `git checkout -b mynewfeature`
11
+ - make your changes (including tests) and commit them
12
+ - run the tests to make sure you haven't broken anything: ```rspec```
13
+ - send a pull request to this project from your fork/branch
14
+
15
+ Once you've sent your pull request, one of the project collaborators will review it and provide feedback. Please accept this commentary as constructive! It is intended as such.
16
+
17
+ ## git
18
+
19
+ We're opinionated about git. Don't be surprised if we ask you to update your pull request to meet the following standards.
20
+
21
+ - rebase+squash your branch into a single commit. For clean git history, we'd prefer we merged in just 1 commit that contains the entire set of changes.
22
+ - don't write commit messages longer than 50 characters. See [How to Write a Git Commit Message](http://chris.beams.io/posts/git-commit/) for some examples of how to achieve this, and why.
data/docs/Releasing.md ADDED
@@ -0,0 +1,20 @@
1
+ # Releasing
2
+
3
+ ## Performing releases
4
+
5
+ 0. Merge the desired commits to master. But merge them cleanly! See: [merging](#merging)
6
+ 1. Edit and commit the version file in `lib/cloudformation-ruby-dsl/version.rb`. Bump the version based on the [version specification](#versioning-specification)
7
+ 2. `git push` to origin/master
8
+ 3. `rake release`
9
+
10
+ ## Versioning specification
11
+
12
+ For this project, we will follow the methodology proposed by http://semver.org/spec/v2.0.0.html.
13
+
14
+ 1. Major versions break existing interfaces.
15
+ 2. Minor versions are additive only.
16
+ 3. Patch versions are for backward-compatible bug fixes.
17
+
18
+ ## Merging
19
+
20
+ When you use the shiny green "Merge" button on a pull request, github creates a separate commit for the merge (because of the use of the `--no-ff` option). This is noisy and makes git history confusing. Instead of using the green merge button, merge the branch into master using [git-land](https://github.com/bazaarvoice/git-land#git-land) (or manually follow the steps described in the project).