cfer 0.4.2 → 0.5.0.pre.rc1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 961dee72c1a9265e73effbc45cd013160829858e
4
- data.tar.gz: f09eb22eb304921bb05542bd8575c926be330180
3
+ metadata.gz: 5d9d002adc64d106f800cb61545ae2a62644cdf6
4
+ data.tar.gz: e6c08b6a6f4d011d23f2b0567f65febb1ebf1a8b
5
5
  SHA512:
6
- metadata.gz: 95e6cb1e1b177516356a98f87ff3cd54b46e95668cf156ddd54f8ef22d22c0b7130905b1c7665473ad8f06d8dee175464eed4f9937dc6f469f06e94d50064b8d
7
- data.tar.gz: 66a4ec1bdcaa018295aa95ca8cde3fba47c95951015ab38c1261a8c4708cdb2766c543ba05e65acae1c3e9b1ed4458def6bc4e241075ed7b8674f5234fb8168a
6
+ metadata.gz: 6eb2bd6ddf3bc719faaeb11361662bbd7ac938b5ac2d4e37583e144b6cbdf7a59aa43c585f48f1117d2ace34be4a85d9f38a5b237f338231d84e03b9ce75aac5
7
+ data.tar.gz: d342f24e5c9329cee1088aed994555be198efea702c063e6a62ef5f5b20843c7319c6c055fe92dc6f00ba821694545e3420507ece940e083d1fc25009ad07431
data/.gitignore CHANGED
@@ -11,3 +11,6 @@
11
11
  **/.tags
12
12
 
13
13
  !/doc/cfer-demo.gif
14
+
15
+ vendor
16
+
@@ -1,13 +1,13 @@
1
1
  language: ruby
2
2
  install: bundle install --without debug --jobs=3 --retry=3
3
3
  rvm:
4
- - 2.1
5
- - 2.2
4
+ - 2.2.5
6
5
  - 2.3.0
7
6
  - ruby-head
8
7
  matrix:
9
8
  allow_failures:
10
- - rvm: ruby-head
9
+ - rvm:
10
+ - ruby-head
11
11
  branches:
12
12
  only:
13
13
  - master
