convection 0.2.25 → 0.2.26

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 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