cfndk 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +23 -14
  3. data/.gitignore +0 -1
  4. data/.rspec_parallel +6 -0
  5. data/Gemfile +1 -0
  6. data/Gemfile.lock +811 -0
  7. data/README.md +122 -10
  8. data/cfndk.gemspec +1 -0
  9. data/lib/cfndk/change_set_command.rb +97 -0
  10. data/lib/cfndk/command.rb +15 -181
  11. data/lib/cfndk/config_file_loadable.rb +13 -0
  12. data/lib/cfndk/global_config.rb +15 -0
  13. data/lib/cfndk/key_pair.rb +7 -4
  14. data/lib/cfndk/key_pair_command.rb +53 -0
  15. data/lib/cfndk/key_pairs.rb +2 -1
  16. data/lib/cfndk/logger.rb +1 -1
  17. data/lib/cfndk/stack.rb +382 -103
  18. data/lib/cfndk/stack_command.rb +110 -0
  19. data/lib/cfndk/stacks.rb +40 -14
  20. data/lib/cfndk/subcommand_help_returnable.rb +16 -0
  21. data/lib/cfndk/version.rb +1 -1
  22. data/lib/cfndk.rb +6 -0
  23. data/skel/cfndk.yml +4 -0
  24. data/spec/cfndk_change_set_create_spec.rb +436 -0
  25. data/spec/cfndk_change_set_destroy_spec.rb +160 -0
  26. data/spec/cfndk_change_set_execute_spec.rb +179 -0
  27. data/spec/cfndk_change_set_report_spec.rb +107 -0
  28. data/spec/cfndk_change_set_spec.rb +37 -0
  29. data/spec/cfndk_create_spec.rb +56 -141
  30. data/spec/cfndk_destroy_spec.rb +4 -2
  31. data/spec/cfndk_keypiar_spec.rb +11 -9
  32. data/spec/cfndk_report_spec.rb +3 -1
  33. data/spec/cfndk_spec.rb +5 -3
  34. data/spec/cfndk_stack_create_spec.rb +454 -0
  35. data/spec/cfndk_stack_destroy_spec.rb +161 -0
  36. data/spec/cfndk_stack_report_spec.rb +181 -0
  37. data/spec/cfndk_stack_spec.rb +6 -1146
  38. data/spec/cfndk_stack_update_spec.rb +467 -0
  39. data/spec/spec_helper.rb +4 -1
  40. data/spec/support/aruba.rb +1 -0
  41. metadata +42 -2
