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
@@ -3,7 +3,6 @@ require 'sfn'
3
3
  module Sfn
4
4
  class Command
5
5
  class Destroy < Command
6
-
7
6
  include Sfn::CommandModule::Base
8
7
 
9
8
  # Run the stack destruction action
@@ -14,7 +13,7 @@ module Sfn
14
13
  globs = stacks.find_all do |s|
15
14
  s !~ /^[a-zA-Z0-9-]+$/
16
15
  end
17
- unless(globs.empty?)
16
+ unless globs.empty?
18
17
  glob_stacks = provider.connection.stacks.all.find_all do |remote_stack|
19
18
  globs.detect do |glob|
20
19
  File.fnmatch(glob, remote_stack.name)
@@ -28,7 +27,7 @@ module Sfn
28
27
  ui.confirm "Destroy listed stack#{plural}?"
29
28
  stacks.each do |stack_name|
30
29
  stack = provider.connection.stacks.get(stack_name)
31
- if(stack)
30
+ if stack
32
31
  nested_stack_cleanup!(stack)
33
32
  begin
34
33
  api_action!(:api_stack => stack) do
@@ -44,12 +43,12 @@ module Sfn
44
43
  ui.warn "Failed to locate requested stack: #{ui.color(stack_name, :bold)}"
45
44
  end
46
45
  end
47
- if(config[:poll])
48
- if(stacks.size == 1)
46
+ if config[:poll]
47
+ if stacks.size == 1
49
48
  begin
50
49
  poll_stack(stacks.first)
51
50
  rescue Miasma::Error::ApiError::RequestError => error
52
- unless(error.response.code == 404)
51
+ unless error.response.code == 404
53
52
  raise error
54
53
  end
55
54
  end
@@ -69,12 +68,12 @@ module Sfn
69
68
  provider.connection.data[:stack_types].include?(resource['Type'])
70
69
  end.each do |resource|
71
70
  url = resource['Properties']['TemplateURL']
72
- if(url && url.is_a?(String))
71
+ if url && url.is_a?(String)
73
72
  _, bucket_name, path = URI.parse(url).path.split('/', 3)
74
73
  bucket = provider.connection.api_for(:storage).buckets.get(bucket_name)
75
- if(bucket)
74
+ if bucket
76
75
  file = bucket.files.get(path)
77
- if(file)
76
+ if file
78
77
  file.destroy
79
78
  ui.info "Deleted nested stack template! (Bucket: #{bucket_name} Template: #{path})"
80
79
  else
@@ -86,7 +85,6 @@ module Sfn
86
85
  end
87
86
  end
88
87
  end
89
-
90
88
  end
91
89
  end
92
90
  end
@@ -6,7 +6,6 @@ module Sfn
6
6
  class Command
7
7
  # Diff command
8
8
  class Diff < Command
9
-
10
9
  include Sfn::CommandModule::Base
11
10
  include Sfn::CommandModule::Template
12
11
  include Sfn::CommandModule::Stack
@@ -22,7 +21,7 @@ module Sfn
22
21
  stack = nil
23
22
  end
24
23
 
25
- if(stack)
24
+ if stack
26
25
  config[:print_only] = true
27
26
  file = load_template_file
28
27
  file = parameter_scrub!(file.dump)
@@ -38,7 +37,7 @@ module Sfn
38
37
  end
39
38
 
40
39
  # @todo needs updates for better provider compat
41
- def diff_stack(stack, file, parent_names=[])
40
+ def diff_stack(stack, file, parent_names = [])
42
41
  stack_template = stack.template
