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,53 +1,54 @@
1
- require 'sfn'
2
- require 'bogo-cli'
1
+ require "sfn"
2
+ require "bogo-cli"
3
3
 
4
4
  module Sfn
5
5
  class Command < Bogo::Cli::Command
6
6
  include CommandModule::Callbacks
7
7
 
8
- autoload :Conf, 'sfn/command/conf'
9
- autoload :Create, 'sfn/command/create'
10
- autoload :Describe, 'sfn/command/describe'
11
- autoload :Destroy, 'sfn/command/destroy'
12
- autoload :Diff, 'sfn/command/diff'
13
- autoload :Events, 'sfn/command/events'
14
- autoload :Export, 'sfn/command/export'
15
- autoload :Graph, 'sfn/command/graph'
16
- autoload :Import, 'sfn/command/import'
17
- autoload :Init, 'sfn/command/init'
18
- autoload :Inspect, 'sfn/command/inspect'
19
- autoload :Lint, 'sfn/command/lint'
20
- autoload :List, 'sfn/command/list'
21
- autoload :Print, 'sfn/command/print'
22
- autoload :Promote, 'sfn/command/promote'
23
- autoload :Update, 'sfn/command/update'
24
- autoload :Validate, 'sfn/command/validate'
8
+ autoload :Conf, "sfn/command/conf"
9
+ autoload :Create, "sfn/command/create"
10
+ autoload :Describe, "sfn/command/describe"
11
+ autoload :Destroy, "sfn/command/destroy"
12
+ autoload :Diff, "sfn/command/diff"
13
+ autoload :Events, "sfn/command/events"
14
+ autoload :Export, "sfn/command/export"
15
+ autoload :Graph, "sfn/command/graph"
16
+ autoload :Import, "sfn/command/import"
17
+ autoload :Init, "sfn/command/init"
18
+ autoload :Inspect, "sfn/command/inspect"
19
+ autoload :Lint, "sfn/command/lint"
20
+ autoload :List, "sfn/command/list"
21
+ autoload :Plan, "sfn/command/plan"
22
+ autoload :Print, "sfn/command/print"
23
+ autoload :Promote, "sfn/command/promote"
24
+ autoload :Update, "sfn/command/update"
25
+ autoload :Validate, "sfn/command/validate"
25
26
 
26
27
  # Base name of configuration file
27
- CONFIG_BASE_NAME = '.sfn'
28
+ CONFIG_BASE_NAME = ".sfn"
28
29
 
29
30
  # Supported configuration file extensions
30
31
  VALID_CONFIG_EXTENSIONS = [
31
- '',
32
- '.rb',
33
- '.json',
34
- '.yaml',
35
- '.yml',
36
- '.xml',
32
+ "",
33
+ ".rb",
34
+ ".json",
35
+ ".yaml",
36
+ ".yml",
37
+ ".xml",
37
38
  ]
38
39
 
39
40
  # Override to provide config file searching
40
41
  def initialize(cli_opts, args)
41
- unless cli_opts['config']
42
+ unless cli_opts["config"]
42
43
  discover_config(cli_opts)
43
44
  end
44
- unless ENV['DEBUG']
45
- ENV['DEBUG'] = 'true' if cli_opts[:debug]
45
+ unless ENV["DEBUG"]
46
+ ENV["DEBUG"] = "true" if cli_opts[:debug]
46
47
  end
47
48
  super(cli_opts, args)
48
49
  load_api_provider_extensions!
49
50
  run_callbacks_for(:after_config)
50
- run_callbacks_for("after_config_#{Bogo::Utility.snake(self.class.name.split('::').last)}")
51
+ run_callbacks_for("after_config_#{Bogo::Utility.snake(self.class.name.split("::").last)}")
51
52
  end
52
53
 
53
54
  # @return [Smash]
@@ -65,7 +66,7 @@ module Sfn
65
66
  def load_api_provider_extensions!
66
67
  if config.get(:credentials, :provider)
67
68
  base_ext = Bogo::Utility.camel(config.get(:credentials, :provider)).to_sym
68
- targ_ext = self.class.name.split('::').last
69
+ targ_ext = self.class.name.split("::").last
69
70
  if ApiProvider.constants.include?(base_ext)
70
71
  base_module = ApiProvider.const_get(base_ext)
71
72
  ui.debug "Loading core provider extensions via `#{base_module}`"
@@ -87,26 +88,26 @@ module Sfn
87
88
  # @return [Slop]
