sfn 3.0.30 → 3.0.32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +6 -0
  3. data/bin/sfn +16 -14
  4. data/lib/chef/knife/knife_plugin_seed.rb +12 -12
  5. data/lib/sfn.rb +17 -17
  6. data/lib/sfn/api_provider.rb +3 -3
  7. data/lib/sfn/api_provider/google.rb +2 -2
  8. data/lib/sfn/api_provider/terraform.rb +2 -2
  9. data/lib/sfn/cache.rb +9 -9
  10. data/lib/sfn/callback.rb +6 -6
  11. data/lib/sfn/callback/aws_assume_role.rb +5 -5
  12. data/lib/sfn/callback/aws_mfa.rb +8 -6
  13. data/lib/sfn/callback/stack_policy.rb +15 -15
  14. data/lib/sfn/command.rb +37 -36
  15. data/lib/sfn/command/conf.rb +12 -12
  16. data/lib/sfn/command/create.rb +9 -9
  17. data/lib/sfn/command/describe.rb +6 -6
  18. data/lib/sfn/command/destroy.rb +8 -8
  19. data/lib/sfn/command/diff.rb +31 -31
  20. data/lib/sfn/command/events.rb +6 -6
  21. data/lib/sfn/command/export.rb +8 -8
  22. data/lib/sfn/command/graph.rb +21 -21
  23. data/lib/sfn/command/graph/aws.rb +34 -34
  24. data/lib/sfn/command/graph/provider.rb +1 -1
  25. data/lib/sfn/command/graph/terraform.rb +41 -41
  26. data/lib/sfn/command/import.rb +17 -17
  27. data/lib/sfn/command/init.rb +15 -15
  28. data/lib/sfn/command/inspect.rb +16 -16
  29. data/lib/sfn/command/lint.rb +6 -6
  30. data/lib/sfn/command/list.rb +2 -2
  31. data/lib/sfn/command/plan.rb +227 -0
  32. data/lib/sfn/command/print.rb +4 -4
  33. data/lib/sfn/command/promote.rb +2 -2
  34. data/lib/sfn/command/update.rb +19 -144
  35. data/lib/sfn/command/validate.rb +17 -13
  36. data/lib/sfn/command_module.rb +6 -5
  37. data/lib/sfn/command_module/base.rb +8 -8
  38. data/lib/sfn/command_module/callbacks.rb +5 -5
  39. data/lib/sfn/command_module/planning.rb +151 -0
  40. data/lib/sfn/command_module/stack.rb +34 -34
  41. data/lib/sfn/command_module/template.rb +50 -50
  42. data/lib/sfn/config.rb +46 -44
  43. data/lib/sfn/config/conf.rb +3 -3
  44. data/lib/sfn/config/create.rb +9 -9
  45. data/lib/sfn/config/describe.rb +7 -7
  46. data/lib/sfn/config/destroy.rb +1 -1
  47. data/lib/sfn/config/diff.rb +3 -3
  48. data/lib/sfn/config/events.rb +9 -9
  49. data/lib/sfn/config/export.rb +5 -5
  50. data/lib/sfn/config/graph.rb +10 -10
  51. data/lib/sfn/config/import.rb +4 -4
  52. data/lib/sfn/config/init.rb +1 -1
  53. data/lib/sfn/config/inspect.rb +16 -16
  54. data/lib/sfn/config/lint.rb +5 -5
  55. data/lib/sfn/config/list.rb +6 -6
  56. data/lib/sfn/config/plan.rb +28 -0
  57. data/lib/sfn/config/print.rb +5 -5
  58. data/lib/sfn/config/promote.rb +4 -4
  59. data/lib/sfn/config/update.rb +18 -18
  60. data/lib/sfn/config/validate.rb +30 -30
  61. data/lib/sfn/lint.rb +5 -5
  62. data/lib/sfn/lint/definition.rb +3 -3
  63. data/lib/sfn/lint/rule.rb +3 -3
  64. data/lib/sfn/lint/rule_set.rb +2 -2
  65. data/lib/sfn/monkey_patch.rb +2 -2
  66. data/lib/sfn/monkey_patch/stack.rb +27 -27
  67. data/lib/sfn/monkey_patch/stack/azure.rb +1 -1
  68. data/lib/sfn/monkey_patch/stack/google.rb +5 -5
  69. data/lib/sfn/planner.rb +4 -4
  70. data/lib/sfn/planner/aws.rb +114 -70
  71. data/lib/sfn/provider.rb +13 -13
  72. data/lib/sfn/utils.rb +10 -10
  73. data/lib/sfn/utils/debug.rb +2 -2
  74. data/lib/sfn/utils/json.rb +1 -1
  75. data/lib/sfn/utils/object_storage.rb +3 -3
  76. data/lib/sfn/utils/output.rb +4 -4
  77. data/lib/sfn/utils/path_selector.rb +15 -15
  78. data/lib/sfn/utils/ssher.rb +4 -4
  79. data/lib/sfn/utils/stack_exporter.rb +16 -16
  80. data/lib/sfn/utils/stack_parameter_scrubber.rb +6 -6
  81. data/lib/sfn/utils/stack_parameter_validator.rb +22 -22
  82. data/lib/sfn/version.rb +1 -1
  83. data/sfn.gemspec +32 -32
  84. metadata +16 -13