43
42
  nested_stacks = Hash[
44
43
  file.fetch('Resources', file.fetch('resources', {})).find_all do |name, value|
@@ -49,7 +48,7 @@ module Sfn
49
48
  n_stack = stack.nested_stacks(false).detect do |ns|
50
49
  ns.data[:logical_id] == name
51
50
  end
52
- if(n_stack)
51
+ if n_stack
53
52
  diff_stack(n_stack, value['Properties']['Stack'], [*parent_names, stack.data.fetch(:logical_id, stack.name)].compact)
54
53
  end
55
54
  file['Resources'][name]['Properties'].delete('Stack')
@@ -59,12 +58,11 @@ module Sfn
59
58
 
60
59
  stack_diff = HashDiff.diff(stack.template, file)
61
60
 
62
- if(config[:raw_diff])
61
+ if config[:raw_diff]
63
62
  ui.info "Dumping raw template diff:"
64
63
  require 'pp'
65
64
  pp stack_diff
66
65
  else
67
-
68
66
  added_resources = stack_diff.find_all do |item|
69
67
  item.first == '+' && item[1].match(/Resources\.[^.]+$/)
70
68
  end
@@ -77,12 +75,11 @@ module Sfn
77
75
  !item[1].include?('Properties.Parameters')
78
76
  end - added_resources - removed_resources
79
77
 
80
- if(added_resources.empty? && removed_resources.empty? && modified_resources.empty?)
78
+ if added_resources.empty? && removed_resources.empty? && modified_resources.empty?
81
79
  ui.info 'No changes detected'
82
80
  ui.puts
83
81
  else
84
-
85
- unless(added_resources.empty?)
82
+ unless added_resources.empty?
86
83
  ui.info ui.color('Added Resources:', :green, :bold)
87
84
  added_resources.each do |item|
88
85
  ui.print ui.color(" -> #{item[1].split('.').last}", :green)
@@ -91,7 +88,7 @@ module Sfn
91
88
  ui.puts
92
89
  end
93
90
 
94
- unless(modified_resources.empty?)
91
+ unless modified_resources.empty?
95
92
  ui.info ui.color('Modified Resources:', :yellow, :bold)
96
93
  m_resources = Hash.new.tap do |hash|
97
94
  modified_resources.each do |item|
@@ -102,8 +99,8 @@ module Sfn
102
99
  matched = hash[key][prefix].detect do |i|
103
100
  i[:path] == a_key
104
101
  end
105
- if(matched)
106
- if(item.first == '-')
102
+ if matched
103
+ if item.first == '-'
107
104
  matched[:original] = item[2]
108
105
  else
109
106
  matched[:new] = item[2]
@@ -137,7 +134,7 @@ module Sfn
137
134
  ui.puts
138
135
  end
139
136
 
140
- unless(removed_resources.empty?)
137
+ unless removed_resources.empty?
141
138
  ui.info ui.color('Removed Resources:', :red, :bold)
142
139
  removed_resources.each do |item|
143
140
  ui.print ui.color(" <- #{item[1].split('.').last}", :red)
@@ -147,21 +144,17 @@ module Sfn
147
144
  end
148
145
 
149
146
  run_callbacks_for(:after_stack_diff,
150
- :diff => stack_diff,
151
- :diff_info => {
152
- :added => added_resources,
153
- :modified => modified_resources,
154
- :removed => removed_resources
155
- },
156
- :api_stack => stack,
157
- :new_template => file
158
- )
147
+ :diff => stack_diff,
148
+ :diff_info => {
149
+ :added => added_resources,
150
+ :modified => modified_resources,
151
+ :removed => removed_resources,
152
+ },
153
+ :api_stack => stack,
154
+ :new_template => file)
159
155
  end
160
-
161
156
  end
162
-
163
157
  end
164
-
165
158
  end
166
159
  end
167
160
  end
@@ -4,7 +4,6 @@ module Sfn
4
4
  class Command
5
5
  # Events command
6
6
  class Events < Command
7
-
8
7
  include Sfn::CommandModule::Base
9
8
 
10
9
  # @return [Miasma::Models::Orchestration::Stack]
@@ -17,14 +16,14 @@ module Sfn
17
16
  ui.info "Events for Stack: #{ui.color(name, :bold)}\n"
18
17
  @seen_events = []
19
18
  @stack = provider.stack(name)
