convection 0.2.25 → 0.2.26

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a9d27d6e4bf8123a1f14054c838e722cc1828734
4
- data.tar.gz: c8bad8c61c133dcc317babdceedab288eb9488fa
3
+ metadata.gz: 973023aa6d5f219238792f3a0c82cab3404b2801
4
+ data.tar.gz: 4ff627e74f2ec7e9d6c3c076c0992a88a339f874
5
5
  SHA512:
6
- metadata.gz: 9b8ea1cf4cb5ff942423e48241126be05a874a30beb6d70fc2dfb632247df22da9937daeb239b3b17e6138fec06509459f170930f58f062b651645dd9fc8deed
7
- data.tar.gz: af1aa6d83c2ee44fe211e6770fb23ab4b601f6b6dad1728e4211e125d90093129df9d63d5a500e025a48628b9e5fbe6e0f683940bb8806bafad1eeaf619cee85
6
+ metadata.gz: 9e9514b28524fdcf080894016117ca4aeb12494c9caf0e68fd0735dbeda32d20ddb4c75c8c600e74de55df20a933da5c6d59936df639541227a705377cf23b3d
7
+ data.tar.gz: 0cc0ad13e48f372d1e63df73e5ef3dbec8e83e8db8ca321a1666edd3eadac36f4698de531daefdb3b698db92e5129474c76149931de1c3917529edf24a4b9f58
@@ -23,7 +23,7 @@ Metrics/AbcSize:
23
23
  # Offense count: 3
24
24
  # Configuration parameters: CountComments.
25
25
  Metrics/ClassLength:
26
- Max: 267
26
+ Max: 304
27
27
 
28
28
  # Offense count: 6
29
29
  Metrics/CyclomaticComplexity:
@@ -38,7 +38,7 @@ Metrics/LineLength:
38
38
  # Offense count: 32
39
39
  # Configuration parameters: CountComments.
40
40
  Metrics/MethodLength:
41
- Max: 35
41
+ Max: 37
42
42
 
43
43
  # Offense count: 5
44
44
  Metrics/PerceivedComplexity:
data/Gemfile CHANGED
@@ -7,7 +7,7 @@ group :development do
7
7
  gem 'bundler', '~> 1.7'
8
8
  gem 'minitest'
9
9
  gem 'rake', '~> 10.0'
10
- gem 'rubocop', '~> 0.34'
10
+ gem 'rubocop', '~> 0.40.0'
11
11
  gem 'simplecov'
12
12
  gem 'thor-scmversion', '= 1.7.0'
13
13
  end
@@ -26,15 +26,15 @@ module Convection
26
26
  end
27
27
  end
28
28
 
29
- desc 'diff', 'Show changes that will be applied by converge'
29
+ desc 'diff STACK', 'Show changes that will be applied by converge'
30
30
  option :verbose, :type => :boolean, :aliases => '--v', :desc => 'Show stack progress'
31
31
  option :'very-verbose', :type => :boolean, :aliases => '--vv', :desc => 'Show unchanged stacks'
32
- def diff
32
+ def diff(stack = nil)
33
33
  @cloud.configure(File.absolute_path(options['cloudfile'], @cwd))
34
34
 
35
35
  last_event = nil
36
36
 
37
- @cloud.diff do |d|
37
+ @cloud.diff(stack) do |d|
38
38
  if d.is_a? Model::Event
39
39
  if options[:'very-verbose']
40
40
  say_status(*d.to_thor)
@@ -43,15 +43,19 @@ module Convection
43
43
  end
44
44
  end
45
45
 
46
- def diff(&block)
46
+ def diff(to_stack, &block)
47
47
  @cloudfile.deck.each do |stack|
48
48
  block.call(Model::Event.new(:compare, "Compare local state of stack #{ stack.name } (#{ stack.cloud_name }) with remote template", :info))
49
- sleep rand @cloudfile.splay || 2
50
49
 
51
50
  difference = stack.diff
