sfn 3.0.30 → 3.0.32

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