88
89
  def discover_config(opts)
89
90
  cwd = Dir.pwd.split(File::SEPARATOR)
90
- detected_path = ''
91
+ detected_path = ""
91
92
  until cwd.empty? || File.exists?(detected_path.to_s)
92
93
  detected_path = Dir.glob(
93
- (cwd + ["#{CONFIG_BASE_NAME}{#{VALID_CONFIG_EXTENSIONS.join(',')}}"]).join(
94
+ (cwd + ["#{CONFIG_BASE_NAME}{#{VALID_CONFIG_EXTENSIONS.join(",")}}"]).join(
94
95
  File::SEPARATOR
95
96
  )
96
97
  ).first
97
98
  cwd.pop
98
99
  end
99
100
  if opts.respond_to?(:fetch_option)
100
- opts.fetch_option('config').value = detected_path if detected_path
101
+ opts.fetch_option("config").value = detected_path if detected_path
101
102
  else
102
- opts['config'] = detected_path if detected_path
103
+ opts["config"] = detected_path if detected_path
103
104
  end
104
105
  opts
105
106
  end
106
107
 
107
108
  # @return [Class] attempt to return customized configuration class
108
109
  def config_class
109
- klass_name = self.class.name.split('::').last
110
+ klass_name = self.class.name.split("::").last
110
111
  if Sfn::Config.const_defined?(klass_name)
111
112
  Sfn::Config.const_get(klass_name)
112
113
  else
@@ -1,4 +1,4 @@
1
- require 'sfn'
1
+ require "sfn"
2
2
 
3
3
  module Sfn
4
4
  class Command
@@ -12,42 +12,42 @@ module Sfn
12
12
  Config::Conf.attributes.sort_by(&:first).each do |k, val|
13
13
  if config.has_key?(k)
14
14
  ui.print " #{ui.color(k, :bold, :green)}: "
15
- format_value(config[k], ' ')
15
+ format_value(config[k], " ")
16
16
  end
17
17
  end
18
18
  if config[:generate]
19
19
  ui.puts
20
- ui.info 'Generating .sfn configuration file..'
20
+ ui.info "Generating .sfn configuration file.."
21
21
  generate_config!
22
- ui.info "Generation of .sfn configuration file #{ui.color('complete!', :green, :bold)}"
22
+ ui.info "Generation of .sfn configuration file #{ui.color("complete!", :green, :bold)}"
23
23
  end
24
24
  end
25
25
 
26
26
  def generate_config!
27
- if File.exists?('.sfn')
28
- ui.warn 'Existing .sfn configuration file detected!'
29
- ui.confirm 'Overwrite current .sfn configuration file?'
27
+ if File.exists?(".sfn")
28
+ ui.warn "Existing .sfn configuration file detected!"
29
+ ui.confirm "Overwrite current .sfn configuration file?"
30
30
  end
31
- run_action 'Writing .sfn file' do
32
- File.open('.sfn', 'w') do |file|
31
+ run_action "Writing .sfn file" do
32
+ File.open(".sfn", "w") do |file|
33
33
  file.write SFN_CONFIG_CONTENTS
34
34
  end
35
35
  nil
36
36
  end
37
37
  end
38
38
 
39
- def format_value(value, indent = '')
39
+ def format_value(value, indent = "")
40
40
  if value.is_a?(Hash)
41
41
  ui.puts
42
42
  value.sort_by(&:first).each do |k, v|
43
43
  ui.print "#{indent} #{ui.color(k, :bold)}: "
44
- format_value(v, indent + ' ')
44
+ format_value(v, indent + " ")
45
45
  end
46
46
  elsif value.is_a?(Array)
47
47
  ui.puts
48
48
  value.map(&:to_s).sort.each do |v|
49
49
  ui.print "#{indent} "
50
- format_value(v, indent + ' ')
50
+ format_value(v, indent + " ")
51
51
  end
52
52
  else
53
53
  ui.puts value.to_s
@@ -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
@@ -24,12 +24,12 @@ module Sfn
24
24
  end
25
25
 
26
26
  unless config[:print_only]
27
- ui.info "#{ui.color('SparkleFormation:', :bold)} #{ui.color('create', :green)}"
27
+ ui.info "#{ui.color("SparkleFormation:", :bold)} #{ui.color("create", :green)}"
28
28
  end
29
29
 
30
- stack_info = "#{ui.color('Name:', :bold)} #{name}"
30
+ stack_info = "#{ui.color("Name:", :bold)} #{name}"
31
31
  if config[:path]
32
- stack_info << " #{ui.color('Path:', :bold)} #{config[:file]}"
32
+ stack_info << " #{ui.color("Path:", :bold)} #{config[:file]}"
33
33
  end
34
34
 
35
35
  if config[:print_only]
@@ -66,14 +66,14 @@ module Sfn
66
66
  stack = provider.stack(name)
67
67
 
68
68
  if stack.reload.state == :create_complete
69
- ui.info "Stack create complete: #{ui.color('SUCCESS', :green)}"
69
+ ui.info "Stack create complete: #{ui.color("SUCCESS", :green)}"
70
70
  namespace.const_get(:Describe).new({:outputs => true}, [name]).execute!
71
71
  else
72
- ui.fatal "Create of new stack #{ui.color(name, :bold)}: #{ui.color('FAILED', :red, :bold)}"
73
- raise 'Stack did not reach a successful completion state.'
72
+ ui.fatal "Create of new stack #{ui.color(name, :bold)}: #{ui.color("FAILED", :red, :bold)}"
73
+ raise "Stack did not reach a successful completion state."
74
74
  end
75
75
  else
76
- ui.warn 'Stack state polling has been disabled.'
76
+ ui.warn "Stack state polling has been disabled."
77
77
  ui.info "Stack creation initialized for #{ui.color(name, :green)}"
78
78
  end
79
79
  end
@@ -1,4 +1,4 @@
1
- require 'sfn'
1
+ require "sfn"
2
2
 
3
3
  module Sfn
4
4
  class Command
@@ -75,11 +75,11 @@ module Sfn
75
75
  unless stack.outputs.nil? || stack.outputs.empty?
76
76
  stack.outputs.each do |output|
77
77
  key, value = output.key, output.value
78
- key = snake(key).to_s.split('_').map(&:capitalize).join(' ')
79
- ui.info [' ', ui.color("#{key}:", :bold), value].join(' ')
78
+ key = snake(key).to_s.split("_").map(&:capitalize).join(" ")
79
+ ui.info [" ", ui.color("#{key}:", :bold), value].join(" ")
80
80
  end
81
81
  else
82
- ui.info " #{ui.color('No outputs found')}"
82
+ ui.info " #{ui.color("No outputs found")}"
83
83
  end
84
84
  end
85
85
 
@@ -90,10 +90,10 @@ module Sfn
90
90
  ui.info "Tags for stack: #{ui.color(stack.name, :bold)}"
91
91
  if stack.tags && !stack.tags.empty?
92
92
  stack.tags.each do |key, value|
93
- ui.info [' ', ui.color("#{key}:", :bold), value].join(' ')
93
+ ui.info [" ", ui.color("#{key}:", :bold), value].join(" ")
94
94
  end
95
95
  else
96
- ui.info " #{ui.color('No tags found')}"
96
+ ui.info " #{ui.color("No tags found")}"
97
97
  end
98
98
  end
99
99
 
@@ -1,4 +1,4 @@
1
- require 'sfn'
1
+ require "sfn"
2
2
 
3
3
  module Sfn
4
4
  class Command
@@ -9,7 +9,7 @@ module Sfn
9
9
  def execute!
10
10
  name_required!
11
11
  stacks = name_args.sort
12
- plural = 's' if stacks.size > 1
12
+ plural = "s" if stacks.size > 1
13
13
  globs = stacks.find_all do |s|
14
14
  s !~ /^[a-zA-Z0-9-]+$/
15
15
  end
@@ -23,7 +23,7 @@ module Sfn
23
23
  stacks -= globs
24
24
  stacks.sort!
25
25
  end
26
- ui.warn "Destroying Stack#{plural}: #{ui.color(stacks.join(', '), :bold)}"
26
+ ui.warn "Destroying Stack#{plural}: #{ui.color(stacks.join(", "), :bold)}"
27
27
  ui.confirm "Destroy listed stack#{plural}?"
28
28
  stacks.each do |stack_name|
29
29
  stack = provider.connection.stacks.get(stack_name)
@@ -56,7 +56,7 @@ module Sfn
56
56
  ui.error "Stack polling is not available when multiple stack deletion is requested!"
57
57
  end
58
58
  end
59
- ui.info " -> Destroyed SparkleFormation#{plural}: #{ui.color(stacks.join(', '), :bold, :red)}"
59
+ ui.info " -> Destroyed SparkleFormation#{plural}: #{ui.color(stacks.join(", "), :bold, :red)}"
60
60
  end
61
61
 
62
62
  # Cleanup persisted templates if nested stack resources are included
@@ -64,12 +64,12 @@ module Sfn
64
64
  stack.nested_stacks.each do |n_stack|
65
65
  nested_stack_cleanup!(n_stack)
66
66
  end
67
- nest_stacks = stack.template.fetch('Resources', {}).values.find_all do |resource|
68
- provider.connection.data[:stack_types].include?(resource['Type'])
67
+ nest_stacks = stack.template.fetch("Resources", {}).values.find_all do |resource|
68
+ provider.connection.data[:stack_types].include?(resource["Type"])
69
69
  end.each do |resource|
70
- url = resource['Properties']['TemplateURL']
70
+ url = resource["Properties"]["TemplateURL"]
71
71
  if url && url.is_a?(String)
72
- _, bucket_name, path = URI.parse(url).path.split('/', 3)
72
+ _, bucket_name, path = URI.parse(url).path.split("/", 3)
73
73
  bucket = provider.connection.api_for(:storage).buckets.get(bucket_name)
74
74
  if bucket
75
75
  file = bucket.files.get(path)
@@ -1,6 +1,6 @@
1
- require 'sparkle_formation'
2
- require 'sfn'
3
- require 'hashdiff'
1
+ require "sparkle_formation"
2
+ require "sfn"
3
+ require "hashdiff"
4
4
 
5
5
  module Sfn
6
6
  class Command
@@ -26,7 +26,7 @@ module Sfn
26
26
  file = load_template_file
27
27
  file = parameter_scrub!(file.dump)
28
28
 
29
- ui.info "#{ui.color('SparkleFormation:', :bold)} #{ui.color('diff', :blue)} - #{name}"
29
+ ui.info "#{ui.color("SparkleFormation:", :bold)} #{ui.color("diff", :blue)} - #{name}"
30
30
  ui.puts
31
31
 
32
32
  diff_stack(stack, MultiJson.load(MultiJson.dump(file)).to_smash)
@@ -40,8 +40,8 @@ module Sfn
40
40
  def diff_stack(stack, file, parent_names = [])
41
41
  stack_template = stack.template
42
42
  nested_stacks = Hash[
43
- file.fetch('Resources', file.fetch('resources', {})).find_all do |name, value|
44
- value.fetch('Properties', {})['Stack']
43
+ file.fetch("Resources", file.fetch("resources", {})).find_all do |name, value|
44
+ value.fetch("Properties", {})["Stack"]
45
45
  end
46
46
  ]
47
47
  nested_stacks.each do |name, value|
@@ -49,58 +49,58 @@ module Sfn
49
49
  ns.data[:logical_id] == name
50
50
  end
51
51
  if n_stack
52
- diff_stack(n_stack, value['Properties']['Stack'], [*parent_names, stack.data.fetch(:logical_id, stack.name)].compact)
52
+ diff_stack(n_stack, value["Properties"]["Stack"], [*parent_names, stack.data.fetch(:logical_id, stack.name)].compact)
53
53
  end
54
- file['Resources'][name]['Properties'].delete('Stack')
54
+ file["Resources"][name]["Properties"].delete("Stack")
55
55
  end
56
56
 
57
- ui.info "#{ui.color('Stack diff:', :bold)} #{ui.color((parent_names + [stack.data.fetch(:logical_id, stack.name)]).compact.join(' > '), :blue)}"
57
+ ui.info "#{ui.color("Stack diff:", :bold)} #{ui.color((parent_names + [stack.data.fetch(:logical_id, stack.name)]).compact.join(" > "), :blue)}"
58
58
 
59
59
  stack_diff = HashDiff.diff(stack.template, file)
60
60
 
61
61
  if config[:raw_diff]
62
62
  ui.info "Dumping raw template diff:"
63
- require 'pp'
63
+ require "pp"
64
64
  pp stack_diff
65
65
  else
66
66
  added_resources = stack_diff.find_all do |item|
67
- item.first == '+' && item[1].match(/Resources\.[^.]+$/)
67
+ item.first == "+" && item[1].match(/Resources\.[^.]+$/)
68
68
  end
69
69
  removed_resources = stack_diff.find_all do |item|
70
- item.first == '-' && item[1].match(/Resources\.[^.]+$/)
70
+ item.first == "-" && item[1].match(/Resources\.[^.]+$/)
71
71
  end
72
72
  modified_resources = stack_diff.find_all do |item|
73
- item[1].start_with?('Resources.') &&
74
- !item[1].end_with?('TemplateURL') &&
75
- !item[1].include?('Properties.Parameters')
73
+ item[1].start_with?("Resources.") &&
74
+ !item[1].end_with?("TemplateURL") &&
75
+ !item[1].include?("Properties.Parameters")
76
76
  end - added_resources - removed_resources
77
77
 
78
78
  if added_resources.empty? && removed_resources.empty? && modified_resources.empty?
79
- ui.info 'No changes detected'
79
+ ui.info "No changes detected"
80
80
  ui.puts
81
81
  else
82
82
  unless added_resources.empty?
83
- ui.info ui.color('Added Resources:', :green, :bold)
83
+ ui.info ui.color("Added Resources:", :green, :bold)
84
84
  added_resources.each do |item|
85
- ui.print ui.color(" -> #{item[1].split('.').last}", :green)
86
- ui.puts " [#{item[2]['Type']}]"
85
+ ui.print ui.color(" -> #{item[1].split(".").last}", :green)
86
+ ui.puts " [#{item[2]["Type"]}]"
87
87
  end
88
88
  ui.puts
89
89
  end
90
90
 
91
91
  unless modified_resources.empty?
92
- ui.info ui.color('Modified Resources:', :yellow, :bold)
92
+ ui.info ui.color("Modified Resources:", :yellow, :bold)
93
93
  m_resources = Hash.new.tap do |hash|
94
94
  modified_resources.each do |item|
95
- _, key, path = item[1].split('.', 3)
95
+ _, key, path = item[1].split(".", 3)
96
96
  hash[key] ||= {}
97
- prefix, a_key = path.split('.', 2)
97
+ prefix, a_key = path.split(".", 2)
98
98
  hash[key][prefix] ||= []
99
99
  matched = hash[key][prefix].detect do |i|
100
100
  i[:path] == a_key
101
101
  end
102
102
  if matched
103
- if item.first == '-'
103
+ if item.first == "-"
104
104
  matched[:original] = item[2]
105
105
  else
106
106
  matched[:new] = item[2]
@@ -109,10 +109,10 @@ module Sfn
109
109
  hash[key][prefix] << Hash.new.tap do |info|
110
110
  info[:path] = a_key
111
111
  case item.first
112
- when '~'
112
+ when "~"
113
113
  info[:original] = item[2]
114
114
  info[:new] = item[3]
115
- when '+'
115
+ when "+"
116
116
  info[:new] = item[2]
117
117
  else
118
118
  info[:original] = item[2]
@@ -121,12 +121,12 @@ module Sfn
121
121
  end
122
122
  end
123
123
  end.to_smash(:sorted).each do |key, value|
124
- ui.puts ui.color(" - #{key}", :yellow) + " [#{stack.template['Resources'][key]['Type']}]"
124
+ ui.puts ui.color(" - #{key}", :yellow) + " [#{stack.template["Resources"][key]["Type"]}]"
125
125
  value.each do |prefix, items|
126
126
  ui.puts ui.color(" #{prefix}:", :bold)
127
127
  items.each do |item|
128
- original = item[:original].nil? ? ui.color('(none)', :yellow) : ui.color(item[:original].inspect, :red)
129
- new_val = item[:new].nil? ? ui.color('(deleted)', :red) : ui.color(item[:new].inspect, :green)
128
+ original = item[:original].nil? ? ui.color("(none)", :yellow) : ui.color(item[:original].inspect, :red)
129
+ new_val = item[:new].nil? ? ui.color("(deleted)", :red) : ui.color(item[:new].inspect, :green)
130
130
  ui.puts " #{item[:path]}: #{original} -> #{new_val}"
131
131
  end
132
132
  end
@@ -135,10 +135,10 @@ module Sfn
135
135
  end
136
136
 
137
137
  unless removed_resources.empty?
138
- ui.info ui.color('Removed Resources:', :red, :bold)
138
+ ui.info ui.color("Removed Resources:", :red, :bold)
139
139
  removed_resources.each do |item|
140
- ui.print ui.color(" <- #{item[1].split('.').last}", :red)
141
- ui.puts " [#{item[2]['Type']}]"
140
+ ui.print ui.color(" <- #{item[1].split(".").last}", :red)
141
+ ui.puts " [#{item[2]["Type"]}]"
142
142
  end
143
143
  ui.puts
144
144
  end