52
- next block.call(Model::Event.new(:unchanged, "Stack #{ stack.cloud_name } Has no changes", :info)) if difference.empty?
51
+ if difference.empty?
52
+ difference << Model::Event.new(:unchanged, "Stack #{ stack.cloud_name } Has no changes", :info)
53
+ end
53
54
 
54
55
  difference.each { |diff| block.call(diff) }
56
+
57
+ break if !to_stack.nil? && stack.name == to_stack
58
+ sleep rand @cloudfile.splay || 2
55
59
  end
56
60
  end
57
61
  end
@@ -20,6 +20,7 @@ module Convection
20
20
  attr_reader :resources
21
21
  attr_reader :attribute_mapping_values
22
22
  attr_reader :outputs
23
+ attr_reader :tasks
23
24
 
24
25
  ## AWS-SDK
25
26
  attr_accessor :region
@@ -52,7 +53,7 @@ module Convection
52
53
  ## Internal status
53
54
  NOT_CREATED = 'NOT_CREATED'.freeze
54
55
 
55
- def initialize(name, template, options = {})
56
+ def initialize(name, template, options = {}, &block)
56
57
  @name = name
57
58
  @template = template.clone(self)
58
59
  @errors = []
@@ -83,6 +84,8 @@ module Convection
83
84
  @id = nil
84
85
  @outputs = {}
85
86
  @resources = {}
87
+ @tasks = { after_create: [], after_delete: [], before_create: [], before_delete: [] }
88
+ instance_exec(&block) if block
86
89
  @current_template = {}
87
90
  @last_event_seen = nil
88
91
 
@@ -131,8 +134,7 @@ module Convection
131
134
  [CREATE_IN_PROGRESS, ROLLBACK_IN_PROGRESS, DELETE_IN_PROGRESS,
132
135
  UPDATE_IN_PROGRESS, UPDATE_COMPLETE_CLEANUP_IN_PROGRESS,
133
136
  UPDATE_ROLLBACK_IN_PROGRESS,
134
- UPDATE_ROLLBACK_COMPLETE_CLEANUP_IN_PROGRESS
135
- ].include?(status)
137
+ UPDATE_ROLLBACK_COMPLETE_CLEANUP_IN_PROGRESS].include?(status)
136
138
  end
137
139
 
138
140
  def complete?
@@ -188,6 +190,12 @@ module Convection
188
190
  o[:stack_name] = id
189
191
  end)
190
192
  else
193
+ ## Execute before create tasks
194
+ @tasks[:before_create].delete_if do |task|
195
+ task.call(self)
196
+ task.success?
197
+ end
198
+
191
199
  ## Create