@@ -1,5 +1,5 @@
1
- require 'sparkle_formation'
2
- require 'sfn'
1
+ require "sparkle_formation"
2
+ require "sfn"
3
3
 
4
4
  module Sfn
5
5
  class Command
@@ -16,7 +16,7 @@ module Sfn
16
16
 
17
17
  output_content = parameter_scrub!(template_content(file))
18
18
  if config[:yaml]
19
- require 'yaml'
19
+ require "yaml"
20
20
  output_content = YAML.dump(output_content)
21
21
  else
22
22
  output_content = format_json(output_content)
@@ -24,7 +24,7 @@ module Sfn
24
24
 
25
25
  if config[:write_to_file]
26
26
  unless File.directory?(File.dirname(config[:write_to_file]))
27
- run_action 'Creating parent directory' do
27
+ run_action "Creating parent directory" do
28
28
  FileUtils.mkdir_p(File.dirname(config[:write_to_file]))
29
29
  nil
30
30
  end
@@ -1,4 +1,4 @@
1
- require 'sfn'
1
+ require "sfn"
2
2
 
3
3
  module Sfn
4
4
  class Command
@@ -7,7 +7,7 @@ module Sfn
7
7
  include Sfn::CommandModule::Base
8
8
 
9
9
  def execute!
10
- raise NotImplementedError.new 'Implementation updates required'
10
+ raise NotImplementedError.new "Implementation updates required"
11
11
  stack_name, destination = name_args
12
12
  end
13
13
  end
@@ -1,4 +1,4 @@
1
- require 'sfn'
1
+ require "sfn"
2
2
 
3
3
  module Sfn
4
4
  class Command
@@ -7,13 +7,14 @@ module Sfn
7
7
  include Sfn::CommandModule::Base
8
8
  include Sfn::CommandModule::Template
9
9
  include Sfn::CommandModule::Stack
10
+ include Sfn::CommandModule::Planning
10
11
 
11
- # Run the stack creation command
12
+ # Run the stack update command
12
13
  def execute!
13
14
  name_required!
14
15
  name = name_args.first
15
16
 
16
- stack_info = "#{ui.color('Name:', :bold)} #{name}"
17
+ stack_info = "#{ui.color("Name:", :bold)} #{name}"
17
18
  begin
18
19
  stack = provider.stacks.get(name)
19
20
  rescue Miasma::Error::ApiError::RequestError
@@ -28,13 +29,13 @@ module Sfn
28
29
  c_setter = lambda do |c_stack|
29
30
  if c_stack.outputs
30
31
  compile_params = c_stack.outputs.detect do |output|
31
- output.key == 'CompileState'
32
+ output.key == "CompileState"
32
33
  end
33
34
  end
34
35
  if compile_params
35
36
  compile_params = MultiJson.load(compile_params.value)
36
- c_current = config[:compile_parameters].fetch(s_name.join('__'), Smash.new)
37
- config[:compile_parameters][s_name.join('__')] = compile_params.merge(c_current)
37
+ c_current = config[:compile_parameters].fetch(s_name.join("__"), Smash.new)
38
+ config[:compile_parameters][s_name.join("__")] = compile_params.merge(c_current)
38
39
  end
39
40
  c_stack.nested_stacks(false).each do |n_stack|
40
41
  s_name.push(n_stack.data.fetch(:logical_id, n_stack.name))
@@ -49,7 +50,7 @@ module Sfn
49
50
 
