cfndk 0.1.1 → 0.1.3

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.
Files changed (46) hide show
  1. checksums.yaml +5 -5
  2. data/.circleci/config.yml +8 -5
  3. data/.gitignore +1 -0
  4. data/.rspec +2 -0
  5. data/Gemfile +0 -11
  6. data/Gemfile.lock +1069 -587
  7. data/README.md +124 -10
  8. data/cfndk.gemspec +7 -2
  9. data/docker/Dockerfile +8 -0
  10. data/docker/build.sh +3 -0
  11. data/docker/cfndk.sh +14 -0
  12. data/lib/cfndk/change_set_command.rb +14 -8
  13. data/lib/cfndk/command.rb +14 -6
  14. data/lib/cfndk/credential_provider_chain.rb +12 -42
  15. data/lib/cfndk/credential_resolvable.rb +10 -0
  16. data/lib/cfndk/diff.rb +38 -0
  17. data/lib/cfndk/global_config.rb +33 -2
  18. data/lib/cfndk/key_pair.rb +33 -1
  19. data/lib/cfndk/key_pair_command.rb +10 -3
  20. data/lib/cfndk/key_pairs.rb +12 -0
  21. data/lib/cfndk/stack.rb +67 -60
  22. data/lib/cfndk/stack_command.rb +26 -8
  23. data/lib/cfndk/stacks.rb +16 -0
  24. data/lib/cfndk/template_packager.rb +210 -0
  25. data/lib/cfndk/uuid.rb +10 -0
  26. data/lib/cfndk/version.rb +1 -1
  27. data/lib/cfndk.rb +12 -1
  28. data/spec/cfndk_spec.rb +1 -1
  29. data/spec/cfndk_stack_create_spec.rb +365 -5
  30. data/spec/cfndk_stack_destroy_spec.rb +64 -0
  31. data/spec/cfndk_stack_update_spec.rb +86 -0
  32. data/spec/fixtures/big_vpc.yaml +533 -0
  33. data/spec/fixtures/lambda_function/index.js +4 -0
  34. data/spec/fixtures/lambda_function/lambda_function.json +4 -0
  35. data/spec/fixtures/lambda_function/lambda_function.yaml +28 -0
  36. data/spec/fixtures/nested_stack.json +35 -0
  37. data/spec/fixtures/nested_stack.yaml +20 -0
  38. data/spec/fixtures/serverless_function/index.js +4 -0
  39. data/spec/fixtures/serverless_function/serverless_function.json +4 -0
  40. data/spec/fixtures/serverless_function/serverless_function.yaml +21 -0
  41. data/spec/fixtures/stack.json +8 -0
  42. data/spec/fixtures/stack.template.json +39 -0
  43. data/spec/fixtures/stack.yaml +22 -0
  44. data/spec/fixtures/vpc.template.json +40 -0
  45. data/vagrant/Vagrantfile +89 -0
  46. metadata +117 -13
@@ -1,17 +1,22 @@
1
1
  module CFnDK
2
2
  class KeyPair
3
- attr_reader :key_file
3
+ attr_reader :key_file, :enabled, :pre_command, :post_command
4
4
  def initialize(name, data, option, global_config, credentials)
5
5
  @global_config = global_config
6
6
  @name = name
7
7
  data = {} unless data
8
8
  @key_file = data['key_file'] || nil
9
9
  @region = data['region'] || @global_config.region
10
+ @pre_command = data['pre_command'] || nil
11
+ @post_command = data['post_command'] || nil
12
+ @enabled = true
13
+ @enabled = false if data['enabled'] === false
10
14
  @option = option
11
15
  @client = Aws::EC2::Client.new(credentials: credentials, region: @region)
12
16
  end
13
17
 
14
18
  def create
19
+ return unless @enabled
15
20
  CFnDK.logger.info(('creating keypair: ' + name).color(:green))