192
200
  @cf_client.create_stack(request_options.tap do |o|
193
201
  o[:stack_name] = cloud_name
@@ -200,11 +208,23 @@ module Convection
200
208
  end
201
209
 
202
210
  watch(&block) if block # Block execution on stack status
211
+
212
+ ## Execute after create tasks
213
+ @tasks[:after_create].delete_if do |task|
214
+ task.call(self)
215
+ task.success?
216
+ end
203
217
  rescue Aws::Errors::ServiceError => e
204
218
  @errors << e
205
219
  end
206
220
 
207
221
  def delete(&block)
222
+ ## Execute before delete tasks
223
+ @tasks[:before_delete].delete_if do |task|
224
+ task.call(self)
225
+ task.success?
226
+ end
227
+
208
228
  @cf_client.delete_stack(
209
229
  :stack_name => id
210
230
  )
@@ -213,6 +233,12 @@ module Convection
213
233
  watch(&block) if block
214
234
 
215
235
  get_status
236
+
237
+ ## Execute after delete tasks
238
+ @tasks[:after_delete].delete_if do |task|
239
+ task.call(self)
240
+ task.success?
241
+ end
216
242
  rescue Aws::Errors::ServiceError => e
217
243
  @errors << e
218
244
  end
@@ -248,6 +274,22 @@ module Convection
248
274
  puts "\nTemplate validated successfully"
249
275
  end
250
276
 
277
+ def after_create_task(task)
278
+ @tasks[:after_create] << task
279
+ end
280
+
281
+ def after_delete_task(task)
282
+ @tasks[:after_delete] << task
283
+ end
284
+
285
+ def before_create_task(task)
286
+ @tasks[:before_create] << task
287
+ end
288
+
289
+ def before_delete_task(task)
290
+ @tasks[:before_delete] << task
291
+ end
292
+
251
293
  private
252
294
 
253
295
  def get_status(stack_name = id)
@@ -24,12 +24,12 @@ module Convection
24
24
  @attributes.set(stack, key, value)
25
25
  end
26
26
 
27
- def stack(stack_name, template, options = {})
27
+ def stack(stack_name, template, options = {}, &block)
28
28
  options[:region] ||= region
29
29
  options[:cloud] = name
30
30
  options[:attributes] = attributes
31
31
 
32
- @stacks[stack_name] = Control::Stack.new(stack_name, template, options)
32
+ @stacks[stack_name] = Control::Stack.new(stack_name, template, options, &block)
33
33
  @deck << @stacks[stack_name]
34
34
  end
35
35
  end
@@ -248,36 +248,33 @@ module Convection
248
248
  end
249
249
 
250
250
  def validate_resources(rendered_stack)
251
- validate_compare(
252
- rendered_stack['Resources'].count,
253
- CF_MAX_RESOURCES,
254
- ExcessiveResourcesError)
251
+ validate_compare(rendered_stack['Resources'].count,
252
+ CF_MAX_RESOURCES,
253
+ ExcessiveResourcesError)
255
254
 
256
255
  largest_resource_name = resources.keys.max || ''
257
- validate_compare(
258
- largest_resource_name.length,
259
- CF_MAX_RESOURCE_NAME,
260
- ExcessiveResourceNameError)
256
+ validate_compare(largest_resource_name.length,
257
+ CF_MAX_RESOURCE_NAME,
258
+ ExcessiveResourceNameError)
261
259
  end
262
260
 
263
261
  def validate_mappings(rendered_stack)
264
262
  mappings = rendered_stack ['Mappings']
265
- validate_compare(
266
- mappings.count,
267
- CF_MAX_MAPPINGS,
268
- ExcessiveMappingsError)
263
+ validate_compare(mappings.count,
264
+ CF_MAX_MAPPINGS,
265
+ ExcessiveMappingsError)
269
266
  mappings.each do |_, value|
270
267
  validate_compare(
271
268
  value.count,
272
269
  CF_MAX_MAPPING_ATTRIBUTES,
273
- ExcessiveMappingAttributesError)
270
+ ExcessiveMappingAttributesError
271
+ )
274
272
  end
275
273
 
276
274
  mappings.keys.each do |key|
277
- validate_compare(
278
- key.length,
279
- CF_MAX_MAPPING_NAME,
280
- ExcessiveMappingNameError)
275
+ validate_compare(key.length,
276
+ CF_MAX_MAPPING_NAME,
277
+ ExcessiveMappingNameError)
281
278
  end
282
279
 
283
280
  ## XXX What are we trying to do here @aburke
@@ -288,60 +285,52 @@ module Convection
288
285
  end
289
286
 
290
287
  mapping_attributes.each do |attribute|
291
- validate_compare(
292
- attribute.length,
293
- CF_MAX_MAPPING_ATTRIBUTE_NAME,
294
- ExcessiveMappingAttributeNameError)
288
+ validate_compare(attribute.length,
289
+ CF_MAX_MAPPING_ATTRIBUTE_NAME,
290
+ ExcessiveMappingAttributeNameError)
295
291
  end
296
292
  end
297
293
 
298
294
  def validate_parameters(rendered_stack)
299
295
  parameters = rendered_stack['Parameters']
