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 +4 -4
- data/.rubocop_todo.yml +2 -2
- data/Gemfile +1 -1
- data/bin/convection +3 -3
- data/lib/convection/control/cloud.rb +7 -3
- data/lib/convection/control/stack.rb +45 -3
- data/lib/convection/model/cloudfile.rb +2 -2
- data/lib/convection/model/template.rb +38 -49
- data/lib/convection/model/template/resource/aws_ec2_vpc.rb +3 -3
- data/lib/convection/model/template/resource/aws_iam_role.rb +7 -33
- data/test/convection/tasks/test_after_create_tasks.rb +66 -0
- data/test/convection/tasks/test_after_delete_tasks.rb +66 -0
- data/test/convection/tasks/test_before_create_tasks.rb +66 -0
- data/test/convection/tasks/test_before_delete_tasks.rb +66 -0
- data/test/test_helper.rb +47 -0
- metadata +10 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 973023aa6d5f219238792f3a0c82cab3404b2801
|
4
|
+
data.tar.gz: 4ff627e74f2ec7e9d6c3c076c0992a88a339f874
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9e9514b28524fdcf080894016117ca4aeb12494c9caf0e68fd0735dbeda32d20ddb4c75c8c600e74de55df20a933da5c6d59936df639541227a705377cf23b3d
|
7
|
+
data.tar.gz: 0cc0ad13e48f372d1e63df73e5ef3dbec8e83e8db8ca321a1666edd3eadac36f4698de531daefdb3b698db92e5129474c76149931de1c3917529edf24a4b9f58
|
data/.rubocop_todo.yml
CHANGED
@@ -23,7 +23,7 @@ Metrics/AbcSize:
|
|
23
23
|
# Offense count: 3
|
24
24
|
# Configuration parameters: CountComments.
|
25
25
|
Metrics/ClassLength:
|
26
|
-
Max:
|
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:
|
41
|
+
Max: 37
|
42
42
|
|
43
43
|
# Offense count: 5
|
44
44
|
Metrics/PerceivedComplexity:
|
data/Gemfile
CHANGED
data/bin/convection
CHANGED
@@ -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
|
-
|
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
|
-
|
253
|
-
|
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
|
-
|
259
|
-
|
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
|
-
|
267
|
-
|
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
|
-
|
279
|
-
|
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
|
-
|
293
|
-
|
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
|
-
|
302
|
-
|
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
|
-
|
308
|
-
|
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
|
-
|
313
|
-
|
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
|
-
|
322
|
-
|
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
|
-
|
328
|
-
|
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
|
-
|
335
|
-
|
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
|
-
|
343
|
-
|
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
|
-
|
64
|
-
|
65
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
data/test/test_helper.rb
CHANGED
@@ -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.
|
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-
|
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
|