sfn 3.0.28 → 3.0.30

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.
Files changed (77) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +5 -0
  3. data/docs/callbacks.md +1 -0
  4. data/lib/chef/knife/knife_plugin_seed.rb +11 -17
  5. data/lib/sfn.rb +0 -2
  6. data/lib/sfn/api_provider.rb +0 -2
  7. data/lib/sfn/api_provider/google.rb +6 -9
  8. data/lib/sfn/api_provider/terraform.rb +4 -6
  9. data/lib/sfn/cache.rb +36 -39
  10. data/lib/sfn/callback.rb +0 -2
  11. data/lib/sfn/callback/aws_assume_role.rb +7 -8
  12. data/lib/sfn/callback/aws_mfa.rb +7 -8
  13. data/lib/sfn/callback/stack_policy.rb +15 -17
  14. data/lib/sfn/command.rb +9 -11
  15. data/lib/sfn/command/conf.rb +7 -10
  16. data/lib/sfn/command/create.rb +8 -12
  17. data/lib/sfn/command/describe.rb +6 -8
  18. data/lib/sfn/command/destroy.rb +8 -10
  19. data/lib/sfn/command/diff.rb +18 -25
  20. data/lib/sfn/command/events.rb +15 -16
  21. data/lib/sfn/command/export.rb +13 -17
  22. data/lib/sfn/command/graph.rb +11 -13
  23. data/lib/sfn/command/graph/aws.rb +27 -29
  24. data/lib/sfn/command/graph/terraform.rb +22 -23
  25. data/lib/sfn/command/import.rb +13 -16
  26. data/lib/sfn/command/init.rb +5 -7
  27. data/lib/sfn/command/inspect.rb +26 -29
  28. data/lib/sfn/command/lint.rb +10 -12
  29. data/lib/sfn/command/list.rb +5 -8
  30. data/lib/sfn/command/print.rb +3 -5
  31. data/lib/sfn/command/promote.rb +0 -2
  32. data/lib/sfn/command/update.rb +42 -46
  33. data/lib/sfn/command/validate.rb +4 -6
  34. data/lib/sfn/command_module/base.rb +17 -25
  35. data/lib/sfn/command_module/callbacks.rb +12 -8
  36. data/lib/sfn/command_module/stack.rb +39 -43
  37. data/lib/sfn/command_module/template.rb +89 -90
  38. data/lib/sfn/config.rb +30 -31
  39. data/lib/sfn/config/conf.rb +1 -3
  40. data/lib/sfn/config/create.rb +5 -7
  41. data/lib/sfn/config/describe.rb +3 -5
  42. data/lib/sfn/config/diff.rb +1 -1
  43. data/lib/sfn/config/events.rb +6 -8
  44. data/lib/sfn/config/export.rb +4 -7
  45. data/lib/sfn/config/graph.rb +4 -6
  46. data/lib/sfn/config/import.rb +3 -5
  47. data/lib/sfn/config/init.rb +0 -1
  48. data/lib/sfn/config/inspect.rb +7 -9
  49. data/lib/sfn/config/lint.rb +4 -4
  50. data/lib/sfn/config/list.rb +3 -5
  51. data/lib/sfn/config/print.rb +3 -5
  52. data/lib/sfn/config/promote.rb +3 -5
  53. data/lib/sfn/config/update.rb +10 -12
  54. data/lib/sfn/config/validate.rb +18 -20
  55. data/lib/sfn/lint.rb +0 -2
  56. data/lib/sfn/lint/definition.rb +3 -5
  57. data/lib/sfn/lint/rule.rb +7 -8
  58. data/lib/sfn/lint/rule_set.rb +11 -20
  59. data/lib/sfn/monkey_patch/stack.rb +32 -34
  60. data/lib/sfn/monkey_patch/stack/azure.rb +0 -1
  61. data/lib/sfn/monkey_patch/stack/google.rb +15 -16
  62. data/lib/sfn/planner.rb +1 -3
  63. data/lib/sfn/planner/aws.rb +82 -89
  64. data/lib/sfn/provider.rb +21 -23
  65. data/lib/sfn/utils.rb +0 -2
  66. data/lib/sfn/utils/debug.rb +1 -2
  67. data/lib/sfn/utils/json.rb +3 -2
  68. data/lib/sfn/utils/object_storage.rb +1 -2
  69. data/lib/sfn/utils/output.rb +8 -9
  70. data/lib/sfn/utils/path_selector.rb +9 -10
  71. data/lib/sfn/utils/ssher.rb +2 -3
  72. data/lib/sfn/utils/stack_exporter.rb +20 -21
  73. data/lib/sfn/utils/stack_parameter_scrubber.rb +6 -7
  74. data/lib/sfn/utils/stack_parameter_validator.rb +14 -16
  75. data/lib/sfn/version.rb +1 -1
  76. data/sfn.gemspec +1 -1
  77. metadata +8 -8
@@ -22,11 +22,11 @@ module Sfn
22
22
  #
23
23
  # @param location [Symbol, String] name of location
24
24
  # @return [Sfn::Provider]
25
- def provider_for(location=nil)
25
+ def provider_for(location = nil)
26
26
  key = ['provider', location].compact.map(&:to_s).join('_')
27
- if(location)
27
+ if location
28
28
  credentials = config.get(:locations, location)
29
- unless(credentials)
29
+ unless credentials
30
30
  raise ArgumentError.new "Failed to locate provider credentials for location `#{location}`!"
31
31
  end
32
32
  else
@@ -37,18 +37,15 @@ module Sfn
37
37
  result = Sfn::Provider.new(
38
38
  :miasma => credentials,
39
39
  :async => false,
40
- :fetch => false
40
+ :fetch => false,
41
41
  )
42
- result.connection.data[:stack_types] = (
43
- [
44
- (result.connection.class.const_get(:RESOURCE_MAPPING).detect do |klass, info|
45
- info[:api] == :orchestration
46
- end || []).first
47
- ] + custom_stack_types
48
- ).compact.uniq
42
+ result.connection.data[:stack_types] = ([
43
+ (result.connection.class.const_get(:RESOURCE_MAPPING).detect do |klass, info|
44
+ info[:api] == :orchestration
45
+ end || []).first,
46
+ ] + custom_stack_types).compact.uniq
49
47
  retry_config = config.fetch(:retry,
50
- config.fetch(:retries, {})
51
- )
48
+ config.fetch(:retries, {}))
52
49
  result.connection.data[:retry_ui] = ui
