cfndk 0.0.7 → 0.1.2
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/.circleci/config.yml +79 -0
- data/.gitignore +1 -1
- data/.rspec +2 -0
- data/.rspec_parallel +6 -0
- data/.simplecov +9 -0
- data/Gemfile +11 -1
- data/Gemfile.lock +815 -0
- data/README.md +269 -76
- data/bin/cfndk +3 -18
- data/cfndk.gemspec +15 -6
- data/docker/Dockerfile +8 -0
- data/docker/build.sh +3 -0
- data/docker/cfndk.sh +14 -0
- data/lib/cfndk.rb +36 -0
- data/lib/cfndk/change_set_command.rb +103 -0
- data/lib/cfndk/command.rb +125 -119
- data/lib/cfndk/config_file_loadable.rb +13 -0
- data/lib/cfndk/credential_provider_chain.rb +12 -42
- data/lib/cfndk/credential_resolvable.rb +10 -0
- data/lib/cfndk/diff.rb +38 -0
- data/lib/cfndk/global_config.rb +46 -0
- data/lib/cfndk/key_pair.rb +66 -14
- data/lib/cfndk/key_pair_command.rb +60 -0
- data/lib/cfndk/key_pairs.rb +22 -5
- data/lib/cfndk/logger.rb +12 -3
- data/lib/cfndk/stack.rb +427 -126
- data/lib/cfndk/stack_command.rb +128 -0
- data/lib/cfndk/stacks.rb +48 -22
- data/lib/cfndk/subcommand_help_returnable.rb +16 -0
- data/lib/cfndk/template_packager.rb +210 -0
- data/lib/cfndk/uuid.rb +10 -0
- data/lib/cfndk/version.rb +1 -1
- data/skel/cfndk.yml +4 -0
- data/spec/.gitignore +1 -0
- data/spec/cfndk_change_set_create_spec.rb +436 -0
- data/spec/cfndk_change_set_destroy_spec.rb +160 -0
- data/spec/cfndk_change_set_execute_spec.rb +179 -0
- data/spec/cfndk_change_set_report_spec.rb +107 -0
- data/spec/cfndk_change_set_spec.rb +37 -0
- data/spec/cfndk_create_spec.rb +504 -0
- data/spec/cfndk_destroy_spec.rb +148 -0
- data/spec/cfndk_keypiar_spec.rb +397 -0
- data/spec/cfndk_report_spec.rb +164 -0
- data/spec/cfndk_spec.rb +103 -0
- data/spec/cfndk_stack_create_spec.rb +814 -0
- data/spec/cfndk_stack_destroy_spec.rb +225 -0
- data/spec/cfndk_stack_report_spec.rb +181 -0
- data/spec/cfndk_stack_spec.rb +133 -0
- data/spec/cfndk_stack_update_spec.rb +553 -0
- data/spec/fixtures/big_vpc.yaml +533 -0
- data/spec/fixtures/empty_resource.yaml +2 -0
- data/spec/fixtures/iam.json +8 -0
- data/spec/fixtures/iam.yaml +38 -0
- data/spec/fixtures/iam_different.json +8 -0
- data/spec/fixtures/invalid_vpc.yaml +21 -0
- data/spec/fixtures/lambda_function/index.js +4 -0
- data/spec/fixtures/lambda_function/lambda_function.json +4 -0
- data/spec/fixtures/lambda_function/lambda_function.yaml +28 -0
- data/spec/fixtures/nested_stack.json +35 -0
- data/spec/fixtures/nested_stack.yaml +20 -0
- data/spec/fixtures/serverless_function/index.js +4 -0
- data/spec/fixtures/serverless_function/serverless_function.json +4 -0
- data/spec/fixtures/serverless_function/serverless_function.yaml +21 -0
- data/spec/fixtures/sg.json +8 -0
- data/spec/fixtures/sg.yaml +27 -0
- data/spec/fixtures/sg_different.yaml +22 -0
- data/spec/fixtures/stack.json +8 -0
- data/spec/fixtures/stack.template.json +39 -0
- data/spec/fixtures/stack.yaml +22 -0
- data/spec/fixtures/vpc.json +8 -0
- data/spec/fixtures/vpc.template.json +40 -0
- data/spec/fixtures/vpc.yaml +21 -0
- data/spec/fixtures/vpc_different.yaml +21 -0
- data/spec/spec_helper.rb +14 -0
- data/spec/support/aruba.rb +6 -0
- data/vagrant/Vagrantfile +89 -0
- metadata +259 -31
data/lib/cfndk/stack.rb
CHANGED
@@ -1,148 +1,352 @@
|
|
1
1
|
module CFnDK
|
2
2
|
class Stack
|
3
|
-
attr_reader :template_file, :parameter_input, :capabilities, :depends, :timeout_in_minutes
|
4
|
-
def initialize(name, data, option, credentials)
|
3
|
+
attr_reader :template_file, :parameter_input, :capabilities, :depends, :timeout_in_minutes, :region, :role_arn, :package, :enabled, :pre_command, :post_command
|
4
|
+
def initialize(name, data, option, global_config, credentials)
|
5
|
+
@global_config = global_config
|
5
6
|
@name = name
|
6
7
|
@template_file = data['template_file'] || ''
|
7
8
|
@parameter_input = data['parameter_input'] || ''
|
8
9
|
@capabilities = data['capabilities'] || []
|
9
10
|
@depends = data['depends'] || []
|
10
|
-
@
|
11
|
+
@region = data['region'] || @global_config.region
|
12
|
+
@role_arn = @global_config.role_arn
|
13
|
+
@package = data['package'] || @global_config.package
|
14
|
+
@pre_command = data['pre_command'] || nil
|
15
|
+
@post_command = data['post_command'] || nil
|
16
|
+
@enabled = true
|
17
|
+
@enabled = false if data['enabled'] === false
|
18
|
+
@timeout_in_minutes = data['timeout_in_minutes'] || @global_config.timeout_in_minutes
|
11
19
|
@override_parameters = data['parameters'] || {}
|
12
20
|
@option = option
|
13
|
-
@client = Aws::CloudFormation::Client.new(credentials: credentials)
|
14
|
-
@
|
21
|
+
@client = Aws::CloudFormation::Client.new(credentials: credentials, region: @region)
|
22
|
+
@s3_client = Aws::S3::Client.new(credentials: credentials, region: @region)
|
23
|
+
@sts_client = Aws::STS::Client.new(credentials: credentials, region: @region)
|
24
|
+
@tp = CFnDK::TemplatePackager.new(@template_file, @region, @package, @global_config, @s3_client, @sts_client)
|
15
25
|
end
|
16
26
|
|
17
27
|
def create
|
18
28
|
return if @option[:stack_names].instance_of?(Array) && !@option[:stack_names].include?(@name)
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
29
|
+
return unless @enabled
|
30
|
+
CFnDK.logger.info(('creating stack: ' + name).color(:green))
|
31
|
+
CFnDK.logger.debug('Name :' + name)
|
32
|
+
CFnDK.logger.debug('Parametres :' + parameters.inspect)
|
33
|
+
CFnDK.logger.debug('Capabilities:' + capabilities.inspect)
|
34
|
+
CFnDK.logger.debug('Timeout :' + timeout_in_minutes.to_s)
|
35
|
+
CFnDK.logger.debug('Region :' + region)
|
36
|
+
tags = [
|
37
|
+
{
|
38
|
+
key: 'origina_name',
|
39
|
+
value: @name,
|
40
|
+
},
|
41
|
+
]
|
42
|
+
tags.push(
|
43
|
+
key: 'UUID',
|
44
|
+
value: @option[:uuid]
|
45
|
+
) if @option[:uuid]
|
46
|
+
hash = {
|
25
47
|
stack_name: name,
|
26
|
-
template_body: template_body,
|
27
48
|
parameters: parameters,
|
28
49
|
capabilities: capabilities,
|
29
|
-
timeout_in_minutes: timeout_in_minutes
|
50
|
+
timeout_in_minutes: timeout_in_minutes,
|
51
|
+
tags: tags,
|
52
|
+
}
|
53
|
+
hash[:role_arn] = @role_arn if @role_arn
|
54
|
+
|
55
|
+
if @tp.large_template?
|
56
|
+
hash[:template_url] = @tp.upload_template_file()
|
57
|
+
else
|
58
|
+
hash[:template_body] = @tp.template_body()
|
59
|
+
end
|
60
|
+
@client.create_stack(
|
61
|
+
hash
|
30
62
|
)
|
31
63
|
end
|
32
64
|
|
33
65
|
def wait_until_create
|
34
66
|
return if @option[:stack_names].instance_of?(Array) && !@option[:stack_names].include?(@name)
|
67
|
+
return unless @enabled
|
68
|
+
CFnDK.logger.info(('waiting create stack: ' + name).color(:green))
|
35
69
|
begin
|
36
70
|
@client.wait_until(
|
37
71
|
:stack_create_complete,
|
38
72
|
stack_name: name
|
39
|
-
)
|
40
|
-
|
73
|
+
) do |w|
|
74
|
+
w.max_attempts = 360
|
75
|
+
w.delay = 10
|
76
|
+
end
|
77
|
+
CFnDK.logger.info(('created stack: ' + name).color(:green))
|
41
78
|
rescue Aws::Waiters::Errors::FailureStateError => ex
|
42
|
-
|
43
|
-
|
79
|
+
CFnDK.logger.error "#{ex.class}: #{ex.message}".color(:red)
|
80
|
+
@option[:type] = %w(tag output parameter resource event)
|
81
|
+
report
|
44
82
|
raise ex
|
45
83
|
end
|
46
84
|
end
|
47
85
|
|
48
86
|
def update
|
49
87
|
return false if @option[:stack_names].instance_of?(Array) && !@option[:stack_names].include?(@name)
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
88
|
+
return unless @enabled
|
89
|
+
CFnDK.logger.info(('updating stack: ' + name).color(:green))
|
90
|
+
CFnDK.logger.debug('Name :' + name)
|
91
|
+
CFnDK.logger.debug('Parametres :' + parameters.inspect)
|
92
|
+
CFnDK.logger.debug('Capabilities:' + capabilities.inspect)
|
93
|
+
CFnDK.logger.debug('Timeout :' + timeout_in_minutes.to_s)
|
94
|
+
CFnDK.logger.debug('Region :' + region)
|
55
95
|
begin
|
56
|
-
|
96
|
+
hash = {
|
57
97
|
stack_name: name,
|
58
|
-
template_body: template_body,
|
59
98
|
parameters: parameters,
|
60
|
-
capabilities: capabilities
|
99
|
+
capabilities: capabilities,
|
100
|
+
}
|
101
|
+
hash[:role_arn] = @role_arn if @role_arn
|
102
|
+
if @tp.large_template?
|
103
|
+
hash[:template_url] = @tp.upload_template_file()
|
104
|
+
else
|
105
|
+
hash[:template_body] = @tp.template_body()
|
106
|
+
end
|
107
|
+
@client.update_stack(
|
108
|
+
hash
|
61
109
|
)
|
62
110
|
true
|
63
111
|
rescue Aws::CloudFormation::Errors::ValidationError => ex
|
64
|
-
|
65
|
-
|
112
|
+
case ex.message
|
113
|
+
when 'No updates are to be performed.'
|
114
|
+
CFnDK.logger.warn "#{ex.message}: #{name}".color(:red)
|
115
|
+
false
|
116
|
+
else
|
117
|
+
raise ex
|
118
|
+
end
|
66
119
|
end
|
67
120
|
end
|
68
121
|
|
69
122
|
def wait_until_update
|
70
123
|
return if @option[:stack_names].instance_of?(Array) && !@option[:stack_names].include?(@name)
|
124
|
+
return unless @enabled
|
125
|
+
CFnDK.logger.info(('waiting update stack: ' + name).color(:green))
|
71
126
|
@client.wait_until(
|
72
127
|
:stack_update_complete,
|
73
128
|
stack_name: name
|
74
|
-
)
|
75
|
-
|
129
|
+
) do |w|
|
130
|
+
w.max_attempts = 360
|
131
|
+
w.delay = 10
|
132
|
+
end
|
133
|
+
CFnDK.logger.info(('updated stack: ' + name).color(:green))
|
76
134
|
end
|
77
135
|
|
78
136
|
def destroy
|
79
137
|
return if @option[:stack_names].instance_of?(Array) && !@option[:stack_names].include?(@name)
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
)
|
138
|
+
return unless @enabled
|
139
|
+
if exits?
|
140
|
+
CFnDK.logger.info(('deleting stack: ' + name).color(:green))
|
141
|
+
CFnDK.logger.debug('Name :' + name)
|
142
|
+
CFnDK.logger.debug('Region :' + region)
|
143
|
+
hash = {
|
144
|
+
stack_name: name,
|
145
|
+
}
|
146
|
+
hash[:role_arn] = @role_arn if @role_arn
|
147
|
+
@client.delete_stack(
|
148
|
+
hash
|
149
|
+
)
|
150
|
+
else
|
151
|
+
CFnDK.logger.info(('do not delete stack: ' + name).color(:red))
|
152
|
+
end
|
85
153
|
end
|
86
154
|
|
87
155
|
def wait_until_destroy
|
88
156
|
return if @option[:stack_names].instance_of?(Array) && !@option[:stack_names].include?(@name)
|
157
|
+
return unless @enabled
|
158
|
+
return unless exits?
|
159
|
+
CFnDK.logger.info(('waiting delete stack: ' + name).color(:green))
|
89
160
|
@client.wait_until(
|
90
161
|
:stack_delete_complete,
|
91
162
|
stack_name: name
|
92
|
-
)
|
93
|
-
|
163
|
+
) do |w|
|
164
|
+
w.max_attempts = 360
|
165
|
+
w.delay = 10
|
166
|
+
end
|
167
|
+
CFnDK.logger.info(('deleted stack: ' + name).color(:green))
|
94
168
|
end
|
95
169
|
|
96
170
|
def create_change_set
|
97
|
-
return if @option[:stack_names].instance_of?(Array) && !@option[:stack_names].include?(@name)
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
171
|
+
return nil if @option[:stack_names].instance_of?(Array) && !@option[:stack_names].include?(@name)
|
172
|
+
return unless @enabled
|
173
|
+
CFnDK.logger.info(('creating change set: ' + change_set_name).color(:green))
|
174
|
+
CFnDK.logger.debug('Parametres :' + parameters.inspect)
|
175
|
+
CFnDK.logger.debug('Capabilities:' + capabilities.inspect)
|
176
|
+
CFnDK.logger.debug('Region :' + region)
|
177
|
+
tags = [
|
178
|
+
{
|
179
|
+
key: 'origina_name',
|
180
|
+
value: @name,
|
181
|
+
},
|
182
|
+
]
|
183
|
+
tags.push(
|
184
|
+
key: 'UUID',
|
185
|
+
value: @option[:uuid]
|
186
|
+
) if @option[:uuid]
|
187
|
+
tags.push(
|
188
|
+
key: 'CHANGE_SET_UUID',
|
189
|
+
value: @option[:change_set_uuid]
|
190
|
+
) if @option[:change_set_uuid]
|
191
|
+
hash = {
|
103
192
|
stack_name: name,
|
104
|
-
template_body: template_body,
|
105
193
|
parameters: parameters,
|
106
194
|
capabilities: capabilities,
|
107
|
-
change_set_name:
|
195
|
+
change_set_name: change_set_name,
|
196
|
+
change_set_type: exits? ? 'UPDATE' : 'CREATE',
|
197
|
+
tags: tags,
|
198
|
+
}
|
199
|
+
hash[:role_arn] = @role_arn if @role_arn
|
200
|
+
if @tp.large_template?
|
201
|
+
hash[:template_url] = @tp.upload_template_file()
|
202
|
+
else
|
203
|
+
hash[:template_body] = @tp.template_body()
|
204
|
+
end
|
205
|
+
@client.create_change_set(
|
206
|
+
hash
|
108
207
|
)
|
208
|
+
@name
|
209
|
+
rescue Aws::CloudFormation::Errors::ValidationError => ex
|
210
|
+
if review_in_progress?
|
211
|
+
CFnDK.logger.warn("failed create change set because the stack on REVIEW_IN_PROGRESS already exist : #{change_set_name}".color(:orange))
|
212
|
+
nil
|
213
|
+
else
|
214
|
+
CFnDK.logger.error("failed create change set: #{change_set_name}".color(:red))
|
215
|
+
raise ex
|
216
|
+
end
|
109
217
|
end
|
110
218
|
|
111
219
|
def wait_until_create_change_set
|
112
220
|
return if @option[:stack_names].instance_of?(Array) && !@option[:stack_names].include?(@name)
|
113
|
-
|
114
|
-
|
115
|
-
|
221
|
+
return unless @enabled
|
222
|
+
return unless exits?
|
223
|
+
CFnDK.logger.info(('waiting create change set: ' + change_set_name).color(:green))
|
224
|
+
@client.wait_until(
|
225
|
+
:change_set_create_complete,
|
226
|
+
stack_name: name,
|
227
|
+
change_set_name: change_set_name
|
228
|
+
) do |w|
|
229
|
+
w.max_attempts = 360
|
230
|
+
w.delay = 10
|
231
|
+
end
|
232
|
+
CFnDK.logger.info("created change set: #{change_set_name}".color(:green))
|
233
|
+
rescue Aws::Waiters::Errors::FailureStateError => ex
|
234
|
+
case ex.message
|
235
|
+
when 'stopped waiting, encountered a failure state'
|
236
|
+
unless available_change_set?
|
237
|
+
delete_change_set
|
238
|
+
CFnDK.logger.warn("failed create change set because this change set is UNAVAILABLE: #{change_set_name}".color(:orange))
|
239
|
+
return
|
240
|
+
end
|
241
|
+
end
|
242
|
+
raise ex
|
243
|
+
end
|
244
|
+
|
245
|
+
def execute_change_set
|
246
|
+
return nil if @option[:stack_names].instance_of?(Array) && !@option[:stack_names].include?(@name)
|
247
|
+
return unless @enabled
|
248
|
+
if available_change_set?
|
249
|
+
CFnDK.logger.info(('executing change set: ' + change_set_name).color(:green))
|
250
|
+
@client.execute_change_set(
|
116
251
|
stack_name: name,
|
117
|
-
change_set_name:
|
118
|
-
)
|
119
|
-
@logger.info(('created chnage set: ' + name).color(:green))
|
120
|
-
rescue Aws::Waiters::Errors::FailureStateError => ex
|
121
|
-
resp = @client.describe_change_set(
|
122
|
-
change_set_name: name,
|
123
|
-
stack_name: name
|
252
|
+
change_set_name: change_set_name
|
124
253
|
)
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
254
|
+
CFnDK.logger.info(('execute change set: ' + change_set_name).color(:green))
|
255
|
+
@name
|
256
|
+
else
|
257
|
+
CFnDK.logger.warn("failed execute change set because this change set is not AVAILABLE: #{change_set_name}".color(:orange))
|
258
|
+
nil
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
def delete_change_set
|
263
|
+
return if @option[:stack_names].instance_of?(Array) && !@option[:stack_names].include?(@name)
|
264
|
+
return unless @enabled
|
265
|
+
CFnDK.logger.info(('deleting change set: ' + change_set_name).color(:green))
|
266
|
+
@client.delete_change_set(
|
267
|
+
stack_name: name,
|
268
|
+
change_set_name: change_set_name
|
269
|
+
)
|
270
|
+
CFnDK.logger.info(('deleted change set: ' + change_set_name).color(:green))
|
271
|
+
end
|
272
|
+
|
273
|
+
def report_change_set
|
274
|
+
return if @option[:stack_names].instance_of?(Array) && !@option[:stack_names].include?(@name)
|
275
|
+
return unless @enabled
|
276
|
+
CFnDK.logger.info('*****************************************************'.color(:green))
|
277
|
+
CFnDK.logger.info(('change set: ' + change_set_name).color(:green))
|
278
|
+
CFnDK.logger.info('*****************************************************'.color(:green))
|
279
|
+
CFnDK.logger.info('')
|
280
|
+
resp = @client.describe_change_set(
|
281
|
+
change_set_name: change_set_name,
|
282
|
+
stack_name: name
|
283
|
+
)
|
284
|
+
CFnDK.logger.info('Execution Status: '.color(:green) + colored_status(resp.execution_status))
|
285
|
+
CFnDK.logger.info('Status: '.color(:green) + colored_status(resp.status))
|
286
|
+
CFnDK.logger.info('Reason: '.color(:green) + resp.status_reason) if resp.status_reason
|
287
|
+
if @option[:types].instance_of?(Array) && @option[:types].include?('tag')
|
288
|
+
CFnDK.logger.info('Tags:'.color(:green))
|
289
|
+
tags_rows = resp.tags.map do |item|
|
290
|
+
[
|
291
|
+
item.key,
|
292
|
+
item.value,
|
293
|
+
]
|
294
|
+
end
|
295
|
+
unless tags_rows.empty?
|
296
|
+
table = Terminal::Table.new headings: %w(Key Value), rows: tags_rows
|
297
|
+
CFnDK.logger.info table
|
298
|
+
end
|
299
|
+
end
|
300
|
+
if @option[:types].instance_of?(Array) && @option[:types].include?('parameter')
|
301
|
+
CFnDK.logger.info('Parameters:'.color(:green))
|
302
|
+
parameter_rows = resp.parameters.map do |item|
|
303
|
+
[
|
304
|
+
item.parameter_key,
|
305
|
+
item.parameter_value,
|
306
|
+
item.use_previous_value,
|
307
|
+
item.resolved_value,
|
308
|
+
]
|
309
|
+
end
|
310
|
+
unless parameter_rows.empty?
|
311
|
+
table = Terminal::Table.new headings: ['Key', 'Value', 'Use Previous Value', 'Resolved Value'], rows: parameter_rows
|
312
|
+
CFnDK.logger.info table
|
313
|
+
end
|
314
|
+
end
|
315
|
+
if @option[:types].instance_of?(Array) && @option[:types].include?('changes')
|
316
|
+
CFnDK.logger.info('Changes:'.color(:green))
|
317
|
+
changes_rows = resp.changes.map do |item|
|
318
|
+
[
|
319
|
+
item.resource_change.action,
|
320
|
+
item.resource_change.logical_resource_id,
|
321
|
+
item.resource_change.physical_resource_id,
|
322
|
+
item.resource_change.resource_type,
|
323
|
+
item.resource_change.replacement,
|
324
|
+
]
|
325
|
+
end
|
326
|
+
unless changes_rows.empty?
|
327
|
+
table = Terminal::Table.new headings: %w(Action Logical Physical Type Replacement), rows: changes_rows
|
328
|
+
CFnDK.logger.info table
|
136
329
|
end
|
137
330
|
end
|
331
|
+
rescue Aws::CloudFormation::Errors::ValidationError => ex
|
332
|
+
CFnDK.logger.warn "#{ex.class}: #{ex.message}".color(:red)
|
333
|
+
rescue Aws::CloudFormation::Errors::ChangeSetNotFound => ex
|
334
|
+
CFnDK.logger.warn "#{ex.class}: #{ex.message}".color(:red)
|
138
335
|
end
|
139
336
|
|
140
337
|
def validate
|
141
338
|
return if @option[:stack_names].instance_of?(Array) && !@option[:stack_names].include?(@name)
|
142
|
-
|
143
|
-
|
339
|
+
return unless @enabled
|
340
|
+
CFnDK.logger.info(('validate stack: ' + name).color(:green))
|
341
|
+
CFnDK.logger.debug('Name :' + @name)
|
342
|
+
hash = {}
|
343
|
+
if @tp.large_template?
|
344
|
+
hash[:template_url] = @tp.upload_template_file()
|
345
|
+
else
|
346
|
+
hash[:template_body] = @tp.template_body()
|
347
|
+
end
|
144
348
|
@client.validate_template(
|
145
|
-
|
349
|
+
hash
|
146
350
|
)
|
147
351
|
end
|
148
352
|
|
@@ -155,71 +359,140 @@ module CFnDK
|
|
155
359
|
false
|
156
360
|
end
|
157
361
|
|
158
|
-
def
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
[
|
167
|
-
item.stack_name,
|
168
|
-
item.creation_time,
|
169
|
-
item.deletion_time,
|
170
|
-
colored_status(item.stack_status),
|
171
|
-
item.stack_status_reason]
|
172
|
-
end
|
173
|
-
table = Terminal::Table.new headings: %w(Name Creation Deletion Status Reason), rows: rows
|
174
|
-
@logger.info table
|
175
|
-
rescue Aws::CloudFormation::Errors::ValidationError => ex
|
176
|
-
@logger.warn ex.message
|
177
|
-
end
|
362
|
+
def created?
|
363
|
+
resp = @client.describe_stacks(
|
364
|
+
stack_name: name
|
365
|
+
)
|
366
|
+
return false if resp.stacks[0].stack_status == 'REVIEW_IN_PROGRESS'
|
367
|
+
true
|
368
|
+
rescue Aws::CloudFormation::Errors::ValidationError
|
369
|
+
false
|
178
370
|
end
|
179
371
|
|
180
|
-
def
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
372
|
+
def review_in_progress?
|
373
|
+
resp = @client.describe_stacks(
|
374
|
+
stack_name: name
|
375
|
+
)
|
376
|
+
return true if resp.stacks[0].stack_status == 'REVIEW_IN_PROGRESS'
|
377
|
+
false
|
378
|
+
rescue Aws::CloudFormation::Errors::ValidationError
|
379
|
+
false
|
380
|
+
end
|
381
|
+
|
382
|
+
def available_change_set?
|
383
|
+
resp = @client.describe_change_set(
|
384
|
+
change_set_name: change_set_name,
|
385
|
+
stack_name: name
|
386
|
+
)
|
387
|
+
return true if resp.execution_status == 'AVAILABLE'
|
388
|
+
false
|
389
|
+
rescue Aws::CloudFormation::Errors::ChangeSetNotFound
|
390
|
+
false
|
199
391
|
end
|
200
392
|
|
201
|
-
def
|
393
|
+
def report
|
202
394
|
return if @option[:stack_names].instance_of?(Array) && !@option[:stack_names].include?(@name)
|
203
|
-
|
204
|
-
|
395
|
+
return unless @enabled
|
396
|
+
CFnDK.logger.info('*****************************************************'.color(:green))
|
397
|
+
CFnDK.logger.info(('stack: ' + name).color(:green))
|
398
|
+
CFnDK.logger.info('*****************************************************'.color(:green))
|
399
|
+
CFnDK.logger.info('')
|
205
400
|
begin
|
206
|
-
|
401
|
+
resp = @client.describe_stacks(
|
207
402
|
stack_name: name
|
208
|
-
).
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
403
|
+
).stacks[0]
|
404
|
+
CFnDK.logger.info('Status: '.color(:green) + colored_status(resp.stack_status))
|
405
|
+
CFnDK.logger.info('Reason: '.color(:green) + resp.stack_status_reason) if resp.stack_status_reason
|
406
|
+
if @option[:types].instance_of?(Array) && @option[:types].include?('tag')
|
407
|
+
CFnDK.logger.info('Tags:'.color(:green))
|
408
|
+
tags_rows = resp.tags.map do |item|
|
409
|
+
[
|
410
|
+
item.key,
|
411
|
+
item.value,
|
412
|
+
]
|
413
|
+
end
|
414
|
+
unless tags_rows.empty?
|
415
|
+
table = Terminal::Table.new headings: %w(Key Value), rows: tags_rows
|
416
|
+
CFnDK.logger.info table
|
417
|
+
end
|
418
|
+
end
|
419
|
+
if @option[:types].instance_of?(Array) && @option[:types].include?('parameter')
|
420
|
+
CFnDK.logger.info('Parameters:'.color(:green))
|
421
|
+
parameter_rows = resp.parameters.map do |item|
|
422
|
+
[
|
423
|
+
item.parameter_key,
|
424
|
+
item.parameter_value,
|
425
|
+
item.use_previous_value,
|
426
|
+
item.resolved_value,
|
427
|
+
]
|
428
|
+
end
|
429
|
+
unless parameter_rows.empty?
|
430
|
+
table = Terminal::Table.new headings: ['Key', 'Value', 'Use Previous Value', 'Resolved Value'], rows: parameter_rows
|
431
|
+
CFnDK.logger.info table
|
432
|
+
end
|
433
|
+
end
|
434
|
+
if @option[:types].instance_of?(Array) && @option[:types].include?('output')
|
435
|
+
CFnDK.logger.info('Outputs:'.color(:green))
|
436
|
+
output_rows = resp.outputs.map do |item|
|
437
|
+
[
|
438
|
+
item.output_key,
|
439
|
+
item.output_value,
|
440
|
+
item.export_name,
|
441
|
+
item.description,
|
442
|
+
]
|
443
|
+
end
|
444
|
+
unless output_rows.empty?
|
445
|
+
table = Terminal::Table.new headings: ['Key', 'Value', 'Export Name', 'Description'], rows: output_rows
|
446
|
+
CFnDK.logger.info table
|
447
|
+
end
|
218
448
|
end
|
219
|
-
table = Terminal::Table.new headings: %w(L-name P-name Type Timestamp Status Reason Desc), rows: rows
|
220
|
-
@logger.info table
|
221
449
|
rescue Aws::CloudFormation::Errors::ValidationError => ex
|
222
|
-
|
450
|
+
CFnDK.logger.warn "#{ex.class}: #{ex.message}".color(:red)
|
451
|
+
end
|
452
|
+
if @option[:types].instance_of?(Array) && @option[:types].include?('resource')
|
453
|
+
begin
|
454
|
+
CFnDK.logger.info('Resources:'.color(:green))
|
455
|
+
rows = @client.describe_stack_resources(
|
456
|
+
stack_name: name
|
457
|
+
).stack_resources.map do |item|
|
458
|
+
[
|
459
|
+
item.logical_resource_id,
|
460
|
+
item.physical_resource_id,
|
461
|
+
item.resource_type,
|
462
|
+
item.timestamp,
|
463
|
+
colored_status(item.resource_status),
|
464
|
+
item.resource_status_reason,
|
465
|
+
item.description,
|
466
|
+
]
|
467
|
+
end
|
468
|
+
unless rows.empty?
|
469
|
+
table = Terminal::Table.new headings: %w(Logical Physical Type Timestamp Status Reason Desc), rows: rows
|
470
|
+
CFnDK.logger.info table
|
471
|
+
end
|
472
|
+
rescue Aws::CloudFormation::Errors::ValidationError => ex
|
473
|
+
CFnDK.logger.warn "#{ex.class}: #{ex.message}".color(:red)
|
474
|
+
end
|
475
|
+
end
|
476
|
+
if @option[:types].instance_of?(Array) && @option[:types].include?('event')
|
477
|
+
CFnDK.logger.info('Events:'.color(:green))
|
478
|
+
begin
|
479
|
+
rows = @client.describe_stack_events(
|
480
|
+
stack_name: name
|
481
|
+
).stack_events.map do |item|
|
482
|
+
[
|
483
|
+
item.resource_type,
|
484
|
+
item.timestamp,
|
485
|
+
colored_status(item.resource_status),
|
486
|
+
item.resource_status_reason,
|
487
|
+
]
|
488
|
+
end
|
489
|
+
unless rows.empty?
|
490
|
+
table = Terminal::Table.new headings: %w(Type Time Status Reason), rows: rows
|
491
|
+
CFnDK.logger.info table
|
492
|
+
end
|
493
|
+
rescue Aws::CloudFormation::Errors::ValidationError => ex
|
494
|
+
CFnDK.logger.warn "#{ex.class}: #{ex.message}".color(:red)
|
495
|
+
end
|
223
496
|
end
|
224
497
|
end
|
225
498
|
|
@@ -227,8 +500,8 @@ module CFnDK
|
|
227
500
|
[@name, @option[:uuid]].compact.join('-')
|
228
501
|
end
|
229
502
|
|
230
|
-
def
|
231
|
-
|
503
|
+
def change_set_name
|
504
|
+
[@name, @option[:change_set_uuid]].compact.join('-')
|
232
505
|
end
|
233
506
|
|
234
507
|
def parameters
|
@@ -242,6 +515,34 @@ module CFnDK
|
|
242
515
|
end.compact
|
243
516
|
end
|
244
517
|
|
518
|
+
def pre_command_execute
|
519
|
+
return if @option[:stack_names].instance_of?(Array) && !@option[:stack_names].include?(@name)
|
520
|
+
return unless @enabled
|
521
|
+
if @pre_command
|
522
|
+
CFnDK.logger.info(('execute pre command: ' + @pre_command).color(:green))
|
523
|
+
IO.popen(@pre_command, :err => [:child, :out]) do |io|
|
524
|
+
io.each_line do |line|
|
525
|
+
CFnDK.logger.info((line).color(:green))
|
526
|
+
end
|
527
|
+
end
|
528
|
+
raise 'pre command is error. status: ' + $?.exitstatus.to_s + ' command: ' + @pre_command if $?.exitstatus != 0
|
529
|
+
end
|
530
|
+
end
|
531
|
+
|
532
|
+
def post_command_execute
|
533
|
+
return if @option[:stack_names].instance_of?(Array) && !@option[:stack_names].include?(@name)
|
534
|
+
return unless @enabled
|
535
|
+
if @post_command
|
536
|
+
CFnDK.logger.info(('execute post command: ' + @post_command).color(:green))
|
537
|
+
IO.popen(@post_command, :err => [:child, :out]) do |io|
|
538
|
+
io.each_line do |line|
|
539
|
+
CFnDK.logger.info((line).color(:green))
|
540
|
+
end
|
541
|
+
end
|
542
|
+
raise 'post command is error. status: ' + $?.exitstatus.to_s + ' command: ' + @post_command if $?.exitstatus != 0
|
543
|
+
end
|
544
|
+
end
|
545
|
+
|
245
546
|
private
|
246
547
|
|
247
548
|
def colored_status(str)
|