cfer 0.4.2 → 0.5.0.pre.rc1

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 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