@@ -0,0 +1,110 @@
1
+ module CFnDK
2
+ class StackCommand < Thor
3
+ include SubcommandHelpReturnable
4
+ include ConfigFileLoadable
5
+
6
+ class_option :verbose, type: :boolean, aliases: 'v', desc: 'More verbose output.'
7
+ class_option :color, type: :boolean, default: true, desc: 'Use colored output'
8
+ 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
+
11
+ desc 'create', 'Create stack'
12
+ option :uuid, type: :string, aliases: 'u', default: ENV['CFNDK_UUID'] || nil, desc: 'Use UUID'
13
+ option :properties, type: :hash, aliases: 'p', default: {}, desc: 'Set property'
14
+ def create
15
+ CFnDK.logger.info 'create...'.color(:green)
16
+ data = load_config_data(options)
17
+
18
+ credentials = CFnDK::CredentialProviderChain.new.resolve
19
+ stacks = CFnDK::Stacks.new(data, options, credentials)
20
+ stacks.validate
21
+ stacks.create
22
+ return 0
23
+ rescue => e
24
+ CFnDK.logger.error "#{e.class}: #{e.message}".color(:red)
25
+ e.backtrace_locations.each do |line|
26
+ CFnDK.logger.debug line
27
+ end
28
+ return 1
29
+ end
30
+
31
+ desc 'update', 'Update stack'
32
+ option :uuid, type: :string, aliases: 'u', default: ENV['CFNDK_UUID'] || nil, desc: 'Use UUID'
33
+ option :properties, type: :hash, aliases: 'p', default: {}, desc: 'Set property'
34
+ def update
35
+ CFnDK.logger.info 'update...'.color(:green)
36
+ data = load_config_data(options)
37
+
38
+ credentials = CFnDK::CredentialProviderChain.new.resolve
39
+ stacks = CFnDK::Stacks.new(data, options, credentials)
40
+ stacks.validate
41
+ stacks.update
42
+ return 0
43
+ rescue => e
44
+ CFnDK.logger.error "#{e.class}: #{e.message}".color(:red)
45
+ e.backtrace_locations.each do |line|
46
+ CFnDK.logger.debug line
47
+ end
48
+ return 1
49
+ end
50
+
51
+ desc 'destroy', 'Destroy stack'
52
+ option :force, type: :boolean, aliases: 'f', default: false, desc: 'Say yes to all prompts for confirmation'
53
+ option :uuid, type: :string, aliases: 'u', default: ENV['CFNDK_UUID'] || nil, desc: 'Use UUID'
54
+ def destroy
55
+ CFnDK.logger.info 'destroy...'.color(:green)
56
+ data = load_config_data(options)
57
+
58
+ credentials = CFnDK::CredentialProviderChain.new.resolve
59
+ stacks = CFnDK::Stacks.new(data, options, credentials)
60
+
61
+ if options[:force] || yes?('Are you sure you want to destroy? (y/n)', :yellow)
62
+ stacks.destroy
63
+ return 0
64
+ else
65
+ CFnDK.logger.info 'destroy command was canceled'.color(:green)
66
+ return 2
67
+ end
68
+ rescue => e
69
+ CFnDK.logger.error "#{e.class}: #{e.message}".color(:red)
70
+ e.backtrace_locations.each do |line|
71
+ CFnDK.logger.debug line
72
+ end
73
+ return 1
74
+ end
75
+
76
+ desc 'validate', 'Validate stack'
77
+ def validate
78
+ CFnDK.logger.info 'validate...'.color(:green)
79
+ data = load_config_data(options)
80
+ credentials = CFnDK::CredentialProviderChain.new.resolve
81
+ stacks = CFnDK::Stacks.new(data, options, credentials)
82
+ stacks.validate
83
+ return 0
84
+ rescue => e
85
+ CFnDK.logger.error "#{e.class}: #{e.message}".color(:red)
86
+ e.backtrace_locations.each do |line|
87
+ CFnDK.logger.debug line
88
+ end
89
+ return 1
90
+ end
91
+
92
+ desc 'report', 'Report stack'
93
+ option :uuid, type: :string, aliases: 'u', default: ENV['CFNDK_UUID'] || nil, desc: 'Use UUID'
94
+ option :types, type: :array, default: %w(tag output parameter resource event), desc: 'Report type'
95
+ def report
96
+ CFnDK.logger.info 'report...'.color(:green)
97
+ data = load_config_data(options)
98
+ credentials = CFnDK::CredentialProviderChain.new.resolve
99
+ stacks = CFnDK::Stacks.new(data, options, credentials)
100
+ stacks.report
101
+ return 0
102
+ rescue => e
103
+ CFnDK.logger.error "#{e.class}: #{e.message}".color(:red)
104
+ e.backtrace_locations.each do |line|
105
+ CFnDK.logger.debug line
106
+ end
107
+ return 1
108
+ end
109
+ end
110
+ end
data/lib/cfndk/stacks.rb CHANGED
@@ -3,7 +3,7 @@ module CFnDK
3
3
  def initialize(data, option, credentials)
4
4
  @option = option
5
5
  @credentials = credentials
6
-
6
+ @global_config = CFnDK::GlobalConfig.new(data, option)
7
7
  prepare_stack(data)
8
8
  prepare_sequence
9
9
  end
@@ -51,24 +51,50 @@ module CFnDK
51
51
  end
52
52
  end
53
53
 
54
- def create_or_changeset
54
+ def create_change_set
55
55
  @sequence.each do |stacks|
56
- create_stacks = []
57
- changeset_stacks = []
56
+ wait_until_stacks = []
58
57
  stacks.each do |name|