20
- if(stack)
19
+ if stack
21
20
  api_action!(:api_stack => stack) do
22
21
  table = ui.table(self) do
23
22
  table(:border => false) do
24
23
  events = get_events
25
24
  row(:header => true) do
26
25
  allowed_attributes.each do |attr|
27
- width_val = events.map{|e| e[attr].to_s.length}.push(attr.length).max + 2
26
+ width_val = events.map { |e| e[attr].to_s.length }.push(attr.length).max + 2
28
27
  width_val = width_val > 70 ? 70 : width_val < 20 ? 20 : width_val
29
28
  column attr.split('_').map(&:capitalize).join(' '), :width => width_val
30
29
  end
@@ -38,10 +37,10 @@ module Sfn
38
37
  end
39
38
  end
40
39
  end.display
41
- if(config[:poll])
42
- while(stack.reload.in_progress?)
40
+ if config[:poll]
41
+ while (stack.reload.in_progress?)
43
42
  to_wait = config.fetch(:poll_wait_time, 10).to_f
44
- while(to_wait > 0)
43
+ while (to_wait > 0)
45
44
  sleep(0.1)
46
45
  to_wait -= 0.1
47
46
  end
@@ -65,13 +64,13 @@ module Sfn
65
64
  stack_events = discover_stacks(stack).map do |i_stack|
66
65
  i_events = []
67
66
  begin
68
- if(@initial_complete && i_stack.in_progress?)
67
+ if @initial_complete && i_stack.in_progress?
69
68
  i_events = i_stack.events.update!
70
69
  else
71
70
  i_events = i_stack.events.all
72
71
  end
73
72
  rescue => e
74
- if(e.class.to_s.start_with?('Errno'))
73
+ if e.class.to_s.start_with?('Errno')
75
74
  ui.warn "Connection error encountered: #{e.message} (retrying)"
76
75
  ui.debug "#{e.class}: #{e}\n#{e.backtrace.join("\n")}"
77
76
  else
@@ -81,23 +80,23 @@ module Sfn
81
80
  sleep(5)
82
81
  retry
83
82
  end
84
- if(i_events)
83
+ if i_events
85
84
  i_events.map do |e|
86
85
  e.attributes.merge(:stack_name => i_stack.name).to_smash
87
86
  end
88
87
  end
89
- end.flatten.compact.find_all{|e| e[:time] }.reverse
90
- stack_events.delete_if{|evt| @seen_events.include?(evt)}
88
+ end.flatten.compact.find_all { |e| e[:time] }.reverse
89
+ stack_events.delete_if { |evt| @seen_events.include?(evt) }
91
90
  @seen_events.concat(stack_events)
92
- unless(@initial_complete)
93
- stack_events = stack_events.sort_by{|e| e[:time] }
94
- unless(config[:all_events])
91
+ unless @initial_complete
92
+ stack_events = stack_events.sort_by { |e| e[:time] }
93
+ unless config[:all_events]
95
94
  start_index = stack_events.rindex do |item|
96
95
  item[:stack_name] == stack.name &&
97
96
  item[:resource_state].to_s.end_with?('in_progress') &&
98
97
  item[:resource_status_reason].to_s.downcase.include?('user init')
99
98
  end
100
- if(start_index)
99
+ if start_index
101
100
  stack_events.slice!(0, start_index)
102
101
  end
103
102
  end
@@ -121,7 +120,7 @@ module Sfn
121
120
  # @return [Array<String>] allowed attributes for events
122
121
  def allowed_attributes
123
122
  result = super
124
- unless(@stacks.size > 1)
123
+ unless @stacks.size > 1
125
124
  result.delete('stack_name')
126
125
  end
127
126
  result
@@ -4,7 +4,6 @@ module Sfn
4
4
  class Command
5
5
  # Export command
6
6
  class Export < Command
7
-
8
7
  include Sfn::CommandModule::Base
9
8
  include Sfn::Utils::ObjectStorage
10
9
 