53
50
  result.connection.data[:location] = location.to_s
54
51
  result.connection.data[:locations] = config.fetch(:locations, {})
@@ -63,19 +60,19 @@ module Sfn
63
60
  raise
64
61
  end
65
62
  end
66
- alias_method :provider, :provider_for
67
63
 
64
+ alias_method :provider, :provider_for
68
65
 
69
66
  # Write exception information if debug is enabled
70
67
  #
71
68
  # @param e [Exception]
72
69
  # @param args [String] extra strings to output
73
70
  def _debug(e, *args)
74
- if(config[:verbose] || config[:debug])
71
+ if config[:verbose] || config[:debug]
75
72
  ui.fatal "Exception information: #{e.class}: #{e.message}"
76
- if(ENV['DEBUG'] || config[:debug])
73
+ if ENV['DEBUG'] || config[:debug]
77
74
  puts "#{e.backtrace.join("\n")}\n"
78
- if(e.is_a?(Miasma::Error::ApiError))
75
+ if e.is_a?(Miasma::Error::ApiError)
79
76
  ui.fatal "Response body: #{e.response.body.to_s.inspect}"
80
77
  end
81
78
  end
@@ -97,7 +94,7 @@ module Sfn
97
94
  #
98
95
  # @param name [String] name of stack
99
96
  # @return [Miasma::Models::Orchestration::Stack]
100
- def stack(name=nil)
97
+ def stack(name = nil)
101
98
  name = name_args.first unless name
102
99
  provider.stacks.get(name)
103
100
  end
@@ -136,7 +133,7 @@ module Sfn
136
133
  # @param message [String] failure message
137
134
  # @yield block to wrap error handling
138
135
  # @return [Object] result of yield
139
- def get_things(stack=nil, message=nil)
136
+ def get_things(stack = nil, message = nil)
140
137
  begin
141
138
  yield
142
139
  rescue => e
@@ -174,18 +171,16 @@ module Sfn
174
171
  # @return [NilClass]
175
172
  # @raise [ArgumentError]
176
173
  def name_required!
177
- if(name_args.empty?)
174
+ if name_args.empty?
178
175
  ui.error 'Name argument must be provided!'
179
176
  raise ArgumentError.new 'Missing required name argument'
180
177
  end
181
178
  end
182
-
183
179
  end
184
180
 
185
181
  class << self
186
182
  def included(klass)
187
183
  klass.instance_eval do
188
-
189
184
  include Sfn::CommandModule::Base::InstanceMethods
190
185
  include Sfn::CommandModule::Callbacks
191
186
  include Sfn::Utils::JSON
@@ -193,12 +188,9 @@ module Sfn
193
188
  include Bogo::AnimalStrings
194
189
  include Bogo::Memoization
195
190
  include Bogo::Constants
196
-
197
191
  end
198
-
199
192
  end
200
193
  end
201
194
  end
202
-
203
195
  end
204
196
  end
@@ -5,7 +5,6 @@ module Sfn
5
5
  module CommandModule
6
6
  # Callback processor helpers
7
7
  module Callbacks
8
-
9
8
  include Bogo::Memoization
10
9
 
11
10
  # Run expected callbacks around action
@@ -16,9 +15,15 @@ module Sfn
16
15
  def api_action!(*args)
17
16
  type = self.class.name.split('::').last.downcase
18
17
  run_callbacks_for(["before_#{type}", :before], *args)
19
- result = yield if block_given?
20
- run_callbacks_for(["after_#{type}", :after], *args)
21
- result
18
+ result = nil
19
+ begin
20
+ result = yield if block_given?
21
+ run_callbacks_for(["after_#{type}", :after], *args)
22
+ result
23
+ rescue => err
24
+ run_callbacks_for(["failed_#{type}", :failed], *(args + [err]))
25
+ raise
26
+ end
22
27
  end
23
28
 
24
29
  # Process requested callbacks
@@ -34,7 +39,7 @@ module Sfn
34
39
  callback_name, callback, quiet = item
35
40
  quiet = true if config[:print_only]
36
41
  ui.info "Callback #{ui.color(type.to_s, :bold)} #{callback_name}: #{ui.color('starting', :yellow)}" unless quiet
37
- if(args.empty?)
42
+ if args.empty?
38
43
  callback.call
39
44
  else
40
45
  callback.call(*args)
@@ -57,15 +62,14 @@ module Sfn
57
62
  klass.new(ui, config, arguments, provider)
58
63
  rescue NameError => e
59
64
  ui.debug "Callback type lookup error: #{e.class} - #{e}"
60
- raise "Unknown #{type} callback requested: #{c_name} (not found)"
65
+ raise NameError.new("Unknown #{type} callback requested: #{c_name} (not found)")
61
66
  end
62
67
  end
63
- if(instance.respond_to?(type))
68
+ if instance.respond_to?(type)
64
69
  [c_name, instance.method(type), instance.respond_to?(:quiet) ? instance.quiet : false]
65
70
  end
66
71
  end.compact
67
72
  end
68
-
69
73
  end
70
74
  end
71
75
  end
@@ -5,7 +5,6 @@ module Sfn
5
5
  module CommandModule
6
6
  # Stack handling helper methods
7
7
  module Stack
8
-
9
8
  module InstanceMethods
10
9
 
11
10
  # maximum number of attempts to get valid parameter value
@@ -30,7 +29,7 @@ module Sfn
30
29
  stack_info.unshift(nil) if stack_info.size == 1
31
30
  stack_location, stack_name = stack_info
32
31
  remote_stack = provider_for(stack_location).stack(stack_name)
33
- if(remote_stack)
32
+ if remote_stack
34
33
  apply_nested_stacks!(remote_stack, stack)
35
34
  mappings = generate_custom_apply_mappings(remote_stack)
36
35
  execute_apply_stack(remote_stack, stack, mappings)
