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
@@ -4,7 +4,6 @@ module Sfn
4
4
  class Command
5
5
  # Lint command
6
6
  class Lint < Command
7
-
8
7
  include Sfn::CommandModule::Base
9
8
  include Sfn::CommandModule::Template
10
9
 
@@ -18,11 +17,11 @@ module Sfn
18
17
 
19
18
  raw_template = parameter_scrub!(template_content(file))
20
19
 
21
- if(config[:print_only])
20
+ if config[:print_only]
22
21
  ui.puts raw_template
23
22
  else
24
23
  result = lint_template(raw_template)
25
- if(result == true)
24
+ if result == true
26
25
  ui.info ui.color(' -> VALID', :green, :bold)
27
26
  else
28
27
  ui.info ui.color(' -> INVALID', :red, :bold)
@@ -44,7 +43,7 @@ module Sfn
44
43
  def lint_template(template)
45
44
  results = rule_sets.map do |set|
46
45
  result = set.apply(template)
47
- unless(result == true)
46
+ unless result == true
48
47
  Smash.new(:rule_set => set, :failures => result)
49
48
  end
50
49
  end.compact
@@ -54,7 +53,7 @@ module Sfn
54
53
  # @return [Array<Sfn::Lint::RuleSet>]
55
54
  def rule_sets
56
55
  sets = [config[:lint_directory]].flatten.compact.map do |directory|
57
- if(File.directory?(directory))
56
+ if File.directory?(directory)
58
57
  files = Dir.glob(File.join(directory, '**', '**', '*.rb'))
59
58
  files.map do |path|
60
59
  begin
@@ -67,21 +66,20 @@ module Sfn
67
66
  end
68
67
  end
69
68
  end
70
- end.flatten.compact.find_all{|rs| rs.provider == provider.connection.provider}
71
- unless(config[:local_rule_sets_only])
69
+ end.flatten.compact.find_all { |rs| rs.provider == provider.connection.provider }
70
+ unless config[:local_rule_sets_only]
72
71
  sets += Sfn::Lint::RuleSet.get_all(provider.connection.provider)
73
72
  end
74
- if(config[:disabled_rule_set])
73
+ if config[:disabled_rule_set]
75
74
  disabled = [config[:disabled_rule_set]].flatten.compact
76
- sets.delete_if{|i| disabled.include?(i.name.to_s) }
75
+ sets.delete_if { |i| disabled.include?(i.name.to_s) }
77
76
  end
78
- if(config[:enabled_rule_set])
77
+ if config[:enabled_rule_set]
79
78
  enabled = [config[:enabled_rule_set]].flatten.compact
80
- sets.delete_if{|i| enabled.include?(i.name.to_s) }
79
+ sets.delete_if { |i| enabled.include?(i.name.to_s) }
81
80
  end
82
81
  sets
83
82
  end
84
-
85
83
  end
86
84
  end
87
85
  end
@@ -4,18 +4,16 @@ module Sfn
4
4
  class Command
5
5
  # List command
6
6
  class List < Command
7
-
8
7
  include Sfn::CommandModule::Base
9
8
 
10
9
  # Run the list command
11
10
  def execute!
12
11
  ui.table(self) do
13
12
  table(:border => false) do
14
- stacks = api_action!{ get_stacks }
13
+ stacks = api_action! { get_stacks }
15
14
  row(:header => true) do
16
-
17
15
  allowed_attributes.each do |attr|
18
- width_val = stacks.map{|e| e[attr].to_s.length}.push(attr.length).max + 2
16
+ width_val = stacks.map { |e| e[attr].to_s.length }.push(attr.length).max + 2
19
17
  width_val = width_val > 70 ? 70 : width_val < 20 ? 20 : width_val
20
18
  column attr.split('_').map(&:capitalize).join(' '), :width => width_val
21
19
  end
@@ -38,9 +36,9 @@ module Sfn
38
36
  provider.stacks.all.map do |stack|
39
37
  Smash.new(stack.attributes)
40
38
  end.sort do |x, y|
41
- if(y[:created].to_s.empty?)
39
+ if y[:created].to_s.empty?
42
40
  -1
43
- elsif(x[:created].to_s.empty?)
41
+ elsif x[:created].to_s.empty?
44
42
  1