@@ -15,7 +14,7 @@ module Sfn
15
14
  ui.info "#{ui.color('Stack Export:', :bold)} #{stack_name}"
16
15
  ui.confirm 'Perform export'
17
16
  stack = provider.stacks.get(stack_name)
18
- if(stack)
17
+ if stack
19
18
  export_options = Smash.new.tap do |opts|
20
19
  [:chef_popsicle, :chef_environment_parameter, :ignore_parameters].each do |key|
21
20
  opts[key] = config[key] unless config[key].nil?
@@ -25,14 +24,14 @@ module Sfn
25
24
  result = exporter.export
26
25
  outputs = [
27
26
  write_to_file(result, stack),
28
- write_to_bucket(result, stack)
27
+ write_to_bucket(result, stack),
29
28
  ].compact
30
- if(outputs.empty?)
29
+ if outputs.empty?
31
30
  ui.warn 'No persistent output location defined. Printing export:'
32
31
  ui.info _format_json(result)
33
32
  end
34
33
  ui.info "#{ui.color('Stack export', :bold)} (#{name_args.first}): #{ui.color('complete', :green)}"
35
- unless(outputs.empty?)
34
+ unless outputs.empty?
36
35
  outputs.each do |output|
37
36
  ui.info ui.color(" -> #{output}", :blue)
38
37
  end
@@ -49,8 +48,8 @@ module Sfn
49
48
  # @return [String] file name
50
49
  def export_file_name(stack)
51
50
  name = config[:file]
52
- if(name)
53
- if(name.respond_to?(:call))
51
+ if name
52
+ if name.respond_to?(:call)
54
53
  name.call(stack)
55
54
  else
56
55
  name.to_s
@@ -67,16 +66,15 @@ module Sfn
67
66
  # @return [String, NilClass] path to file
68
67
  def write_to_file(payload, stack)
69
68
  raise NotImplementedError
70
- if(config[:path])
69
+ if config[:path]
71
70
  full_path = File.join(
72
71
  config[:path],
73
72
  export_file_name(stack)
74
73
  )
75
74
  _, bucket, path = full_path.split('/', 3)
76
75
  directory = provider.service_for(:storage,
77
- :provider => :local,
78
- :local_root => '/'
79
- ).directories.get(bucket)
76
+ :provider => :local,
77
+ :local_root => '/').directories.get(bucket)
80
78
  file_store(payload, path, directory)
81
79
  end
82
80
  end
@@ -88,16 +86,14 @@ module Sfn
88
86
  # @return [String, NilClass] remote bucket key
89
87
  def write_to_bucket(payload, stack)
90
88
  raise NotImplementedError
91
- if(bucket = config[:bucket])
89
+ if bucket = config[:bucket]
92
90
  key_path = File.join(*[
93
- bucket_prefix(stack),
94
- export_file_name(stack)
95
- ].compact
96
- )
91
+ bucket_prefix(stack),
92
+ export_file_name(stack),
93
+ ].compact)
97
94
  file_store(payload, key_path, provider.service_for(:storage).directories.get(bucket))
98
95
  end
99
96
  end
100
-
101
97
  end
102
98
  end
103
99
  end
@@ -5,7 +5,6 @@ module Sfn
5
5
  class Command
6
6
  # Graph command
7
7
  class Graph < Command
8
-
9
8
  autoload :Provider, 'sfn/command/graph/provider'
10
9
 
11
10
  include Sfn::CommandModule::Base
@@ -15,7 +14,7 @@ module Sfn
15
14
  # Valid graph styles
16
15
  GRAPH_STYLES = [
17
16
  'creation',
18
- 'dependency'
17
+ 'dependency',
19
18
  ]
20
19
 
21
20
  # Generate graph
@@ -24,13 +23,13 @@ module Sfn
24
23
  validate_graph_style!
25
24
  file = load_template_file
26
25
  provider = Bogo::Utility.camel(file.provider).to_sym
