sfn 3.0.30 → 3.0.32
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/bin/sfn +16 -14
- data/lib/chef/knife/knife_plugin_seed.rb +12 -12
- data/lib/sfn.rb +17 -17
- data/lib/sfn/api_provider.rb +3 -3
- data/lib/sfn/api_provider/google.rb +2 -2
- data/lib/sfn/api_provider/terraform.rb +2 -2
- data/lib/sfn/cache.rb +9 -9
- data/lib/sfn/callback.rb +6 -6
- data/lib/sfn/callback/aws_assume_role.rb +5 -5
- data/lib/sfn/callback/aws_mfa.rb +8 -6
- data/lib/sfn/callback/stack_policy.rb +15 -15
- data/lib/sfn/command.rb +37 -36
- data/lib/sfn/command/conf.rb +12 -12
- data/lib/sfn/command/create.rb +9 -9
- data/lib/sfn/command/describe.rb +6 -6
- data/lib/sfn/command/destroy.rb +8 -8
- data/lib/sfn/command/diff.rb +31 -31
- data/lib/sfn/command/events.rb +6 -6
- data/lib/sfn/command/export.rb +8 -8
- data/lib/sfn/command/graph.rb +21 -21
- data/lib/sfn/command/graph/aws.rb +34 -34
- data/lib/sfn/command/graph/provider.rb +1 -1
- data/lib/sfn/command/graph/terraform.rb +41 -41
- data/lib/sfn/command/import.rb +17 -17
- data/lib/sfn/command/init.rb +15 -15
- data/lib/sfn/command/inspect.rb +16 -16
- data/lib/sfn/command/lint.rb +6 -6
- data/lib/sfn/command/list.rb +2 -2
- data/lib/sfn/command/plan.rb +227 -0
- data/lib/sfn/command/print.rb +4 -4
- data/lib/sfn/command/promote.rb +2 -2
- data/lib/sfn/command/update.rb +19 -144
- data/lib/sfn/command/validate.rb +17 -13
- data/lib/sfn/command_module.rb +6 -5
- data/lib/sfn/command_module/base.rb +8 -8
- data/lib/sfn/command_module/callbacks.rb +5 -5
- data/lib/sfn/command_module/planning.rb +151 -0
- data/lib/sfn/command_module/stack.rb +34 -34
- data/lib/sfn/command_module/template.rb +50 -50
- data/lib/sfn/config.rb +46 -44
- data/lib/sfn/config/conf.rb +3 -3
- data/lib/sfn/config/create.rb +9 -9
- data/lib/sfn/config/describe.rb +7 -7
- data/lib/sfn/config/destroy.rb +1 -1
- data/lib/sfn/config/diff.rb +3 -3
- data/lib/sfn/config/events.rb +9 -9
- data/lib/sfn/config/export.rb +5 -5
- data/lib/sfn/config/graph.rb +10 -10
- data/lib/sfn/config/import.rb +4 -4
- data/lib/sfn/config/init.rb +1 -1
- data/lib/sfn/config/inspect.rb +16 -16
- data/lib/sfn/config/lint.rb +5 -5
- data/lib/sfn/config/list.rb +6 -6
- data/lib/sfn/config/plan.rb +28 -0
- data/lib/sfn/config/print.rb +5 -5
- data/lib/sfn/config/promote.rb +4 -4
- data/lib/sfn/config/update.rb +18 -18
- data/lib/sfn/config/validate.rb +30 -30
- data/lib/sfn/lint.rb +5 -5
- data/lib/sfn/lint/definition.rb +3 -3
- data/lib/sfn/lint/rule.rb +3 -3
- data/lib/sfn/lint/rule_set.rb +2 -2
- data/lib/sfn/monkey_patch.rb +2 -2
- data/lib/sfn/monkey_patch/stack.rb +27 -27
- data/lib/sfn/monkey_patch/stack/azure.rb +1 -1
- data/lib/sfn/monkey_patch/stack/google.rb +5 -5
- data/lib/sfn/planner.rb +4 -4
- data/lib/sfn/planner/aws.rb +114 -70
- data/lib/sfn/provider.rb +13 -13
- data/lib/sfn/utils.rb +10 -10
- data/lib/sfn/utils/debug.rb +2 -2
- data/lib/sfn/utils/json.rb +1 -1
- data/lib/sfn/utils/object_storage.rb +3 -3
- data/lib/sfn/utils/output.rb +4 -4
- data/lib/sfn/utils/path_selector.rb +15 -15
- data/lib/sfn/utils/ssher.rb +4 -4
- data/lib/sfn/utils/stack_exporter.rb +16 -16
- data/lib/sfn/utils/stack_parameter_scrubber.rb +6 -6
- data/lib/sfn/utils/stack_parameter_validator.rb +22 -22
- data/lib/sfn/version.rb +1 -1
- data/sfn.gemspec +32 -32
- metadata +16 -13
data/lib/sfn/command/events.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "sfn"
|
2
2
|
|
3
3
|
module Sfn
|
4
4
|
class Command
|
@@ -25,7 +25,7 @@ module Sfn
|
|
25
25
|
allowed_attributes.each do |attr|
|
26
26
|
width_val = events.map { |e| e[attr].to_s.length }.push(attr.length).max + 2
|
27
27
|
width_val = width_val > 70 ? 70 : width_val < 20 ? 20 : width_val
|
28
|
-
column attr.split(
|
28
|
+
column attr.split("_").map(&:capitalize).join(" "), :width => width_val
|
29
29
|
end
|
30
30
|
end
|
31
31
|
events.each do |event|
|
@@ -70,7 +70,7 @@ module Sfn
|
|
70
70
|
i_events = i_stack.events.all
|
71
71
|
end
|
72
72
|
rescue => e
|
73
|
-
if e.class.to_s.start_with?(
|
73
|
+
if e.class.to_s.start_with?("Errno")
|
74
74
|
ui.warn "Connection error encountered: #{e.message} (retrying)"
|
75
75
|
ui.debug "#{e.class}: #{e}\n#{e.backtrace.join("\n")}"
|
76
76
|
else
|
@@ -93,8 +93,8 @@ module Sfn
|
|
93
93
|
unless config[:all_events]
|
94
94
|
start_index = stack_events.rindex do |item|
|
95
95
|
item[:stack_name] == stack.name &&
|
96
|
-
item[:resource_state].to_s.end_with?(
|
97
|
-
item[:resource_status_reason].to_s.downcase.include?(
|
96
|
+
item[:resource_state].to_s.end_with?("in_progress") &&
|
97
|
+
item[:resource_status_reason].to_s.downcase.include?("user init")
|
98
98
|
end
|
99
99
|
if start_index
|
100
100
|
stack_events.slice!(0, start_index)
|
@@ -121,7 +121,7 @@ module Sfn
|
|
121
121
|
def allowed_attributes
|
122
122
|
result = super
|
123
123
|
unless @stacks.size > 1
|
124
|
-
result.delete(
|
124
|
+
result.delete("stack_name")
|
125
125
|
end
|
126
126
|
result
|
127
127
|
end
|
data/lib/sfn/command/export.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "sfn"
|
2
2
|
|
3
3
|
module Sfn
|
4
4
|
class Command
|
@@ -9,10 +9,10 @@ module Sfn
|
|
9
9
|
|
10
10
|
# Run export action
|
11
11
|
def execute!
|
12
|
-
raise NotImplementedError.new
|
12
|
+
raise NotImplementedError.new "Implementation updates required"
|
13
13
|
stack_name = name_args.first
|
14
|
-
ui.info "#{ui.color(
|
15
|
-
ui.confirm
|
14
|
+
ui.info "#{ui.color("Stack Export:", :bold)} #{stack_name}"
|
15
|
+
ui.confirm "Perform export"
|
16
16
|
stack = provider.stacks.get(stack_name)
|
17
17
|
if stack
|
18
18
|
export_options = Smash.new.tap do |opts|
|
@@ -27,10 +27,10 @@ module Sfn
|
|
27
27
|
write_to_bucket(result, stack),
|
28
28
|
].compact
|
29
29
|
if outputs.empty?
|
30
|
-
ui.warn
|
30
|
+
ui.warn "No persistent output location defined. Printing export:"
|
31
31
|
ui.info _format_json(result)
|
32
32
|
end
|
33
|
-
ui.info "#{ui.color(
|
33
|
+
ui.info "#{ui.color("Stack export", :bold)} (#{name_args.first}): #{ui.color("complete", :green)}"
|
34
34
|
unless outputs.empty?
|
35
35
|
outputs.each do |output|
|
36
36
|
ui.info ui.color(" -> #{output}", :blue)
|
@@ -71,10 +71,10 @@ module Sfn
|
|
71
71
|
config[:path],
|
72
72
|
export_file_name(stack)
|
73
73
|
)
|
74
|
-
_, bucket, path = full_path.split(
|
74
|
+
_, bucket, path = full_path.split("/", 3)
|
75
75
|
directory = provider.service_for(:storage,
|
76
76
|
:provider => :local,
|
77
|
-
:local_root =>
|
77
|
+
:local_root => "/").directories.get(bucket)
|
78
78
|
file_store(payload, path, directory)
|
79
79
|
end
|
80
80
|
end
|
data/lib/sfn/command/graph.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require "sfn"
|
2
|
+
require "graph"
|
3
3
|
|
4
4
|
module Sfn
|
5
5
|
class Command
|
6
6
|
# Graph command
|
7
7
|
class Graph < Command
|
8
|
-
autoload :Provider,
|
8
|
+
autoload :Provider, "sfn/command/graph/provider"
|
9
9
|
|
10
10
|
include Sfn::CommandModule::Base
|
11
11
|
include Sfn::CommandModule::Template
|
@@ -13,8 +13,8 @@ module Sfn
|
|
13
13
|
|
14
14
|
# Valid graph styles
|
15
15
|
GRAPH_STYLES = [
|
16
|
-
|
17
|
-
|
16
|
+
"creation",
|
17
|
+
"dependency",
|
18
18
|
]
|
19
19
|
|
20
20
|
# Generate graph
|
@@ -33,23 +33,23 @@ module Sfn
|
|
33
33
|
ui.puts " -> path: #{config[:file]}"
|
34
34
|
end
|
35
35
|
template_dump = file.compile.sparkle_dump!.to_smash
|
36
|
-
run_action
|
36
|
+
run_action "Pre-processing template for graphing" do
|
37
37
|
output_discovery(template_dump, @outputs, nil, nil)
|
38
|
-
ui.debug
|
38
|
+
ui.debug "Output remapping results from pre-processing:"
|
39
39
|
@outputs.each_pair do |o_key, o_value|
|
40
40
|
ui.debug "#{o_key} -> #{o_value}"
|
41
41
|
end
|
42
42
|
nil
|
43
43
|
end
|
44
44
|
graph = nil
|
45
|
-
run_action
|
45
|
+
run_action "Generating resource graph" do
|
46
46
|
graph = generate_graph(template_dump)
|
47
47
|
nil
|
48
48
|
end
|
49
|
-
run_action
|
49
|
+
run_action "Writing graph result" do
|
50
50
|
FileUtils.mkdir_p(File.dirname(config[:output_file]))
|
51
|
-
if config[:output_type] ==
|
52
|
-
File.open("#{config[:output_file]}.dot",
|
51
|
+
if config[:output_type] == "dot"
|
52
|
+
File.open("#{config[:output_file]}.dot", "w") do |o_file|
|
53
53
|
o_file.puts graph.to_s
|
54
54
|
end
|
55
55
|
else
|
@@ -60,7 +60,7 @@ module Sfn
|
|
60
60
|
else
|
61
61
|
valid_providers = Provider.constants.sort.map { |provider|
|
62
62
|
Bogo::Utility.snake(provider)
|
63
|
-
}.join(
|
63
|
+
}.join("`, `")
|
64
64
|
ui.error "Graphing for provider `#{file.provider}` not currently supported."
|
65
65
|
ui.error "Currently supported providers: `#{valid_providers}`."
|
66
66
|
end
|
@@ -69,9 +69,9 @@ module Sfn
|
|
69
69
|
def generate_graph(template, args = {})
|
70
70
|
graph = ::Graph.new
|
71
71
|
@root_graph = graph unless @root_graph
|
72
|
-
graph.graph_attribs << ::Graph::Attribute.new(
|
73
|
-
graph.graph_attribs << ::Graph::Attribute.new(
|
74
|
-
graph.graph_attribs << ::Graph::Attribute.new(
|
72
|
+
graph.graph_attribs << ::Graph::Attribute.new("overlap = false")
|
73
|
+
graph.graph_attribs << ::Graph::Attribute.new("splines = true")
|
74
|
+
graph.graph_attribs << ::Graph::Attribute.new("pack = true")
|
75
75
|
graph.graph_attribs << ::Graph::Attribute.new('start = "random"')
|
76
76
|
if args[:name]
|
77
77
|
graph.name = "cluster_#{args[:name]}"
|
@@ -79,9 +79,9 @@ module Sfn
|
|
79
79
|
graph.plaintext << graph.node(labelnode_key)
|
80
80
|
graph.node(labelnode_key).label args[:name]
|
81
81
|
else
|
82
|
-
graph.name =
|
82
|
+
graph.name = "root"
|
83
83
|
end
|
84
|
-
edge_detection(template, graph, args[:name].to_s.sub(
|
84
|
+
edge_detection(template, graph, args[:name].to_s.sub("cluster_", ""), args.fetch(:resource_names, []))
|
85
85
|
graph
|
86
86
|
end
|
87
87
|
|
@@ -93,7 +93,7 @@ module Sfn
|
|
93
93
|
memo + chr.ord
|
94
94
|
end
|
95
95
|
end
|
96
|
-
color =
|
96
|
+
color = "#"
|
97
97
|
3.times do |i|
|
98
98
|
color << (255 ^ hash).to_s(16)
|
99
99
|
new_val = hash + (hash * (1 / (i + 1.to_f))).to_i
|
@@ -108,12 +108,12 @@ module Sfn
|
|
108
108
|
|
109
109
|
def validate_graph_style!
|
110
110
|
if config[:luckymike]
|
111
|
-
ui.warn
|
112
|
-
config[:graph_style] =
|
111
|
+
ui.warn "Detected luckymike power override. Forcing `dependency` style!"
|
112
|
+
config[:graph_style] = "dependency"
|
113
113
|
end
|
114
114
|
config[:graph_style] = config[:graph_style].to_s
|
115
115
|
unless GRAPH_STYLES.include?(config[:graph_style])
|
116
|
-
raise ArgumentError.new "Invalid graph style provided `#{config[:graph_style]}`. Valid: `#{GRAPH_STYLES.join(
|
116
|
+
raise ArgumentError.new "Invalid graph style provided `#{config[:graph_style]}`. Valid: `#{GRAPH_STYLES.join("`, `")}`"
|
117
117
|
end
|
118
118
|
end
|
119
119
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "sfn"
|
2
2
|
|
3
3
|
module Sfn
|
4
4
|
class Command
|
@@ -22,11 +22,11 @@ module Sfn
|
|
22
22
|
k, v = hash.first
|
23
23
|
if hash.size == 1
|
24
24
|
case k
|
25
|
-
when
|
25
|
+
when "Ref"
|
26
26
|
parameters.key?(v) ? parameters[v] : hash
|
27
|
-
when
|
27
|
+
when "Fn::Join"
|
28
28
|
v.last
|
29
|
-
when
|
29
|
+
when "Fn::Select"
|
30
30
|
v.last[v.first.to_i]
|
31
31
|
else
|
32
32
|
hash
|
@@ -37,25 +37,25 @@ module Sfn
|
|
37
37
|
end
|
38
38
|
end
|
39
39
|
|
40
|
-
def output_discovery(template, outputs, resource_name, parent_template, name =
|
41
|
-
if template[
|
42
|
-
template[
|
43
|
-
r_info = template[
|
44
|
-
if r_info[
|
45
|
-
output_discovery(r_info[
|
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
46
|
end
|
47
47
|
end
|
48
48
|
end
|
49
49
|
if parent_template
|
50
50
|
ui.debug "Pre-processing stack resource `#{resource_name}`"
|
51
51
|
substack_parameters = Smash[
|
52
|
-
parent_template.fetch(
|
52
|
+
parent_template.fetch("Resources", resource_name, "Properties", "Parameters", {}).map do |key, value|
|
53
53
|
result = [key, value]
|
54
54
|
if value.is_a?(Hash)
|
55
55
|
v_key = value.keys.first
|
56
56
|
v_value = value.values.first
|
57
|
-
if v_key ==
|
58
|
-
output_key = v_value.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
59
|
ui.debug "Output key for check: #{output_key}"
|
60
60
|
if outputs.key?(output_key)
|
61
61
|
new_value = outputs[output_key]
|
@@ -72,33 +72,33 @@ module Sfn
|
|
72
72
|
|
73
73
|
processor = AwsGraphProcessor.new({},
|
74
74
|
:parameters => substack_parameters)
|
75
|
-
template[
|
76
|
-
template[
|
75
|
+
template["Resources"] = processor.dereference_processor(
|
76
|
+
template["Resources"], ["Ref"]
|
77
77
|
)
|
78
|
-
template[
|
79
|
-
template[
|
78
|
+
template["Outputs"] = processor.dereference_processor(
|
79
|
+
template["Outputs"], ["Ref"]
|
80
80
|
)
|
81
81
|
rename_processor = AwsGraphProcessor.new({},
|
82
82
|
:parameters => Smash[
|
83
|
-
template.fetch(
|
84
|
-
[r_key, {
|
83
|
+
template.fetch("Resources", {}).keys.map do |r_key|
|
84
|
+
[r_key, {"Ref" => [name, r_key].join}]
|
85
85
|
end
|
86
86
|
])
|
87
87
|
derefed_outs = rename_processor.dereference_processor(
|
88
|
-
template.fetch(
|
88
|
+
template.fetch("Outputs", {})
|
89
89
|
) || {}
|
90
90
|
|
91
91
|
derefed_outs.each do |o_name, o_data|
|
92
|
-
o_key = [name, o_name].join(
|
93
|
-
outputs[o_key] = o_data[
|
92
|
+
o_key = [name, o_name].join("__")
|
93
|
+
outputs[o_key] = o_data["Value"]
|
94
94
|
end
|
95
95
|
end
|
96
96
|
outputs.dup.each do |key, value|
|
97
97
|
if value.is_a?(Hash)
|
98
98
|
v_key = value.keys.first
|
99
99
|
v_value = value.values.first
|
100
|
-
if v_key ==
|
101
|
-
output_key = v_value.first <<
|
100
|
+
if v_key == "Fn::GetAtt" && v_value.last.start_with?("Outputs.")
|
101
|
+
output_key = v_value.first << "__" << v_value.last.split(".", 2).last
|
102
102
|
if outputs.key?(output_key)
|
103
103
|
outputs[key] = outputs[output_key]
|
104
104
|
end
|
@@ -107,16 +107,16 @@ module Sfn
|
|
107
107
|
end
|
108
108
|
end
|
109
109
|
|
110
|
-
def edge_detection(template, graph, name =
|
111
|
-
resources = template.fetch(
|
110
|
+
def edge_detection(template, graph, name = "", resource_names = [])
|
111
|
+
resources = template.fetch("Resources", {})
|
112
112
|
node_prefix = name
|
113
113
|
resources.each do |resource_name, resource_data|
|
114
114
|
node_name = [node_prefix, resource_name].join
|
115
|
-
if resource_data[
|
115
|
+
if resource_data["Type"] == "AWS::CloudFormation::Stack"
|
116
116
|
graph.subgraph << generate_graph(
|
117
|
-
resource_data[
|
117
|
+
resource_data["Properties"].delete("Stack"),
|
118
118
|
:name => resource_name,
|
119
|
-
:type => resource_data[
|
119
|
+
:type => resource_data["Type"],
|
120
120
|
:resource_names => resource_names,
|
121
121
|
)
|
122
122
|
next
|
@@ -125,12 +125,12 @@ module Sfn
|
|
125
125
|
graph.box3d << graph.node(node_name)
|
126
126
|
end
|
127
127
|
graph.filled << graph.node(node_name)
|
128
|
-
graph.node(node_name).label "#{resource_name}\n<#{resource_data[
|
128
|
+
graph.node(node_name).label "#{resource_name}\n<#{resource_data["Type"]}>\n#{name}"
|
129
129
|
resource_dependencies(resource_data, resource_names + resources.keys).each do |dep_name|
|
130
130
|
if resources.keys.include?(dep_name)
|
131
131
|
dep_name = [node_prefix, dep_name].join
|
132
132
|
end
|
133
|
-
if config[:graph_style] ==
|
133
|
+
if config[:graph_style] == "creation"
|
134
134
|
@root_graph.edge(dep_name, node_name)
|
135
135
|
else
|
136
136
|
@root_graph.edge(node_name, dep_name)
|
@@ -144,13 +144,13 @@ module Sfn
|
|
144
144
|
case data
|
145
145
|
when Hash
|
146
146
|
data.map do |key, value|
|
147
|
-
if key ==
|
147
|
+
if key == "Ref" && names.include?(value)
|
148
148
|
value
|
149
|
-
elsif key ==
|
149
|
+
elsif key == "DependsOn"
|
150
150
|
[value].flatten.compact.find_all do |dependson_name|
|
151
151
|
names.include?(dependson_name)
|
152
152
|
end
|
153
|
-
elsif key ==
|
153
|
+
elsif key == "Fn::GetAtt" && names.include?(res = [value].flatten.compact.first)
|
154
154
|
res
|
155
155
|
else
|
156
156
|
resource_dependencies(key, names) +
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "sfn"
|
2
2
|
|
3
3
|
module Sfn
|
4
4
|
class Command
|
@@ -36,18 +36,18 @@ module Sfn
|
|
36
36
|
|
37
37
|
def parameters
|
38
38
|
Hash[
|
39
|
-
@original.fetch(
|
40
|
-
[k, v.fetch(
|
39
|
+
@original.fetch("parameters", {}).map do |k, v|
|
40
|
+
[k, v.fetch("default", "")]
|
41
41
|
end
|
42
42
|
].merge(@parameters)
|
43
43
|
end
|
44
44
|
|
45
45
|
def resources
|
46
|
-
@original.fetch(
|
46
|
+
@original.fetch("resources", {})
|
47
47
|
end
|
48
48
|
|
49
49
|
def outputs
|
50
|
-
@original.fetch(
|
50
|
+
@original.fetch("outputs", {})
|
51
51
|
end
|
52
52
|
|
53
53
|
def apply_function(string, funcs = [])
|
@@ -61,22 +61,22 @@ module Sfn
|
|
61
61
|
end
|
62
62
|
end
|
63
63
|
|
64
|
-
def output_discovery(template, outputs, resource_name, parent_template, name =
|
65
|
-
if template[
|
66
|
-
template[
|
67
|
-
r_info = template[
|
68
|
-
if r_info[
|
69
|
-
output_discovery(r_info[
|
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
70
|
end
|
71
71
|
end
|
72
72
|
end
|
73
73
|
if parent_template
|
74
74
|
ui.debug "Pre-processing stack resource `#{resource_name}`"
|
75
75
|
substack_parameters = Smash[
|
76
|
-
parent_template.fetch(
|
76
|
+
parent_template.fetch("resources", resource_name, "properties", "parameters", {}).map do |key, value|
|
77
77
|
result = [key, value]
|
78
|
-
if value.to_s.start_with?(
|
79
|
-
output_key = value.sub(
|
78
|
+
if value.to_s.start_with?("${module.")
|
79
|
+
output_key = value.sub("${module.", "").sub("}", "").sub(".", "__")
|
80
80
|
ui.debug "Output key for check: #{output_key}"
|
81
81
|
if outputs.key?(output_key)
|
82
82
|
new_value = outputs[output_key]
|
@@ -92,27 +92,27 @@ module Sfn
|
|
92
92
|
|
93
93
|
processor = TerraformGraphProcessor.new({},
|
94
94
|
:parameters => substack_parameters)
|
95
|
-
template[
|
96
|
-
template[
|
95
|
+
template["resources"] = processor.dereference_processor(
|
96
|
+
template["resources"], []
|
97
97
|
)
|
98
|
-
template[
|
99
|
-
template[
|
98
|
+
template["outputs"] = processor.dereference_processor(
|
99
|
+
template["outputs"], []
|
100
100
|
)
|
101
|
-
derefed_outs = template[
|
101
|
+
derefed_outs = template["outputs"] || {}
|
102
102
|
derefed_outs.each do |o_name, o_data|
|
103
|
-
o_key = [name, o_name].join(
|
104
|
-
val = o_data[
|
105
|
-
if val.start_with?(
|
106
|
-
val = val.split(
|
103
|
+
o_key = [name, o_name].join("__")
|
104
|
+
val = o_data["value"]
|
105
|
+
if val.start_with?("${") && val.scan(".").count == 2
|
106
|
+
val = val.split(".")
|
107
107
|
val[1] = "#{name}__#{val[1]}"
|
108
|
-
val = val.join(
|
108
|
+
val = val.join(".")
|
109
109
|
end
|
110
110
|
outputs[o_key] = val
|
111
111
|
end
|
112
112
|
end
|
113
113
|
outputs.dup.each do |key, value|
|
114
|
-
if value.to_s.start_with?(
|
115
|
-
output_key = value.to_s.sub(
|
114
|
+
if value.to_s.start_with?("${module.")
|
115
|
+
output_key = value.to_s.sub("${module.", "").sub("}", "").sub(".", "__")
|
116
116
|
if outputs.key?(output_key)
|
117
117
|
outputs[key] = outputs[output_key]
|
118
118
|
end
|
@@ -120,16 +120,16 @@ module Sfn
|
|
120
120
|
end
|
121
121
|
end
|
122
122
|
|
123
|
-
def edge_detection(template, graph, name =
|
124
|
-
resources = (template.fetch(
|
123
|
+
def edge_detection(template, graph, name = "", resource_names = [])
|
124
|
+
resources = (template.fetch("resources", {}) || {})
|
125
125
|
node_prefix = name
|
126
126
|
resources.each do |resource_name, resource_data|
|
127
|
-
node_name = [node_prefix, resource_name].join(
|
128
|
-
if resource_data[
|
127
|
+
node_name = [node_prefix, resource_name].join("__")
|
128
|
+
if resource_data["type"] == "module"
|
129
129
|
graph.subgraph << generate_graph(
|
130
|
-
resource_data[
|
130
|
+
resource_data["properties"].delete("stack"),
|
131
131
|
:name => resource_name,
|
132
|
-
:type => resource_data[
|
132
|
+
:type => resource_data["type"],
|
133
133
|
:resource_names => resource_names,
|
134
134
|
)
|
135
135
|
next
|
@@ -138,28 +138,28 @@ module Sfn
|
|
138
138
|
graph.box3d << graph.node(node_name)
|
139
139
|
end
|
140
140
|
graph.filled << graph.node(node_name)
|
141
|
-
graph.node(node_name).label "#{resource_name}\n<#{resource_data[
|
141
|
+
graph.node(node_name).label "#{resource_name}\n<#{resource_data["type"]}>\n#{name}"
|
142
142
|
resource_dependencies(resource_data, resource_names + resources.keys).each do |dep_name|
|
143
143
|
if resources.keys.include?(dep_name)
|
144
|
-
dep_name = [node_prefix, dep_name].join(
|
144
|
+
dep_name = [node_prefix, dep_name].join("__")
|
145
145
|
end
|
146
|
-
if config[:graph_style] ==
|
146
|
+
if config[:graph_style] == "creation"
|
147
147
|
@root_graph.edge(dep_name, node_name)
|
148
148
|
else
|
149
149
|
@root_graph.edge(node_name, dep_name)
|
150
150
|
end
|
151
151
|
end
|
152
152
|
end
|
153
|
-
resource_names.concat resources.keys.map { |r_name| [node_prefix, r_name].join(
|
153
|
+
resource_names.concat resources.keys.map { |r_name| [node_prefix, r_name].join("__") }
|
154
154
|
end
|
155
155
|
|
156
156
|
def resource_dependencies(data, names)
|
157
157
|
case data
|
158
158
|
when String
|
159
159
|
result = []
|
160
|
-
if data.start_with?(
|
161
|
-
data = data.tr(
|
162
|
-
check_name = data.split(
|
160
|
+
if data.start_with?("${") && data.scan(".").count >= 1
|
161
|
+
data = data.tr("${}", "")
|
162
|
+
check_name = data.split(".")[1]
|
163
163
|
if names.include?(check_name)
|
164
164
|
result.push(check_name)
|
165
165
|
end
|
@@ -167,9 +167,9 @@ module Sfn
|
|
167
167
|
result
|
168
168
|
when Hash
|
169
169
|
data.map do |key, value|
|
170
|
-
if key ==
|
170
|
+
if key == "depends_on"
|
171
171
|
[value].flatten.compact.map do |dependson_name|
|
172
|
-
dep_name = dependson_name.split(
|
172
|
+
dep_name = dependson_name.split(".").last
|
173
173
|
dep_name if names.include?(dep_name)
|
174
174
|
end
|
175
175
|
else
|