300
- validate_compare(
301
- parameters.count,
302
- CF_MAX_PARAMETERS,
303
- ExcessiveParametersError)
296
+ validate_compare(parameters.count,
297
+ CF_MAX_PARAMETERS,
298
+ ExcessiveParametersError)
304
299
  largest_parameter_name = parameters.keys.max
305
300
  largest_parameter_name ||= ''
306
- validate_compare(
307
- largest_parameter_name.length,
308
- CF_MAX_PARAMETER_NAME_CHARACTERS,
309
- ExcessiveParameterNameError)
301
+ validate_compare(largest_parameter_name.length,
302
+ CF_MAX_PARAMETER_NAME_CHARACTERS,
303
+ ExcessiveParameterNameError)
310
304
  parameters.values.each do |value|
311
- validate_compare(
312
- JSON.generate(value).bytesize,
313
- CF_MAX_PARAMETER_VALUE_BYTESIZE,
314
- ExcessiveParameterBytesizeError)
305
+ validate_compare(JSON.generate(value).bytesize,
306
+ CF_MAX_PARAMETER_VALUE_BYTESIZE,
307
+ ExcessiveParameterBytesizeError)
315
308
  end
316
309
  end
317
310
 
318
311
  def validate_outputs(rendered_stack)
319
312
  outputs = rendered_stack['Outputs']
320
- validate_compare(
321
- outputs.count,
322
- CF_MAX_OUTPUTS,
323
- ExcessiveOutputsError)
313
+ validate_compare(outputs.count,
314
+ CF_MAX_OUTPUTS,
315
+ ExcessiveOutputsError)
324
316
  largest_output_name = outputs.keys.max
325
317
  largest_output_name ||= ''
326
- validate_compare(
327
- largest_output_name.length,
328
- CF_MAX_OUTPUT_NAME_CHARACTERS,
329
- ExcessiveOutputNameError)
318
+ validate_compare(largest_output_name.length,
319
+ CF_MAX_OUTPUT_NAME_CHARACTERS,
320
+ ExcessiveOutputNameError)
330
321
  end
331
322
 
332
323
  def validate_description(rendered_stack)
333
- validate_compare(
334
- rendered_stack['Description'].bytesize,
335
- CF_MAX_DESCRIPTION_BYTESIZE,
336
- ExcessiveDescriptionError)
324
+ validate_compare(rendered_stack['Description'].bytesize,
325
+ CF_MAX_DESCRIPTION_BYTESIZE,
326
+ ExcessiveDescriptionError)
337
327
  end
338
328
 
339
329
  def validate_bytesize(rendered_stack)
340
330
  json = JSON.generate(rendered_stack)
341
- validate_compare(
342
- json.bytesize,
343
- CF_MAX_BYTESIZE,
344
- ExcessiveTemplateSizeError)
331
+ validate_compare(json.bytesize,
332
+ CF_MAX_BYTESIZE,
333
+ ExcessiveTemplateSizeError)
345
334
  end
346
335
  end
347
336
  end
@@ -60,9 +60,9 @@ module Convection
60
60
 
61
61
  ## Allocate the next available subnet
62
62
  @subnet_allocated += 1
63
- s.network(network.subnet(
64
- :Bits => @subnet_length,
65
- :NumSubnets => @subnet_allocated)[@subnet_allocated - 1])
63
+ subnets = network.subnet(:Bits => @subnet_length,
64
+ :NumSubnets => @subnet_allocated)
65
+ s.network(subnets[@subnet_allocated - 1])
66
66
 
67
67
  s.instance_exec(&block) if block
68
68
  @template.resources[s.name] = s
@@ -25,8 +25,9 @@ module Convection
25
25
  end
26
26
 
27
27
  ## Add a canned trust policy for any AWS service
28
- def trust_service(name, &block)
29
- @trust_relationship = Model::Mixin::Policy.new(:name => "trust-#{name}-service", :template => @template)
28
+ def trust_service(name, policy_name = nil, &block)
29
+ policy_name ||= "trust-#{name}-service"
30
+ @trust_relationship = Model::Mixin::Policy.new(:name => policy_name, :template => @template)
30
31
  trust_relationship.allow do