45
43
  else
46
44
  Time.parse(x[:created].to_s) <=> Time.parse(y[:created].to_s)
@@ -50,13 +48,12 @@ module Sfn
50
48
 
51
49
  # @return [Array<String>] default attributes to display
52
50
  def default_attributes
53
- if(provider.connection.provider == :aws)
51
+ if provider.connection.provider == :aws
54
52
  %w(name created updated status template_description)
55
53
  else
56
54
  %w(name created updated status description)
57
55
  end
58
56
  end
59
-
60
57
  end
61
58
  end
62
59
  end
@@ -5,7 +5,6 @@ module Sfn
5
5
  class Command
6
6
  # Print command
7
7
  class Print < Command
8
-
9
8
  include Sfn::CommandModule::Base
10
9
  include Sfn::CommandModule::Template
11
10
  include Sfn::CommandModule::Stack
@@ -16,15 +15,15 @@ module Sfn
16
15
  file = load_template_file
17
16
 
18
17
  output_content = parameter_scrub!(template_content(file))
19
- if(config[:yaml])
18
+ if config[:yaml]
20
19
  require 'yaml'
21
20
  output_content = YAML.dump(output_content)
22
21
  else
23
22
  output_content = format_json(output_content)
24
23
  end
25
24
 
26
- if(config[:write_to_file])
27
- unless(File.directory?(File.dirname(config[:write_to_file])))
25
+ if config[:write_to_file]
26
+ unless File.directory?(File.dirname(config[:write_to_file]))
28
27
  run_action 'Creating parent directory' do
29
28
  FileUtils.mkdir_p(File.dirname(config[:write_to_file]))
30
29
  nil
@@ -38,7 +37,6 @@ module Sfn
38
37
  ui.puts output_content
39
38
  end
40
39
  end
41
-
42
40
  end
43
41
  end
44
42
  end
@@ -4,14 +4,12 @@ module Sfn
4
4
  class Command
5
5
  # Promote command
6
6
  class Promote < Command
7
-
8
7
  include Sfn::CommandModule::Base
9
8
 
10
9
  def execute!
11
10
  raise NotImplementedError.new 'Implementation updates required'
12
11
  stack_name, destination = name_args
13
12
  end
14
-
15
13
  end
16
14
  end
17
15
  end
@@ -4,7 +4,6 @@ module Sfn
4
4
  class Command
5
5
  # Update command
6
6
  class Update < Command
7
-
8
7
  include Sfn::CommandModule::Base
9
8
  include Sfn::CommandModule::Template
10
9
  include Sfn::CommandModule::Stack
@@ -23,16 +22,16 @@ module Sfn
23
22
 
24
23
  config[:compile_parameters] ||= Smash.new
25
24
 
26
- if(config[:file])
25
+ if config[:file]
27
26
  s_name = [name]
28
27
 
29
28
  c_setter = lambda do |c_stack|
30
- if(c_stack.outputs)
29
+ if c_stack.outputs
31
30
  compile_params = c_stack.outputs.detect do |output|
32
31
  output.key == 'CompileState'
33
32
  end
34
33
  end
35
- if(compile_params)
34
+ if compile_params
36
35
  compile_params = MultiJson.load(compile_params.value)
37
36
  c_current = config[:compile_parameters].fetch(s_name.join('__'), Smash.new)
38
37
  config[:compile_parameters][s_name.join('__')] = compile_params.merge(c_current)
@@ -44,7 +43,7 @@ module Sfn
44
43
  end
45
44
  end
46
45
 
47
- if(stack)
46
+ if stack
48
47
  c_setter.call(stack)
49
48
  end
50
49
 
@@ -55,28 +54,28 @@ module Sfn
55
54
  file = stack.template.dup if config[:plan]
56
55
  end
57
56
 
58
- unless(stack)
57
+ unless stack
59
58
  ui.fatal "Failed to locate requested stack: #{ui.color(name, :red, :bold)}"
60
59
  raise "Failed to locate stack: #{name}"
61
60
  end
62
61
 
63
- unless(config[:print_only])
62
+ unless config[:print_only]
64
63
  ui.info "#{ui.color('SparkleFormation:', :bold)} #{ui.color('update', :green)}"