16
21
  key_pair = @client.create_key_pair(
17
22
  key_name: name
@@ -22,6 +27,7 @@ module CFnDK
22
27
  end
23
28
 
24
29
  def destroy
30
+ return unless @enabled
25
31
  if exists?
26
32
  CFnDK.logger.info(('deleting keypair: ' + name).color(:green))
27
33
  @client.delete_key_pair(
@@ -51,6 +57,32 @@ module CFnDK
51
57
  @name
52
58
  end
53
59
 
60
+ def pre_command_execute
61
+ return unless @enabled
62
+ if @pre_command
63
+ CFnDK.logger.info(('execute pre command: ' + @pre_command).color(:green))
64
+ IO.popen(@pre_command, :err => [:child, :out]) do |io|
65
+ io.each_line do |line|
66
+ CFnDK.logger.info((line).color(:green))
67
+ end
68
+ end
69
+ raise 'pre command is error. status: ' + $?.exitstatus.to_s + ' command: ' + @pre_command if $?.exitstatus != 0
70
+ end
71
+ end
72
+
73
+ def post_command_execute
74
+ return unless @enabled
75
+ if @post_command
76
+ CFnDK.logger.info(('execute post command: ' + @post_command).color(:green))
77
+ IO.popen(@post_command, :err => [:child, :out]) do |io|
78
+ io.each_line do |line|
79
+ CFnDK.logger.info((line).color(:green))
80
+ end
81
+ end
82
+ raise 'post command is error. status: ' + $?.exitstatus.to_s + ' command: ' + @post_command if $?.exitstatus != 0
83
+ end
84
+ end
85
+
54
86
  private
55
87
 
56
88
  def create_key_file(key_pair)
@@ -2,6 +2,8 @@ module CFnDK
2
2
  class KeyPairCommand < Thor
3
3
  include SubcommandHelpReturnable
4
4
  include ConfigFileLoadable
5
+ include CredentialResolvable
6
+
5
7
  class_option :verbose, type: :boolean, aliases: 'v', desc: 'More verbose output.'
6
8
  class_option :color, type: :boolean, default: true, desc: 'Use colored output'
7
9
  class_option :config_path, type: :string, aliases: 'c', default: "#{Dir.getwd}/cfndk.yml", desc: 'The configuration file to use'
@@ -13,10 +15,15 @@ module CFnDK
13
15
  def create
14
16
  CFnDK.logger.info 'create...'.color(:green)
15
17
  data = load_config_data(options)
16
-
17
- credentials = CFnDK::CredentialProviderChain.new.resolve
18
+ credentials = resolve_credential(data, options)
19
+ global_config = CFnDK::GlobalConfig.new(data, options)
18
20
  keypairs = CFnDK::KeyPairs.new(data, options, credentials)
21
+
22
+ global_config.pre_command_execute
23
+ keypairs.pre_command_execute
19
24
  keypairs.create
25
+ keypairs.post_command_execute
26
+ global_config.post_command_execute
20
27
  return 0
21
28
  rescue => e
22
29
  CFnDK.logger.error "#{e.class}: #{e.message}".color(:red)
@@ -31,8 +38,8 @@ module CFnDK
31
38
  def destroy
32
39
  CFnDK.logger.info 'destroy...'.color(:green)
33
40
  data = load_config_data(options)
41
+ credentials = resolve_credential(data, options)
34
42
 
35
- credentials = CFnDK::CredentialProviderChain.new.resolve
36
43
  keypairs = CFnDK::KeyPairs.new(data, options, credentials)
37
44
 
38
45
  if options[:force] || yes?('Are you sure you want to destroy? (y/n)', :yellow)
@@ -21,6 +21,18 @@ module CFnDK
21
21
  end
22
22
  end
23
23
 
24
+ def pre_command_execute
25
+ @keypairs.each_value do |keypair|
26
+ keypair.pre_command_execute
27
+ end
28
+ end
29
+
30
+ def post_command_execute
31
+ @keypairs.each_value do |keypair|
32
+ keypair.post_command_execute
33
+ end
34
+ end
35
+
24
36
  private
25
37
 
26
38
  def prepare_keypairs(data)
data/lib/cfndk/stack.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  module CFnDK
2
2
  class Stack
3
- attr_reader :template_file, :parameter_input, :capabilities, :depends, :timeout_in_minutes, :region
3
+ attr_reader :template_file, :parameter_input, :capabilities, :depends, :timeout_in_minutes, :region, :role_arn, :package, :enabled, :pre_command, :post_command
4
4
  def initialize(name, data, option, global_config, credentials)
5
5
  @global_config = global_config
6
6
  @name = name
@@ -9,16 +9,24 @@ module CFnDK
9
9
  @capabilities = data['capabilities'] || []
10
10
  @depends = data['depends'] || []
11
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
12
18
  @timeout_in_minutes = data['timeout_in_minutes'] || @global_config.timeout_in_minutes
13
19
  @override_parameters = data['parameters'] || {}
14
20
  @option = option
15
21
  @client = Aws::CloudFormation::Client.new(credentials: credentials, region: @region)
16
22
  @s3_client = Aws::S3::Client.new(credentials: credentials, region: @region)
17
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)
18
25
  end
19
26
 
20
27
  def create
21
28
  return if @option[:stack_names].instance_of?(Array) && !@option[:stack_names].include?(@name)
29
+ return unless @enabled
22
30
  CFnDK.logger.info(('creating stack: ' + name).color(:green))
23
31
  CFnDK.logger.debug('Name :' + name)
24
32
  CFnDK.logger.debug('Parametres :' + parameters.inspect)
@@ -42,10 +50,12 @@ module CFnDK
42
50
  timeout_in_minutes: timeout_in_minutes,
43
51
  tags: tags,
44
52
  }