31
32
  action 'sts:AssumeRole'
32
33
  principal :Service => "#{name}.amazonaws.com"
@@ -36,49 +37,22 @@ module Convection
36
37
 
37
38
  ## Add a canned trust policy for EC2 instances
38
39
  def trust_ec2_instances(&block)
39
- @trust_relationship = Model::Mixin::Policy.new(:name => 'trust-ec2-instances', :template => @template)
40
- trust_relationship.allow do
41
- action 'sts:AssumeRole'
42
- principal :Service => 'ec2.amazonaws.com'
43
- end
44
- trust_relationship.instance_exec(&block) if block
45
- trust_relationship
40
+ trust_service('ec2', 'trust-ec2-instances', &block)
46
41
  end
47
42
 
48
43
  ## Add a canned trust policy for Flow Logs
49
44
  def trust_flow_logs(&block)
50
- @trust_relationship = Model::Mixin::Policy.new(:name => 'trust-flow-logs', :template => @template)
51
- trust_relationship.allow do
52
- action 'sts:AssumeRole'
53
- principal :Service => 'vpc-flow-logs.amazonaws.com'
54
- end
55
- trust_relationship.instance_exec(&block) if block
56
- trust_relationship
45
+ trust_service('vpc-flow-logs', 'trust-flow-logs', &block)
57
46
  end
58
47
 
59
48
  ## Add a canned trust policy for EMR
60
49
  def trust_emr(&block)
61
- @trust_relationship = Model::Mixin::Policy.new(:name => 'trust-emr', :template => @template)
62
- trust_relationship.allow do
63
- action 'sts:AssumeRole'
64
- principal :Service => 'elasticmapreduce.amazonaws.com'
65
- end
66
- trust_relationship.instance_exec(&block) if block
67
- trust_relationship
50
+ trust_service('elasticmapreduce', 'trust-emr', &block)
68
51
  end
69
52
 
70
53
  ## Add a canned trust policy for Cloudtrail
71
54
  def trust_cloudtrail(&block)
72
- @trust_relationship =
73
- Model::Mixin::Policy.new(:name => 'trust-cloudtrail-instances', :template => @template)
74
-
75
- trust_relationship.allow do
76
- action 'sts:AssumeRole'
77
- principal :Service => 'cloudtrail.amazonaws.com'
78
- end
79
-
80
- trust_relationship.instance_exec(&block) if block
81
- trust_relationship
55
+ trust_service('cloudtrail', 'trust-cloudtrail-instances', &block)
82
56
  end
83
57
 
84
58
  ## Add a policy to allow instance to self-terminate
