sfn 3.0.28 → 3.0.30

Sign up to get free protection for your applications and to get access to all the features.
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