@@ -49,7 +48,7 @@ module Sfn
49
48
  # @return [Miasma::Models::Orchestration::Stack]
50
49
  def apply_nested_stacks!(remote_stack, stack)
51
50
  remote_stack.resources.all.each do |resource|
52
- if(valid_stack_types.include?(resource.type))
51
+ if valid_stack_types.include?(resource.type)
53
52
  nested_stack = resource.expand
54
53
  apply_nested_stacks!(nested_stack, stack)
55
54
  mappings = generate_custom_apply_mappings(nested_stack)
@@ -64,7 +63,7 @@ module Sfn
64
63
  # @param provider_stack [Miasma::Models::Orchestration::Stack] stack providing outputs
65
64
  # @return [Hash] output to parameter mapping
66
65
  def generate_custom_apply_mappings(provider_stack)
67
- if(config[:apply_mapping])
66
+ if config[:apply_mapping]
68
67
  valid_keys = config[:apply_mapping].keys.find_all do |a_key|
69
68
  a_key = a_key.to_s
70
69
  key_parts = a_key.split('__')
@@ -81,7 +80,7 @@ module Sfn
81
80
  end
82
81
  end
83
82
  to_remove = valid_keys.find_all do |key|
84
- valid_keys.any?{|v_key| v_key.match(/__#{Regexp.escape(key)}$/)}
83
+ valid_keys.any? { |v_key| v_key.match(/__#{Regexp.escape(key)}$/) }
85
84
  end
86
85
  valid_keys -= to_remove
87
86
  Hash[
@@ -130,15 +129,14 @@ module Sfn
130
129
 
131
130
  # Format config defined parameters to ensure expected layout
132
131
  def format_config_parameters!
133
- if(config.get(:parameter).is_a?(Array))
132
+ if config.get(:parameter).is_a?(Array)
134
133
  config[:parameter] = Smash[
135
134
  *config.get(:parameter).map(&:to_a).flatten
136
135
  ]
137
136
  end
138
- if(config.get(:parameters))
137
+ if config.get(:parameters)
139
138
  config.set(:parameters,
140
- config.get(:parameters).merge(config.fetch(:parameter, Smash.new))
141
- )
139
+ config.get(:parameters).merge(config.fetch(:parameter, Smash.new)))
142
140
  else
143
141
  config.set(:parameters, config.fetch(:parameter, Smash.new))
144
142
  end
@@ -151,16 +149,16 @@ module Sfn
151
149
  # @return [Array<String>] [expected_template_key, configuration_used_key]
152
150
  def locate_config_parameter_key(parameter_prefix, parameter_name, root_name)
153
151
  check_name = parameter_name.downcase.tr('-_', '')
154
- check_prefix = parameter_prefix.map{|i| i.downcase.tr('-_', '') }
152
+ check_prefix = parameter_prefix.map { |i| i.downcase.tr('-_', '') }
155
153
  key_match = config[:parameters].keys.detect do |cp_key|
156
- cp_key = cp_key.to_s.downcase.split('__').map{|i| i.tr('-_', '') }.join('__')
154
+ cp_key = cp_key.to_s.downcase.split('__').map { |i| i.tr('-_', '') }.join('__')
157
155
  non_root_matcher = (check_prefix + [check_name]).join('__')
158
156
  root_matcher = ([root_name] + check_prefix + [check_name]).join('__')
159
157
  cp_key == non_root_matcher ||
160
158
  cp_key == root_matcher
161
159
  end
162
160
  actual_key = (parameter_prefix + [parameter_name]).compact.join('__')
163
- if(key_match)
161
+ if key_match
164
162
  ui.debug "Remapping configuration runtime parameter `#{key_match}` -> `#{actual_key}`"
165
163
  config[:parameters][actual_key] = config[:parameters].delete(key_match)
166
164
  end
@@ -179,23 +177,23 @@ module Sfn
179
177
  def set_parameter(sparkle, ns_key, param_name, param_value, current_parameters, param_banner)
180
178
  valid = false
181
179
  attempt = 0
182
- if(!valid && !param_banner)
183
- if(sparkle.is_a?(SparkleFormation))
180
+ if !valid && !param_banner
181
+ if sparkle.is_a?(SparkleFormation)
184
182
  ui.info "#{ui.color('Stack runtime parameters:', :bold)} - template: #{ui.color(sparkle.root_path.map(&:name).map(&:to_s).join(' > '), :green, :bold)}"
185
183
  else
186
184
  ui.info ui.color('Stack runtime parameters:', :bold)
187
185
  end
188
186
  param_banner = true
189
187
  end
190
- until(valid)
188
+ until valid
191
189
  attempt += 1
192
190
  default = config[:parameters].fetch(
193
191
  ns_key, current_parameters.fetch(
194
- param_name, TEMPLATE_PARAMETER_DEFAULTS.map{|loc_key| param_value[loc_key]}.compact.first
192
+ param_name, TEMPLATE_PARAMETER_DEFAULTS.map { |loc_key| param_value[loc_key] }.compact.first
195
193
  )
196
194
  )
197
- if(config[:interactive_parameters])
198
- no_echo = !!TEMPLATE_PARAMETER_NOECHO.detect{|loc_key|
195
+ if config[:interactive_parameters]
196
+ no_echo = !!TEMPLATE_PARAMETER_NOECHO.detect { |loc_key|
199
197
  param_value[loc_key].to_s.downcase == 'true'
200
198
  }
201
199
  sfn_no_echo = TEMPLATE_PARAMETER_SFN_NOECHO.map do |loc_key|
@@ -204,16 +202,16 @@ module Sfn
204
202
  end.compact.first
205
203
  no_echo = sfn_no_echo if sfn_no_echo
206
204
  answer = ui.ask_question(
207
- "#{param_name.split(/([A-Z]+[^A-Z]*)/).find_all{|s|!s.empty?}.join(' ')}",
205
+ "#{param_name.split(/([A-Z]+[^A-Z]*)/).find_all { |s| !s.empty? }.join(' ')}",
208
206
  :default => default,
209
207
  :hide_default => sfn_no_echo == 'all',
210
- :no_echo => !!no_echo
208
+ :no_echo => !!no_echo,
211
209
  )
212
210
  else
213
211
  answer = default
214
212
  end
215
213
  validation = validate_parameter(answer, param_value)
216
- if(validation == true)
214
+ if validation == true
217
215
  config[:parameters][ns_key] = answer
218
216
  valid = true
219
217
  else
@@ -221,7 +219,7 @@ module Sfn
221
219
  ui.error validation_error.last
222
220
  end
223
221
  end
224
- if(attempt > MAX_PARAMETER_ATTEMPTS)
222
+ if attempt > MAX_PARAMETER_ATTEMPTS
225
223
  ui.fatal 'Failed to receive allowed parameter!'
226
224
  exit 1
227
225
  end
@@ -236,29 +234,29 @@ module Sfn
236
234
  # @option opts [Hash] :current_parameters current stack parameter values
237
235
  # @option opts [Miasma::Models::Orchestration::Stack] :stack existing stack
238
236
  # @return [Hash]
239
- def populate_parameters!(sparkle, opts={})
237
+ def populate_parameters!(sparkle, opts = {})
240
238
  current_parameters = opts[:current_parameters] || {}
241
239
  current_stack = opts[:stack]
242
240
  parameter_prefix, stack_parameters = prefix_parameters_setup(sparkle)
243
241
  sparkle_root_name = sparkle.is_a?(SparkleFormation) ? sparkle.root.name : nil
244
- unless(stack_parameters.empty?)
242
+ unless stack_parameters.empty?
245
243
  format_config_parameters!
246
244
  param_banner = false
247
245
  stack_parameters.each do |param_name, param_value|
248
246
  ns_key = locate_config_parameter_key(parameter_prefix, param_name, sparkle_root_name)
249
247
  # When parameter is a hash type, it is being set via
250
248
  # intrinsic function and we don't modify
251
- if(function_set_parameter?(current_parameters[param_name]))
252
- if(!config[:parameters][ns_key].nil?)
249
+ if function_set_parameter?(current_parameters[param_name])
250
+ if !config[:parameters][ns_key].nil?
253
251
  ui.warn "Overriding mapped parameter value with explicit assignment `#{ns_key}`!"
254
252
  else
255
- if(current_stack)
253
+ if current_stack
256
254
  enable_set = validate_stack_parameter(current_stack, param_name, ns_key, current_parameters[param_name])
257
255
  else
258
256
  enable_set = true
259
257
  end
260
258
  end
261
- if(enable_set)
259
+ if enable_set
262
260
  # NOTE: direct set dumps the stack (nfi). Smash will
263
261
  # auto dup it, and works, so yay i guess.
264
262
  config[:parameters][ns_key] = current_parameters[param_name].is_a?(Hash) ?
@@ -267,22 +265,22 @@ module Sfn
267
265
  valid = true
268
266
  end
269
267
  else
270
- if(current_stack && current_stack.data[:parent_stack])
268
+ if current_stack && current_stack.data[:parent_stack]
271
269
  use_expected = validate_stack_parameter(current_stack, param_name, ns_key, current_parameters[param_name])
272
- unless(use_expected)
270
+ unless use_expected
273
271
  current_parameters[param_name] = current_stack.parameters[param_name]
274
272
  end
275
273
  end
276
274
  end
277
- unless(valid)
275
+ unless valid
278
276
  param_banner = set_parameter(sparkle, ns_key, param_name, param_value, current_parameters, param_banner)
279
277
  end
280
278
  end
281
279
  end
282
280
  Smash[
283
- config.fetch(:parameters, {}).map do |k,v|
281
+ config.fetch(:parameters, {}).map do |k, v|
284
282
  strip_key = parameter_prefix ? k.sub(/#{parameter_prefix.join('__')}_{2}?/, '') : k
285
- unless(strip_key.include?('__'))
283
+ unless strip_key.include?('__')
286
284
  [strip_key, v]
287
285
  end
288
286
  end.compact
@@ -300,7 +298,7 @@ module Sfn
300
298
  # @return [Hash] parameters for root stack create/update
301
299
  def config_root_parameters
302
300
  Hash[
303
- config.fetch(:parameters, {}).find_all do |k,v|
301
+ config.fetch(:parameters, {}).find_all do |k, v|
304
302
  !k.include?('__')
305
303
  end
306
304
  ]
@@ -320,19 +318,19 @@ module Sfn
320
318
  def validate_stack_parameter(c_stack, p_key, p_ns_key, c_value)
321
319
  stack_value = c_stack.parameters[p_key]
322
320
  p_stack = c_stack.data[:parent_stack]
323
- unless(config[:parameter_validation] == 'none')
324
- if(c_value.is_a?(Hash))
321
+ unless config[:parameter_validation] == 'none'
322
+ if c_value.is_a?(Hash)
325
323
  case c_value.keys.first
326
324
  when 'Ref'
327
325
  current_value = p_stack.parameters[c_value.values.first]
328
326
  when 'Fn::Att'
329
327
  resource_name, output_name = c_value.values.first.split('.', 2)
330
- ref_stack = p_stack.nested_stacks.detect{|i| i.data[:logical_id] == resource_name}
331
- if(ref_stack)
328
+ ref_stack = p_stack.nested_stacks.detect { |i| i.data[:logical_id] == resource_name }
329
+ if ref_stack
332
330
  output = ref_stack.outputs.detect do |o|
333
331
  o.key == output_name
334
332
  end
335
- if(output)
333
+ if output
336
334
  current_value = output.value
337
335
  end
338
336
  end
@@ -340,8 +338,8 @@ module Sfn
340
338
  else
341
339
  current_value = c_value
342
340
  end
343
- if(current_value && current_value.to_s != stack_value.to_s)
344
- if(config[:parameter_validation] == 'default')
341
+ if current_value && current_value.to_s != stack_value.to_s
342
+ if config[:parameter_validation] == 'default'
345
343
  ui.warn 'Nested stack has been altered directly! This update may cause unexpected modifications!'
346
344
  ui.warn "Stack name: #{c_stack.name}. Parameter: #{p_key}. Current value: #{stack_value}. Expected value: #{current_value} (via: #{c_value.inspect})"
347
345
  answer = ui.ask_question("Use current value or expected value for #{p_key} [current/expected]?", :valid => ['current', 'expected'])
@@ -356,7 +354,6 @@ module Sfn
356
354
  true
357
355
  end
358
356
  end
359
-
360
357
  end
361
358
 
362
359
  module ClassMethods
@@ -372,7 +369,6 @@ module Sfn
372
369
  include Utils::StackParameterValidator
373
370
  end
374
371
  end
375
-
376
372
  end
377
373
  end
378
374
  end
@@ -22,9 +22,9 @@ module Sfn
22
22
  # @param thing [SparkleFormation, Hash]
23
23
  # @param scrub [Truthy, Falsey] scrub nested templates
24
24
  # @return [Hash]
25
- def template_content(thing, scrub=false)
26
- if(thing.is_a?(SparkleFormation))
27
- if(scrub)
25
+ def template_content(thing, scrub = false)
26
+ if thing.is_a?(SparkleFormation)
27
+ if scrub
28
28
  dump_stack_for_storage(thing)
29
29
  else
30
30
  config[:sparkle_dump] ? thing.sparkle_dump : thing.dump
@@ -45,41 +45,41 @@ module Sfn
45
45
  # @option p_config [String, Symbol] :description
46
46
  # @option p_config [String, Symbol] :multiple
47
47
  # @return [Object]
48
- def request_compile_parameter(p_name, p_config, cur_val, nested=false)
48
+ def request_compile_parameter(p_name, p_config, cur_val, nested = false)
49
49
  result = nil
50
50
  attempts = 0
51
51
  parameter_type = p_config.fetch(:type, 'string').to_s.downcase.to_sym
52
- if(parameter_type == :complex)
52
+ if parameter_type == :complex
53
53
  ui.debug "Compile time parameter `#{p_name}` is a complex type. Not requesting value from user."
54
- if(cur_val.nil?)
54
+ if cur_val.nil?
55
55
  raise ArgumentError.new "No value provided for `#{p_name}` parameter (Complex data type)"
56
56
  else
57
57
  cur_val
58
58
  end
59
59
  else
60
- unless(cur_val || p_config[:default].nil?)
60
+ unless cur_val || p_config[:default].nil?
61
61
  cur_val = p_config[:default]
62
62
  end
63
- if(cur_val.is_a?(Array))
63
+ if cur_val.is_a?(Array)
64
64
  cur_val = cur_val.map(&:to_s).join(',')
65
65
  end
66
- until(result && (!result.respond_to?(:empty?) || !result.empty?))
66
+ until result && (!result.respond_to?(:empty?) || !result.empty?)
67
67
  attempts += 1
68
- if(config[:interactive_parameters] && (!nested || !p_config.key?(:prompt_when_nested) || p_config[:prompt_when_nested] == true))
68
+ if config[:interactive_parameters] && (!nested || !p_config.key?(:prompt_when_nested) || p_config[:prompt_when_nested] == true)
69
69
  result = ui.ask_question(
70
70
  p_name.to_s.split('_').map(&:capitalize).join,
71
- :default => cur_val.to_s.empty? ? nil : cur_val.to_s
71
+ :default => cur_val.to_s.empty? ? nil : cur_val.to_s,
72
72
  )
73
73
  else
74
74
  result = cur_val.to_s
75
75
  end
76
76
  case parameter_type
77
77
  when :string
78
- if(p_config[:multiple])
78
+ if p_config[:multiple]
79
79
  result = result.split(',').map(&:strip)
80
80
  end
81
81
  when :number
82
- if(p_config[:multiple])
82
+ if p_config[:multiple]
83
83
  result = result.split(',').map(&:strip)
84
84
  new_result = result.map do |item|
85
85
  new_item = item.to_i
@@ -94,14 +94,14 @@ module Sfn
94
94
  raise ArgumentError.new "Unknown compile time parameter type provided: `#{p_config[:type].inspect}` (Parameter: #{p_name})"
95
95
  end
96
96
  valid = validate_parameter(result, p_config.to_smash)
97
- unless(valid == true)
97
+ unless valid == true
98
98
  result = nil
99
99
  valid.each do |invalid_msg|
100
100
  ui.error invalid_msg.last
101
101
  end
102
102
  end
103
- if(result.nil? || (result.respond_to?(:empty?) && result.empty?))
104
- if(attempts > MAX_PARAMETER_ATTEMPTS)
103
+ if result.nil? || (result.respond_to?(:empty?) && result.empty?)
104
+ if attempts > MAX_PARAMETER_ATTEMPTS
105
105
  ui.fatal "Failed to receive allowed parameter! (Parameter: #{p_name})"
106
106
  exit 1
107
107
  end
@@ -135,17 +135,17 @@ module Sfn
135
135
  def sparkle_collection
136
136
  memoize(:sparkle_collection) do
137
137
  collection = SparkleFormation::SparkleCollection.new(
138
- :provider => config.fetch(:credentials, :provider, DEFAULT_PROVIDER_NAME)
138
+ :provider => config.fetch(:credentials, :provider, DEFAULT_PROVIDER_NAME),
139
139
  )
140
140
  begin
141
- if(config[:base_directory])
141
+ if config[:base_directory]
142
142
  root_pack = SparkleFormation::SparklePack.new(
143
143
  :root => config[:base_directory],
144
- :provider => config.fetch(:credentials, :provider, DEFAULT_PROVIDER_NAME)
144
+ :provider => config.fetch(:credentials, :provider, DEFAULT_PROVIDER_NAME),
145
145
  )
146
146
  else
147
147
  root_pack = SparkleFormation::SparklePack.new(
148
- :provider => config.fetch(:credentials, :provider, DEFAULT_PROVIDER_NAME)
148
+ :provider => config.fetch(:credentials, :provider, DEFAULT_PROVIDER_NAME),
149
149
  )
150
150
  end
151
151
  collection.set_root(root_pack)
@@ -164,30 +164,30 @@ module Sfn
164
164
  # @param args [Symbol] options (:allow_missing)
165
165
  # @return [Hash] loaded template
166
166
  def load_template_file(*args)
167
- c_stack = (args.detect{|i| i.is_a?(Hash)} || {})[:stack]
168
- unless(config[:template])
167
+ c_stack = (args.detect { |i| i.is_a?(Hash) } || {})[:stack]
168
+ unless config[:template]
169
169
  set_paths_and_discover_file!
170
- unless(config[:file])
171
- unless(args.include?(:allow_missing))
170
+ unless config[:file]
171
+ unless args.include?(:allow_missing)
172
172
  ui.fatal "Invalid formation file path provided: #{config[:file]}"
173
173
  raise IOError.new "Failed to locate file: #{config[:file]}"
174
174
  end
175
175
  end
176
176
  end
177
- if(config[:template])
177
+ if config[:template]
178
178
  config[:template]
179
- elsif(config[:file])
180
- if(config[:processing])
179
+ elsif config[:file]
180
+ if config[:processing]
181
181
  compile_state = merge_compile_time_parameters
182
182
  sf = SparkleFormation.compile(config[:file], :sparkle)
183
- if(name_args.first)
183
+ if name_args.first
184
184
  sf.name = name_args.first
185
185
  end
186
186
  sf.compile_time_parameter_setter do |formation|
187
187
  f_name = formation.root_path.map(&:name).map(&:to_s)
188
188
  pathed_name = f_name.join(' > ')
189
189
  f_name = f_name.join('__')
190
- if(formation.root? && compile_state[f_name].nil?)
190
+ if formation.root? && compile_state[f_name].nil?
191
191
  current_state = compile_state
192
192
  else
193
193
  current_state = compile_state.fetch(f_name, Smash.new)
@@ -196,40 +196,39 @@ module Sfn
196
196
  # NOTE: Prevent nesting stack compile state within stack compile state
197
197
  current_state.delete("#{f_name}__#{f_name}")
198
198
 
199
- if(formation.compile_state)
199
+ if formation.compile_state
200
200
  current_state = current_state.merge(formation.compile_state)
201
201
  end
202
- unless(formation.parameters.empty?)
202
+ unless formation.parameters.empty?
203
203
  ui.info "#{ui.color('Compile time parameters:', :bold)} - template: #{ui.color(pathed_name, :green, :bold)}" unless config[:print_only]
204
- formation.parameters.each do |k,v|
204
+ formation.parameters.each do |k, v|
205
205
  valid_keys = [
206
206
  "#{f_name}__#{k}",
207
207
  Bogo::Utility.camel("#{f_name}__#{k}").downcase,
208
208
  k,
209
- Bogo::Utility.camel(k).downcase
209
+ Bogo::Utility.camel(k).downcase,
210
210
  ]
211
211
  current_value = valid_keys.map do |key|
212
212
  current_state[key]
213
213
  end.compact.first
214
214
  primary_key, secondary_key = ["#{f_name}__#{k}", k]
215
215
  current_state[k] = request_compile_parameter(k, v,
216
- current_value,
217
- !!formation.parent
218
- )
216
+ current_value,
217
+ !!formation.parent)
219
218
  end
220
219
  formation.compile_state = current_state
221
220
  end
222
221
  end
223
222
  sf.sparkle.apply sparkle_collection
224
223
  custom_stack_types.each do |s_type|
225
- unless(sf.stack_resource_types.include?(s_type))
224
+ unless sf.stack_resource_types.include?(s_type)
226
225
  sf.stack_resource_types.push(s_type)
227
226
  end
228
227
  end
229
228
  run_callbacks_for(:template, :stack_name => arguments.first, :sparkle_stack => sf)
230
- if(sf.nested? && config[:apply_nesting])
229
+ if sf.nested? && config[:apply_nesting]
231
230
  validate_nesting_bucket!
232
- if(config[:apply_nesting] == true)
231
+ if config[:apply_nesting] == true
233
232
  config[:apply_nesting] = :deep
234
233
  end
235
234
  case config[:apply_nesting].to_sym
@@ -262,12 +261,15 @@ module Sfn
262
261
  compile_state = config.fetch(:compile_parameters, Smash.new)
263
262
  ui.debug "Initial compile parameters - #{compile_state}"
264
263
  compile_state.keys.each do |cs_key|
265
- unless(cs_key.to_s.start_with?("#{arguments.first}__"))
264
+ unless cs_key.to_s.start_with?("#{arguments.first}__")
266
265
  named_cs_key = [arguments.first, cs_key].compact.join('__')
267
266
  non_named = compile_state.delete(cs_key)
268
- if(non_named && !compile_state.key?(named_cs_key))
267
+ if non_named && !compile_state.key?(named_cs_key)
269
268
  ui.debug "Setting non-named compile parameter `#{cs_key}` into `#{named_cs_key}`"
270
269
  compile_state[named_cs_key] = non_named
270
+ elsif non_named && compile_state.key?(named_cs_key)
271
+ ui.debug "Merging none-named `#{cs_key}` with named `#{named_cs_key}`"
272
+ compile_state[named_cs_key].merge!(non_named)
271
273
  else
272
274
  ui.debug "Discarding non-named compile parameter due to set named - `#{cs_key}` </> `#{named_cs_key}`"
273
275
  end
@@ -279,7 +281,7 @@ module Sfn
279
281
 
280
282
  # Force user friendly error if nesting bucket is not set within configuration
281
283
  def validate_nesting_bucket!
282
- if(config[:nesting_bucket].to_s.empty?)
284
+ if config[:nesting_bucket].to_s.empty?
283
285
  ui.error 'Missing required configuration value for `nesting_bucket`. Cannot generated nested templates!'
284
286
  raise ArgumentError.new 'Required configuration value for `nesting_bucket` not provided.'
285
287
  end
@@ -290,17 +292,17 @@ module Sfn
290
292
  # @param sf [SparkleFormation] stack formation
291
293
  # @param c_stack [Miasma::Models::Orchestration::Stack] existing stack
292
294
  # @return [Hash] dumped stack
293
- def process_nested_stack_shallow(sf, c_stack=nil)
295
+ def process_nested_stack_shallow(sf, c_stack = nil)
294
296
  sf.apply_nesting(:shallow) do |stack_name, stack, resource|
295
297
  run_callbacks_for(:template, :stack_name => stack_name, :sparkle_stack => stack)
296
298
  bucket = provider.connection.api_for(:storage).buckets.get(
297
299
  config[:nesting_bucket]
298
300
  )
299
- if(config[:print_only])
301
+ if config[:print_only]
300
302
  template_url = "http://example.com/bucket/#{name_args.first}_#{stack_name}.json"
301
303
  else
302
304
  stack_definition = dump_stack_for_storage(stack)
303
- unless(bucket)
305
+ unless bucket
304
306
  raise "Failed to locate configured bucket for stack template storage (#{bucket})!"
305
307
  end
306
308
  file = bucket.files.build
@@ -320,13 +322,13 @@ module Sfn
320
322
  # @param sf [SparkleFormation] stack
321
323
  # @param c_stack [Miasma::Models::Orchestration::Stack] existing stack
322
324
  # @return [SparkleFormation::SparkleStruct] compiled structure
323
- def process_nested_stack_deep(sf, c_stack=nil)
325
+ def process_nested_stack_deep(sf, c_stack = nil)
324
326
  sf.apply_nesting(:deep) do |stack_name, stack, resource|
325
327
  run_callbacks_for(:template, :stack_name => stack_name, :sparkle_stack => stack)
326
328
  stack_resource = resource._dump
327
- current_stack = c_stack ? c_stack.nested_stacks.detect{|s| s.data[:logical_id] == stack_name} : nil
329
+ current_stack = c_stack ? c_stack.nested_stacks.detect { |s| s.data[:logical_id] == stack_name } : nil
328
330
  current_parameters = extract_current_nested_template_parameters(stack, stack_name, current_stack)
329
- if(current_stack && current_stack.data[:parent_stack])
331
+ if current_stack && current_stack.data[:parent_stack]
330
332
  current_parameters.merge!(
331
333
  current_stack.data[:parent_stack].template.fetch(
332
334
  'Resources', stack_name, 'Properties', 'Parameters', current_stack.data[:parent_stack].template.fetch(
@@ -337,22 +339,21 @@ module Sfn
337
339
  end
338
340
  full_stack_name = [
339
341
  config[:nesting_prefix],
340
- stack.root_path.map(&:name).map(&:to_s).join('_')
342
+ stack.root_path.map(&:name).map(&:to_s).join('_'),
341
343
  ].compact.join('/')
342
- unless(config[:print_only])
344
+ unless config[:print_only]
343
345
  result = Smash.new(
344
346
  :parameters => populate_parameters!(stack,
345
- :stack => current_stack,
346
- :current_parameters => current_parameters
347
- )
347
+ :stack => current_stack,
348
+ :current_parameters => current_parameters),
348
349
  )
349
350
  store_template(full_stack_name, stack, result)
350
351
  else
351
352
  result = Smash.new(
352
- :url => "http://example.com/bucket/#{full_stack_name}.json"
353
+ :url => "http://example.com/bucket/#{full_stack_name}.json",
353
354
  )
354
355
  end
355
- format_nested_stack_results(resource._self.provider, result).each do |k,v|
356
+ format_nested_stack_results(resource._self.provider, result).each do |k, v|
356
357
  resource.properties.set!(k, v)
357
358
  end
358
359
  end
@@ -364,8 +365,8 @@ module Sfn
364
365
  # @param stack_name [String]
365
366
  # @param c_stack [Miasma::Models::Orchestration::Stack]
366
367
  # @return [Hash]
367
- def extract_current_nested_template_parameters(template, stack_name, c_stack=nil)
368
- if(template.parent)
368
+ def extract_current_nested_template_parameters(template, stack_name, c_stack = nil)
369
+ if template.parent
369
370
  current_parameters = template.parent.compile.resources.set!(stack_name).properties.parameters
370
371
  current_parameters.nil? ? Smash.new : current_parameters._dump
371
372
  else
@@ -384,7 +385,7 @@ module Sfn
384
385
  bucket = provider.connection.api_for(:storage).buckets.get(
385
386
  config[:nesting_bucket]
386
387
  )
387
- unless(bucket)
388
+ unless bucket
388
389
  raise "Failed to locate configured bucket for stack template storage (#{config[:nesting_bucket]})!"
389
390
  end
390
391
  file = bucket.files.build
@@ -393,7 +394,7 @@ module Sfn
393
394
  file.body = MultiJson.dump(parameter_scrub!(stack_definition))
394
395
  file.save
395
396
  result.merge!(
396
- :url => file.url
397
+ :url => file.url,
397
398
  )
398
399
  end
399
400
 
@@ -407,7 +408,7 @@ module Sfn
407
408
  [nested_name, nested_resource, nested_resource.properties.delete!(:stack)]
408
409
  end
409
410
  stack_definition = template.dump
410
- if(config[:plan])
411
+ if config[:plan]
411
412
  nested_stacks.each do |nested_name, nested_resource, nested_data|
412
413
  nested_resource.properties.set!(:stack, nested_data)
413
414
  end
@@ -422,7 +423,7 @@ module Sfn
422
423
  def scrub_template(template)
423
424
  template = parameter_scrub!(template)
424
425
  (template['Resources'] || {}).each do |r_name, r_content|
425
- if(valid_stack_types.include?(r_content['Type']))
426
+ if valid_stack_types.include?(r_content['Type'])
426
427
  result = (r_content['Properties'] || {}).delete('Stack')
427
428
  end
428
429
  end
@@ -437,10 +438,10 @@ module Sfn
437
438
  def format_nested_stack_results(provider, results)
438
439
  case provider
439
440
  when :aws
440
- if(results[:parameters])
441
+ if results[:parameters]
441
442
  results['Parameters'] = results.delete(:parameters)
442
443
  end
443
- if(results[:url])
444
+ if results[:url]
444
445
  url = URI.parse(results.delete(:url))
445
446
  results['TemplateURL'] = "#{url.scheme}://#{url.host}#{url.path}"
446
447
  end
@@ -449,18 +450,18 @@ module Sfn
449
450
  results[:template] = results.delete(:url)
450
451
  results
451
452
  when :azure
452
- if(results[:parameters])
453
+ if results[:parameters]
453
454
  results[:parameters] = Smash[
454
455
  results[:parameters].map do |key, value|
455
456
  [key,
456
- value.is_a?(Hash) ? value : Smash.new(:value => value)]
457
+ value.is_a?(Hash) ? value : Smash.new(:value => value)]
457
458
  end
458
459
  ]
459
460
  end
460
- if(results[:url])
461
+ if results[:url]
461
462
  results[:templateLink] = Smash.new(
462
463
  :uri => results.delete(:url),
463
- :contentVersion => '1.0.0.0'
464
+ :contentVersion => '1.0.0.0',
464
465
  )
465
466
  end
466
467
  results[:mode] = 'Incremental'
@@ -475,16 +476,16 @@ module Sfn
475
476
  # @param template [Hash]
476
477
  # @return [Hash]
477
478
  def translate_template(template)
478
- if(klass_name = config[:translate])
479
+ if klass_name = config[:translate]
479
480
  klass = SparkleFormation::Translation.const_get(camel(klass_name))
480
481
  args = {
481
- :parameters => config.fetch(:options, :parameters, Smash.new)
482
+ :parameters => config.fetch(:options, :parameters, Smash.new),
482
483
  }
483
- if(chunk_size = config[:translate_chunk_size])
484
+ if chunk_size = config[:translate_chunk_size]
484
485
  args.merge!(
485
486
  :options => {
486
- :serialization_chunk_size => chunk_size
487
- }
487
+ :serialization_chunk_size => chunk_size,
488
+ },
488
489
  )
489
490
  end
490
491
  translator = klass.new(template, args)
@@ -499,12 +500,12 @@ module Sfn
499
500
  #
500
501
  # @return [TrueClass]
501
502
  def set_paths_and_discover_file!
502
- if(config[:processing])
503
- if(!config[:file] && config[:file_path_prompt])
503
+ if config[:processing]
504
+ if !config[:file] && config[:file_path_prompt]
504
505
  config[:file] = prompt_for_template
505
506
  else
506
507
  file_lookup_path = File.expand_path(config[:file])
507
- unless(File.exists?(file_lookup_path))
508
+ unless File.exists?(file_lookup_path)
508
509
  file_lookup_path = config[:file]
509
510
  end
510
511
  config[:file] = sparkle_collection.get(
@@ -512,8 +513,8 @@ module Sfn
512
513
  )[:path]
513
514
  end
514
515
  else
515
- if(config[:file])
516
- unless(File.exists?(config[:file]))
516
+ if config[:file]
517
+ unless File.exists?(config[:file])
517
518
  raise Errno::ENOENT.new("No such file - #{config[:file]}")
518
519
  end
519
520
  else
@@ -527,8 +528,8 @@ module Sfn
527
528
  #
528
529
  # @param prefix [String] prefix filter for names
529
530
  # @return [String] path to template
530
- def prompt_for_template(prefix=nil)
531
- if(prefix)
531
+ def prompt_for_template(prefix = nil)
532
+ if prefix
532
533
  collection_name = prefix.split('__').map do |c_name|
533
534
  c_name.split('_').map(&:capitalize).join(' ')
534
535
  end.join(' / ')
@@ -541,26 +542,26 @@ module Sfn
541
542
  end
542
543
  collections = template_names.map do |t_name|
543
544
  t_name = t_name.to_s.sub(/^#{Regexp.escape(prefix.to_s)}/, '')
544
- if(t_name.include?('__'))
545
+ if t_name.include?('__')
545
546
  c_name = t_name.split('__').first
546
547
  [[prefix, c_name].compact.join('') + '__', c_name]
547
548
  end
548
549
  end.compact.uniq(&:first)
549
550
  templates = template_names.map do |t_name|
550
551
  t_name = t_name.to_s.sub(/^#{Regexp.escape(prefix.to_s)}/, '')
551
- unless(t_name.include?('__'))
552
+ unless t_name.include?('__')
552
553
  [[prefix, t_name].compact.join(''), t_name]
553
554
  end
554
555
  end.compact
555
- if(collections.empty? && templates.empty?)
556
+ if collections.empty? && templates.empty?
556
557
  ui.error 'Failed to locate any templates!'
557
558
  return nil
558
559
  end
559
- ui.info "Please select an entry#{ '(or collection to list)' unless collections.empty?}:"
560
+ ui.info "Please select an entry#{'(or collection to list)' unless collections.empty?}:"
560
561
  output = []
561
562
  idx = 1
562
563
  valid = {}
563
- unless(collections.empty?)
564
+ unless collections.empty?
564
565
  output << ui.color('Collections:', :bold)
565
566
  collections.each do |full_name, part_name|
566
567
  valid[idx] = {:name => full_name, :type => :collection}
@@ -568,7 +569,7 @@ module Sfn
568
569
  idx += 1
569
570
  end
570
571
  end
571
- unless(templates.empty?)
572
+ unless templates.empty?
572
573
  output << ui.color('Templates:', :bold)
573
574
  templates.each do |full_name, part_name|
574
575
  valid[idx] = {:name => full_name, :type => :template}
@@ -578,7 +579,7 @@ module Sfn
578
579
  end
579
580
  max = idx.to_s.length
580
581
  output.map! do |line|
581
- if(line.is_a?(Array))
582
+ if line.is_a?(Array)
582
583
  " #{line.first}.#{' ' * (max - line.first.to_s.length)} #{line.last}"
583
584
  else
584
585
  line
@@ -586,17 +587,16 @@ module Sfn
586
587
  end
587
588
  ui.puts "#{output.join("\n")}\n"
588
589
  response = nil
589
- until(valid[response])
590
+ until valid[response]
590
591
  response = ui.ask_question('Enter selection').to_i
591
592
  end
592
593
  entry = valid[response]
593
- if(entry[:type] == :collection)
594
+ if entry[:type] == :collection
594
595
  prompt_for_template(entry[:name])
595
596
  else
596
597
  sparkle_collection.get(:template, entry[:name])[:path]
597
598
  end
598
599
  end
599
-
600
600
  end
601
601
 
602
602
  module ClassMethods
@@ -614,7 +614,6 @@ module Sfn
614
614
  include Sfn::Utils::StackParameterValidator
615
615
  end
616
616
  end
617
-
618
617
  end
619
618
  end
620
619
  end