@@ -0,0 +1,66 @@
1
+ require 'test_helper'
2
+
3
+ class TestAfterCreateTasks < Minitest::Test
4
+ include TestHelper
5
+
6
+ def setup
7
+ @template = ::Convection.template do
8
+ description 'EC2 VPC Test Template'
9
+
10
+ ec2_vpc 'TargetVPC' do
11
+ network '10.0.0.0'
12
+ subnet_length 24
13
+ enable_dns
14
+ end
15
+ end
16
+ end
17
+
18
+ def test_after_create_task_is_registered
19
+ Aws::CloudFormation::Client.stub :new, mock_cloudformation_client do
20
+ Aws::EC2::Client.stub :new, mock_ec2_client do
21
+ # when - a stack is initialized with a after_create_task
22
+ stack = ::Convection::Control::Stack.new('EC2 VPC Test Stack', @template) do
23
+ after_create_task CollectAvailabilityZonesTask.new
24
+ end
25
+
26
+ # then - at least one task should be present
27
+ refute_empty stack.tasks[:after_create]
28
+ end
29
+ end
30
+ end
31
+
32
+ def test_after_create_task_is_executed
33
+ Aws::CloudFormation::Client.stub :new, mock_cloudformation_client do
34
+ Aws::EC2::Client.stub :new, mock_ec2_client do
35
+ # given - a stack initialized with a after_create_task
36
+ task = CollectAvailabilityZonesTask.new
37
+ stack = ::Convection::Control::Stack.new('EC2 VPC Test Stack', @template) do
38
+ after_create_task task
39
+ end
40
+
41
+ # when - any changes to the stack are applied
42
+ stack.apply
43
+
44
+ # then - the task should have been executed
45
+ assert_includes task.availability_zones, 'eu-central-1'
46
+ end
47
+ end
48
+ end
49
+
50
+ def test_after_create_task_is_deregistered
51
+ Aws::CloudFormation::Client.stub :new, mock_cloudformation_client do
52
+ Aws::EC2::Client.stub :new, mock_ec2_client do
53
+ # given - a stack initialized with a after_create_task
54
+ stack = ::Convection::Control::Stack.new('EC2 VPC Test Stack', @template) do
55
+ after_create_task CollectAvailabilityZonesTask.new
56
+ end
57
+
58
+ # when - any changes to the stack are applied
59
+ stack.apply
60
+
61
+ # then - the task should have been deregistered
62
+ assert_empty stack.tasks[:after_create]
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,66 @@
1
+ require 'test_helper'
2
+
3
+ class TestBeforeDeleteTasks < Minitest::Test
4
+ include TestHelper
5
+
6
+ def setup
7
+ @template = ::Convection.template do
8
+ description 'EC2 VPC Test Template'
9
+
10
+ ec2_vpc 'TargetVPC' do
11
+ network '10.0.0.0'
12
+ subnet_length 24
13
+ enable_dns
14
+ end
15
+ end
16
+ end
17
+
18
+ def test_after_delete_task_is_registered
19
+ Aws::CloudFormation::Client.stub :new, mock_cloudformation_client do
20
+ Aws::EC2::Client.stub :new, mock_ec2_client do
21
+ # when - a stack is initialized with a after_delete_task
22
+ stack = ::Convection::Control::Stack.new('EC2 VPC Test Stack', @template) do
23
+ after_delete_task CollectAvailabilityZonesTask.new
24
+ end
25
+
26
+ # then - at least one task should be present
27
+ refute_empty stack.tasks[:after_delete]
28
+ end
29
+ end
30
+ end
31
+
32
+ def test_after_delete_task_is_executed
33
+ Aws::CloudFormation::Client.stub :new, mock_cloudformation_client do
34
+ Aws::EC2::Client.stub :new, mock_ec2_client do
35
+ # given - a stack initialized with a after_delete_task
36
+ task = CollectAvailabilityZonesTask.new
37
+ stack = ::Convection::Control::Stack.new('EC2 VPC Test Stack', @template) do
38
+ after_delete_task task
39
+ end
40
+
41
+ # when - any changes to the stack are applied
42
+ stack.delete
43
+
44
+ # then - the task should have been executed
45
+ assert_includes task.availability_zones, 'eu-central-1'
46
+ end
47
+ end
48
+ end
49
+
50
+ def test_after_delete_task_is_deregistered
51
+ Aws::CloudFormation::Client.stub :new, mock_cloudformation_client do
52
+ Aws::EC2::Client.stub :new, mock_ec2_client do
53
+ # given - a stack initialized with a after_delete_task
54
+ stack = ::Convection::Control::Stack.new('EC2 VPC Test Stack', @template) do
55
+ after_delete_task CollectAvailabilityZonesTask.new
56
+ end
57
+
58
+ # when - any changes to the stack are applied
59
+ stack.delete
60
+
61
+ # then - the task should have been deregistered
62
+ assert_empty stack.tasks[:after_delete]
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,66 @@
1
+ require 'test_helper'
2
+
3
+ class TestBeforeCreateTasks < Minitest::Test
4
+ include TestHelper
5
+
6
+ def setup
7
+ @template = ::Convection.template do
8
+ description 'EC2 VPC Test Template'
9
+
10
+ ec2_vpc 'TargetVPC' do
11
+ network '10.0.0.0'
12
+ subnet_length 24
13
+ enable_dns
14
+ end
15
+ end
16
+ end
17
+
18
+ def test_before_create_task_is_registered
19
+ Aws::CloudFormation::Client.stub :new, mock_cloudformation_client do
20
+ Aws::EC2::Client.stub :new, mock_ec2_client do
21
+ # when - a stack is initialized with a before_create_task
22
+ stack = ::Convection::Control::Stack.new('EC2 VPC Test Stack', @template) do
23
+ before_create_task CollectAvailabilityZonesTask.new
24
+ end
25
+
26
+ # then - at least one task should be present
27
+ refute_empty stack.tasks[:before_create]
28
+ end
29
+ end
30
+ end
31
+
32
+ def test_before_create_task_is_executed
33
+ Aws::CloudFormation::Client.stub :new, mock_cloudformation_client do
34
+ Aws::EC2::Client.stub :new, mock_ec2_client do
35
+ # given - a stack initialized with a before_create_task
36
+ task = CollectAvailabilityZonesTask.new
37
+ stack = ::Convection::Control::Stack.new('EC2 VPC Test Stack', @template) do
38
+ before_create_task task
39
+ end
40
+
41
+ # when - any changes to the stack are applied
42
+ stack.apply
43
+
44
+ # then - the task should have been executed
45
+ assert_includes task.availability_zones, 'eu-central-1'
46
+ end
47
+ end
48
+ end
49
+
50
+ def test_before_create_task_is_deregistered
51
+ Aws::CloudFormation::Client.stub :new, mock_cloudformation_client do
52
+ Aws::EC2::Client.stub :new, mock_ec2_client do
53
+ # given - a stack initialized with a before_create_task
54
+ stack = ::Convection::Control::Stack.new('EC2 VPC Test Stack', @template) do
55
+ before_create_task CollectAvailabilityZonesTask.new
56
+ end
57
+
58
+ # when - any changes to the stack are applied
59
+ stack.apply
60
+
61
+ # then - the task should have been deregistered
62
+ assert_empty stack.tasks[:before_create]
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,66 @@
1
+ require 'test_helper'
2
+
3
+ class TestBeforeDeleteTasks < Minitest::Test
4
+ include TestHelper
5
+
6
+ def setup
7
+ @template = ::Convection.template do
8
+ description 'EC2 VPC Test Template'
9
+
10
+ ec2_vpc 'TargetVPC' do
11
+ network '10.0.0.0'
12
+ subnet_length 24
13
+ enable_dns
14
+ end
15
+ end
16
+ end
17
+
18
+ def test_before_delete_task_is_registered
19
+ Aws::CloudFormation::Client.stub :new, mock_cloudformation_client do
20
+ Aws::EC2::Client.stub :new, mock_ec2_client do
21
+ # when - a stack is initialized with a before_delete_task
22
+ stack = ::Convection::Control::Stack.new('EC2 VPC Test Stack', @template) do
23
+ before_delete_task CollectAvailabilityZonesTask.new
24
+ end
25
+
26
+ # then - at least one task should be present
27
+ refute_empty stack.tasks[:before_delete]
28
+ end
29
+ end
30
+ end
31
+
32
+ def test_before_delete_task_is_executed
33
+ Aws::CloudFormation::Client.stub :new, mock_cloudformation_client do
34
+ Aws::EC2::Client.stub :new, mock_ec2_client do
35
+ # given - a stack initialized with a before_delete_task
36
+ task = CollectAvailabilityZonesTask.new
37
+ stack = ::Convection::Control::Stack.new('EC2 VPC Test Stack', @template) do
38
+ before_delete_task task
39
+ end
40
+
41
+ # when - any changes to the stack are applied
42
+ stack.delete
43
+
44
+ # then - the task should have been executed
45
+ assert_includes task.availability_zones, 'eu-central-1'
46
+ end
47
+ end
48
+ end
49
+
50
+ def test_before_delete_task_is_deregistered
51
+ Aws::CloudFormation::Client.stub :new, mock_cloudformation_client do
52
+ Aws::EC2::Client.stub :new, mock_ec2_client do
53
+ # given - a stack initialized with a before_delete_task
54
+ stack = ::Convection::Control::Stack.new('EC2 VPC Test Stack', @template) do
55
+ before_delete_task CollectAvailabilityZonesTask.new
56
+ end
57
+
58
+ # when - any changes to the stack are applied
59
+ stack.delete
60
+
61
+ # then - the task should have been deregistered
62
+ assert_empty stack.tasks[:before_delete]
63
+ end
64
+ end
65
+ end
66
+ end
@@ -15,3 +15,50 @@ module Minitest::Assertions
15
15
  yield