65
64
  end
66
65
 
67
- unless(file)
68
- if(config[:template])
66
+ unless file
67
+ if config[:template]
69
68
  file = config[:template]
70
69
  stack_info << " #{ui.color('(template provided)', :green)}"
71
70
  else
72
71
  stack_info << " #{ui.color('(no template update)', :yellow)}"
73
72
  end
74
73
  end
75
- unless(config[:print_only])
74
+ unless config[:print_only]
76
75
  ui.info " -> #{stack_info}"
77
76
  end
78
- if(file)
79
- if(config[:print_only])
77
+ if file
78
+ if config[:print_only]
80
79
  ui.puts format_json(parameter_scrub!(template_content(file)))
81
80
  return
82
81
  end
@@ -89,12 +88,12 @@ module Sfn
89
88
  populate_parameters!(file, :current_parameters => stack.root_parameters)
90
89
  update_template = stack.template
91
90
 
92
- if(config[:plan])
91
+ if config[:plan]
93
92
  begin
94
93
  stack.template = original_template
95
94
  stack.parameters = original_parameters
96
95
  plan = build_planner(stack)
97
- if(plan)
96
+ if plan
98
97
  result = plan.generate_plan(
99
98
  file.respond_to?(:dump) ? file.dump : file,
100
99
  config_root_parameters
@@ -102,7 +101,7 @@ module Sfn
102
101
  display_plan_information(result)
103
102
  end
104
103
  rescue => e
105
- unless(e.message.include?('Confirmation declined'))
104
+ unless e.message.include?('Confirmation declined')
106
105
  ui.error "Unexpected error when generating plan information: #{e.class} - #{e}"
107
106
  ui.debug "#{e.class}: #{e}\n#{e.backtrace.join("\n")}"
108
107
  ui.confirm 'Continue with stack update?' unless config[:plan_only]
@@ -110,14 +109,14 @@ module Sfn
110
109
  raise
111
110
  end
112
111
  end
113
- if(config[:plan_only])
112
+ if config[:plan_only]
114
113
  ui.info 'Plan only mode requested. Exiting.'
115
114
  exit 0
116
115
  end
117
116
  end
118
117
  stack.parameters = config_root_parameters
119
118
 
120
- if(config[:upload_root_template])
119
+ if config[:upload_root_template]
121
120
  upload_result = store_template(name, file, Smash.new)
122
121
  stack.template_url = upload_result[:url]
123
122
  else
@@ -131,9 +130,9 @@ module Sfn
131
130
  end
132
131
 
133
132
  # Set options defined within config into stack instance for update request
134
- if(config[:merge_api_options])
133
+ if config[:merge_api_options]
135
134
  config.fetch(:options, Smash.new).each_pair do |key, value|
136
- if(stack.respond_to?("#{key}="))
135
+ if stack.respond_to?("#{key}=")
137
136
  stack.send("#{key}=", value)
138
137
  end
139
138
  end
@@ -142,9 +141,9 @@ module Sfn
142
141
  begin
143
142
  api_action!(:api_stack => stack) do
144
143
  stack.save
145
- if(config[:poll])
144
+ if config[:poll]
146
145
  poll_stack(stack.name)
147
- if(stack.reload.state == :update_complete)
146
+ if stack.reload.state == :update_complete
148
147
  ui.info "Stack update complete: #{ui.color('SUCCESS', :green)}"
149
148
  namespace.const_get(:Describe).new({:outputs => true}, [name]).execute!
150
149
  else
@@ -157,18 +156,17 @@ module Sfn
157
156
  end
158
157
  end
159
158
  rescue Miasma::Error::ApiError::RequestError => e
160
- if(e.message.downcase.include?('no updates'))
159
+ if e.message.downcase.include?('no updates')
161
160
  ui.warn "No updates detected for stack (#{stack.name})"
162
161
  else
163
162
  raise
164
163
  end
165
164
  end
166
-
167
165
  end
168
166
 
169
167
  def build_planner(stack)
170
168
  klass_name = stack.api.class.to_s.split('::').last
171
- if(Planner.const_defined?(klass_name))
169
+ if Planner.const_defined?(klass_name)
172
170
  Planner.const_get(klass_name).new(ui, config, arguments, stack)
173
171
  else
174
172
  warn "Failed to build planner for current provider. No provider implemented. (`#{klass_name}`)"
@@ -178,62 +176,61 @@ module Sfn
178
176
 
179
177
  def display_plan_information(result)
180
178
  ui.info ui.color('Pre-update resource planning report:', :bold)
181
- unless(print_plan_result(result))
179
+ unless print_plan_result(result)
182
180
  ui.info 'No resources life cycle changes detected in this update!'
183
181
  end
184
182
  ui.confirm 'Apply this stack update?' unless config[:plan_only]
185
183
  end
186
184
 
187
-
188
- def print_plan_result(info, names=[])
185
+ def print_plan_result(info, names = [])
189
186
  said_any_things = false
190
- unless(info[:stacks].empty?)
187
+ unless info[:stacks].empty?
191
188
  info[:stacks].each do |s_name, s_info|
192
189
  result = print_plan_result(s_info, [*names, s_name].compact)
193
190
  said_any_things ||= result
194
191
  end
195
192
  end
196
- unless(names.flatten.compact.empty?)
193
+ unless names.flatten.compact.empty?
197
194
  said_things = false
198
195
  ui.puts
199
196
  ui.puts " #{ui.color('Update plan for:', :bold)} #{ui.color(names.join(' > '), :blue)}"
200
- unless(info[:unknown].empty?)
197
+ unless info[:unknown].empty?
201
198
  ui.puts " #{ui.color('!!! Unknown update effect:', :red, :bold)}"
202
199
  print_plan_items(info, :unknown, :red)
203
200
  ui.puts
204
201
  said_any_things = said_things = true
205
202
  end
206
- unless(info[:unavailable].empty?)
203
+ unless info[:unavailable].empty?
207
204
  ui.puts " #{ui.color('Update request not allowed:', :red, :bold)}"
208
205
  print_plan_items(info, :unavailable, :red)
209
206
  ui.puts
210
207
  said_any_things = said_things = true
211
208
  end
212
- unless(info[:replace].empty?)
209
+ unless info[:replace].empty?
213
210
  ui.puts " #{ui.color('Resources to be replaced:', :red, :bold)}"
214
211
  print_plan_items(info, :replace, :red)
215
212
  ui.puts
216
213
  said_any_things = said_things = true
217
214
  end
218
- unless(info[:interrupt].empty?)
215
+ unless info[:interrupt].empty?
219
216
  ui.puts " #{ui.color('Resources to be interrupted:', :yellow, :bold)}"
220
217
  print_plan_items(info, :interrupt, :yellow)
221
218
  ui.puts
222
219
  said_any_things = said_things = true
223
220
  end
224
- unless(info[:removed].empty?)
221
+ unless info[:removed].empty?
225
222
  ui.puts " #{ui.color('Resources to be removed:', :red, :bold)}"
226
223
  print_plan_items(info, :removed, :red)
227
224
  ui.puts
228
225
  said_any_things = said_things = true
229
226
  end
230
- unless(info[:added].empty?)
227
+ unless info[:added].empty?
231
228
  ui.puts " #{ui.color('Resources to be added:', :green, :bold)}"
232
229
  print_plan_items(info, :added, :green)
233
230
  ui.puts
234
231
  said_any_things = said_things = true
235
232
  end
236
- unless(said_things)
233
+ unless said_things
237
234
  ui.puts " #{ui.color('No resource lifecycle changes detected!', :green)}"
238
235
  ui.puts
239
236
  said_any_things = true
@@ -249,26 +246,26 @@ module Sfn
249
246
  # @param color [Symbol] color to flag
250
247
  def print_plan_items(info, key, color)
251
248
  max_name = info[key].keys.map(&:size).max
252
- max_type = info[key].values.map{|i|i[:type]}.map(&:size).max
253
- max_p = info[key].values.map{|i| i.fetch(:diffs, [])}.flatten(1).map{|d| d.fetch(:property_name, :path).to_s.size}.max
254
- max_o = info[key].values.map{|i| i.fetch(:diffs, [])}.flatten(1).map{|d| d[:original].to_s.size}.max
249
+ max_type = info[key].values.map { |i| i[:type] }.map(&:size).max
250
+ max_p = info[key].values.map { |i| i.fetch(:diffs, []) }.flatten(1).map { |d| d.fetch(:property_name, :path).to_s.size }.max
251
+ max_o = info[key].values.map { |i| i.fetch(:diffs, []) }.flatten(1).map { |d| d[:original].to_s.size }.max
255
252
  info[key].each do |name, val|
256
253
  ui.print ' ' * 6
257
254
  ui.print ui.color("[#{val[:type]}]", color)
258
255
  ui.print ' ' * (max_type - val[:type].size)
259
256
  ui.print ' ' * 4
260
257
  ui.print ui.color(name, :bold)
261
- unless(val[:properties].nil? || val[:properties].empty?)
258
+ unless val[:properties].nil? || val[:properties].empty?
262
259
  ui.print ' ' * (max_name - name.size)
263
260
  ui.print ' ' * 4
264
261
  ui.print "Reason: Updated properties: `#{val[:properties].join('`, `')}`"
265
262
  end
266
263
  ui.puts
267
- if(config[:diffs])
268
- unless(val[:diffs].empty?)
264
+ if config[:diffs]
265
+ unless val[:diffs].empty?
269
266
  p_name = nil
270
267
  val[:diffs].each do |diff|
271
- if(!diff[:updated].nil? || !diff[:original].nil?)
268
+ if !diff[:updated].nil? || !diff[:original].nil?
272
269
  p_name = diff.fetch(:property_name, :path)
273
270
  ui.print ' ' * 8
274
271
  ui.print "#{p_name}: "
@@ -276,10 +273,10 @@ module Sfn
276
273
  ui.print ui.color("-#{diff[:original]}", :red) unless diff[:original].nil?
277
274
  ui.print ' ' * (max_o - diff[:original].to_s.size)
278
275
  ui.print ' '
279
- if(diff[:updated] == Sfn::Planner::RUNTIME_MODIFIED)
276
+ if diff[:updated] == Sfn::Planner::RUNTIME_MODIFIED
280
277
  ui.puts ui.color("+#{diff[:original]} <Dependency Modified>", :green)
281
278
  else
282
- if(diff[:updated].nil?)
279
+ if diff[:updated].nil?
283
280
  ui.puts
284
281
  else
285
282
  ui.puts ui.color("+#{diff[:updated].to_s.gsub('__MODIFIED_REFERENCE_VALUE__', '<Dependency Modified>')}", :green)
@@ -292,7 +289,6 @@ module Sfn
292
289
  end
293
290
  end
294
291
  end
295
-
296
292
  end
297
293
  end
298
294
  end
@@ -5,7 +5,6 @@ module Sfn
5
5
  class Command
6
6
  # Validate command
7
7
  class Validate < Command
8
-
9
8
  include Sfn::CommandModule::Base
10
9
  include Sfn::CommandModule::Template
11
10
  include Sfn::CommandModule::Stack
@@ -19,7 +18,7 @@ module Sfn
19
18
 
20
19
  raw_template = _format_json(parameter_scrub!(template_content(file)))
21
20
 
22
- if(config[:print_only])
21
+ if config[:print_only]
23
22
  ui.puts raw_template
24
23
  else
25
24
  validate_stack(
@@ -46,16 +45,16 @@ module Sfn
46
45
  end
47
46
  begin
48
47
  ui.info "Validating: #{ui.color(name, :bold)}"
49
- if(config[:upload_root_template])
48
+ if config[:upload_root_template]
50
49
  upload_result = store_template('validation-stack', template, Smash.new)
51
50
  stack = provider.connection.stacks.build(
52
51
  :name => 'validation-stack',
53
- :template_url => upload_result[:url]
52
+ :template_url => upload_result[:url],
54
53
  )
55
54
  else
56
55
  stack = provider.connection.stacks.build(
57
56
  :name => 'validation-stack',
58
- :template => parameter_scrub!(template)
57
+ :template => parameter_scrub!(template),
59
58
  )
60
59
  end
61
60
  result = api_action!(:api_stack => stack) do
@@ -69,7 +68,6 @@ module Sfn
69
68
  raise e
70
69
  end
71
70
  end
72
-
73
71
  end
74
72
  end
75
73
  end