27
- if(Provider.constants.include?(provider))
26
+ if Provider.constants.include?(provider)
28
27
  graph_const = Provider.const_get(provider)
29
28
  ui.debug "Loading provider graph implementation - #{graph_const}"
30
29
  extend graph_const
31
30
  @outputs = Smash.new
32
31
  ui.info "Template resource graph generation - Style: #{ui.color(config[:graph_style], :bold)}"
33
- if(config[:file])
32
+ if config[:file]
34
33
  ui.puts " -> path: #{config[:file]}"
35
34
  end
36
35
  template_dump = file.compile.sparkle_dump!.to_smash
@@ -49,7 +48,7 @@ module Sfn
49
48
  end
50
49
  run_action 'Writing graph result' do
51
50
  FileUtils.mkdir_p(File.dirname(config[:output_file]))
52
- if(config[:output_type] == 'dot')
51
+ if config[:output_type] == 'dot'
53
52
  File.open("#{config[:output_file]}.dot", 'w') do |o_file|
54
53
  o_file.puts graph.to_s
55
54
  end
@@ -59,7 +58,7 @@ module Sfn
59
58
  nil
60
59
  end
61
60
  else
62
- valid_providers = Provider.constants.sort.map{ |provider|
61
+ valid_providers = Provider.constants.sort.map { |provider|
63
62
  Bogo::Utility.snake(provider)
64
63
  }.join('`, `')
65
64
  ui.error "Graphing for provider `#{file.provider}` not currently supported."
@@ -67,14 +66,14 @@ module Sfn
67
66
  end
68
67
  end
69
68
 
70
- def generate_graph(template, args={})
69
+ def generate_graph(template, args = {})
71
70
  graph = ::Graph.new
72
71
  @root_graph = graph unless @root_graph
73
72
  graph.graph_attribs << ::Graph::Attribute.new('overlap = false')
74
73
  graph.graph_attribs << ::Graph::Attribute.new('splines = true')
75
74
  graph.graph_attribs << ::Graph::Attribute.new('pack = true')
76
75
  graph.graph_attribs << ::Graph::Attribute.new('start = "random"')
77
- if(args[:name])
76
+ if args[:name]
78
77
  graph.name = "cluster_#{args[:name]}"
79
78
  labelnode_key = "cluster_#{args[:name]}"
80
79
  graph.plaintext << graph.node(labelnode_key)
@@ -88,7 +87,7 @@ module Sfn
88
87
 
89
88
  def colorize(string)
90
89
  hash = string.chars.inject(0) do |memo, chr|
91
- if(memo + chr.ord > 127)
90
+ if memo + chr.ord > 127
92
91
  (memo - chr.ord).abs
93
92
  else
94
93
  memo + chr.ord
@@ -98,7 +97,7 @@ module Sfn
98
97
  3.times do |i|
99
98
  color << (255 ^ hash).to_s(16)
100
99
  new_val = hash + (hash * (1 / (i + 1.to_f))).to_i
101
- if(hash * (i + 1) < 127)
100
+ if hash * (i + 1) < 127
102
101
  hash = new_val
103
102
  else
104
103
  hash = hash / (i + 1)
@@ -108,16 +107,15 @@ module Sfn
108
107
  end
109
108
 
110
109
  def validate_graph_style!
111
- if(config[:luckymike])
110
+ if config[:luckymike]
112
111
  ui.warn 'Detected luckymike power override. Forcing `dependency` style!'
113
112
  config[:graph_style] = 'dependency'
114
113
  end
115
114
  config[:graph_style] = config[:graph_style].to_s
116
- unless(GRAPH_STYLES.include?(config[:graph_style]))
115
+ unless GRAPH_STYLES.include?(config[:graph_style])
117
116
  raise ArgumentError.new "Invalid graph style provided `#{config[:graph_style]}`. Valid: `#{GRAPH_STYLES.join('`, `')}`"
118
117
  end
119
118
  end
120
-
121
119
  end
122
120
  end
123
121
  end