16
16
  end
17
17
  end
18
+
19
+ module TestHelper
20
+ class CollectAvailabilityZonesTask
21
+ attr_writer :availability_zones
22
+
23
+ def availability_zones
24
+ @availability_zones ||= []
25
+ end
26
+
27
+ def call(stack)
28
+ self.availability_zones += stack.availability_zones
29
+ end
30
+
31
+ def success?
32
+ availability_zones.any?
33
+ end
34
+ end
35
+
36
+ private
37
+
38
+ def mock_cloudformation_client
39
+ cf_client = Minitest::Mock.new
40
+ any_args = [->(*) { true }]
41
+ cf_client.expect(:create_stack, nil, any_args)
42
+ cf_client.expect(:delete_stack, nil, any_args)
43
+ cf_client.expect(:describe_stacks, nil)
44
+ def cf_client.describe_stacks(*)
45
+ context = nil # we don't need any request context here.
46
+ raise Aws::CloudFormation::Errors::ValidationError.new(context, 'Stack does not exist.')
47
+ end
48
+
49
+ cf_client
50
+ end
51
+
52
+ def mock_ec2_client
53
+ zones = %w(eu-central-1 eu-west-1).map do |zone|
54
+ mock = Minitest::Mock.new
55
+ mock.expect(:zone_name, zone)
56
+ end
57
+ availability_zone_description = Minitest::Mock.new
58
+ availability_zone_description.expect(:availability_zones, zones)
59
+
60
+ ec2_client = Minitest::Mock.new
61
+ ec2_client.expect(:describe_availability_zones, availability_zone_description)
62
+ ec2_client
63
+ end
64
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: convection
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.25
4
+ version: 0.2.26
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Manero
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-05-09 00:00:00.000000000 Z
11
+ date: 2016-05-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aws-sdk
@@ -222,6 +222,10 @@ files:
222
222
  - test/convection/model/test_update_policies.rb
223
223
  - test/convection/model/test_validation.rb
224
224
  - test/convection/model/test_vpc_endpoint.rb
225
+ - test/convection/tasks/test_after_create_tasks.rb
226
+ - test/convection/tasks/test_after_delete_tasks.rb
227
+ - test/convection/tasks/test_before_create_tasks.rb
228
+ - test/convection/tasks/test_before_delete_tasks.rb
225
229
  - test/test_helper.rb
226
230
  homepage: https://github.com/rapid7/convection
227
231
  licenses:
@@ -260,4 +264,8 @@ test_files:
260
264
  - test/convection/model/test_update_policies.rb
261
265
  - test/convection/model/test_validation.rb
262
266
  - test/convection/model/test_vpc_endpoint.rb
267
+ - test/convection/tasks/test_after_create_tasks.rb
268
+ - test/convection/tasks/test_after_delete_tasks.rb
269
+ - test/convection/tasks/test_before_create_tasks.rb
270
+ - test/convection/tasks/test_before_delete_tasks.rb
263
271
  - test/test_helper.rb