45
- if large_template?
46
- hash[:template_url] = upload_template_file()
53
+ hash[:role_arn] = @role_arn if @role_arn
54
+
55
+ if @tp.large_template?
56
+ hash[:template_url] = @tp.upload_template_file()
47
57
  else
48
- hash[:template_body] = template_body()
58
+ hash[:template_body] = @tp.template_body()
49
59
  end
50
60
  @client.create_stack(
51
61
  hash
@@ -54,6 +64,7 @@ module CFnDK
54
64
 
55
65
  def wait_until_create
56
66
  return if @option[:stack_names].instance_of?(Array) && !@option[:stack_names].include?(@name)
67
+ return unless @enabled
57
68
  CFnDK.logger.info(('waiting create stack: ' + name).color(:green))
58
69
  begin
59
70
  @client.wait_until(
@@ -74,6 +85,7 @@ module CFnDK
74
85
 
75
86
  def update
76
87
  return false if @option[:stack_names].instance_of?(Array) && !@option[:stack_names].include?(@name)
88
+ return unless @enabled
77
89
  CFnDK.logger.info(('updating stack: ' + name).color(:green))
78
90
  CFnDK.logger.debug('Name :' + name)
79
91
  CFnDK.logger.debug('Parametres :' + parameters.inspect)
@@ -86,10 +98,11 @@ module CFnDK
86
98
  parameters: parameters,
87
99
  capabilities: capabilities,
88
100
  }
89
- if large_template?
90
- hash[:template_url] = upload_template_file()
101
+ hash[:role_arn] = @role_arn if @role_arn
102
+ if @tp.large_template?
103
+ hash[:template_url] = @tp.upload_template_file()
91
104
  else
92
- hash[:template_body] = template_body()
105
+ hash[:template_body] = @tp.template_body()
93
106
  end
94
107
  @client.update_stack(
95
108
  hash
@@ -108,6 +121,7 @@ module CFnDK
108
121
 
109
122
  def wait_until_update
110
123
  return if @option[:stack_names].instance_of?(Array) && !@option[:stack_names].include?(@name)
124
+ return unless @enabled
111
125
  CFnDK.logger.info(('waiting update stack: ' + name).color(:green))
112
126
  @client.wait_until(
113
127
  :stack_update_complete,
@@ -121,12 +135,17 @@ module CFnDK
121
135
 
122
136
  def destroy
123
137
  return if @option[:stack_names].instance_of?(Array) && !@option[:stack_names].include?(@name)
138
+ return unless @enabled
124
139
  if exits?
125
140
  CFnDK.logger.info(('deleting stack: ' + name).color(:green))
126
141
  CFnDK.logger.debug('Name :' + name)
127
142
  CFnDK.logger.debug('Region :' + region)
143
+ hash = {
144
+ stack_name: name,
145
+ }
146
+ hash[:role_arn] = @role_arn if @role_arn
128
147
  @client.delete_stack(
129
- stack_name: name
148
+ hash
130
149
  )
131
150
  else
132
151
  CFnDK.logger.info(('do not delete stack: ' + name).color(:red))
@@ -135,6 +154,7 @@ module CFnDK
135
154
 
136
155
  def wait_until_destroy
137
156
  return if @option[:stack_names].instance_of?(Array) && !@option[:stack_names].include?(@name)
157
+ return unless @enabled
138
158
  return unless exits?
139
159
  CFnDK.logger.info(('waiting delete stack: ' + name).color(:green))
140
160
  @client.wait_until(
@@ -149,6 +169,7 @@ module CFnDK
149
169
 
150
170
  def create_change_set
151
171
  return nil if @option[:stack_names].instance_of?(Array) && !@option[:stack_names].include?(@name)
172
+ return unless @enabled
152
173
  CFnDK.logger.info(('creating change set: ' + change_set_name).color(:green))
153
174
  CFnDK.logger.debug('Parametres :' + parameters.inspect)
154
175
  CFnDK.logger.debug('Capabilities:' + capabilities.inspect)
@@ -175,10 +196,11 @@ module CFnDK
175
196
  change_set_type: exits? ? 'UPDATE' : 'CREATE',
176
197
  tags: tags,
177
198
  }
178
- if large_template?
179
- hash[:template_url] = upload_template_file()
199
+ hash[:role_arn] = @role_arn if @role_arn
200
+ if @tp.large_template?
201
+ hash[:template_url] = @tp.upload_template_file()
180
202
  else
181
- hash[:template_body] = template_body()
203
+ hash[:template_body] = @tp.template_body()
182
204
  end
183
205
  @client.create_change_set(
184
206
  hash
@@ -196,6 +218,7 @@ module CFnDK
196
218
 
197
219
  def wait_until_create_change_set
198
220
  return if @option[:stack_names].instance_of?(Array) && !@option[:stack_names].include?(@name)
221
+ return unless @enabled
199
222
  return unless exits?
200
223
  CFnDK.logger.info(('waiting create change set: ' + change_set_name).color(:green))
201
224
  @client.wait_until(
@@ -221,6 +244,7 @@ module CFnDK
221
244
 
222
245
  def execute_change_set
223
246
  return nil if @option[:stack_names].instance_of?(Array) && !@option[:stack_names].include?(@name)
247
+ return unless @enabled
224
248
  if available_change_set?
225
249
  CFnDK.logger.info(('executing change set: ' + change_set_name).color(:green))
226
250
  @client.execute_change_set(
@@ -237,6 +261,7 @@ module CFnDK
237
261
 
238
262
  def delete_change_set
239
263
  return if @option[:stack_names].instance_of?(Array) && !@option[:stack_names].include?(@name)
264
+ return unless @enabled
240
265
  CFnDK.logger.info(('deleting change set: ' + change_set_name).color(:green))
241
266
  @client.delete_change_set(
242
267
  stack_name: name,
@@ -247,6 +272,7 @@ module CFnDK
247
272
 
248
273
  def report_change_set
249
274
  return if @option[:stack_names].instance_of?(Array) && !@option[:stack_names].include?(@name)
275
+ return unless @enabled
250
276
  CFnDK.logger.info('*****************************************************'.color(:green))
251
277
  CFnDK.logger.info(('change set: ' + change_set_name).color(:green))
252
278
  CFnDK.logger.info('*****************************************************'.color(:green))
@@ -310,13 +336,14 @@ module CFnDK
310
336
 
311
337
  def validate
312
338
  return if @option[:stack_names].instance_of?(Array) && !@option[:stack_names].include?(@name)
339
+ return unless @enabled
313
340
  CFnDK.logger.info(('validate stack: ' + name).color(:green))
314
341
  CFnDK.logger.debug('Name :' + @name)
315
342
  hash = {}
316
- if large_template?
317
- hash[:template_url] = upload_template_file()
343
+ if @tp.large_template?
344
+ hash[:template_url] = @tp.upload_template_file()
318
345
  else
319
- hash[:template_body] = template_body()
346
+ hash[:template_body] = @tp.template_body()
320
347
  end
321
348
  @client.validate_template(
322
349
  hash
@@ -365,6 +392,7 @@ module CFnDK
365
392
 
366
393
  def report
367
394
  return if @option[:stack_names].instance_of?(Array) && !@option[:stack_names].include?(@name)
395
+ return unless @enabled
368
396
  CFnDK.logger.info('*****************************************************'.color(:green))
369
397
  CFnDK.logger.info(('stack: ' + name).color(:green))
370
398
  CFnDK.logger.info('*****************************************************'.color(:green))
@@ -476,14 +504,6 @@ module CFnDK
476
504
  [@name, @option[:change_set_uuid]].compact.join('-')
477
505
  end
478
506
 
479
- def template_body
480
- File.open(@template_file, 'r').read
481
- end
482
-
483
- def large_template?
484
- File.size(@template_file) > 51200
485
- end
486
-
487
507
  def parameters
488
508
  json = JSON.load(open(@parameter_input).read)
489
509
  json['Parameters'].map do |item|
@@ -495,49 +515,36 @@ module CFnDK
495
515
  end.compact
496
516
  end
497
517
 
498
- private
499
-
500
- def upload_template_file
501
- begin
502
- @s3_client.head_bucket(bucket: bucket_name)
503
- rescue Aws::S3::Errors::NotFound, Aws::S3::Errors::Forbidden
504
- @s3_client.create_bucket(bucket: bucket_name)
505
- CFnDK.logger.info('Creatt S3 bucket: ' + bucket_name)
506
- @s3_client.put_bucket_lifecycle_configuration(
507
- bucket: bucket_name,
508
- lifecycle_configuration: {
509
- rules: [
510
- {
511
- expiration: {
512
- days: 1,
513
- },
514
- status: 'Enabled',
515
- id: 'Delete Old Files',
516
- prefix: '',
517
- abort_incomplete_multipart_upload: {
518
- days_after_initiation: 1,
519
- },
520
- },
521
- ],
522
- }
523
- )
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
524
529
  end
525
- key = [@global_config.s3_template_hash, @template_file].compact.join('/')
526
- @s3_client.put_object(
527
- body: template_body,
528
- bucket: bucket_name,
529
- key: key
530
- )
531
- url = "https://s3.amazonaws.com/#{bucket_name}/#{key}"
532
- CFnDK.logger.info('Put S3 object: ' + url)
533
- url
534
530
  end
535
531
 
536
- def bucket_name
537
- resp = @sts_client.get_caller_identity({})
538
- resp.account + '-' + @region + '-' + @global_config.s3_template_bucket
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
539
544
  end
540
545
 
546
+ private
547
+
541
548
  def colored_status(str)
542
549
  case str
543
550
  when 'CREATE_FAILED' then
@@ -2,11 +2,12 @@ module CFnDK
2
2
  class StackCommand < Thor
3
3
  include SubcommandHelpReturnable
4
4
  include ConfigFileLoadable
5
+ include CredentialResolvable
5
6
 
6
7
  class_option :verbose, type: :boolean, aliases: 'v', desc: 'More verbose output.'
7
8
  class_option :color, type: :boolean, default: true, desc: 'Use colored output'
8
9
  class_option :config_path, type: :string, aliases: 'c', default: "#{Dir.getwd}/cfndk.yml", desc: 'The configuration file to use'
9
- class_option :stack_names, type: :array, desc: 'Target stack names'
10
+ class_option :stack_names, type: :array, aliases: 's', desc: 'Target stack names'
10
11
 
11
12
  desc 'create', 'Create stack'
12
13
  option :uuid, type: :string, aliases: 'u', default: ENV['CFNDK_UUID'] || nil, desc: 'Use UUID'
@@ -14,11 +15,16 @@ module CFnDK
14
15
  def create
15
16
  CFnDK.logger.info 'create...'.color(:green)
16
17
  data = load_config_data(options)
17
-
18
- credentials = CFnDK::CredentialProviderChain.new.resolve
18
+ credentials = resolve_credential(data, options)
19
+ global_config = CFnDK::GlobalConfig.new(data, options)
19
20
  stacks = CFnDK::Stacks.new(data, options, credentials)
21
+
22
+ global_config.pre_command_execute
23
+ stacks.pre_command_execute
20
24
  stacks.validate
21
25
  stacks.create
26
+ stacks.post_command_execute
27
+ global_config.post_command_execute
22
28
  return 0
23
29
  rescue => e
24
30
  CFnDK.logger.error "#{e.class}: #{e.message}".color(:red)
@@ -34,11 +40,16 @@ module CFnDK
34
40
  def update
35
41
  CFnDK.logger.info 'update...'.color(:green)
36
42
  data = load_config_data(options)
37
-
38
- credentials = CFnDK::CredentialProviderChain.new.resolve
43
+ credentials = resolve_credential(data, options)
44
+ global_config = CFnDK::GlobalConfig.new(data, options)
39
45
  stacks = CFnDK::Stacks.new(data, options, credentials)
46
+
47
+ global_config.pre_command_execute
48
+ stacks.pre_command_execute
40
49
  stacks.validate
41
50
  stacks.update
51
+ stacks.post_command_execute
52
+ global_config.post_command_execute
42
53
  return 0
43
54
  rescue => e
44
55
  CFnDK.logger.error "#{e.class}: #{e.message}".color(:red)
@@ -54,8 +65,8 @@ module CFnDK
54
65
  def destroy
55
66
  CFnDK.logger.info 'destroy...'.color(:green)
56
67
  data = load_config_data(options)
68
+ credentials = resolve_credential(data, options)
57
69
 
58
- credentials = CFnDK::CredentialProviderChain.new.resolve
59
70
  stacks = CFnDK::Stacks.new(data, options, credentials)
60
71
 
61
72
  if options[:force] || yes?('Are you sure you want to destroy? (y/n)', :yellow)
@@ -77,9 +88,15 @@ module CFnDK
77
88
  def validate
78
89
  CFnDK.logger.info 'validate...'.color(:green)
79
90
  data = load_config_data(options)
80
- credentials = CFnDK::CredentialProviderChain.new.resolve
91
+ credentials = resolve_credential(data, options)
92
+ global_config = CFnDK::GlobalConfig.new(data, options)
81
93
  stacks = CFnDK::Stacks.new(data, options, credentials)
94
+
95
+ global_config.pre_command_execute
96
+ stacks.pre_command_execute
82
97
  stacks.validate
98
+ stacks.post_command_execute
99
+ global_config.post_command_execute
83
100
  return 0
84
101
  rescue => e
85
102
  CFnDK.logger.error "#{e.class}: #{e.message}".color(:red)
@@ -95,7 +112,8 @@ module CFnDK
95
112
  def report
96
113
  CFnDK.logger.info 'report...'.color(:green)
97
114
  data = load_config_data(options)
98
- credentials = CFnDK::CredentialProviderChain.new.resolve
115
+ credentials = resolve_credential(data, options)
116
+
99
117
  stacks = CFnDK::Stacks.new(data, options, credentials)
100
118
  stacks.report
101
119
  return 0
data/lib/cfndk/stacks.rb CHANGED
@@ -107,6 +107,22 @@ module CFnDK
107
107
  end
108
108
  end
109
109
 
110
+ def pre_command_execute
111
+ @sequence.each do |stacks|
112
+ stacks.each do |name|
113
+ @stacks[name].pre_command_execute
114
+ end
115
+ end
116
+ end
117
+
118
+ def post_command_execute
119
+ @sequence.each do |stacks|
120
+ stacks.each do |name|
121
+ @stacks[name].post_command_execute
122
+ end
123
+ end
124
+ end
125
+
110
126
  private
111
127
 
112
128
  def prepare_stack(data)