sfn 3.0.26 → 3.0.28

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1000514f95a36a106dc13fd6eaf7a38a9e716776
4
- data.tar.gz: fc0d733bafcd09198a2a56252c574956ded1ae22
3
+ metadata.gz: 403602f06deb39fe3f2751236c97dd6f06443431
4
+ data.tar.gz: 69f16806fb62a281b40d8f6588b4d5bf5772419d
5
5
  SHA512:
6
- metadata.gz: 7ef25e6f6722a338b428d5707dde1912d0c94a8c3adab30a297fe9ad830f0cbc415eff1130e3f824bcc0d46bd2f6e423259595f6093486dd3efe51d50e8d801c
7
- data.tar.gz: a179f76dd94173102a5e6d07fb20e91a4f689b21a02a6d79024d09bc10c373dee37403f8e15e7152692642de738c457039d76523c9a5c693408e195df8e2b4dc
6
+ metadata.gz: b36166fbdb2424563aec23d2c068616264582b25192ab4e377ae7312aa210d1565d721270af1885bc14196e4f56a05afa47afa1b926a815de278aa8c90591415
7
+ data.tar.gz: 710cf024266fbe9725150f0930756e28d5a284b85db61ad033b048e106fd90bc3cd94c3c8e4b316f474b65e2148acc3e02afa9b06c2b3f676f557cb48a09c07d
@@ -1,3 +1,8 @@
1
+ # v3.0.28
2
+ * [fix] Fix stack save policy callback (#264)
3
+ * [fix] Prevent processing unset event arrays
4
+ * [enhancement] Support graphing terraform provider templates
5
+
1
6
  # v3.0.26
2
7
  * [fix] Properly support compile time parameter setting with/without stack name (#261)
3
8
  * [fix] Default stack name when storing policy internally if no name provided
@@ -66,6 +66,5 @@ module Sfn
66
66
  end
67
67
 
68
68
  end
69
-
70
69
  end
71
70
  end
@@ -80,8 +80,8 @@ module Sfn
80
80
  @policies[p_stack.name]
81
81
  ).to_smash
82
82
  if(stack_policy)
83
- stack_policy[:statement].delete_if do |policy_item|
84
- policy_match = policy_item[:resource].to_s.match(
83
+ stack_policy[:Statement].delete_if do |policy_item|
84
+ policy_match = policy_item[:Resource].to_s.match(
85
85
  %r{LogicalResourceId/(?<logical_id>.+)$}
86
86
  )
87
87
  if(policy_match)
@@ -65,13 +65,13 @@ module Sfn
65
65
  # @return [TrueClass, FalseClass]
66
66
  def load_api_provider_extensions!
67
67
  if(config.get(:credentials, :provider))
68
- base_ext = Bogo::Utility.camel(config.get(:credentials, :provider))
68
+ base_ext = Bogo::Utility.camel(config.get(:credentials, :provider)).to_sym
69
69
  targ_ext = self.class.name.split('::').last
70
- if(ApiProvider.const_defined?(base_ext))
70
+ if(ApiProvider.constants.include?(base_ext))
71
71
  base_module = ApiProvider.const_get(base_ext)
72
72
  ui.debug "Loading core provider extensions via `#{base_module}`"
73
73
  extend base_module
74
- if(base_module.const_defined?(targ_ext))
74
+ if(base_module.constants.include?(targ_ext))
75
75
  targ_module = base_module.const_get(targ_ext)
76
76
  ui.debug "Loading targeted provider extensions via `#{targ_module}`"
77
77
  extend targ_module
@@ -63,6 +63,7 @@ module Sfn
63
63
  # @return [Array<Hash>]
64
64
  def get_events(*args)
65
65
  stack_events = discover_stacks(stack).map do |i_stack|
66
+ i_events = []
66
67
  begin
67
68
  if(@initial_complete && i_stack.in_progress?)
68
69
  i_events = i_stack.events.update!
@@ -73,12 +74,17 @@ module Sfn
73
74
  if(e.class.to_s.start_with?('Errno'))
74
75
  ui.warn "Connection error encountered: #{e.message} (retrying)"
75
76
  ui.debug "#{e.class}: #{e}\n#{e.backtrace.join("\n")}"
76
- sleep(5)
77
- retry
77
+ else
78
+ ui.error "Unexpected error received fetching events: #{e.message}"
79
+ ui.debug "#{e.class}: #{e}\n#{e.backtrace.join("\n")}"
78
80
  end
81
+ sleep(5)
82
+ retry
79
83
  end
80
- i_events.map do |e|
81
- e.attributes.merge(:stack_name => i_stack.name).to_smash
84
+ if(i_events)
85
+ i_events.map do |e|
86
+ e.attributes.merge(:stack_name => i_stack.name).to_smash
87
+ end
82
88
  end
83
89
  end.flatten.compact.find_all{|e| e[:time] }.reverse
84
90
  stack_events.delete_if{|evt| @seen_events.include?(evt)}
@@ -6,6 +6,8 @@ module Sfn
6
6
  # Graph command
7
7
  class Graph < Command
8
8
 
9
+ autoload :Provider, 'sfn/command/graph/provider'
10
+
9
11
  include Sfn::CommandModule::Base
10
12
  include Sfn::CommandModule::Template
11
13
  include Sfn::CommandModule::Stack
@@ -21,13 +23,17 @@ module Sfn
21
23
  config[:print_only] = true
22
24
  validate_graph_style!
23
25
  file = load_template_file
24
- if(file.provider == :aws)
26
+ provider = Bogo::Utility.camel(file.provider).to_sym
27
+ if(Provider.constants.include?(provider))
28
+ graph_const = Provider.const_get(provider)
29
+ ui.debug "Loading provider graph implementation - #{graph_const}"
30
+ extend graph_const
25
31
  @outputs = Smash.new
26
32
  ui.info "Template resource graph generation - Style: #{ui.color(config[:graph_style], :bold)}"
27
33
  if(config[:file])
28
34
  ui.puts " -> path: #{config[:file]}"
29
35
  end
30
- template_dump = file.compile.dump!.to_smash
36
+ template_dump = file.compile.sparkle_dump!.to_smash
31
37
  run_action 'Pre-processing template for graphing' do
32
38
  output_discovery(template_dump, @outputs, nil, nil)
33
39
  ui.debug 'Output remapping results from pre-processing:'
@@ -53,8 +59,11 @@ module Sfn
53
59
  nil
54
60
  end
55
61
  else
62
+ valid_providers = Provider.constants.sort.map{ |provider|
63
+ Bogo::Utility.snake(provider)
64
+ }.join('`, `')
56
65
  ui.error "Graphing for provider `#{file.provider}` not currently supported."
57
- ui.error "Currently supported providers: `aws`."
66
+ ui.error "Currently supported providers: `#{valid_providers}`."
58
67
  end
59
68
  end
60
69
 
@@ -77,137 +86,6 @@ module Sfn
77
86
  graph
78
87
  end
79
88
 
80
- def output_discovery(template, outputs, resource_name, parent_template, name='')
81
- if(template['Resources'])
82
- template['Resources'].keys.each do |r_name|
83
- r_info = template['Resources'][r_name]
84
- if(r_info['Type'] == 'AWS::CloudFormation::Stack')
85
- output_discovery(r_info['Properties']['Stack'], outputs, r_name, template, r_name)
86
- end
87
- end
88
- end
89
- if(parent_template)
90
- ui.debug "Pre-processing stack resource `#{resource_name}`"
91
- substack_parameters = Smash[
92
- parent_template.fetch('Resources', resource_name, 'Properties', 'Parameters', {}).map do |key, value|
93
- result = [key, value]
94
- if(value.is_a?(Hash))
95
- v_key = value.keys.first
96
- v_value = value.values.first
97
- if(v_key == 'Fn::GetAtt' && parent_template.fetch('Resources', {}).keys.include?(v_value.first) && v_value.last.start_with?('Outputs.'))
98
- output_key = v_value.first + '__' + v_value.last.split('.', 2).last
99
- ui.debug "Output key for check: #{output_key}"
100
- if(outputs.key?(output_key))
101
- new_value = outputs[output_key]
102
- result = [key, new_value]
103
- ui.debug "Parameter for output swap `#{key}`: #{value} -> #{new_value}"
104
- end
105
- end
106
- end
107
- result
108
- end
109
- ]
110
-
111
- ui.debug "Generated internal parameters for `#{resource_name}`: #{substack_parameters}"
112
-
113
- processor = GraphProcessor.new({},
114
- :parameters => substack_parameters
115
- )
116
- template['Resources'] = processor.dereference_processor(
117
- template['Resources'], ['Ref']
118
- )
119
- template['Outputs'] = processor.dereference_processor(
120
- template['Outputs'], ['Ref']
121
- )
122
- rename_processor = GraphProcessor.new({},
123
- :parameters => Smash[
124
- template.fetch('Resources', {}).keys.map do |r_key|
125
- [r_key, {'Ref' => [name, r_key].join}]
126
- end
127
- ]
128
- )
129
- derefed_outs = rename_processor.dereference_processor(
130
- template.fetch('Outputs', {})
131
- ) || {}
132
-
133
- derefed_outs.each do |o_name, o_data|
134
- o_key = [name, o_name].join('__')
135
- outputs[o_key] = o_data['Value']
136
- end
137
- end
138
- outputs.dup.each do |key, value|
139
- if(value.is_a?(Hash))
140
- v_key = value.keys.first
141
- v_value = value.values.first
142
- if(v_key == 'Fn::GetAtt' && v_value.last.start_with?('Outputs.'))
143
- output_key = v_value.first << '__' << v_value.last.split('.', 2).last
144
- if(outputs.key?(output_key))
145
- outputs[key] = outputs[output_key]
146
- end
147
- end
148
- end
149
- end
150
- end
151
-
152
- def edge_detection(template, graph, name = '', resource_names = [])
153
- resources = template.fetch('Resources', {})
154
- node_prefix = name
155
- resources.each do |resource_name, resource_data|
156
- node_name = [node_prefix, resource_name].join
157
- if(resource_data['Type'] == 'AWS::CloudFormation::Stack')
158
- graph.subgraph << generate_graph(
159
- resource_data['Properties'].delete('Stack'),
160
- :name => resource_name,
161
- :type => resource_data['Type'],
162
- :resource_names => resource_names
163
- )
164
- next
165
- else
166
- graph.node(node_name).attributes << graph.fillcolor(colorize(node_prefix.empty? ? config[:file] : node_prefix).inspect)
167
- graph.box3d << graph.node(node_name)
168
- end
169
- graph.filled << graph.node(node_name)
170
- graph.node(node_name).label "#{resource_name}\n<#{resource_data['Type']}>\n#{name}"
171
- resource_dependencies(resource_data, resource_names + resources.keys).each do |dep_name|
172
- if(resources.keys.include?(dep_name))
173
- dep_name = [node_prefix, dep_name].join
174
- end
175
- if(config[:graph_style] == 'creation')
176
- @root_graph.edge(dep_name, node_name)
177
- else
178
- @root_graph.edge(node_name, dep_name)
179
- end
180
- end
181
- end
182
- resource_names.concat resources.keys.map{|r_name| [node_prefix, r_name].join}
183
- end
184
-
185
- def resource_dependencies(data, names)
186
- case data
187
- when Hash
188
- data.map do |key, value|
189
- if(key == 'Ref' && names.include?(value))
190
- value
191
- elsif(key == 'DependsOn')
192
- [value].flatten.compact.find_all do |dependson_name|
193
- names.include?(dependson_name)
194
- end
195
- elsif(key == 'Fn::GetAtt' && names.include?(res = [value].flatten.compact.first))
196
- res
197
- else
198
- resource_dependencies(key, names) +
199
- resource_dependencies(value, names)
200
- end
201
- end.flatten.compact.uniq
202
- when Array
203
- data.map do |item|
204
- resource_dependencies(item, names)
205
- end.flatten.compact.uniq
206
- else
207
- []
208
- end
209
- end
210
-
211
89
  def colorize(string)
212
90
  hash = string.chars.inject(0) do |memo, chr|
213
91
  if(memo + chr.ord > 127)
@@ -240,38 +118,6 @@ module Sfn
240
118
  end
241
119
  end
242
120
 
243
- class GraphProcessor < SparkleFormation::Translation
244
- MAP = {}
245
- REF_MAPPING = {}
246
- FN_MAPPING = {}
247
-
248
- attr_accessor :name
249
-
250
- def initialize(template, args={})
251
- super
252
- @name = args[:name]
253
- end
254
-
255
- def apply_function(hash, funcs=[])
256
- k, v = hash.first
257
- if(hash.size == 1)
258
- case k
259
- when 'Ref'
260
- parameters.key?(v) ? parameters[v] : hash
261
- when 'Fn::Join'
262
- v.last
263
- when 'Fn::Select'
264
- v.last[v.first.to_i]
265
- else
266
- hash
267
- end
268
- else
269
- hash
270
- end
271
- end
272
-
273
- end
274
-
275
121
  end
276
122
  end
277
123
  end
@@ -0,0 +1,174 @@
1
+ require 'sfn'
2
+
3
+ module Sfn
4
+ class Command
5
+ # Graph command
6
+ class Graph < Command
7
+ module Provider
8
+ module Aws
9
+ class AwsGraphProcessor < SparkleFormation::Translation
10
+ MAP = {}
11
+ REF_MAPPING = {}
12
+ FN_MAPPING = {}
13
+
14
+ attr_accessor :name
15
+
16
+ def initialize(template, args={})
17
+ super
18
+ @name = args[:name]
19
+ end
20
+
21
+ def apply_function(hash, funcs=[])
22
+ k, v = hash.first
23
+ if(hash.size == 1)
24
+ case k
25
+ when 'Ref'
26
+ parameters.key?(v) ? parameters[v] : hash
27
+ when 'Fn::Join'
28
+ v.last
29
+ when 'Fn::Select'
30
+ v.last[v.first.to_i]
31
+ else
32
+ hash
33
+ end
34
+ else
35
+ hash
36
+ end
37
+ end
38
+ end
39
+
40
+ def output_discovery(template, outputs, resource_name, parent_template, name='')
41
+ if(template['Resources'])
42
+ template['Resources'].keys.each do |r_name|
43
+ r_info = template['Resources'][r_name]
44
+ if(r_info['Type'] == 'AWS::CloudFormation::Stack')
45
+ output_discovery(r_info['Properties']['Stack'], outputs, r_name, template, r_name)
46
+ end
47
+ end
48
+ end
49
+ if(parent_template)
50
+ ui.debug "Pre-processing stack resource `#{resource_name}`"
51
+ substack_parameters = Smash[
52
+ parent_template.fetch('Resources', resource_name, 'Properties', 'Parameters', {}).map do |key, value|
53
+ result = [key, value]
54
+ if(value.is_a?(Hash))
55
+ v_key = value.keys.first
56
+ v_value = value.values.first
57
+ if(v_key == 'Fn::GetAtt' && parent_template.fetch('Resources', {}).keys.include?(v_value.first) && v_value.last.start_with?('Outputs.'))
58
+ output_key = v_value.first + '__' + v_value.last.split('.', 2).last
59
+ ui.debug "Output key for check: #{output_key}"
60
+ if(outputs.key?(output_key))
61
+ new_value = outputs[output_key]
62
+ result = [key, new_value]
63
+ ui.debug "Parameter for output swap `#{key}`: #{value} -> #{new_value}"
64
+ end
65
+ end
66
+ end
67
+ result
68
+ end
69
+ ]
70
+
71
+ ui.debug "Generated internal parameters for `#{resource_name}`: #{substack_parameters}"
72
+
73
+ processor = AwsGraphProcessor.new({},
74
+ :parameters => substack_parameters
75
+ )
76
+ template['Resources'] = processor.dereference_processor(
77
+ template['Resources'], ['Ref']
78
+ )
79
+ template['Outputs'] = processor.dereference_processor(
80
+ template['Outputs'], ['Ref']
81
+ )
82
+ rename_processor = AwsGraphProcessor.new({},
83
+ :parameters => Smash[
84
+ template.fetch('Resources', {}).keys.map do |r_key|
85
+ [r_key, {'Ref' => [name, r_key].join}]
86
+ end
87
+ ]
88
+ )
89
+ derefed_outs = rename_processor.dereference_processor(
90
+ template.fetch('Outputs', {})
91
+ ) || {}
92
+
93
+ derefed_outs.each do |o_name, o_data|
94
+ o_key = [name, o_name].join('__')
95
+ outputs[o_key] = o_data['Value']
96
+ end
97
+ end
98
+ outputs.dup.each do |key, value|
99
+ if(value.is_a?(Hash))
100
+ v_key = value.keys.first
101
+ v_value = value.values.first
102
+ if(v_key == 'Fn::GetAtt' && v_value.last.start_with?('Outputs.'))
103
+ output_key = v_value.first << '__' << v_value.last.split('.', 2).last
104
+ if(outputs.key?(output_key))
105
+ outputs[key] = outputs[output_key]
106
+ end
107
+ end
108
+ end
109
+ end
110
+ end
111
+
112
+ def edge_detection(template, graph, name = '', resource_names = [])
113
+ resources = template.fetch('Resources', {})
114
+ node_prefix = name
115
+ resources.each do |resource_name, resource_data|
116
+ node_name = [node_prefix, resource_name].join
117
+ if(resource_data['Type'] == 'AWS::CloudFormation::Stack')
118
+ graph.subgraph << generate_graph(
119
+ resource_data['Properties'].delete('Stack'),
120
+ :name => resource_name,
121
+ :type => resource_data['Type'],
122
+ :resource_names => resource_names
123
+ )
124
+ next
125
+ else
126
+ graph.node(node_name).attributes << graph.fillcolor(colorize(node_prefix.empty? ? config[:file] : node_prefix).inspect)
127
+ graph.box3d << graph.node(node_name)
128
+ end
129
+ graph.filled << graph.node(node_name)
130
+ graph.node(node_name).label "#{resource_name}\n<#{resource_data['Type']}>\n#{name}"
131
+ resource_dependencies(resource_data, resource_names + resources.keys).each do |dep_name|
132
+ if(resources.keys.include?(dep_name))
133
+ dep_name = [node_prefix, dep_name].join
134
+ end
135
+ if(config[:graph_style] == 'creation')
136
+ @root_graph.edge(dep_name, node_name)
137
+ else
138
+ @root_graph.edge(node_name, dep_name)
139
+ end
140
+ end
141
+ end
142
+ resource_names.concat resources.keys.map{|r_name| [node_prefix, r_name].join}
143
+ end
144
+
145
+ def resource_dependencies(data, names)
146
+ case data
147
+ when Hash
148
+ data.map do |key, value|
149
+ if(key == 'Ref' && names.include?(value))
150
+ value
151
+ elsif(key == 'DependsOn')
152
+ [value].flatten.compact.find_all do |dependson_name|
153
+ names.include?(dependson_name)
154
+ end
155
+ elsif(key == 'Fn::GetAtt' && names.include?(res = [value].flatten.compact.first))
156
+ res
157
+ else
158
+ resource_dependencies(key, names) +
159
+ resource_dependencies(value, names)
160
+ end
161
+ end.flatten.compact.uniq
162
+ when Array
163
+ data.map do |item|
164
+ resource_dependencies(item, names)
165
+ end.flatten.compact.uniq
166
+ else
167
+ []
168
+ end
169
+ end
170
+ end
171
+ end
172
+ end
173
+ end
174
+ end
@@ -0,0 +1,13 @@
1
+ require 'sfn'
2
+
3
+ module Sfn
4
+ class Command
5
+ # Graph command
6
+ class Graph < Command
7
+ module Provider
8
+ autoload :Aws, "sfn/command/graph/aws"
9
+ autoload :Terraform, "sfn/command/graph/terraform"
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,193 @@
1
+ require 'sfn'
2
+
3
+ module Sfn
4
+ class Command
5
+ # Graph command
6
+ class Graph < Command
7
+ module Provider
8
+ module Terraform
9
+ class TerraformGraphProcessor < SparkleFormation::Translation
10
+ MAP = {}
11
+ REF_MAPPING = {}
12
+ FN_MAPPING = {}
13
+
14
+ attr_accessor :name
15
+
16
+ def initialize(template, args={})
17
+ super
18
+ @name = args[:name]
19
+ end
20
+
21
+ def dereference_processor(obj, funcs=[])
22
+ case obj
23
+ when Array
24
+ obj = obj.map{|v| dereference_processor(v, funcs)}
25
+ when Hash
26
+ new_hash = {}
27
+ obj.each do |k, v|
28
+ new_hash[k] = dereference_processor(v, funcs)
29
+ end
30
+ obj = new_hash
31
+ when String
32
+ obj = apply_function(obj, funcs)
33
+ end
34
+ obj
35
+ end
36
+
37
+ def parameters
38
+ Hash[
39
+ @original.fetch('parameters', {}).map do |k, v|
40
+ [k, v.fetch('default', '')]
41
+ end
42
+ ].merge(@parameters)
43
+ end
44
+
45
+ def resources
46
+ @original.fetch('resources', {})
47
+ end
48
+
49
+ def outputs
50
+ @original.fetch('outputs', {})
51
+ end
52
+
53
+ def apply_function(string, funcs=[])
54
+ # first check for vars and replace with params
55
+ string.scan(/(\$\{var\.(.+?)\})/).each do |match|
56
+ if(parameters[match.last])
57
+ string.sub!(match.first, parameters[match.last])
58
+ end
59
+ end
60
+ string
61
+ end
62
+ end
63
+
64
+ def output_discovery(template, outputs, resource_name, parent_template, name='')
65
+ if(template['resources'])
66
+ template['resources'].keys.each do |r_name|
67
+ r_info = template['resources'][r_name]
68
+ if(r_info['type'] == 'module')
69
+ output_discovery(r_info['properties']['stack'], outputs, r_name, template, r_name)
70
+ end
71
+ end
72
+ end
73
+ if(parent_template)
74
+ ui.debug "Pre-processing stack resource `#{resource_name}`"
75
+ substack_parameters = Smash[
76
+ parent_template.fetch('resources', resource_name, 'properties', 'parameters', {}).map do |key, value|
77
+ result = [key, value]
78
+ if(value.to_s.start_with?('${module.'))
79
+ output_key = value.sub('${module.', '').sub('}', '').sub('.', '__')
80
+ ui.debug "Output key for check: #{output_key}"
81
+ if(outputs.key?(output_key))
82
+ new_value = outputs[output_key]
83
+ result = [key, new_value]
84
+ ui.debug "Parameter for output swap `#{key}`: #{value} -> #{new_value}"
85
+ end
86
+ end
87
+ result
88
+ end
89
+ ]
90
+
91
+ ui.debug "Generated internal parameters for `#{resource_name}`: #{substack_parameters}"
92
+
93
+ processor = TerraformGraphProcessor.new({},
94
+ :parameters => substack_parameters
95
+ )
96
+ template['resources'] = processor.dereference_processor(
97
+ template['resources'], []
98
+ )
99
+ template['outputs'] = processor.dereference_processor(
100
+ template['outputs'], []
101
+ )
102
+ derefed_outs = template['outputs'] || {}
103
+ derefed_outs.each do |o_name, o_data|
104
+ o_key = [name, o_name].join('__')
105
+ val = o_data['value']
106
+ if(val.start_with?('${') && val.scan('.').count == 2)
107
+ val = val.split('.')
108
+ val[1] = "#{name}__#{val[1]}"
109
+ val = val.join('.')
110
+ end
111
+ outputs[o_key] = val
112
+ end
113
+ end
114
+ outputs.dup.each do |key, value|
115
+ if(value.to_s.start_with?('${module.'))
116
+ output_key = value.to_s.sub('${module.', '').sub('}', '').sub('.', '__')
117
+ if(outputs.key?(output_key))
118
+ outputs[key] = outputs[output_key]
119
+ end
120
+ end
121
+ end
122
+ end
123
+
124
+ def edge_detection(template, graph, name = '', resource_names = [])
125
+ resources = (template.fetch('resources', {}) || {})
126
+ node_prefix = name
127
+ resources.each do |resource_name, resource_data|
128
+ node_name = [node_prefix, resource_name].join('__')
129
+ if(resource_data['type'] == 'module')
130
+ graph.subgraph << generate_graph(
131
+ resource_data['properties'].delete('stack'),
132
+ :name => resource_name,
133
+ :type => resource_data['type'],
134
+ :resource_names => resource_names
135
+ )
136
+ next
137
+ else
138
+ graph.node(node_name).attributes << graph.fillcolor(colorize(node_prefix.empty? ? config[:file] : node_prefix).inspect)
139
+ graph.box3d << graph.node(node_name)
140
+ end
141
+ graph.filled << graph.node(node_name)
142
+ graph.node(node_name).label "#{resource_name}\n<#{resource_data['type']}>\n#{name}"
143
+ resource_dependencies(resource_data, resource_names + resources.keys).each do |dep_name|
144
+ if(resources.keys.include?(dep_name))
145
+ dep_name = [node_prefix, dep_name].join('__')
146
+ end
147
+ if(config[:graph_style] == 'creation')
148
+ @root_graph.edge(dep_name, node_name)
149
+ else
150
+ @root_graph.edge(node_name, dep_name)
151
+ end
152
+ end
153
+ end
154
+ resource_names.concat resources.keys.map{|r_name| [node_prefix, r_name].join('__')}
155
+ end
156
+
157
+ def resource_dependencies(data, names)
158
+ case data
159
+ when String
160
+ result = []
161
+ if(data.start_with?('${') && data.scan('.').count >= 1)
162
+ data = data.tr('${}', '')
163
+ check_name = data.split('.')[1]
164
+ if names.include?(check_name)
165
+ result.push(check_name)
166
+ end
167
+ end
168
+ result
169
+ when Hash
170
+ data.map do |key, value|
171
+ if(key == 'depends_on')
172
+ [value].flatten.compact.map do |dependson_name|
173
+ dep_name = dependson_name.split('.').last
174
+ dep_name if names.include?(dep_name)
175
+ end
176
+ else
177
+ resource_dependencies(key, names) +
178
+ resource_dependencies(value, names)
179
+ end
180
+ end.flatten.compact.uniq
181
+ when Array
182
+ data.map do |item|
183
+ resource_dependencies(item, names)
184
+ end.flatten.compact.uniq
185
+ else
186
+ []
187
+ end
188
+ end
189
+ end
190
+ end
191
+ end
192
+ end
193
+ end
@@ -1,4 +1,4 @@
1
1
  module Sfn
2
2
  # Current library version
3
- VERSION = Gem::Version.new('3.0.26')
3
+ VERSION = Gem::Version.new('3.0.28')
4
4
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sfn
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.26
4
+ version: 3.0.28
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Roberts
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-06-25 00:00:00.000000000 Z
11
+ date: 2017-09-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bogo-cli
@@ -409,6 +409,9 @@ files:
409
409
  - lib/sfn/command/events.rb
410
410
  - lib/sfn/command/export.rb
411
411
  - lib/sfn/command/graph.rb
412
+ - lib/sfn/command/graph/aws.rb
413
+ - lib/sfn/command/graph/provider.rb
414
+ - lib/sfn/command/graph/terraform.rb
412
415
  - lib/sfn/command/import.rb
413
416
  - lib/sfn/command/init.rb
414
417
  - lib/sfn/command/inspect.rb
@@ -484,7 +487,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
484
487
  version: '0'
485
488
  requirements: []
486
489
  rubyforge_project:
487
- rubygems_version: 2.4.8
490
+ rubygems_version: 2.6.11
488
491
  signing_key:
489
492
  specification_version: 4
490
493
  summary: SparkleFormation CLI