59
- if @stacks[name].exits?
60
- @stacks[name].create_change_set
61
- changeset_stacks.push name
58
+ wait_until_stacks.push(@stacks[name].create_change_set)
59
+ end
60
+ wait_until_stacks.compact!
61
+ wait_until_stacks.each do |name|
62
+ @stacks[name].wait_until_create_change_set
63
+ end
64
+ end
65
+ end
66
+
67
+ def execute_change_set
68
+ @sequence.each do |stacks|
69
+ created_stacks = []
70
+ wait_until_stacks = []
71
+ stacks.each do |name|
72
+ created_stacks.push(name) if @stacks[name].created?
73
+ wait_until_stacks.push(@stacks[name].execute_change_set)
74
+ end
75
+ wait_until_stacks.compact!
76
+ wait_until_stacks.each do |name|
77
+ if created_stacks.include?(name)
78
+ @stacks[name].wait_until_update
62
79
  else
63
- @stacks[name].create
64
- create_stacks.push name
80
+ @stacks[name].wait_until_create
65
81
  end
66
82
  end
67
- create_stacks.each do |name|
68
- @stacks[name].wait_until_create
83
+ end
84
+ end
85
+
86
+ def delete_change_set
87
+ @sequence.reverse_each do |stacks|
88
+ stacks.each do |name|
89
+ @stacks[name].delete_change_set
69
90
  end
70
- changeset_stacks.each do |name|
71
- @stacks[name].wait_until_create_change_set
91
+ end
92
+ end
93
+
94
+ def report_change_set
95
+ @sequence.each do |stacks|
96
+ stacks.each do |name|
97
+ @stacks[name].report_change_set
72
98
  end
73
99
  end
74
100
  end
@@ -87,7 +113,7 @@ module CFnDK
87
113
  @stacks = {}
88
114
  return unless data['stacks'].is_a?(Hash)
89
115
  data['stacks'].each do |name, properties|
90
- @stacks[name] = Stack.new(name, properties, @option, @credentials)
116
+ @stacks[name] = Stack.new(name, properties, @option, @global_config, @credentials)
91
117
  end
92
118
  end
93
119
 
@@ -0,0 +1,16 @@
1
+ module CFnDK
2
+ module SubcommandHelpReturnable
3
+ module ClassMethods
4
+ def subcommand_help(cmd)
5
+ desc 'help [COMMAND]', 'Describe subcommands or one specific subcommand'
6
+ class_eval "
7
+ def help(command = nil, subcommand = true); super; return 2; end
8
+ "
9
+ end
10
+ end
11
+ extend ClassMethods
12
+ def self.included(klass)
13
+ klass.extend ClassMethods
14
+ end
15
+ end
16
+ end
data/lib/cfndk/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module CFnDK
2
- VERSION = '0.1.0'.freeze
2
+ VERSION = '0.1.1'.freeze
3
3
  end
data/lib/cfndk.rb CHANGED
@@ -25,8 +25,14 @@ require 'cfndk/stacks'
25
25
  require 'cfndk/key_pair'
26
26
  require 'cfndk/key_pairs'
27
27
  require 'cfndk/erb_string'
28
+ require 'cfndk/global_config'
28
29
  require 'cfndk/logger'
29
30
  require 'cfndk/credential_provider_chain'
31
+ require 'cfndk/subcommand_help_returnable'
32
+ require 'cfndk/config_file_loadable'
33
+ require 'cfndk/key_pair_command'
34
+ require 'cfndk/stack_command'
35
+ require 'cfndk/change_set_command'
30
36
  require 'cfndk/command'
31
37
 
32
38
  module CFnDK
data/skel/cfndk.yml CHANGED
@@ -1,3 +1,7 @@
1
+ global:
2
+ region: ap-northeast-1
3
+ s3_template_bucket: cfndk-templates
4
+ timeout_in_minutes: 10
1
5
  keypairs:
2
6
  CFnDKSampleKey:
3
7
  CFnDKSampleKey2:
@@ -0,0 +1,436 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe 'CFnDK', type: :aruba do
4
+ before(:each) { set_environment_variable('AWS_REGION', ENV['AWS_REGION']) }
5
+ before(:each) { set_environment_variable('AWS_PROFILE', ENV['AWS_PROFILE']) }
6
+ before(:each) { set_environment_variable('AWS_ACCESS_KEY_ID', ENV["AWS_ACCESS_KEY_ID#{ENV['TEST_ENV_NUMBER']}"]) }
7
+ before(:each) { set_environment_variable('AWS_SECRET_ACCESS_KEY', ENV["AWS_SECRET_ACCESS_KEY#{ENV['TEST_ENV_NUMBER']}"]) }
8
+ describe 'bin/cfndk' do
9
+ before(:each) { setup_aruba }
10
+ let(:file) { 'cfndk.yml' }
11
+ let(:file2) { 'cfndk2.yml' }
12
+ let(:uuid) { '38437346-c75c-47c5-83b4-d504f85e275b' }
13
+ let(:change_set_uuid) { '38437346-c75c-47c5-83b4-d504f85e27ca' }
14
+
15
+ describe 'changeset' do
16
+ describe 'create', create: true do
17
+ context 'without cfndk.yml' do
18
+ before(:each) { run_command('cfndk changeset create') }
19
+ it 'displays file does not exist error and status code = 1' do
20
+ aggregate_failures do
21
+ expect(last_command_started).to have_exit_status(1)
22
+ expect(last_command_started).to have_output(/ERROR RuntimeError: File does not exist./)
23
+ end
24
+ end
25
+ end
26
+
27
+ context 'with cfndk2.yml' do
28
+ yaml = <<-"YAML"
29
+ keypairs:
30
+ YAML
31
+ before(:each) { write_file(file2, yaml) }
32
+ context 'when -c cfndk2.yml and empty stacks' do
33
+ before(:each) { run_command("cfndk changeset create -c=#{file2}") }
34
+ it 'displays empty stack log' do
35
+ aggregate_failures do
36
+ expect(last_command_started).to be_successfully_executed
37
+ expect(last_command_started).to have_output(/INFO create.../)
38
+ end
39
+ end
40
+ end
41
+ end
42
+
43
+ context 'with cfndk.yml' do
44
+ context 'when cfndk.yml is empty' do
45
+ before(:each) { touch(file) }
46
+ before(:each) { run_command('cfndk changeset create') }
47
+ it 'displays File is empty error and status code = 1' do
48
+ aggregate_failures do
49
+ expect(last_command_started).to have_exit_status(1)
50
+ expect(last_command_started).to have_output(/ERROR File is empty./)
51
+ end
52
+ end
53
+ end
54
+
55
+ context 'with stacks:' do
56
+ context 'without stack' do
57
+ before(:each) { write_file(file, 'stacks:') }
58
+ before(:each) { run_command('cfndk changeset create') }
59
+ it 'displays create log' do
60
+ aggregate_failures do
61
+ expect(last_command_started).to be_successfully_executed
62
+ expect(last_command_started).to have_output(/INFO create.../)
63
+ end
64
+ end
65
+ end
66
+
67
+ context 'with a stack' do
68
+ yaml = <<-"YAML"
69
+ stacks:
70
+ Test:
71
+ template_file: vpc.yaml
72
+ parameter_input: vpc.json
73
+ timeout_in_minutes: 2
74
+ YAML
75
+ before(:each) { write_file(file, yaml) }
76
+ before(:each) { copy('%/vpc.yaml', 'vpc.yaml') }
77
+ before(:each) { copy('%/vpc.json', 'vpc.json') }
78
+ before(:each) { append_to_file('vpc.yaml', ' ' * (51200 + 1 - file_size('vpc.yaml').to_i)) }
79
+ before(:each) { run_command('cfndk changeset create') }
80
+ it 'displays created log' do
81
+ aggregate_failures do
82
+ expect(last_command_started).to be_successfully_executed
83
+ expect(last_command_started).to have_output(/INFO validate stack: Test$/)
84
+ expect(last_command_started).to have_output(/INFO creating change set: Test$/)
85
+ expect(last_command_started).to have_output(/INFO created change set: Test$/)
86
+ end
87
+ end
88
+ after(:each) { run_command('cfndk destroy -f') }
89
+ end
90
+ context 'with two stacks' do
91
+ yaml = <<-"YAML"
92
+ stacks:
93
+ Test:
94
+ template_file: vpc.yaml
95
+ parameter_input: vpc.json
96
+ timeout_in_minutes: 2
97
+ Test2:
98
+ template_file: sg.yaml
99
+ parameter_input: sg.json
100
+ depends:
101
+ - Test
102
+ YAML
103
+
104
+ before(:each) { write_file(file, yaml) }
105
+ before(:each) { copy('%/vpc.yaml', 'vpc.yaml') }
106
+ before(:each) { copy('%/vpc.json', 'vpc.json') }
107
+ before(:each) { copy('%/sg.yaml', 'sg.yaml') }
108
+ before(:each) { copy('%/sg.json', 'sg.json') }
109
+ before(:each) { run_command('cfndk changeset create') }
110
+ it 'displays created logs' do
111
+ aggregate_failures do
112
+ expect(last_command_started).to be_successfully_executed
113
+ expect(last_command_started).to have_output(/INFO validate stack: Test$/)
114
+ expect(last_command_started).to have_output(/INFO creating change set: Test$/)
115
+ expect(last_command_started).to have_output(/INFO created change set: Test$/)
116
+ expect(last_command_started).to have_output(/INFO validate stack: Test2$/)
117
+ expect(last_command_started).to have_output(/INFO creating change set: Test2$/)
118
+ expect(last_command_started).to have_output(/INFO created change set: Test2$/)
119
+ end
120
+ end
121
+ after(:each) { run_command('cfndk destroy -f') }
122
+ end
123
+ context 'when invalid dependency', dependency: true do
124
+ yaml = <<-"YAML"
125
+ stacks:
126
+ Test:
127
+ template_file: vpc.yaml
128
+ parameter_input: vpc.json
129
+ timeout_in_minutes: 2
130
+ depends:
131
+ - Test2
132
+ Test2:
133
+ template_file: sg.yaml
134
+ parameter_input: sg.json
135
+ YAML
136
+
137
+ before(:each) { write_file(file, yaml) }
138
+ before(:each) { copy('%/vpc.yaml', 'vpc.yaml') }
139
+ before(:each) { copy('%/vpc.json', 'vpc.json') }
140
+ before(:each) { copy('%/sg.yaml', 'sg.yaml') }
141
+ before(:each) { copy('%/sg.json', 'sg.json') }
142
+ before(:each) { run_command('cfndk changeset create') }
143
+ it 'displays created logs' do
144
+ aggregate_failures do
145
+ expect(last_command_started).to be_successfully_executed
146
+ expect(last_command_started).to have_output(/INFO validate stack: Test$/)
147
+ expect(last_command_started).to have_output(/INFO creating change set: Test$/)
148
+ expect(last_command_started).to have_output(/INFO created change set: Test$/)
149
+ expect(last_command_started).to have_output(/INFO validate stack: Test2$/)
150
+ expect(last_command_started).to have_output(/INFO creating change set: Test2$/)
151
+ expect(last_command_started).to have_output(/INFO created change set: Test2$/)
152
+ end
153
+ end
154
+ after(:each) { run_command('cfndk destroy -f') }
155
+ end
156
+ context 'when cyclic dependency', dependency: true do
157
+ yaml = <<-"YAML"
158
+ stacks:
159
+ Test:
160
+ template_file: vpc.yaml
161
+ parameter_input: vpc.json
162
+ timeout_in_minutes: 2
163
+ depends:
164
+ - Test2
165
+ Test2:
166
+ template_file: sg.yaml
167
+ parameter_input: sg.json
168
+ depends:
169
+ - Test
170
+ YAML
171
+
172
+ before(:each) { write_file(file, yaml) }
173
+ before(:each) { copy('%/vpc.yaml', 'vpc.yaml') }
174
+ before(:each) { copy('%/vpc.json', 'vpc.json') }
175
+ before(:each) { copy('%/sg.yaml', 'sg.yaml') }
176
+ before(:each) { copy('%/sg.json', 'sg.json') }
177
+ before(:each) { run_command('cfndk changeset create') }
178
+ it 'displays cyclic dependency error and exit code = 1' do
179
+ aggregate_failures do
180
+ expect(last_command_started).to have_exit_status(1)
181
+ expect(last_command_started).to have_output(/ERROR RuntimeError: There are cyclic dependency or stack doesn't exist. unprocessed_stack: Test,Test2$/)
182
+ end
183
+ end
184
+ after(:each) { run_command('cfndk destroy -f') }
185
+ end
186
+ context 'when requires capabilities without capabilities', capabilities: true do
187
+ yaml = <<-"YAML"
188
+ stacks:
189
+ Test:
190
+ template_file: iam.yaml
191
+ parameter_input: iam.json
192
+ timeout_in_minutes: 2
193
+ YAML
194
+
195
+ before(:each) { write_file(file, yaml) }
196
+ before(:each) { copy('%/iam.yaml', 'iam.yaml') }
197
+ before(:each) { copy('%/iam.json', 'iam.json') }
198
+ before(:each) { run_command('cfndk changeset create') }
199
+ it 'displays Requires capabilities error and exit code = 1' do
200
+ aggregate_failures do
201
+ expect(last_command_started).to have_exit_status(1)
202
+ expect(last_command_started).to have_output(/ERROR Aws::CloudFormation::Errors::InsufficientCapabilitiesException: Requires capabilities : \[CAPABILITY_NAMED_IAM\]/)
203
+ end
204
+ end
205
+ after(:each) { run_command('cfndk destroy -f') }
206
+ end
207
+ context 'when success with capabilities', capabilities: true do
208
+ yaml = <<-"YAML"
209
+ stacks:
210
+ Test:
211
+ template_file: iam.yaml
212
+ parameter_input: iam.json
213
+ capabilities:
214
+ - CAPABILITY_NAMED_IAM
215
+ timeout_in_minutes: 3
216
+ YAML
217
+
218
+ before(:each) { write_file(file, yaml) }
219
+ before(:each) { copy('%/iam.yaml', 'iam.yaml') }
220
+ before(:each) { copy('%/iam.json', 'iam.json') }
221
+ before(:each) { run_command('cfndk changeset create') }
222
+ it do
223
+ aggregate_failures do
224
+ expect(last_command_started).to be_successfully_executed
225
+ expect(last_command_started).to have_output(/INFO created change set: Test$/)
226
+ end
227
+ end
228
+ after(:each) { run_command('cfndk destroy -f') }
229
+ end
230
+ context 'with UUID', uuid: true do
231
+ context 'when -u 38437346-c75c-47c5-83b4-d504f85e275b' do
232
+ yaml = <<-"YAML"
233
+ stacks:
234
+ Test:
235
+ template_file: vpc.yaml
236
+ parameter_input: vpc.json
237
+ parameters:
238
+ VpcName: sample<%= append_uuid%>
239
+ timeout_in_minutes: 2
240
+ Test2:
241
+ template_file: sg.yaml
242
+ parameter_input: sg.json
243
+ parameters:
244
+ VpcName: sample<%= append_uuid%>
245
+ depends:
246
+ - Test
247
+ YAML
248
+ before(:each) { write_file(file, yaml) }
249
+ before(:each) { copy('%/vpc.yaml', 'vpc.yaml') }
250
+ before(:each) { copy('%/vpc.json', 'vpc.json') }
251
+ before(:each) { copy('%/sg.yaml', 'sg.yaml') }
252
+ before(:each) { copy('%/sg.json', 'sg.json') }
253
+ before(:each) { run_command("cfndk changeset create -u=#{uuid}") }
254
+ it do
255
+ aggregate_failures do
256
+ expect(last_command_started).to be_successfully_executed
257
+ expect(last_command_started).to have_output(/INFO validate stack: Test-#{uuid}$/)
258
+ expect(last_command_started).to have_output(/INFO creating change set: Test$/)
259
+ expect(last_command_started).to have_output(/INFO created change set: Test$/)
260
+ expect(last_command_started).to have_output(/INFO validate stack: Test2-#{uuid}$/)
261
+ expect(last_command_started).to have_output(/INFO creating change set: Test2$/)
262
+ expect(last_command_started).to have_output(/INFO created change set: Test2$/)
263
+ end
264
+ end
265
+ after(:each) { run_command("cfndk destroy -f -u=#{uuid}") }
266
+ end
267
+ context 'when env CFNDK_UUID=38437346-c75c-47c5-83b4-d504f85e275b' do
268
+ before(:each) { set_environment_variable('CFNDK_UUID', uuid) }
269
+ context 'with two stacks' do
270
+ yaml = <<-"YAML"
271
+ stacks:
272
+ Test:
273
+ template_file: vpc.yaml
274
+ parameter_input: vpc.json
275
+ parameters:
276
+ VpcName: sample<%= append_uuid%>
277
+ timeout_in_minutes: 2
278
+ Test2:
279
+ template_file: sg.yaml
280
+ parameter_input: sg.json
281
+ parameters:
282
+ VpcName: sample<%= append_uuid%>
283
+ depends:
284
+ - Test
285
+ YAML
286
+ before(:each) { write_file(file, yaml) }
287
+ before(:each) { copy('%/vpc.yaml', 'vpc.yaml') }
288
+ before(:each) { copy('%/vpc.json', 'vpc.json') }
289
+ before(:each) { copy('%/sg.yaml', 'sg.yaml') }
290
+ before(:each) { copy('%/sg.json', 'sg.json') }
291
+ before(:each) { run_command('cfndk changeset create') }
292
+ it do
293
+ aggregate_failures do
294
+ expect(last_command_started).to be_successfully_executed
295
+ expect(last_command_started).to have_output(/INFO validate stack: Test-#{uuid}$/)
296
+ expect(last_command_started).to have_output(/INFO creating change set: Test$/)
297
+ expect(last_command_started).to have_output(/INFO created change set: Test$/)
298
+ expect(last_command_started).to have_output(/INFO validate stack: Test2-#{uuid}$/)
299
+ expect(last_command_started).to have_output(/INFO creating change set: Test2$/)
300
+ expect(last_command_started).to have_output(/INFO created change set: Test2$/)
301
+ end
302
+ end
303
+ after(:each) { run_command('cfndk destroy -f') }
304
+ end
305
+ context 'when --stack-names=Test' do
306
+ yaml = <<-"YAML"
307
+ stacks:
308
+ Test:
309
+ template_file: vpc.yaml
310
+ parameter_input: vpc.json
311
+ parameters:
312
+ VpcName: sample<%= append_uuid%>
313
+ timeout_in_minutes: 2
314
+ Test2:
315
+ template_file: sg.yaml
316
+ parameter_input: sg.json
317
+ parameters:
318
+ VpcName: sample<%= append_uuid%>
319
+ depends:
320
+ - Test
321
+ YAML
322
+ before(:each) { write_file(file, yaml) }
323
+ before(:each) { copy('%/vpc.yaml', 'vpc.yaml') }
324
+ before(:each) { copy('%/vpc.json', 'vpc.json') }
325
+ before(:each) { copy('%/sg.yaml', 'sg.yaml') }
326
+ before(:each) { copy('%/sg.json', 'sg.json') }
327
+ before(:each) { run_command('cfndk changeset create --stack-names=Test') }
328
+ it do
329
+ aggregate_failures do
330
+ expect(last_command_started).to be_successfully_executed
331
+ expect(last_command_started).to have_output(/INFO create.../)
332
+ expect(last_command_started).to have_output(/INFO validate stack: Test-#{uuid}$/)
333
+ expect(last_command_started).to have_output(/INFO creating change set: Test$/)
334
+ expect(last_command_started).to have_output(/INFO created change set: Test$/)
335
+ expect(last_command_started).not_to have_output(/INFO validate stack: Test2-#{uuid}$/)
336
+ expect(last_command_started).not_to have_output(/INFO creating change set: Test2$/)
337
+ expect(last_command_started).not_to have_output(/INFO created change set: Test2$/)
338
+ end
339
+ end
340
+ after(:each) { run_command('cfndk destroy -f') }
341
+ end
342
+ context 'when --stack-names=Test Test2' do
343
+ yaml = <<-"YAML"
344
+ stacks:
345
+ Test:
346
+ template_file: vpc.yaml
347
+ parameter_input: vpc.json
348
+ parameters:
349
+ VpcName: sample<%= append_uuid%>
350
+ timeout_in_minutes: 2
351
+ Test2:
352
+ template_file: sg.yaml
353
+ parameter_input: sg.json
354
+ parameters:
355
+ VpcName: sample<%= append_uuid%>
356
+ depends:
357
+ - Test
358
+ Test3:
359
+ template_file: iam.yaml
360
+ parameter_input: iam.json
361
+ parameters:
362
+ WebRoleName: WebhRole<%= append_uuid%>
363
+ capabilities:
364
+ - CAPABILITY_NAMED_IAM
365
+ timeout_in_minutes: 3
366
+ YAML
367
+ before(:each) { write_file(file, yaml) }
368
+ before(:each) { copy('%/vpc.yaml', 'vpc.yaml') }
369
+ before(:each) { copy('%/vpc.json', 'vpc.json') }
370
+ before(:each) { copy('%/sg.yaml', 'sg.yaml') }
371
+ before(:each) { copy('%/sg.json', 'sg.json') }
372
+ before(:each) { copy('%/iam.yaml', 'iam.yaml') }
373
+ before(:each) { copy('%/iam.json', 'iam.json') }
374
+ before(:each) { run_command('cfndk changeset create --stack-names=Test Test2') }
375
+ it do
376
+ aggregate_failures do
377
+ expect(last_command_started).to be_successfully_executed
378
+ expect(last_command_started).to have_output(/INFO create.../)
379
+ expect(last_command_started).to have_output(/INFO validate stack: Test-#{uuid}$/)
380
+ expect(last_command_started).to have_output(/INFO creating change set: Test$/)
381
+ expect(last_command_started).to have_output(/INFO created change set: Test$/)
382
+ expect(last_command_started).to have_output(/INFO validate stack: Test2-#{uuid}$/)
383
+ expect(last_command_started).to have_output(/INFO creating change set: Test2$/)
384
+ expect(last_command_started).to have_output(/INFO created change set: Test2$/)
385
+ expect(last_command_started).not_to have_output(/INFO validate stack: Test3-#{uuid}$/)
386
+ expect(last_command_started).not_to have_output(/INFO creating change set: Test3$/)
387
+ expect(last_command_started).not_to have_output(/INFO created change set: Test3$/)
388
+ end
389
+ end
390
+ after(:each) { run_command('cfndk destroy -f') }
391
+ end
392
+ end
393
+
394
+ context 'when -u 38437346-c75c-47c5-83b4-d504f85e275b and --change-set-uuid 38437346-c75c-47c5-83b4-d504f85e275c' do
395
+ yaml = <<-"YAML"
396
+ stacks:
397
+ Test:
398
+ template_file: vpc.yaml
399
+ parameter_input: vpc.json
400
+ parameters:
401
+ VpcName: sample<%= append_uuid%>
402
+ timeout_in_minutes: 2
403
+ Test2:
404
+ template_file: sg.yaml
405
+ parameter_input: sg.json
406
+ parameters:
407
+ VpcName: sample<%= append_uuid%>
408
+ depends:
409
+ - Test
410
+ YAML
411
+ before(:each) { write_file(file, yaml) }
412
+ before(:each) { copy('%/vpc.yaml', 'vpc.yaml') }
413
+ before(:each) { copy('%/vpc.json', 'vpc.json') }
414
+ before(:each) { copy('%/sg.yaml', 'sg.yaml') }
415
+ before(:each) { copy('%/sg.json', 'sg.json') }
416
+ before(:each) { run_command("cfndk changeset create -u=#{uuid} --change-set-uuid 38437346-c75c-47c5-83b4-d504f85e275c") }
417
+ it do
418
+ aggregate_failures do
419
+ expect(last_command_started).to be_successfully_executed
420
+ expect(last_command_started).to have_output(/INFO validate stack: Test-#{uuid}$/)
421
+ expect(last_command_started).to have_output(/INFO creating change set: Test-38437346-c75c-47c5-83b4-d504f85e275c$/)
422
+ expect(last_command_started).to have_output(/INFO created change set: Test-38437346-c75c-47c5-83b4-d504f85e275c$/)
423
+ expect(last_command_started).to have_output(/INFO validate stack: Test2-#{uuid}$/)
424
+ expect(last_command_started).to have_output(/INFO creating change set: Test2-38437346-c75c-47c5-83b4-d504f85e275c$/)
425
+ expect(last_command_started).to have_output(/INFO created change set: Test2-38437346-c75c-47c5-83b4-d504f85e275c$/)
426
+ end
427
+ end
428
+ after(:each) { run_command("cfndk destroy -f -u=#{uuid}") }
429
+ end
430
+ end
431
+ end
432
+ end
433
+ end
434
+ end
435
+ end
436
+ end