@@ -0,0 +1,68 @@
1
+ # Cfer Change Log
2
+
3
+ ## 0.5.0
4
+
5
+ ### Enhancements
6
+ * Adds support for Pre-build and Post-build hooks for resources and stacks.
7
+ * Adds `json-to-cfer` script to automatically convert json templates to Cfer DSL code.
8
+ * Adds support for directly converging JSON files.
9
+ * Relaxes some version constraints to make it easier to integrate with older Rails projects.
10
+ * Pulled stack validation out into an extension using post-build hooks.
11
+ * Adds some extension methods to improve usability of certain resources.
12
+ * Namespace cleanup.
13
+ * Supports reading ruby template from stdin by specifying the filename `-`
14
+ * Adds exponential backoff to `tail` command.
15
+ * `--on-failure` flag is now case insensitive.
16
+ * Various test improvements.
17
+
18
+ ### Bugfixes
19
+ * Fixes "Stack does not exist" error being reported when stack creation fails and `--on-failure=DELETE` is specified.
20
+
21
+ ## 0.4.2
22
+
23
+ ### Bugfixes
24
+ * Templates now uploaded to S3 in all cases where they should be.
25
+ * Fixes extensions (should be `class_eval`, not `instance_eval`)
26
+
27
+ ## 0.4.0
28
+
29
+ ### **BREAKING CHANGES**
30
+ * Provisioning is removed from Cfer core and moved to [cfer-provisioning](https://github.com/seanedwards/cfer-provisioning)
31
+
32
+ ### Enhancements
33
+ * Adds support for assume-role authentication with MFA (see: https://docs.aws.amazon.com/cli/latest/userguide/cli-roles.html)
34
+ * Adds support for yml-format parameter files with environment-specific sections.
35
+ * Adds a DSL for IAM policies.
36
+ * Adds `cfer estimate` command to estimate the cost of a template using the AWS CloudFormation cost estimation API.
37
+ * Enhancements to chef provisioner to allow for references in chef attributes. (Thanks to @eropple)
38
+ * Adds continue/rollback/quit selection when `^C` is caught during a converge.
39
+ * Stores Cfer version and Git repo information in the Repo metadata.
40
+ * Added support for uploading templates to S3 with the `--s3-path` and `--force-s3` options.
41
+ * Added new way of extending resources, making plugins easier.
42
+ * Added support for [CloudFormation Change Sets](https://aws.amazon.com/blogs/aws/new-change-sets-for-aws-cloudformation/) via the `--change` option.
43
+
44
+ ### Bugfixes
45
+
46
+ ## 0.3.0
47
+
48
+ ### Enhancements:
49
+ * `parameters` hash now includes parameters that are set on the existing stack, but not passed in via CLI during a stack update.
50
+ * `parameters` hash now includes defaults for parameters that were not passed on the CLI during a stack creation.
51
+ * Adds a `lookup_output` function, for looking up outputs of stacks in the same account+region. (See #8)
52
+ * Adds provisioning for cfn-init and chef-solo, including resource signaling.
53
+ * Adds support for stack policies.
54
+ * Cfer no longer validates parameters itself. CloudFormation will throw an error if something is wrong.
55
+ * Adds release notes to the README.
56
+
57
+ ### Bugfixes:
58
+ * Removes automatic parameter mapping in favor of an explicit function available to resources. (Fixes Issue #8)
59
+ * No more double-printing the stack summary when converging a stack with tailing enabled.
60
+ * Update demo to only use 2 AZs, since us-west-1 only has two.
61
+ * `AllowedValues` attribute on parameters is now an array, not a CSV string. (Thanks to @rlister)
62
+
63
+ ## 0.2.0
64
+
65
+ ### Enhancements:
66
+ * Adds support for including other files via `include_template` function.
67
+ * Adds basic Dockerfile
68
+
data/Dockerfile CHANGED
@@ -1,5 +1,7 @@
1
- FROM ruby:2.2
1
+ FROM ruby:2.3
2
2
  COPY . /usr/src/app
3
3
  WORKDIR /usr/src/app
4
4
  RUN bundle install
5
+ RUN rake install
6
+ RUN cfer version
5
7
 
data/README.md CHANGED
@@ -298,45 +298,5 @@ This project also contains a [Code of Conduct](https://github.com/seanedwards/cf
298
298
 
299
299
  # Release Notes
300
300
 
301
- ## 0.4.0
302
-
303
- ### **BREAKING CHANGES**
304
- * Provisioning is removed from Cfer core and moved to [cfer-provisioning](https://github.com/seanedwards/cfer-provisioning)
305
-
306
- ### Enhancements
307
- * Adds support for assume-role authentication with MFA (see: https://docs.aws.amazon.com/cli/latest/userguide/cli-roles.html)
308
- * Adds support for yml-format parameter files with environment-specific sections.
309
- * Adds a DSL for IAM policies.
310
- * Adds `cfer estimate` command to estimate the cost of a template using the AWS CloudFormation cost estimation API.
311
- * Enhancements to chef provisioner to allow for references in chef attributes. (Thanks to @eropple)
312
- * Adds continue/rollback/quit selection when `^C` is caught during a converge.
313
- * Stores Cfer version and Git repo information in the Repo metadata.
314
- * Added support for uploading templates to S3 with the `--s3-path` and `--force-s3` options.
315
- * Added new way of extending resources, making plugins easier.
316
- * Added support for [CloudFormation Change Sets](https://aws.amazon.com/blogs/aws/new-change-sets-for-aws-cloudformation/) via the `--change` option.
317
-
318
- ### Bugfixes
319
-
320
- ## 0.3.0
321
-
322
- ### Enhancements:
323
- * `parameters` hash now includes parameters that are set on the existing stack, but not passed in via CLI during a stack update.
324
- * `parameters` hash now includes defaults for parameters that were not passed on the CLI during a stack creation.
325
- * Adds a `lookup_output` function, for looking up outputs of stacks in the same account+region. (See #8)
326
- * Adds provisioning for cfn-init and chef-solo, including resource signaling.
327
- * Adds support for stack policies.
328
- * Cfer no longer validates parameters itself. CloudFormation will throw an error if something is wrong.
329
- * Adds release notes to the README.
330
-
331
- ### Bugfixes:
332
- * Removes automatic parameter mapping in favor of an explicit function available to resources. (Fixes Issue #8)
333
- * No more double-printing the stack summary when converging a stack with tailing enabled.
334
- * Update demo to only use 2 AZs, since us-west-1 only has two.
335
- * `AllowedValues` attribute on parameters is now an array, not a CSV string. (Thanks to @rlister)
336
-
337
- ## 0.2.0
338
-
339
- ### Enhancements:
340
- * Adds support for including other files via `include_template` function.
341
- * Adds basic Dockerfile
301
+ [Change Log](https://github.com/seanedwards/cfer/CHANGELOG.md)
342
302
 
@@ -0,0 +1,82 @@
1
+ #!/usr/bin/env ruby
2
+ require 'json'
3
+ require 'pp'
4
+ require 'active_support/inflector'
5
+
6
+ template = JSON.parse(STDIN.read)
7
+
8
+ def indent(str, prefix = ' ')
9
+ prefix + str.gsub("\n", "\n#{prefix}")
10
+ end
11
+
12
+ def serialize_arg(arg, indent=0)
13
+ ret = ""
14
+ PP.pp(arg, ret)
15
+ ret.strip
16
+ end
17
+
18
+ def serialize_args(*args)
19
+ options = args.last.is_a?(Hash) ? args.pop : {}
20
+ args_str = []
21
+
22
+ args.each do |arg|
23
+ args_str << serialize_arg(arg)
24
+ end
25
+
26
+ opts_str = []
27
+ options.each do |k, v|
28
+ opts_str << "#{serialize_arg(k)}: #{serialize_arg(v)}"
29
+ end
30
+ args_str << indent(opts_str.join(",\n"), ' ') unless opts_str.empty?
31
+
32
+ args_str.join(', ').strip
33
+ end
34
+
35
+ description = template.delete('Description')
36
+ parameters = template.delete('Parameters') || {}
37
+ resources = template.delete('Resources') || {}
38
+ outputs = template.delete('Outputs') || {}
39
+ version = template.delete('AWSTemplateFormatVersion')
40
+
41
+ if description
42
+ puts "description #{serialize_arg(description)}"
43
+ puts ""
44
+ end
45
+
46
+ puts "##############"
47
+ puts "# Parameters #"
48
+ puts "##############"
49
+
50
+ parameters.each do |k, param|
51
+ puts "parameter #{serialize_args(k, param)}"
52
+ puts ""
53
+ end
54
+
55
+ puts "#############"
56
+ puts "# Resources #"
57
+ puts "#############"
58
+
59
+ resources.each do |k, attrs|
60
+ properties = attrs.delete('Properties') || {}
61
+ type = attrs.delete('Type')
62
+
63
+ puts "resource #{serialize_args(k, type, attrs)} do"
64
+ properties.each do |k, v|
65
+ puts indent("#{k.underscore} #{serialize_args(v)}", ' ')
66
+ end
67
+ puts "end"
68
+ puts ""
69
+ end
70
+
71
+ outputs.each do |k, out|
72
+ value = out.delete('Value')
73
+
74
+ puts "output #{serialize_args(k, value, out)}"
75
+ end
76
+
77
+ puts ""
78
+
79
+ template.each do |k, v|
80
+ puts "self[#{serialize_arg(k)}] = #{serialize_arg(v)}"
81
+ end
82
+
@@ -14,23 +14,25 @@ Gem::Specification.new do |spec|
14
14
  spec.homepage = "https://github.com/seanedwards/cfer"
15
15
  spec.license = "MIT"
16
16
 
17
+ spec.required_ruby_version = ['~> 2.2', '>= 2.2.5']
18
+
17
19
  spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
20
  spec.bindir = 'bin'
19
- spec.executables = 'cfer'
21
+ spec.executables = ['cfer', 'json-to-cfer']
20
22
  spec.require_paths = ["lib"]
21
23
 
22
- spec.add_runtime_dependency 'docile', '~> 1.1', '>= 1.1.5'
24
+ spec.add_runtime_dependency 'docile', '~> 1.1'
23
25
  spec.add_runtime_dependency 'thor', '~> 0.19.1'
24
- spec.add_runtime_dependency 'activesupport', '~> 4.2', '>= 4.2.6'
25
- spec.add_runtime_dependency 'aws-sdk', '~> 2.2', '>= 2.2.33'
26
- spec.add_runtime_dependency 'aws-sdk-resources', '~> 2.2', '>= 2.2.33'
26
+ spec.add_runtime_dependency 'activesupport', '>= 3'
27
+ spec.add_runtime_dependency 'aws-sdk', '~> 2.2'
28
+ spec.add_runtime_dependency 'aws-sdk-resources', '~> 2.2'
27
29
  spec.add_runtime_dependency 'preconditions', '~> 0.3.0'
28
- spec.add_runtime_dependency 'semantic', '~> 1.4', '>= 1.4.1'
30
+ spec.add_runtime_dependency 'semantic', '~> 1.4'
29
31
  spec.add_runtime_dependency 'rainbow', '~> 2.1'
30
- spec.add_runtime_dependency 'highline', '~> 1.7', '>= 1.7.8'
31
- spec.add_runtime_dependency 'table_print', '~> 1.5', '>= 1.5.6'
32
+ spec.add_runtime_dependency 'highline', '~> 1.7'
33
+ spec.add_runtime_dependency 'table_print', '~> 1.5'
32
34
  spec.add_runtime_dependency "git", '~> 1.3'
33
- spec.add_runtime_dependency "bundler"
34
35
 
35
36
  spec.add_development_dependency "yard", '~> 0.8.7.6'
37
+ spec.add_development_dependency "rake"
36
38
  end
@@ -14,9 +14,11 @@ end
14
14
 
15
15
  # Contains the core Cfer logic
16
16
  module Cfer
17
+ # Code relating to working with Amazon CloudFormation
17
18
  module Cfn
18
19
  end
19
20
 
21
+ # Code relating to building the CloudFormation document out of the Ruby DSL
20
22
  module Core
21
23
  end
22
24
 
@@ -50,8 +52,12 @@ module Cfer
50
52
 
51
53
  class << self
52
54
 
55
+ # Creates or updates a CloudFormation stack
56
+ # @param stack_name [String] The name of the stack to update
57
+ # @param options [Hash]
53
58
  def converge!(stack_name, options = {})
54
59
  config(options)
60
+ options[:on_failure].upcase! if options[:on_failure]
55
61
  tmpl = options[:template] || "#{stack_name}.rb"
56
62
  cfn = options[:aws_options] || {}
57
63
 
@@ -85,19 +91,29 @@ module Cfer
85
91
  end
86
92
  end
87
93
  end
94
+ describe! stack_name, options rescue nil # It's fine if we can't do this.
88
95
  rescue Aws::CloudFormation::Errors::ValidationError => e
89
96
  Cfer::LOGGER.info "CFN validation error: #{e.message}"
90
97
  end
91
- describe! stack_name, options unless options[:follow]
98
+ stack
92
99
  end
93
100
 
94
101
  def describe!(stack_name, options = {})
95
102
  config(options)
96
103
  cfn = options[:aws_options] || {}
97
104
  cfn_stack = options[:cfer_client] || Cfer::Cfn::Client.new(cfn.merge(stack_name: stack_name))
105
+ cfn_metadata = cfn_stack.fetch_metadata
98
106
  cfn_stack = cfn_stack.fetch_stack
99
107
 
108
+ cfer_version = cfn_metadata.fetch("Cfer", {}).fetch("Version", nil)
109
+ if cfer_version
110
+ cfer_version_str = [cfer_version["major"], cfer_version["minor"], cfer_version["patch"]].join '.'
111
+ cfer_version_str << '-' << cfer_version["pre"] unless cfer_version["pre"].nil?
112
+ cfer_version_str << '+' << cfer_version["pre"] unless cfer_version["pre"].nil?
113
+ end
114
+
100
115
  Cfer::LOGGER.debug "Describe stack: #{cfn_stack}"
116
+ Cfer::LOGGER.debug "Describe metadata: #{cfn_metadata}"
101
117
 
102
118
  case options[:output_format]
103
119
  when 'json'
@@ -105,6 +121,7 @@ module Cfer
105
121
  when 'table', nil
106
122
  puts "Status: #{cfn_stack[:stack_status]}"
107
123
  puts "Description: #{cfn_stack[:description]}" if cfn_stack[:description]
124
+ puts "Created with Cfer version: #{Semantic::Version.new(cfer_version_str).to_s} (current: #{Cfer::SEMANTIC_VERSION.to_s})" if cfer_version
108
125
  puts ""
109
126
  def tablify(list, type)
110
127
  list ||= []
@@ -122,6 +139,7 @@ module Cfer
122
139
  else
123
140
  raise Cfer::Util::CferError, "Invalid output format #{options[:output_format]}."
124
141
  end
142
+ cfn_stack
125
143
  end
126
144
 
127
145
  def tail!(stack_name, options = {}, &block)
@@ -135,7 +153,6 @@ module Cfer
135
153
  Cfer::LOGGER.info "%s %-30s %-40s %-20s %s" % [event.timestamp, color_map(event.resource_status), event.resource_type, event.logical_resource_id, event.resource_status_reason]
136
154
  end
137
155
  end
138
- describe! stack_name, options
139
156
  end
140
157
 
141
158
  def generate!(tmpl, options = {})
@@ -163,6 +180,10 @@ module Cfer
163
180
  cfn = options[:aws_options] || {}
164
181
  cfn_stack = options[:cfer_client] || cfn_stack = Cfer::Cfn::Client.new(cfn.merge(stack_name: stack_name))
165
182
  cfn_stack.delete_stack(stack_name)
183
+
184
+ if options[:follow]
185
+ tail! stack_name, options.merge(cfer_client: cfn_stack)
186
+ end
166
187
  end
167
188
 
168
189
  # Builds a Cfer::Core::Stack from a Ruby block
@@ -181,13 +202,31 @@ module Cfer
181
202
 
182
203
  # Builds a Cfer::Core::Stack from a ruby script
183
204
  #
184
- # @param file [String] The file containing the Cfn DSL
205
+ # @param file [String] The file containing the Cfn DSL or plain JSON
185
206
  # @param options [Hash] (see #stack_from_block)
186
207
  # @return [Cfer::Core::Stack] The assembled stack object
187
208
  def stack_from_file(file, options = {})
209
+ return stack_from_stdin(options) if file == '-'
210
+
211
+ s = Cfer::Core::Stack.new(options)
212
+ if file.ends_with?('.json')
213
+ s.deep_merge! JSON.parse(File.read(file))
214
+ else
215
+ templatize_errors(file) do
216
+ s.build_from_file file
217
+ end
218
+ end
219
+ s
220
+ end
221
+
222
+ # Builds a Cfer::Core::Stack from stdin
223
+ #
224
+ # @param options [Hash] (see #stack_from_block)
225
+ # @return [Cfer::Core::Stack] The assembled stack object
226
+ def stack_from_stdin(options = {})
188
227
  s = Cfer::Core::Stack.new(options)
189
- templatize_errors(file) do
190
- s.build_from_file file
228
+ templatize_errors('STDIN') do
229
+ s.build_from_string STDIN.read, 'STDIN'
191
230
  end
192
231
  s
193
232
  end
@@ -198,9 +237,6 @@ module Cfer
198
237
  Cfer::LOGGER.debug "Options: #{options}"
199
238
  Cfer::LOGGER.level = Logger::DEBUG if options[:verbose]
200
239
 
201
- require 'rubygems'
202
- require 'bundler/setup'
203
-
204
240
  Aws.config.update region: options[:region] if options[:region]
205
241
  Aws.config.update credentials: Cfer::Cfn::CferCredentialsProvider.new(profile_name: options[:profile]) if options[:profile]
206
242
  end
@@ -12,14 +12,22 @@ module Cfer
12
12
  self
13
13
  end
14
14
 
15
+ # Evaluates a DSL from a Ruby string
16
+ # @param args [Array<Object>] Extra arguments to be passed into the block
17
+ # @param str [String] The Cfer source template to evaluate
18
+ # @param file [File] The file that will be reported in any error messages
19
+ def build_from_string(*args, str, file)
20
+ build_from_block(*args) do
21
+ instance_eval str, file
22
+ end
23
+ self
24
+ end
25
+
15
26
  # Evaluates a DSL from a Ruby script file
16
27
  # @param args [Array<Object>] (see: #build_from_block)
17
28
  # @param file [File] The Ruby script to evaluate
18
29
  def build_from_file(*args, file)
19
- build_from_block(*args) do
20
- instance_eval File.read(file), file
21
- end
22
- self
30
+ build_from_string File.read(file), file
23
31
  end
24
32
 
25
33
  # Executed just before the DSL is evaluated
@@ -31,13 +39,23 @@ module Cfer
31
39
  end
32
40
  end
33
41
 
42
+ # BlockHash is a Block that responds to DSL-style properties.
34
43
  class BlockHash < Block
35
- NON_PROXIED_METHODS = [:parameters, :options, :lookup_output]
44
+ NON_PROXIED_METHODS = [
45
+ :parameters,
46
+ :options,
47
+ :lookup_output,
48
+ :lookup_outputs
49
+ ].freeze
36
50
 
51
+ # Directly sets raw properties in the underlying CloudFormation structure.
52
+ # @param keyvals [Hash] The properties to set on this object.
37
53
  def properties(keyvals = {})
38
54
  self.merge!(keyvals)
39
55
  end
40
56
 
57
+ # Gets the current value of a given property
58
+ # @param key [String] The name of the property to fetch
41
59
  def get_property(key)
42
60
  self.fetch key
43
61
  end
@@ -157,6 +157,9 @@ module Cfer::Cfn
157
157
  # @param options [Hash] The options hash
158
158
  # @option options [Fixnum] :number The maximum number of already-existing CloudFormation events to yield.
159
159
  # @option options [Boolean] :follow Set to true to wait until the stack enters a `COMPLETE` or `FAILED` state, yielding events as they occur.
160
+ # @option options [Boolean] :no_sleep Don't pause between polling. This is used for tests, and shouldn't be when polling the AWS API.
161
+ # @option options [Fixnum] :backoff The exponential backoff factor (default 1.5)
162
+ # @option options [Fixnum] :backoff_max_wait The maximum amount of time that exponential backoff will wait before polling agian (default 15s)
160
163
  def tail(options = {})
161
164
  q = []
162
165
  event_id_highwater = nil
@@ -173,30 +176,38 @@ module Cfer::Cfn
173
176
  event_id_highwater = event.event_id
174
177
  end
175
178
 
179
+ sleep_time = 1
180
+
176
181
  running = true
177
182
  if options[:follow]
178
183
  while running
179
- stack_status = describe_stacks(stack_name: name).stacks.first.stack_status
180
- running = running && (/.+_(COMPLETE|FAILED)$/.match(stack_status) == nil)
181
-
182
- yielding = true
183
- for_each_event name do |fetched_event|
184
- if event_id_highwater == fetched_event.event_id
185
- yielding = false
186
- end
187
-
188
- if yielding
189
- q.unshift fetched_event
184
+ sleep_time = [sleep_time * (options[:backoff] || 1), options[:backoff_max_wait] || 15].min
185
+ begin
186
+ stack_status = describe_stacks(stack_name: name).stacks.first.stack_status
187
+ running = running && (/.+_(COMPLETE|FAILED)$/.match(stack_status) == nil)
188
+
189
+ yielding = true
190
+ for_each_event name do |fetched_event|
191
+ if event_id_highwater == fetched_event.event_id
192
+ yielding = false
193
+ end
194
+
195
+ if yielding
196
+ q.unshift fetched_event
197
+ end
190
198
  end
199
+ rescue Aws::CloudFormation::Errors::ValidationError
200
+ running = false
191
201
  end
192
202
 
193
203
  while q.size > 0
194
204
  event = q.shift
195
205
  yield event
196
206
  event_id_highwater = event.event_id
207
+ sleep_time = 1
197
208
  end
198
209
 
199
- sleep 1 if running unless options[:no_sleep]
210
+ sleep sleep_time if running unless options[:no_sleep]
200
211
  end
201
212
  end
202
213
  end
@@ -0,0 +1,86 @@
1
+ # Utility methods to make CloudFormation functions feel more like Ruby
2
+ module Cfer::Core::Functions
3
+ def join(sep, *args)
4
+ {"Fn::Join" => [sep, [ *args ].flatten ]}
5
+ end
6
+
7
+ def ref(r)
8
+ {"Ref" => r}
9
+ end
10
+
11
+ def get_att(r, att)
12
+ {"Fn::GetAtt" => [r, att]}
13
+ end
14
+
15
+ def find_in_map(map_name, key1, key2)
16
+ {"Fn::FindInMap" => [map_name, key1, key2]}
17
+ end
18
+
19
+ def select(i, o)
20
+ {"Fn::Select" => [i, o]}
21
+ end
22
+
23
+ def base64(v)
24
+ {"Fn::Base64" => v}
25
+ end
26
+
27
+ def condition(cond)
28
+ {"Condition" => cond}
29
+ end
30
+
31
+ def and(*conds)
32
+ {"Fn::And" => conds}
33
+ end
34
+
35
+ def or(*conds)
36
+ {"Fn::Or" => conds}
37
+ end
38
+
39
+ def equals(a, b)
40
+ {"Fn::Equals" => [a, b]}
41
+ end
42
+
43
+ def if(cond, t, f)
44
+ {"Fn::If" => [cond, t, f]}
45
+ end
46
+
47
+ def not(cond)
48
+ {"Fn::Not" => [cond]}
49
+ end
50
+
51
+ def get_azs(region)
52
+ {"Fn::GetAZs" => region}
53
+ end
54
+
55
+ def account_id
56
+ Fn::ref 'AWS::AccountId'
57
+ end
58
+
59
+ def notification_arns
60
+ Fn::ref 'AWS::NotificationARNs'
61
+ end
62
+
63
+ def no_value
64
+ Fn::ref 'AWS::NoValue'
65
+ end
66
+
67
+ def region
68
+ Fn::ref 'AWS::Region'
69
+ end
70
+
71
+ def stack_id
72
+ Fn::ref 'AWS::StackId'
73
+ end
74
+
75
+ def stack_name
76
+ Fn::ref 'AWS::StackName'
77
+ end
78
+ end
79
+
80
+ module Cfer::Core::Functions::AWS
81
+ extend Cfer::Core::Functions
82
+ end
83
+
84
+ module Cfer::Core::Functions::Fn
85
+ extend Cfer::Core::Functions
86
+ end
@@ -0,0 +1,42 @@
1
+ module Cfer::Core
2
+ # Provides support for hooking into resource types, and evaluating code before or after properties are set
3
+ module Hooks
4
+ def pre_block
5
+ self.class.pre_hooks.each do |hook|
6
+ instance_eval &hook
7
+ end
8
+ end
9
+
10
+ def post_block
11
+ self.class.post_hooks.each do |hook|
12
+ instance_eval &hook
13
+ end
14
+ end
15
+
16
+ def self.included(base)
17
+ base.extend(ClassMethods)
18
+ end
19
+
20
+ module ClassMethods
21
+ def before(&block)
22
+ self.pre_hooks << block
23
+ end
24
+
25
+ def after(&block)
26
+ self.post_hooks << block
27
+ end
28
+
29
+ def pre_hooks
30
+ @pre_hooks ||= []
31
+ end
32
+
33
+ def post_hooks
34
+ @post_hooks ||= []
35
+ end
36
+
37
+ def inherited(subclass)
38
+ subclass.include Cfer::Core::Hooks
39
+ end
40
+ end
41
+ end
42
+ end
@@ -1,41 +1,67 @@
1
1
  module Cfer::Core
2
2
  class Resource < Cfer::BlockHash
3
+ include Cfer::Core::Hooks
4
+
3
5
  @@types = {}
4
6
 
5
- def initialize(name, type, **options, &block)
7
+ attr_reader :stack
8
+
9
+ def initialize(name, type, stack, **options, &block)
6
10
  @name = name
11
+ @stack = stack
7
12
 
8
13
  self[:Type] = type
9
14
  self.merge!(options)
10
15
  self[:Properties] = HashWithIndifferentAccess.new
11
16
  build_from_block(&block)
12
-
13
17
  end
14
18
 
15
-
19
+ # Sets a tag on this resource. The resource must support the CloudFormation `Tags` property.
20
+ # @param k [String] The name of the tag to set
21
+ # @param v [String] The value for this tag
22
+ # @param options [Hash] An arbitrary set of additional properties to be added to this tag, for example `PropagateOnLaunch` on `AWS::AutoScaling::AutoScalingGroup`
16
23
  def tag(k, v, **options)
17
24
  self[:Properties][:Tags] ||= []
18
25
  self[:Properties][:Tags].unshift({"Key" => k, "Value" => v}.merge(options))
19
26
  end
20
27
 
28
+ # Directly sets raw properties in the underlying CloudFormation structure.
29
+ # @param keyvals [Hash] The properties to set on this object.
21
30
  def properties(keyvals = {})
22
31
  self[:Properties].merge!(keyvals)
23
32
  end
24
33
 
34
+ # Gets the current value of a given property
35
+ # @param key [String] The name of the property to fetch
25
36
  def get_property(key)
26
37
  self[:Properties].fetch key
27
38
  end
28
39
 
29
40
  class << self
41
+ # Fetches the DSL class for a CloudFormation resource type
42
+ # @param type [String] The type of resource, for example `AWS::EC2::Instance`
43
+ # @return [Class] The DSL class representing this resource type, including all extensions
30
44
  def resource_class(type)
31
45
  @@types[type] ||= "CferExt::#{type}".split('::').inject(Object) { |o, c| o.const_get c if o && o.const_defined?(c) } || Class.new(Cfer::Core::Resource)
32
46
  end
33
47
 
48
+ # Patches code into DSL classes for CloudFormation resources
49
+ # @param type [String] The type of resource, for example `AWS::EC2::Instance`
34
50
  def extend_resource(type, &block)
35
- resource_class(type).instance_eval(&block)
51
+ resource_class(type).class_eval(&block)
36
52
  end
37
- end
38
53
 
39
- private
54
+ # Registers a hook that will be run before properties are set on a resource
55
+ # @param type [String] The type of resource, for example `AWS::EC2::Instance`
56
+ def before(type, &block)
57
+ resource_class(type).pre_hooks << block
58
+ end
59
+
60
+ # Registers a hook that will be run after properties have been set on a resource
61
+ # @param type [String] The type of resource, for example `AWS::EC2::Instance`
62
+ def after(type, &block)
63
+ resource_class(type).post_hooks << block
64
+ end
65
+ end
40
66
  end
41
67
  end
@@ -2,8 +2,8 @@ module Cfer::Core
2
2
 
3
3
  # Defines the structure of a CloudFormation stack
4
4
  class Stack < Cfer::Block
5
- include Cfer::Core
6
- include Cfer::Cfn
5
+ include Cfer::Core::Functions
6
+ include Cfer::Core::Hooks
7
7
 
8
8
  # The parameters strictly as passed via command line
9
9
  attr_reader :input_parameters
@@ -137,7 +137,7 @@ module Cfer::Core
137
137
  Preconditions.check_argument(/[[:alnum:]]+/ =~ name, "Resource name must be alphanumeric")
138
138
 
139
139
  clazz = Cfer::Core::Resource.resource_class(type)
140
- rc = clazz.new(name, type, options, &block)
140
+ rc = clazz.new(name, type, self, options, &block)
141
141
 
142
142
  self[:Resources][name] = rc
143
143
  rc
@@ -158,6 +158,7 @@ module Cfer::Core
158
158
  to_h.to_json
159
159
  end
160
160
 
161
+ # Gets the Cfn client, if one exists, or throws an error if one does not
161
162
  def client
162
163
  @options[:client] || raise(Cfer::Util::CferError, "Stack has no associated client.")
163
164
  end
@@ -168,71 +169,32 @@ module Cfer::Core
168
169
  include_base = options[:include_base] || File.dirname(caller.first.split(/:\d/,2).first)
169
170
  files.each do |file|
170
171
  path = File.join(include_base, file)
171
- instance_eval(File.read(path), path)
172
+ if path.ends_with?('.json')
173
+ self.deep_merge! JSON.parse(File.read(path))
174
+ else
175
+ instance_eval(File.read(path), path)
176
+ end
172
177
  end
173
178
  end
174
179
 
180
+ # Looks up a specific output of another CloudFormation stack in the same region.
181
+ # @param stack [String] The name of the stack to fetch an output from
182
+ # @param out [String] The name of the output to fetch from the stack
175
183
  def lookup_output(stack, out)
176
- client = @options[:client] || raise(Cfer::Util::CferError, "Can not fetch stack outputs without a client")
177
- client.fetch_output(stack, out)
184
+ lookup_outputs(stack).fetch(out)
178
185
  end
179
186
 
187
+ # Looks up a hash of all outputs from another CloudFormation stack in the same region.
188
+ # @param stack [String] The name of the stack to fetch outputs from
180
189
  def lookup_outputs(stack)
181
190
  client = @options[:client] || raise(Cfer::Util::CferError, "Can not fetch stack outputs without a client")
182
191
  client.fetch_outputs(stack)
183
192
  end
184
193
 
185
- private
186
-
187
- def post_block
188
- begin
189
- validate_stack!(self)
190
- rescue Cfer::Util::CferValidationError => e
191
- Cfer::LOGGER.error "Cfer detected #{e.errors.size > 1 ? 'errors' : 'an error'} when generating the stack:"
192
- e.errors.each do |err|
193
- Cfer::LOGGER.error "* #{err[:error]} in Stack#{validation_contextualize(err[:context])}"
194
- end
195
- raise e
196
- end
197
- end
198
-
199
- def validate_stack!(hash)
200
- errors = []
201
- context = []
202
- _inner_validate_stack!(hash, errors, context)
203
-
204
- raise Cfer::Util::CferValidationError, errors unless errors.empty?
205
- end
206
-
207
- def _inner_validate_stack!(hash, errors = [], context = [])
208
- case hash
209
- when Hash
210
- hash.each do |k, v|
211
- _inner_validate_stack!(v, errors, context + [k])
212
- end
213
- when Array
214
- hash.each_index do |i|
215
- _inner_validate_stack!(hash[i], errors, context + [i])
216
- end
217
- when nil
218
- errors << {
219
- error: "CloudFormation does not allow nulls in templates",
220
- context: context
221
- }
222
- end
223
- end
224
-
225
- def validation_contextualize(err_ctx)
226
- err_ctx.inject("") do |err_str, ctx|
227
- err_str <<
228
- case ctx
229
- when String
230
- ".#{ctx}"
231
- when Numeric
232
- "[#{ctx}]"
233
- end
194
+ class << self
195
+ def extend_stack(&block)
196
+ class_eval(&block)
234
197
  end
235
198
  end
236
199
  end
237
-
238
200
  end
@@ -1,5 +1,5 @@
1
1
  module Cfer
2
- VERSION = "0.4.2"
2
+ VERSION = "0.5.0-rc1"
3
3
 
4
4
  begin
5
5
  require 'semantic'
@@ -0,0 +1,6 @@
1
+ Cfer::Core::Resource.extend_resource 'AWS::CloudFormation::WaitCondition' do
2
+ def timeout(t)
3
+ properties :Timeout => t
4
+ end
5
+ end
6
+
@@ -10,7 +10,7 @@ module CferExt
10
10
  end
11
11
 
12
12
  def statement(options = {}, &block)
13
- statement = Cfer::BlockHash.new(&block)
13
+ statement = ::Cfer::BlockHash.new(&block)
14
14
  statement.merge! options
15
15
  statement.build_from_block(&block)
16
16
  self[:Statement].unshift statement
@@ -34,7 +34,7 @@ module CferExt
34
34
  doc = CferExt::AWS::IAM.generate_policy(&block) if doc == nil
35
35
  get_property(:Policies) << {
36
36
  PolicyName: name,
37
- PolicyDocument: doc.to_h
37
+ PolicyDocument: doc
38
38
  }
39
39
  end
40
40
  end
@@ -0,0 +1,7 @@
1
+ Cfer::Core::Resource.extend_resource "AWS::KMS::Key" do
2
+ def key_policy(doc = nil, &block)
3
+ doc = CferExt::AWS::IAM.generate_policy(&block) if doc == nil
4
+ properties :KeyPolicy => doc
5
+ end
6
+ end
7
+
@@ -0,0 +1,5 @@
1
+ Cfer::Core::Resource.extend_resource 'AWS::RDS::DBInstance' do
2
+ def vpc_security_groups(groups)
3
+ properties :VPCSecurityGroups => groups
4
+ end
5
+ end
@@ -0,0 +1,52 @@
1
+ Cfer::Core::Stack.extend_stack do
2
+ def validate_stack!(hash)
3
+ errors = []
4
+ context = []
5
+ _inner_validate_stack!(hash, errors, context)
6
+
7
+ raise Cfer::Util::CferValidationError, errors unless errors.empty?
8
+ end
9
+
10
+ def _inner_validate_stack!(hash, errors = [], context = [])
11
+ case hash
12
+ when Hash
13
+ hash.each do |k, v|
14
+ _inner_validate_stack!(v, errors, context + [k])
15
+ end
16
+ when Array
17
+ hash.each_index do |i|
18
+ _inner_validate_stack!(hash[i], errors, context + [i])
19
+ end
20
+ when nil
21
+ errors << {
22
+ error: "CloudFormation does not allow nulls in templates",
23
+ context: context
24
+ }
25
+ end
26
+ end
27
+
28
+ def validation_contextualize(err_ctx)
29
+ err_ctx.inject("") do |err_str, ctx|
30
+ err_str <<
31
+ case ctx
32
+ when String
33
+ ".#{ctx}"
34
+ when Numeric
35
+ "[#{ctx}]"
36
+ end
37
+ end
38
+ end
39
+ end
40
+
41
+ Cfer::Core::Stack.after do
42
+ begin
43
+ validate_stack!(self)
44
+ rescue Cfer::Util::CferValidationError => e
45
+ Cfer::LOGGER.error "Cfer detected #{e.errors.size > 1 ? 'errors' : 'an error'} when generating the stack:"
46
+ e.errors.each do |err|
47
+ Cfer::LOGGER.error "* #{err[:error]} in Stack#{validation_contextualize(err[:context])}"
48
+ end
49
+ raise e
50
+ end
51
+ end
52
+
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cfer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.2
4
+ version: 0.5.0.pre.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sean Edwards
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-05-18 00:00:00.000000000 Z
11
+ date: 2016-08-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: docile
@@ -17,9 +17,6 @@ dependencies:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
19
  version: '1.1'
20
- - - ">="
21
- - !ruby/object:Gem::Version
22
- version: 1.1.5
23
20
  type: :runtime
24
21
  prerelease: false
25
22
  version_requirements: !ruby/object:Gem::Requirement
@@ -27,9 +24,6 @@ dependencies:
27
24
  - - "~>"
28
25
  - !ruby/object:Gem::Version
29
26
  version: '1.1'
30
- - - ">="
31
- - !ruby/object:Gem::Version
32
- version: 1.1.5
33
27
  - !ruby/object:Gem::Dependency
34
28
  name: thor
35
29
  requirement: !ruby/object:Gem::Requirement
@@ -48,22 +42,16 @@ dependencies:
48
42
  name: activesupport
49
43
  requirement: !ruby/object:Gem::Requirement
50
44
  requirements:
51
- - - "~>"
52
- - !ruby/object:Gem::Version
53
- version: '4.2'
54
45
  - - ">="
55
46
  - !ruby/object:Gem::Version
56
- version: 4.2.6
47
+ version: '3'
57
48
  type: :runtime
58
49
  prerelease: false
59
50
  version_requirements: !ruby/object:Gem::Requirement
60
51
  requirements:
61
- - - "~>"
62
- - !ruby/object:Gem::Version
63
- version: '4.2'
64
52
  - - ">="
65
53
  - !ruby/object:Gem::Version
66
- version: 4.2.6
54
+ version: '3'
67
55
  - !ruby/object:Gem::Dependency
68
56
  name: aws-sdk
69
57
  requirement: !ruby/object:Gem::Requirement
@@ -71,9 +59,6 @@ dependencies:
71
59
  - - "~>"
72
60
  - !ruby/object:Gem::Version
73
61
  version: '2.2'
74
- - - ">="
75
- - !ruby/object:Gem::Version
76
- version: 2.2.33
77
62
  type: :runtime
78
63
  prerelease: false
79
64
  version_requirements: !ruby/object:Gem::Requirement
@@ -81,9 +66,6 @@ dependencies:
81
66
  - - "~>"
82
67
  - !ruby/object:Gem::Version
83
68
  version: '2.2'
84
- - - ">="
85
- - !ruby/object:Gem::Version
86
- version: 2.2.33
87
69
  - !ruby/object:Gem::Dependency
88
70
  name: aws-sdk-resources
89
71
  requirement: !ruby/object:Gem::Requirement
@@ -91,9 +73,6 @@ dependencies:
91
73
  - - "~>"
92
74
  - !ruby/object:Gem::Version
93
75
  version: '2.2'
94
- - - ">="
95
- - !ruby/object:Gem::Version
96
- version: 2.2.33
97
76
  type: :runtime
98
77
  prerelease: false
99
78
  version_requirements: !ruby/object:Gem::Requirement
@@ -101,9 +80,6 @@ dependencies:
101
80
  - - "~>"
102
81
  - !ruby/object:Gem::Version
103
82
  version: '2.2'
104
- - - ">="
105
- - !ruby/object:Gem::Version
106
- version: 2.2.33
107
83
  - !ruby/object:Gem::Dependency
108
84
  name: preconditions
109
85
  requirement: !ruby/object:Gem::Requirement
@@ -125,9 +101,6 @@ dependencies:
125
101
  - - "~>"
126
102
  - !ruby/object:Gem::Version
127
103
  version: '1.4'
128
- - - ">="
129
- - !ruby/object:Gem::Version
130
- version: 1.4.1
131
104
  type: :runtime
132
105
  prerelease: false
133
106
  version_requirements: !ruby/object:Gem::Requirement
@@ -135,9 +108,6 @@ dependencies:
135
108
  - - "~>"
136
109
  - !ruby/object:Gem::Version
137
110
  version: '1.4'
138
- - - ">="
139
- - !ruby/object:Gem::Version
140
- version: 1.4.1
141
111
  - !ruby/object:Gem::Dependency
142
112
  name: rainbow
143
113
  requirement: !ruby/object:Gem::Requirement
@@ -159,9 +129,6 @@ dependencies:
159
129
  - - "~>"
160
130
  - !ruby/object:Gem::Version
161
131
  version: '1.7'
162
- - - ">="
163
- - !ruby/object:Gem::Version
164
- version: 1.7.8
165
132
  type: :runtime
166
133
  prerelease: false
167
134
  version_requirements: !ruby/object:Gem::Requirement
@@ -169,9 +136,6 @@ dependencies:
169
136
  - - "~>"
170
137
  - !ruby/object:Gem::Version
171
138
  version: '1.7'
172
- - - ">="
173
- - !ruby/object:Gem::Version
174
- version: 1.7.8
175
139
  - !ruby/object:Gem::Dependency
176
140
  name: table_print
177
141
  requirement: !ruby/object:Gem::Requirement
@@ -179,9 +143,6 @@ dependencies:
179
143
  - - "~>"
180
144
  - !ruby/object:Gem::Version
181
145
  version: '1.5'
182
- - - ">="
183
- - !ruby/object:Gem::Version
184
- version: 1.5.6
185
146
  type: :runtime
186
147
  prerelease: false
187
148
  version_requirements: !ruby/object:Gem::Requirement
@@ -189,9 +150,6 @@ dependencies:
189
150
  - - "~>"
190
151
  - !ruby/object:Gem::Version
191
152
  version: '1.5'
192
- - - ">="
193
- - !ruby/object:Gem::Version
194
- version: 1.5.6
195
153
  - !ruby/object:Gem::Dependency
196
154
  name: git
197
155
  requirement: !ruby/object:Gem::Requirement
@@ -207,38 +165,39 @@ dependencies:
207
165
  - !ruby/object:Gem::Version
208
166
  version: '1.3'
209
167
  - !ruby/object:Gem::Dependency
210
- name: bundler
168
+ name: yard
211
169
  requirement: !ruby/object:Gem::Requirement
212
170
  requirements:
213
- - - ">="
171
+ - - "~>"
214
172
  - !ruby/object:Gem::Version
215
- version: '0'
216
- type: :runtime
173
+ version: 0.8.7.6
174
+ type: :development
217
175
  prerelease: false
218
176
  version_requirements: !ruby/object:Gem::Requirement
219
177
  requirements:
220
- - - ">="
178
+ - - "~>"
221
179
  - !ruby/object:Gem::Version
222
- version: '0'
180
+ version: 0.8.7.6
223
181
  - !ruby/object:Gem::Dependency
224
- name: yard
182
+ name: rake
225
183
  requirement: !ruby/object:Gem::Requirement
226
184
  requirements:
227
- - - "~>"
185
+ - - ">="
228
186
  - !ruby/object:Gem::Version
229
- version: 0.8.7.6
187
+ version: '0'
230
188
  type: :development
231
189
  prerelease: false
232
190
  version_requirements: !ruby/object:Gem::Requirement
233
191
  requirements:
234
- - - "~>"
192
+ - - ">="
235
193
  - !ruby/object:Gem::Version
236
- version: 0.8.7.6
194
+ version: '0'
237
195
  description: Toolkit for automating infrastructure using AWS CloudFormation
238
196
  email:
239
197
  - stedwards87+cfer@gmail.com
240
198
  executables:
241
199
  - cfer
200
+ - json-to-cfer
242
201
  extensions: []
243
202
  extra_rdoc_files: []
244
203
  files:
@@ -248,6 +207,7 @@ files:
248
207
  - ".rubocop.yml"
249
208
  - ".travis.yml"
250
209
  - ".yardopts"
210
+ - CHANGELOG.md
251
211
  - CODE_OF_CONDUCT.md
252
212
  - Dockerfile
253
213
  - Gemfile
@@ -257,6 +217,7 @@ files:
257
217
  - bin/cfer
258
218
  - bin/cfer-dbg
259
219
  - bin/console
220
+ - bin/json-to-cfer
260
221
  - bin/setup
261
222
  - cfer.gemspec
262
223
  - doc/cfer-demo.gif
@@ -265,19 +226,23 @@ files:
265
226
  - examples/vpc.rb
266
227
  - lib/cfer.rb
267
228
  - lib/cfer/block.rb
268
- - lib/cfer/cfn/aws.rb
269
229
  - lib/cfer/cfn/cfer_credentials_provider.rb
270
230
  - lib/cfer/cfn/client.rb
271
231
  - lib/cfer/cli.rb
272
232
  - lib/cfer/core/client.rb
273
- - lib/cfer/core/fn.rb
233
+ - lib/cfer/core/functions.rb
234
+ - lib/cfer/core/hooks.rb
274
235
  - lib/cfer/core/resource.rb
275
236
  - lib/cfer/core/stack.rb
276
237
  - lib/cfer/util/error.rb
277
238
  - lib/cfer/version.rb
278
239
  - lib/cferext/aws/auto_scaling/auto_scaling_group.rb
240
+ - lib/cferext/aws/cloud_formation/wait_condition.rb
279
241
  - lib/cferext/aws/iam/policy.rb
280
242
  - lib/cferext/aws/iam/policy_generator.rb
243
+ - lib/cferext/aws/kms/key.rb
244
+ - lib/cferext/aws/rds/db_instance.rb
245
+ - lib/cferext/cfer/stack_validation.rb
281
246
  homepage: https://github.com/seanedwards/cfer
282
247
  licenses:
283
248
  - MIT
@@ -288,14 +253,17 @@ require_paths:
288
253
  - lib
289
254
  required_ruby_version: !ruby/object:Gem::Requirement
290
255
  requirements:
256
+ - - "~>"
257
+ - !ruby/object:Gem::Version
258
+ version: '2.2'
291
259
  - - ">="
292
260
  - !ruby/object:Gem::Version
293
- version: '0'
261
+ version: 2.2.5
294
262
  required_rubygems_version: !ruby/object:Gem::Requirement
295
263
  requirements:
296
- - - ">="
264
+ - - ">"
297
265
  - !ruby/object:Gem::Version
298
- version: '0'
266
+ version: 1.3.1
299
267
  requirements: []
300
268
  rubyforge_project:
301
269
  rubygems_version: 2.5.1
@@ -1,29 +0,0 @@
1
- module Cfer::Cfn::AWS
2
- class << self
3
- include Cfer::Core
4
- def account_id
5
- Fn::ref 'AWS::AccountId'
6
- end
7
-
8
- def notification_arns
9
- Fn::ref 'AWS::NotificationARNs'
10
- end
11
-
12
- def no_value
13
- Fn::ref 'AWS::NoValue'
14
- end
15
-
16
- def region
17
- Fn::ref 'AWS::Region'
18
- end
19
-
20
- def stack_id
21
- Fn::ref 'AWS::StackId'
22
- end
23
-
24
- def stack_name
25
- Fn::ref 'AWS::StackName'
26
- end
27
- end
28
- end
29
-
@@ -1,55 +0,0 @@
1
- module Cfer::Core::Fn
2
- class << self
3
- def join(sep, *args)
4
- {"Fn::Join" => [sep, [ *args ].flatten ]}
5
- end
6
-
7
- def ref(r)
8
- {"Ref" => r}
9
- end
10
-
11
- def get_att(r, att)
12
- {"Fn::GetAtt" => [r, att]}
13
- end
14
-
15
- def find_in_map(map_name, key1, key2)
16
- {"Fn::FindInMap" => [map_name, key1, key2]}
17
- end
18
-
19
- def select(i, o)
20
- {"Fn::Select" => [i, o]}
21
- end
22
-
23
- def base64(v)
24
- {"Fn::Base64" => v}
25
- end
26
-
27
- def condition(cond)
28
- {"Condition" => cond}
29
- end
30
-
31
- def and(*conds)
32
- {"Fn::And" => conds}
33
- end
34
-
35
- def or(*conds)
36
- {"Fn::Or" => conds}
37
- end
38
-
39
- def equals(a, b)
40
- {"Fn::Equals" => [a, b]}
41
- end
42
-
43
- def if(cond, t, f)
44
- {"Fn::If" => [cond, t, f]}
45
- end
46
-
47
- def not(cond)
48
- {"Fn::Not" => [cond]}
49
- end
50
-
51
- def get_azs(region)
52
- {"Fn::GetAZs" => region}
53
- end
54
- end
55
- end