sfn 3.0.28 → 3.0.30
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.
- checksums.yaml +5 -5
- data/CHANGELOG.md +5 -0
- data/docs/callbacks.md +1 -0
- data/lib/chef/knife/knife_plugin_seed.rb +11 -17
- data/lib/sfn.rb +0 -2
- data/lib/sfn/api_provider.rb +0 -2
- data/lib/sfn/api_provider/google.rb +6 -9
- data/lib/sfn/api_provider/terraform.rb +4 -6
- data/lib/sfn/cache.rb +36 -39
- data/lib/sfn/callback.rb +0 -2
- data/lib/sfn/callback/aws_assume_role.rb +7 -8
- data/lib/sfn/callback/aws_mfa.rb +7 -8
- data/lib/sfn/callback/stack_policy.rb +15 -17
- data/lib/sfn/command.rb +9 -11
- data/lib/sfn/command/conf.rb +7 -10
- data/lib/sfn/command/create.rb +8 -12
- data/lib/sfn/command/describe.rb +6 -8
- data/lib/sfn/command/destroy.rb +8 -10
- data/lib/sfn/command/diff.rb +18 -25
- data/lib/sfn/command/events.rb +15 -16
- data/lib/sfn/command/export.rb +13 -17
- data/lib/sfn/command/graph.rb +11 -13
- data/lib/sfn/command/graph/aws.rb +27 -29
- data/lib/sfn/command/graph/terraform.rb +22 -23
- data/lib/sfn/command/import.rb +13 -16
- data/lib/sfn/command/init.rb +5 -7
- data/lib/sfn/command/inspect.rb +26 -29
- data/lib/sfn/command/lint.rb +10 -12
- data/lib/sfn/command/list.rb +5 -8
- data/lib/sfn/command/print.rb +3 -5
- data/lib/sfn/command/promote.rb +0 -2
- data/lib/sfn/command/update.rb +42 -46
- data/lib/sfn/command/validate.rb +4 -6
- data/lib/sfn/command_module/base.rb +17 -25
- data/lib/sfn/command_module/callbacks.rb +12 -8
- data/lib/sfn/command_module/stack.rb +39 -43
- data/lib/sfn/command_module/template.rb +89 -90
- data/lib/sfn/config.rb +30 -31
- data/lib/sfn/config/conf.rb +1 -3
- data/lib/sfn/config/create.rb +5 -7
- data/lib/sfn/config/describe.rb +3 -5
- data/lib/sfn/config/diff.rb +1 -1
- data/lib/sfn/config/events.rb +6 -8
- data/lib/sfn/config/export.rb +4 -7
- data/lib/sfn/config/graph.rb +4 -6
- data/lib/sfn/config/import.rb +3 -5
- data/lib/sfn/config/init.rb +0 -1
- data/lib/sfn/config/inspect.rb +7 -9
- data/lib/sfn/config/lint.rb +4 -4
- data/lib/sfn/config/list.rb +3 -5
- data/lib/sfn/config/print.rb +3 -5
- data/lib/sfn/config/promote.rb +3 -5
- data/lib/sfn/config/update.rb +10 -12
- data/lib/sfn/config/validate.rb +18 -20
- data/lib/sfn/lint.rb +0 -2
- data/lib/sfn/lint/definition.rb +3 -5
- data/lib/sfn/lint/rule.rb +7 -8
- data/lib/sfn/lint/rule_set.rb +11 -20
- data/lib/sfn/monkey_patch/stack.rb +32 -34
- data/lib/sfn/monkey_patch/stack/azure.rb +0 -1
- data/lib/sfn/monkey_patch/stack/google.rb +15 -16
- data/lib/sfn/planner.rb +1 -3
- data/lib/sfn/planner/aws.rb +82 -89
- data/lib/sfn/provider.rb +21 -23
- data/lib/sfn/utils.rb +0 -2
- data/lib/sfn/utils/debug.rb +1 -2
- data/lib/sfn/utils/json.rb +3 -2
- data/lib/sfn/utils/object_storage.rb +1 -2
- data/lib/sfn/utils/output.rb +8 -9
- data/lib/sfn/utils/path_selector.rb +9 -10
- data/lib/sfn/utils/ssher.rb +2 -3
- data/lib/sfn/utils/stack_exporter.rb +20 -21
- data/lib/sfn/utils/stack_parameter_scrubber.rb +6 -7
- data/lib/sfn/utils/stack_parameter_validator.rb +14 -16
- data/lib/sfn/version.rb +1 -1
- data/sfn.gemspec +1 -1
- metadata +8 -8
@@ -13,14 +13,14 @@ module Sfn
|
|
13
13
|
|
14
14
|
attr_accessor :name
|
15
15
|
|
16
|
-
def initialize(template, args={})
|
16
|
+
def initialize(template, args = {})
|
17
17
|
super
|
18
18
|
@name = args[:name]
|
19
19
|
end
|
20
20
|
|
21
|
-
def apply_function(hash, funcs=[])
|
21
|
+
def apply_function(hash, funcs = [])
|
22
22
|
k, v = hash.first
|
23
|
-
if
|
23
|
+
if hash.size == 1
|
24
24
|
case k
|
25
25
|
when 'Ref'
|
26
26
|
parameters.key?(v) ? parameters[v] : hash
|
@@ -37,27 +37,27 @@ module Sfn
|
|
37
37
|
end
|
38
38
|
end
|
39
39
|
|
40
|
-
def output_discovery(template, outputs, resource_name, parent_template, name='')
|
41
|
-
if
|
40
|
+
def output_discovery(template, outputs, resource_name, parent_template, name = '')
|
41
|
+
if template['Resources']
|
42
42
|
template['Resources'].keys.each do |r_name|
|
43
43
|
r_info = template['Resources'][r_name]
|
44
|
-
if
|
44
|
+
if r_info['Type'] == 'AWS::CloudFormation::Stack'
|
45
45
|
output_discovery(r_info['Properties']['Stack'], outputs, r_name, template, r_name)
|
46
46
|
end
|
47
47
|
end
|
48
48
|
end
|
49
|
-
if
|
49
|
+
if parent_template
|
50
50
|
ui.debug "Pre-processing stack resource `#{resource_name}`"
|
51
51
|
substack_parameters = Smash[
|
52
52
|
parent_template.fetch('Resources', resource_name, 'Properties', 'Parameters', {}).map do |key, value|
|
53
53
|
result = [key, value]
|
54
|
-
if
|
54
|
+
if value.is_a?(Hash)
|
55
55
|
v_key = value.keys.first
|
56
56
|
v_value = value.values.first
|
57
|
-
if
|
57
|
+
if v_key == 'Fn::GetAtt' && parent_template.fetch('Resources', {}).keys.include?(v_value.first) && v_value.last.start_with?('Outputs.')
|
58
58
|
output_key = v_value.first + '__' + v_value.last.split('.', 2).last
|
59
59
|
ui.debug "Output key for check: #{output_key}"
|
60
|
-
if
|
60
|
+
if outputs.key?(output_key)
|
61
61
|
new_value = outputs[output_key]
|
62
62
|
result = [key, new_value]
|
63
63
|
ui.debug "Parameter for output swap `#{key}`: #{value} -> #{new_value}"
|
@@ -71,8 +71,7 @@ module Sfn
|
|
71
71
|
ui.debug "Generated internal parameters for `#{resource_name}`: #{substack_parameters}"
|
72
72
|
|
73
73
|
processor = AwsGraphProcessor.new({},
|
74
|
-
|
75
|
-
)
|
74
|
+
:parameters => substack_parameters)
|
76
75
|
template['Resources'] = processor.dereference_processor(
|
77
76
|
template['Resources'], ['Ref']
|
78
77
|
)
|
@@ -80,12 +79,11 @@ module Sfn
|
|
80
79
|
template['Outputs'], ['Ref']
|
81
80
|
)
|
82
81
|
rename_processor = AwsGraphProcessor.new({},
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
)
|
82
|
+
:parameters => Smash[
|
83
|
+
template.fetch('Resources', {}).keys.map do |r_key|
|
84
|
+
[r_key, {'Ref' => [name, r_key].join}]
|
85
|
+
end
|
86
|
+
])
|
89
87
|
derefed_outs = rename_processor.dereference_processor(
|
90
88
|
template.fetch('Outputs', {})
|
91
89
|
) || {}
|
@@ -96,12 +94,12 @@ module Sfn
|
|
96
94
|
end
|
97
95
|
end
|
98
96
|
outputs.dup.each do |key, value|
|
99
|
-
if
|
97
|
+
if value.is_a?(Hash)
|
100
98
|
v_key = value.keys.first
|
101
99
|
v_value = value.values.first
|
102
|
-
if
|
100
|
+
if v_key == 'Fn::GetAtt' && v_value.last.start_with?('Outputs.')
|
103
101
|
output_key = v_value.first << '__' << v_value.last.split('.', 2).last
|
104
|
-
if
|
102
|
+
if outputs.key?(output_key)
|
105
103
|
outputs[key] = outputs[output_key]
|
106
104
|
end
|
107
105
|
end
|
@@ -114,12 +112,12 @@ module Sfn
|
|
114
112
|
node_prefix = name
|
115
113
|
resources.each do |resource_name, resource_data|
|
116
114
|
node_name = [node_prefix, resource_name].join
|
117
|
-
if
|
115
|
+
if resource_data['Type'] == 'AWS::CloudFormation::Stack'
|
118
116
|
graph.subgraph << generate_graph(
|
119
117
|
resource_data['Properties'].delete('Stack'),
|
120
118
|
:name => resource_name,
|
121
119
|
:type => resource_data['Type'],
|
122
|
-
:resource_names => resource_names
|
120
|
+
:resource_names => resource_names,
|
123
121
|
)
|
124
122
|
next
|
125
123
|
else
|
@@ -129,30 +127,30 @@ module Sfn
|
|
129
127
|
graph.filled << graph.node(node_name)
|
130
128
|
graph.node(node_name).label "#{resource_name}\n<#{resource_data['Type']}>\n#{name}"
|
131
129
|
resource_dependencies(resource_data, resource_names + resources.keys).each do |dep_name|
|
132
|
-
if
|
130
|
+
if resources.keys.include?(dep_name)
|
133
131
|
dep_name = [node_prefix, dep_name].join
|
134
132
|
end
|
135
|
-
if
|
133
|
+
if config[:graph_style] == 'creation'
|
136
134
|
@root_graph.edge(dep_name, node_name)
|
137
135
|
else
|
138
136
|
@root_graph.edge(node_name, dep_name)
|
139
137
|
end
|
140
138
|
end
|
141
139
|
end
|
142
|
-
resource_names.concat resources.keys.map{|r_name| [node_prefix, r_name].join}
|
140
|
+
resource_names.concat resources.keys.map { |r_name| [node_prefix, r_name].join }
|
143
141
|
end
|
144
142
|
|
145
143
|
def resource_dependencies(data, names)
|
146
144
|
case data
|
147
145
|
when Hash
|
148
146
|
data.map do |key, value|
|
149
|
-
if
|
147
|
+
if key == 'Ref' && names.include?(value)
|
150
148
|
value
|
151
|
-
elsif
|
149
|
+
elsif key == 'DependsOn'
|
152
150
|
[value].flatten.compact.find_all do |dependson_name|
|
153
151
|
names.include?(dependson_name)
|
154
152
|
end
|
155
|
-
elsif
|
153
|
+
elsif key == 'Fn::GetAtt' && names.include?(res = [value].flatten.compact.first)
|
156
154
|
res
|
157
155
|
else
|
158
156
|
resource_dependencies(key, names) +
|
@@ -13,15 +13,15 @@ module Sfn
|
|
13
13
|
|
14
14
|
attr_accessor :name
|
15
15
|
|
16
|
-
def initialize(template, args={})
|
16
|
+
def initialize(template, args = {})
|
17
17
|
super
|
18
18
|
@name = args[:name]
|
19
19
|
end
|
20
20
|
|
21
|
-
def dereference_processor(obj, funcs=[])
|
21
|
+
def dereference_processor(obj, funcs = [])
|
22
22
|
case obj
|
23
23
|
when Array
|
24
|
-
obj = obj.map{|v| dereference_processor(v, funcs)}
|
24
|
+
obj = obj.map { |v| dereference_processor(v, funcs) }
|
25
25
|
when Hash
|
26
26
|
new_hash = {}
|
27
27
|
obj.each do |k, v|
|
@@ -50,10 +50,10 @@ module Sfn
|
|
50
50
|
@original.fetch('outputs', {})
|
51
51
|
end
|
52
52
|
|
53
|
-
def apply_function(string, funcs=[])
|
53
|
+
def apply_function(string, funcs = [])
|
54
54
|
# first check for vars and replace with params
|
55
55
|
string.scan(/(\$\{var\.(.+?)\})/).each do |match|
|
56
|
-
if
|
56
|
+
if parameters[match.last]
|
57
57
|
string.sub!(match.first, parameters[match.last])
|
58
58
|
end
|
59
59
|
end
|
@@ -61,24 +61,24 @@ module Sfn
|
|
61
61
|
end
|
62
62
|
end
|
63
63
|
|
64
|
-
def output_discovery(template, outputs, resource_name, parent_template, name='')
|
65
|
-
if
|
64
|
+
def output_discovery(template, outputs, resource_name, parent_template, name = '')
|
65
|
+
if template['resources']
|
66
66
|
template['resources'].keys.each do |r_name|
|
67
67
|
r_info = template['resources'][r_name]
|
68
|
-
if
|
68
|
+
if r_info['type'] == 'module'
|
69
69
|
output_discovery(r_info['properties']['stack'], outputs, r_name, template, r_name)
|
70
70
|
end
|
71
71
|
end
|
72
72
|
end
|
73
|
-
if
|
73
|
+
if parent_template
|
74
74
|
ui.debug "Pre-processing stack resource `#{resource_name}`"
|
75
75
|
substack_parameters = Smash[
|
76
76
|
parent_template.fetch('resources', resource_name, 'properties', 'parameters', {}).map do |key, value|
|
77
77
|
result = [key, value]
|
78
|
-
if
|
78
|
+
if value.to_s.start_with?('${module.')
|
79
79
|
output_key = value.sub('${module.', '').sub('}', '').sub('.', '__')
|
80
80
|
ui.debug "Output key for check: #{output_key}"
|
81
|
-
if
|
81
|
+
if outputs.key?(output_key)
|
82
82
|
new_value = outputs[output_key]
|
83
83
|
result = [key, new_value]
|
84
84
|
ui.debug "Parameter for output swap `#{key}`: #{value} -> #{new_value}"
|
@@ -91,8 +91,7 @@ module Sfn
|
|
91
91
|
ui.debug "Generated internal parameters for `#{resource_name}`: #{substack_parameters}"
|
92
92
|
|
93
93
|
processor = TerraformGraphProcessor.new({},
|
94
|
-
|
95
|
-
)
|
94
|
+
:parameters => substack_parameters)
|
96
95
|
template['resources'] = processor.dereference_processor(
|
97
96
|
template['resources'], []
|
98
97
|
)
|
@@ -103,7 +102,7 @@ module Sfn
|
|
103
102
|
derefed_outs.each do |o_name, o_data|
|
104
103
|
o_key = [name, o_name].join('__')
|
105
104
|
val = o_data['value']
|
106
|
-
if
|
105
|
+
if val.start_with?('${') && val.scan('.').count == 2
|
107
106
|
val = val.split('.')
|
108
107
|
val[1] = "#{name}__#{val[1]}"
|
109
108
|
val = val.join('.')
|
@@ -112,9 +111,9 @@ module Sfn
|
|
112
111
|
end
|
113
112
|
end
|
114
113
|
outputs.dup.each do |key, value|
|
115
|
-
if
|
114
|
+
if value.to_s.start_with?('${module.')
|
116
115
|
output_key = value.to_s.sub('${module.', '').sub('}', '').sub('.', '__')
|
117
|
-
if
|
116
|
+
if outputs.key?(output_key)
|
118
117
|
outputs[key] = outputs[output_key]
|
119
118
|
end
|
120
119
|
end
|
@@ -126,12 +125,12 @@ module Sfn
|
|
126
125
|
node_prefix = name
|
127
126
|
resources.each do |resource_name, resource_data|
|
128
127
|
node_name = [node_prefix, resource_name].join('__')
|
129
|
-
if
|
128
|
+
if resource_data['type'] == 'module'
|
130
129
|
graph.subgraph << generate_graph(
|
131
130
|
resource_data['properties'].delete('stack'),
|
132
131
|
:name => resource_name,
|
133
132
|
:type => resource_data['type'],
|
134
|
-
:resource_names => resource_names
|
133
|
+
:resource_names => resource_names,
|
135
134
|
)
|
136
135
|
next
|
137
136
|
else
|
@@ -141,24 +140,24 @@ module Sfn
|
|
141
140
|
graph.filled << graph.node(node_name)
|
142
141
|
graph.node(node_name).label "#{resource_name}\n<#{resource_data['type']}>\n#{name}"
|
143
142
|
resource_dependencies(resource_data, resource_names + resources.keys).each do |dep_name|
|
144
|
-
if
|
143
|
+
if resources.keys.include?(dep_name)
|
145
144
|
dep_name = [node_prefix, dep_name].join('__')
|
146
145
|
end
|
147
|
-
if
|
146
|
+
if config[:graph_style] == 'creation'
|
148
147
|
@root_graph.edge(dep_name, node_name)
|
149
148
|
else
|
150
149
|
@root_graph.edge(node_name, dep_name)
|
151
150
|
end
|
152
151
|
end
|
153
152
|
end
|
154
|
-
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('__') }
|
155
154
|
end
|
156
155
|
|
157
156
|
def resource_dependencies(data, names)
|
158
157
|
case data
|
159
158
|
when String
|
160
159
|
result = []
|
161
|
-
if
|
160
|
+
if data.start_with?('${') && data.scan('.').count >= 1
|
162
161
|
data = data.tr('${}', '')
|
163
162
|
check_name = data.split('.')[1]
|
164
163
|
if names.include?(check_name)
|
@@ -168,7 +167,7 @@ module Sfn
|
|
168
167
|
result
|
169
168
|
when Hash
|
170
169
|
data.map do |key, value|
|
171
|
-
if
|
170
|
+
if key == 'depends_on'
|
172
171
|
[value].flatten.compact.map do |dependson_name|
|
173
172
|
dep_name = dependson_name.split('.').last
|
174
173
|
dep_name if names.include?(dep_name)
|
data/lib/sfn/command/import.rb
CHANGED
@@ -5,7 +5,6 @@ module Sfn
|
|
5
5
|
class Command
|
6
6
|
# Import command
|
7
7
|
class Import < Command
|
8
|
-
|
9
8
|
include Sfn::CommandModule::Base
|
10
9
|
include Sfn::Utils::JSON
|
11
10
|
include Sfn::Utils::ObjectStorage
|
@@ -16,19 +15,19 @@ module Sfn
|
|
16
15
|
raise NotImplementedError.new 'Implementation updates required'
|
17
16
|
stack_name, json_file = name_args
|
18
17
|
ui.info "#{ui.color('Stack Import:', :bold)} #{stack_name}"
|
19
|
-
unless
|
18
|
+
unless json_file
|
20
19
|
entries = [].tap do |_entries|
|
21
20
|
_entries.push('s3') if config[:bucket]
|
22
21
|
_entries.push('fs') if config[:path]
|
23
22
|
end
|
24
|
-
if
|
23
|
+
if entries.size > 1
|
25
24
|
valid = false
|
26
|
-
until
|
25
|
+
until valid
|
27
26
|
answer = ui.ask_question('Import via file system (fs) or remote bucket (remote)?', :default => 'remote')
|
28
27
|
valid = true if %w(remote fs).include?(answer)
|
29
28
|
entries = [answer]
|
30
29
|
end
|
31
|
-
elsif
|
30
|
+
elsif entries.size < 1
|
32
31
|
ui.fatal 'No path or bucket set. Unable to perform dynamic lookup!'
|
33
32
|
exit 1
|
34
33
|
end
|
@@ -39,14 +38,14 @@ module Sfn
|
|
39
38
|
json_file = local_discovery
|
40
39
|
end
|
41
40
|
end
|
42
|
-
if
|
41
|
+
if File.exists?(json_file) || json_file.is_a?(IO)
|
43
42
|
content = json_file.is_a?(IO) ? json_file.read : File.read(json_file)
|
44
43
|
export = Mash.new(_from_json(content))
|
45
44
|
begin
|
46
45
|
creator = namespace.const_val(:Create).new(
|
47
46
|
Smash.new(
|
48
47
|
:template => _from_json(export[:stack][:template]),
|
49
|
-
:options => _from_json(export[:stack][:options])
|
48
|
+
:options => _from_json(export[:stack][:options]),
|
50
49
|
),
|
51
50
|
[stack_name]
|
52
51
|
)
|
@@ -68,8 +67,8 @@ module Sfn
|
|
68
67
|
#
|
69
68
|
# @return [String, NilClass]
|
70
69
|
def bucket_prefix
|
71
|
-
if
|
72
|
-
if
|
70
|
+
if prefix = config[:bucket_prefix]
|
71
|
+
if prefix.respond_to?(:call)
|
73
72
|
prefix.call
|
74
73
|
else
|
75
74
|
prefix.to_s
|
@@ -87,9 +86,9 @@ module Sfn
|
|
87
86
|
directory,
|
88
87
|
:directories_name => 'Collections',
|
89
88
|
:files_names => 'Exports',
|
90
|
-
:filter_prefix => bucket_prefix
|
89
|
+
:filter_prefix => bucket_prefix,
|
91
90
|
)
|
92
|
-
if
|
91
|
+
if file
|
93
92
|
remote_file = storage.files.get(file)
|
94
93
|
StringIO.new(remote_file.body)
|
95
94
|
end
|
@@ -101,17 +100,15 @@ module Sfn
|
|
101
100
|
def local_discovery
|
102
101
|
_, bucket = config[:path].split('/', 2)
|
103
102
|
storage = provider.service_for(:storage,
|
104
|
-
|
105
|
-
|
106
|
-
)
|
103
|
+
:provider => :local,
|
104
|
+
:local_root => '/')
|
107
105
|
directory = storage.directories.get(bucket)
|
108
106
|
prompt_for_file(
|
109
107
|
directory,
|
110
108
|
:directories_name => 'Collections',
|
111
|
-
:files_names => 'Exports'
|
109
|
+
:files_names => 'Exports',
|
112
110
|
)
|
113
111
|
end
|
114
|
-
|
115
112
|
end
|
116
113
|
end
|
117
114
|
end
|
data/lib/sfn/command/init.rb
CHANGED
@@ -5,26 +5,25 @@ module Sfn
|
|
5
5
|
class Command
|
6
6
|
# Init command
|
7
7
|
class Init < Command
|
8
|
-
|
9
8
|
include Sfn::CommandModule::Base
|
10
9
|
|
11
10
|
INIT_DIRECTORIES = [
|
12
11
|
'sparkleformation/dynamics',
|
13
12
|
'sparkleformation/components',
|
14
|
-
'sparkleformation/registry'
|
13
|
+
'sparkleformation/registry',
|
15
14
|
]
|
16
15
|
|
17
16
|
# Run the init command to initialize new project
|
18
17
|
def execute!
|
19
|
-
unless
|
18
|
+
unless name_args.size == 1
|
20
19
|
raise ArgumentError.new 'Please provide path argument only for project initialization'
|
21
20
|
else
|
22
21
|
path = name_args.first
|
23
22
|
end
|
24
|
-
if
|
23
|
+
if File.file?(path)
|
25
24
|
raise "Cannot create project directory. Given path is a file. (`#{path}`)"
|
26
25
|
end
|
27
|
-
if
|
26
|
+
if File.directory?(path)
|
28
27
|
ui.warn "Project directory already exists at given path. (`#{path}`)"
|
29
28
|
ui.confirm 'Overwrite existing files?'
|
30
29
|
end
|
@@ -46,7 +45,7 @@ module Sfn
|
|
46
45
|
end
|
47
46
|
ui.info 'Installing project bundle'
|
48
47
|
Dir.chdir(path) do
|
49
|
-
if
|
48
|
+
if defined?(Bundler)
|
50
49
|
Bundler.clean_system('bundle install')
|
51
50
|
else
|
52
51
|
system('bundle install')
|
@@ -55,7 +54,6 @@ module Sfn
|
|
55
54
|
ui.info 'Project initialization complete!'
|
56
55
|
ui.puts " Project path -> #{File.expand_path(path)}"
|
57
56
|
end
|
58
|
-
|
59
57
|
end
|
60
58
|
end
|
61
59
|
end
|
data/lib/sfn/command/inspect.rb
CHANGED
@@ -4,7 +4,6 @@ module Sfn
|
|
4
4
|
class Command
|
5
5
|
# Inspect command
|
6
6
|
class Inspect < Command
|
7
|
-
|
8
7
|
include Sfn::CommandModule::Base
|
9
8
|
include Sfn::Utils::Ssher
|
10
9
|
|
@@ -16,19 +15,19 @@ module Sfn
|
|
16
15
|
ui.info "Stack inspection #{ui.color(stack_name, :bold)}:"
|
17
16
|
outputs = api_action!(:api_stack => stack) do
|
18
17
|
[:attribute, :nodes, :load_balancers, :instance_failure].map do |key|
|
19
|
-
if
|
18
|
+
if config.has_key?(key)
|
20
19
|
send("display_#{key}", stack)
|
21
20
|
key
|
22
21
|
end
|
23
22
|
end.compact
|
24
23
|
end
|
25
|
-
if
|
24
|
+
if outputs.empty?
|
26
25
|
ui.info ' Stack dump:'
|
27
26
|
ui.puts MultiJson.dump(
|
28
27
|
MultiJson.load(
|
29
28
|
stack.reload.to_json
|
30
29
|
),
|
31
|
-
:pretty => true
|
30
|
+
:pretty => true,
|
32
31
|
)
|
33
32
|
end
|
34
33
|
end
|
@@ -38,32 +37,32 @@ module Sfn
|
|
38
37
|
resource.state.to_s.end_with?('failed')
|
39
38
|
end.map do |resource|
|
40
39
|
# If compute instance, simply expand
|
41
|
-
if
|
40
|
+
if resource.within?(:compute, :servers)
|
42
41
|
resource.instance
|
43
|
-
|
44
|
-
elsif
|
45
|
-
if
|
42
|
+
# If a waitcondition, check for instance ID
|
43
|
+
elsif resource.type.to_s.downcase.end_with?('waitcondition')
|
44
|
+
if resource.status_reason.to_s.include?('uniqueId')
|
46
45
|
srv_id = resource.status_reason.split(' ').last.strip
|
47
46
|
provider.connection.api_for(:compute).servers.get(srv_id)
|
48
47
|
end
|
49
48
|
end
|
50
49
|
end.compact
|
51
|
-
if
|
50
|
+
if instances.empty?
|
52
51
|
ui.error 'Failed to locate any failed instances'
|
53
52
|
else
|
54
53
|
log_path = config[:failure_log_path]
|
55
|
-
if
|
54
|
+
if log_path.to_s.empty?
|
56
55
|
log_path = '/var/log/chef/client.log'
|
57
56
|
end
|
58
57
|
opts = ssh_key ? {:keys => [ssh_key]} : {}
|
59
58
|
instances.each do |instance|
|
60
59
|
ui.info " -> Log inspect for #{instance.id}:"
|
61
60
|
address = instance.addresses_public.map do |address|
|
62
|
-
if
|
61
|
+
if address.version == 4
|
63
62
|
address.address
|
64
63
|
end
|
65
64
|
end
|
66
|
-
if
|
65
|
+
if address
|
67
66
|
ssh_attempt_users.each do |user|
|
68
67
|
begin
|
69
68
|
ui.info remote_file_contents(address.first, user, log_path, opts)
|
@@ -96,12 +95,12 @@ module Sfn
|
|
96
95
|
[config[:attribute]].flatten.compact.each do |stack_attribute|
|
97
96
|
attr = stack_attribute.split('.').inject(stack) do |memo, key|
|
98
97
|
args = key.scan(/\(([^\)]*)\)/).flatten.first.to_s
|
99
|
-
if
|
100
|
-
args = args.split(',').map{|a| a.to_i.to_s == a ? a.to_i : a}
|
98
|
+
if args
|
99
|
+
args = args.split(',').map { |a| a.to_i.to_s == a ? a.to_i : a }
|
101
100
|
key = key.split('(').first
|
102
101
|
end
|
103
|
-
if
|
104
|
-
if
|
102
|
+
if memo.public_methods.include?(key.to_sym)
|
103
|
+
if args.size == 1 && args.first.to_s.start_with?('&')
|
105
104
|
memo.send(key, &args.first.slice(2, args.first.size).to_sym)
|
106
105
|
else
|
107
106
|
memo.send(*[key, args].flatten.compact)
|
@@ -115,7 +114,7 @@ module Sfn
|
|
115
114
|
MultiJson.load(
|
116
115
|
MultiJson.dump(attr)
|
117
116
|
),
|
118
|
-
:pretty => true
|
117
|
+
:pretty => true,
|
119
118
|
)
|
120
119
|
end
|
121
120
|
end
|
@@ -129,13 +128,13 @@ module Sfn
|
|
129
128
|
[
|
130
129
|
asg.name,
|
131
130
|
Smash[
|
132
|
-
asg.servers.map(&:expand).compact.map{|s|
|
131
|
+
asg.servers.map(&:expand).compact.map { |s|
|
133
132
|
[s.id, Smash.new(
|
134
|
-
|
135
|
-
|
133
|
+
:name => s.name,
|
134
|
+
:addresses => s.addresses.map(&:address),
|
136
135
|
)]
|
137
136
|
}
|
138
|
-
]
|
137
|
+
],
|
139
138
|
]
|
140
139
|
end
|
141
140
|
]
|
@@ -144,19 +143,19 @@ module Sfn
|
|
144
143
|
resource.within?(:compute, :servers)
|
145
144
|
end.map do |srv|
|
146
145
|
srv = srv.instance
|
147
|
-
if
|
146
|
+
if srv
|
148
147
|
[srv.id, Smash.new(
|
149
148
|
:name => srv.name,
|
150
|
-
:addresses => srv.addresses.map(&:address)
|
149
|
+
:addresses => srv.addresses.map(&:address),
|
151
150
|
)]
|
152
151
|
end
|
153
152
|
end.compact
|
154
153
|
]
|
155
|
-
unless
|
154
|
+
unless asg_nodes.empty?
|
156
155
|
ui.info ' AutoScale Group Instances:'
|
157
156
|
ui.puts MultiJson.dump(asg_nodes, :pretty => true)
|
158
157
|
end
|
159
|
-
unless
|
158
|
+
unless compute_nodes.empty?
|
160
159
|
ui.info ' Compute Instances:'
|
161
160
|
ui.puts MultiJson.dump(compute_nodes, :pretty => true)
|
162
161
|
end
|
@@ -175,9 +174,8 @@ module Sfn
|
|
175
174
|
:state => exp_lb.state,
|
176
175
|
:public_addresses => lb_pub_addrs,
|
177
176
|
:private_addresses => lb_priv_addrs,
|
178
|
-
:server_states => exp_lb.server_states
|
179
|
-
).delete_if {|k,v| v.nil?}
|
180
|
-
]
|
177
|
+
:server_states => exp_lb.server_states,
|
178
|
+
).delete_if { |k, v| v.nil? }]
|
181
179
|
end
|
182
180
|
]
|
183
181
|
unless load_balancers.empty?
|
@@ -185,7 +183,6 @@ module Sfn
|
|
185
183
|
ui.puts MultiJson.dump(load_balancers, :pretty => true)
|
186
184
|
end
|
187
185
|
end
|
188
|
-
|
189
186
|
end
|
190
187
|
end
|
191
188
|
end
|