50
51
  ui.debug "Compile parameters - #{config[:compile_parameters]}"
51
52
  file = load_template_file(:stack => stack)
52
- stack_info << " #{ui.color('Path:', :bold)} #{config[:file]}"
53
+ stack_info << " #{ui.color("Path:", :bold)} #{config[:file]}"
53
54
  else
54
55
  file = stack.template.dup if config[:plan]
55
56
  end
@@ -60,15 +61,15 @@ module Sfn
60
61
  end
61
62
 
62
63
  unless config[:print_only]
63
- ui.info "#{ui.color('SparkleFormation:', :bold)} #{ui.color('update', :green)}"
64
+ ui.info "#{ui.color("SparkleFormation:", :bold)} #{ui.color("update", :green)}"
64
65
  end
65
66
 
66
67
  unless file
67
68
  if config[:template]
68
69
  file = config[:template]
69
- stack_info << " #{ui.color('(template provided)', :green)}"
70
+ stack_info << " #{ui.color("(template provided)", :green)}"
70
71
  else
71
- stack_info << " #{ui.color('(no template update)', :yellow)}"
72
+ stack_info << " #{ui.color("(no template update)", :yellow)}"
72
73
  end
73
74
  end
74
75
  unless config[:print_only]
@@ -101,16 +102,16 @@ module Sfn
101
102
  display_plan_information(result)
102
103
  end
103
104
  rescue => e
104
- unless e.message.include?('Confirmation declined')
105
+ unless e.message.include?("Confirmation declined")
105
106
  ui.error "Unexpected error when generating plan information: #{e.class} - #{e}"
106
107
  ui.debug "#{e.class}: #{e}\n#{e.backtrace.join("\n")}"
107
- ui.confirm 'Continue with stack update?' unless config[:plan_only]
108
+ ui.confirm "Continue with stack update?" unless config[:plan_only]
108
109
  else
109
110
  raise
110
111
  end
111
112
  end
112
113
  if config[:plan_only]
113
- ui.info 'Plan only mode requested. Exiting.'
114
+ ui.info "Plan only mode requested. Exiting."
114
115
  exit 0
115
116
  end
116
117
  end
@@ -144,151 +145,25 @@ module Sfn
144
145
  if config[:poll]
145
146
  poll_stack(stack.name)
146
147
  if stack.reload.state == :update_complete
147
- ui.info "Stack update complete: #{ui.color('SUCCESS', :green)}"
148
+ ui.info "Stack update complete: #{ui.color("SUCCESS", :green)}"
148
149
  namespace.const_get(:Describe).new({:outputs => true}, [name]).execute!
149
150
  else
150
- ui.fatal "Update of stack #{ui.color(name, :bold)}: #{ui.color('FAILED', :red, :bold)}"
151
- raise 'Stack did not reach a successful update completion state.'
151
+ ui.fatal "Update of stack #{ui.color(name, :bold)}: #{ui.color("FAILED", :red, :bold)}"
152
+ raise "Stack did not reach a successful update completion state."
152
153
  end
153
154
  else
154
- ui.warn 'Stack state polling has been disabled.'
155
+ ui.warn "Stack state polling has been disabled."
155
156
  ui.info "Stack update initialized for #{ui.color(name, :green)}"
156
157
  end
157
158
  end
158
159
  rescue Miasma::Error::ApiError::RequestError => e
159
- if e.message.downcase.include?('no updates')
160
+ if e.message.downcase.include?("no updates")
160
161
  ui.warn "No updates detected for stack (#{stack.name})"
161
162
  else
162
163
  raise
163
164
  end
164
165
  end
165
166
  end
166
-
167
- def build_planner(stack)
168
- klass_name = stack.api.class.to_s.split('::').last
169
- if Planner.const_defined?(klass_name)
170
- Planner.const_get(klass_name).new(ui, config, arguments, stack)
171
- else
172
- warn "Failed to build planner for current provider. No provider implemented. (`#{klass_name}`)"
173
- nil
174
- end
175
- end
176
-
177
- def display_plan_information(result)
178
- ui.info ui.color('Pre-update resource planning report:', :bold)
179
- unless print_plan_result(result)
180
- ui.info 'No resources life cycle changes detected in this update!'
181
- end
182
- ui.confirm 'Apply this stack update?' unless config[:plan_only]
183
- end
184
-
185
- def print_plan_result(info, names = [])
186
- said_any_things = false
187
- unless info[:stacks].empty?
188
- info[:stacks].each do |s_name, s_info|
189
- result = print_plan_result(s_info, [*names, s_name].compact)
190
- said_any_things ||= result
191
- end
192
- end
193
- unless names.flatten.compact.empty?
194
- said_things = false
195
- ui.puts
196
- ui.puts " #{ui.color('Update plan for:', :bold)} #{ui.color(names.join(' > '), :blue)}"
197
- unless info[:unknown].empty?
198
- ui.puts " #{ui.color('!!! Unknown update effect:', :red, :bold)}"
199
- print_plan_items(info, :unknown, :red)
200
- ui.puts
201
- said_any_things = said_things = true
202
- end
203
- unless info[:unavailable].empty?
204
- ui.puts " #{ui.color('Update request not allowed:', :red, :bold)}"
205
- print_plan_items(info, :unavailable, :red)
206
- ui.puts
207
- said_any_things = said_things = true
208
- end
209
- unless info[:replace].empty?
210
- ui.puts " #{ui.color('Resources to be replaced:', :red, :bold)}"
211
- print_plan_items(info, :replace, :red)
212
- ui.puts
213
- said_any_things = said_things = true
214
- end
215
- unless info[:interrupt].empty?
216
- ui.puts " #{ui.color('Resources to be interrupted:', :yellow, :bold)}"
217
- print_plan_items(info, :interrupt, :yellow)
218
- ui.puts
219
- said_any_things = said_things = true
220
- end
221
- unless info[:removed].empty?
222
- ui.puts " #{ui.color('Resources to be removed:', :red, :bold)}"
223
- print_plan_items(info, :removed, :red)
224
- ui.puts
225
- said_any_things = said_things = true
226
- end
227
- unless info[:added].empty?
228
- ui.puts " #{ui.color('Resources to be added:', :green, :bold)}"
229
- print_plan_items(info, :added, :green)
230
- ui.puts
231
- said_any_things = said_things = true
232
- end
233
- unless said_things
234
- ui.puts " #{ui.color('No resource lifecycle changes detected!', :green)}"
235
- ui.puts
236
- said_any_things = true
237
- end
238
- end
239
- said_any_things
240
- end
241
-
242
- # Print planning items
243
- #
244
- # @param info [Hash] plan
245
- # @param key [Symbol] key of items
246
- # @param color [Symbol] color to flag
247
- def print_plan_items(info, key, color)
248
- max_name = info[key].keys.map(&: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
252
- info[key].each do |name, val|
253
- ui.print ' ' * 6
254
- ui.print ui.color("[#{val[:type]}]", color)
255
- ui.print ' ' * (max_type - val[:type].size)
256
- ui.print ' ' * 4
257
- ui.print ui.color(name, :bold)
258
- unless val[:properties].nil? || val[:properties].empty?
259
- ui.print ' ' * (max_name - name.size)
260
- ui.print ' ' * 4
261
- ui.print "Reason: Updated properties: `#{val[:properties].join('`, `')}`"
262
- end
263
- ui.puts
264
- if config[:diffs]
265
- unless val[:diffs].empty?
266
- p_name = nil
267
- val[:diffs].each do |diff|
268
- if !diff[:updated].nil? || !diff[:original].nil?
269
- p_name = diff.fetch(:property_name, :path)
270
- ui.print ' ' * 8
271
- ui.print "#{p_name}: "
272
- ui.print ' ' * (max_p - p_name.size)
273
- ui.print ui.color("-#{diff[:original]}", :red) unless diff[:original].nil?
274
- ui.print ' ' * (max_o - diff[:original].to_s.size)
275
- ui.print ' '
276
- if diff[:updated] == Sfn::Planner::RUNTIME_MODIFIED
277
- ui.puts ui.color("+#{diff[:original]} <Dependency Modified>", :green)
278
- else
279
- if diff[:updated].nil?
280
- ui.puts
281
- else
282
- ui.puts ui.color("+#{diff[:updated].to_s.gsub('__MODIFIED_REFERENCE_VALUE__', '<Dependency Modified>')}", :green)
283
- end
284
- end
285
- end
286
- end
287
- ui.puts if p_name
288
- end
289
- end
290
- end
291
- end
292
167
  end
293
168
  end
294
169
  end
@@ -1,5 +1,5 @@
1
- require 'sparkle_formation'
2
- require 'sfn'
1
+ require "sparkle_formation"
2
+ require "sfn"
3
3
 
4
4
  module Sfn
5
5
  class Command
@@ -13,7 +13,7 @@ module Sfn
13
13
  print_only_original = config[:print_only]
14
14
  config[:print_only] = true
15
15
  file = load_template_file
16
- ui.info "#{ui.color("Template Validation (#{provider.connection.provider}): ", :bold)} #{config[:file].sub(Dir.pwd, '').sub(%r{^/}, '')}"
16
+ ui.info "#{ui.color("Template Validation (#{provider.connection.provider}): ", :bold)} #{config[:file].sub(Dir.pwd, "").sub(%r{^/}, "")}"
17
17
  config[:print_only] = print_only_original
18
18
 
19
19
  raw_template = _format_json(parameter_scrub!(template_content(file)))
@@ -23,7 +23,11 @@ module Sfn
23
23
  else
24
24
  validate_stack(
25
25
  file.respond_to?(:dump) ? file.dump : file,
26
- sparkle_collection.get(:template, config[:file])[:name]
26
+ if config[:processing]
27
+ sparkle_collection.get(:template, config[:file])[:name]
28
+ else
29
+ config[:file]
30
+ end
27
31
  )
28
32
  end
29
33
  end
@@ -34,36 +38,36 @@ module Sfn
34
38
  # @param name [String] name of template
35
39
  # @return [TrueClass]
36
40
  def validate_stack(template, name)
37
- resources = template.fetch('Resources', {})
41
+ resources = template.fetch("Resources", {})
38
42
  nested_stacks = resources.find_all do |r_name, r_value|
39
43
  r_value.is_a?(Hash) &&
40
- provider.connection.data[:stack_types].include?(r_value['Type'])
44
+ provider.connection.data[:stack_types].include?(r_value["Type"])
41
45
  end
42
46
  nested_stacks.each do |n_name, n_resource|
43
- validate_stack(n_resource.fetch('Properties', {}).fetch('Stack', {}), "#{name} > #{n_name}")
44
- n_resource['Properties'].delete('Stack')
47
+ validate_stack(n_resource.fetch("Properties", {}).fetch("Stack", {}), "#{name} > #{n_name}")
48
+ n_resource["Properties"].delete("Stack")
45
49
  end
46
50
  begin
47
51
  ui.info "Validating: #{ui.color(name, :bold)}"
48
52
  if config[:upload_root_template]
49
- upload_result = store_template('validation-stack', template, Smash.new)
53
+ upload_result = store_template("validation-stack", template, Smash.new)
50
54
  stack = provider.connection.stacks.build(
51
- :name => 'validation-stack',
55
+ :name => "validation-stack",
52
56
  :template_url => upload_result[:url],
53
57
  )
54
58
  else
55
59
  stack = provider.connection.stacks.build(
56
- :name => 'validation-stack',
60
+ :name => "validation-stack",
57
61
  :template => parameter_scrub!(template),
58
62
  )
59
63
  end
60
64
  result = api_action!(:api_stack => stack) do
61
65
  stack.validate
62
66
  end
63
- ui.info ui.color(' -> VALID', :bold, :green)
67
+ ui.info ui.color(" -> VALID", :bold, :green)
64
68
  true
65
69
  rescue => e
66
- ui.info ui.color(' -> INVALID', :bold, :red)
70
+ ui.info ui.color(" -> INVALID", :bold, :red)
67
71
  ui.fatal e.message
68
72
  raise e
69
73
  end
@@ -1,10 +1,11 @@
1
- require 'sfn'
1
+ require "sfn"
2
2
 
3
3
  module Sfn
4
4
  module CommandModule
5
- autoload :Base, 'sfn/command_module/base'
6
- autoload :Callbacks, 'sfn/command_module/callbacks'
7
- autoload :Stack, 'sfn/command_module/stack'
8
- autoload :Template, 'sfn/command_module/template'
5
+ autoload :Base, "sfn/command_module/base"
6
+ autoload :Callbacks, "sfn/command_module/callbacks"
7
+ autoload :Planning, "sfn/command_module/planning"
8
+ autoload :Stack, "sfn/command_module/stack"
9
+ autoload :Template, "sfn/command_module/template"
9
10
  end
10
11
  end
@@ -1,4 +1,4 @@
1
- require 'sfn'
1
+ require "sfn"
2
2
 
3
3
  module Sfn
4
4
  module CommandModule
@@ -23,7 +23,7 @@ module Sfn
23
23
  # @param location [Symbol, String] name of location
24
24
  # @return [Sfn::Provider]
25
25
  def provider_for(location = nil)
26
- key = ['provider', location].compact.map(&:to_s).join('_')
26
+ key = ["provider", location].compact.map(&:to_s).join("_")
27
27
  if location
28
28
  credentials = config.get(:locations, location)
29
29
  unless credentials
@@ -55,7 +55,7 @@ module Sfn
55
55
  result
56
56
  end
57
57
  rescue => e
58
- ui.error 'Failed to create remote API connection. Please validate configuration!'
58
+ ui.error "Failed to create remote API connection. Please validate configuration!"
59
59
  ui.error "Connection failure reason - #{e.class} - #{e}"
60
60
  raise
61
61
  end
@@ -70,7 +70,7 @@ module Sfn
70
70
  def _debug(e, *args)
71
71
  if config[:verbose] || config[:debug]
72
72
  ui.fatal "Exception information: #{e.class}: #{e.message}"
73
- if ENV['DEBUG'] || config[:debug]
73
+ if ENV["DEBUG"] || config[:debug]
74
74
  puts "#{e.backtrace.join("\n")}\n"
75
75
  if e.is_a?(Miasma::Error::ApiError)
76
76
  ui.fatal "Response body: #{e.response.body.to_s.inspect}"
@@ -87,7 +87,7 @@ module Sfn
87
87
  # @param string [String, Symbol]
88
88
  # @return [String
89
89
  def as_title(string)
90
- string.to_s.split('_').map(&:capitalize).join(' ')
90
+ string.to_s.split("_").map(&:capitalize).join(" ")
91
91
  end
92
92
 
93
93
  # Get stack
@@ -137,7 +137,7 @@ module Sfn
137
137
  begin
138
138
  yield
139
139
  rescue => e
140
- ui.fatal "#{message || 'Failed to retrieve information'}#{" for requested stack: #{stack}" if stack}"
140
+ ui.fatal "#{message || "Failed to retrieve information"}#{" for requested stack: #{stack}" if stack}"
141
141
  ui.fatal "Reason: #{e}"
142
142
  _debug(e)
143
143
  exit 1
@@ -172,8 +172,8 @@ module Sfn
172
172
  # @raise [ArgumentError]
173
173
  def name_required!
174
174
  if name_args.empty?
175
- ui.error 'Name argument must be provided!'
176
- raise ArgumentError.new 'Missing required name argument'
175
+ ui.error "Name argument must be provided!"
176
+ raise ArgumentError.new "Missing required name argument"
177
177
  end
178
178
  end
179
179
  end
@@ -1,5 +1,5 @@
1
- require 'sfn'
2
- require 'sparkle_formation'
1
+ require "sfn"
2
+ require "sparkle_formation"
3
3
 
4
4
  module Sfn
5
5
  module CommandModule
@@ -13,7 +13,7 @@ module Sfn
13
13
  # @yieldresult [Object] result from call
14
14
  # @return [Object] result of yield block
15
15
  def api_action!(*args)
16
- type = self.class.name.split('::').last.downcase
16
+ type = self.class.name.split("::").last.downcase
17
17
  run_callbacks_for(["before_#{type}", :before], *args)
18
18
  result = nil
19
19
  begin
@@ -38,13 +38,13 @@ module Sfn
38
38
  end.flatten(1).compact.uniq.each do |item|
39
39
  callback_name, callback, quiet = item
40
40
  quiet = true if config[:print_only]
41
- ui.info "Callback #{ui.color(type.to_s, :bold)} #{callback_name}: #{ui.color('starting', :yellow)}" unless quiet
41
+ ui.info "Callback #{ui.color(type.to_s, :bold)} #{callback_name}: #{ui.color("starting", :yellow)}" unless quiet
42
42
  if args.empty?
43
43
  callback.call
44
44
  else
45
45
  callback.call(*args)
46
46
  end
47
- ui.info "Callback #{ui.color(type.to_s, :bold)} #{callback_name}: #{ui.color('complete', :green)}" unless quiet
47
+ ui.info "Callback #{ui.color(type.to_s, :bold)} #{callback_name}: #{ui.color("complete", :green)}" unless quiet
48
48
  end
49
49
  nil
50
50
  end