convection 2.2.29 → 2.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +5 -0
- data/lib/convection/model/diff.rb +17 -2
- data/lib/convection/model/template.rb +39 -1
- data/spec/convection/model/template/template_spec.rb +73 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 80472b7ae2163bf2c2bff8dc870c2e3571257a1d
|
4
|
+
data.tar.gz: b3b70747b74829069d110b96eccc74b1ae70e902
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fec53677c235b009423cc61dafb3ae9f0a4bd4400d3ee65e67f13441631b21993542d880663aa8017269fd7271e6f99ee083dd2fcb5459fa8cd4f6b9bcd5e989
|
7
|
+
data.tar.gz: 2f7011b1226f5397465f2c4a9d534cc63fab2c29dea4572d117cd346a024d38ec86e65498505d417e99da24256ac9df9101a0448a50294d7abe99584f20e276c
|
data/.rubocop.yml
CHANGED
@@ -7,13 +7,14 @@ module Convection
|
|
7
7
|
# Difference between an item in two templates
|
8
8
|
##
|
9
9
|
class Diff
|
10
|
+
include Comparable
|
10
11
|
extend Mixin::Colorize
|
11
12
|
|
12
13
|
attr_reader :key
|
13
|
-
|
14
|
+
attr_accessor :action
|
14
15
|
attr_reader :ours
|
15
16
|
attr_reader :theirs
|
16
|
-
colorize :action, :green => [:create], :yellow => [:update], :red => [:delete, :replace]
|
17
|
+
colorize :action, :green => [:create], :yellow => [:update, :retain], :red => [:delete, :replace]
|
17
18
|
|
18
19
|
def initialize(key, ours, theirs)
|
19
20
|
@key = key
|
@@ -40,10 +41,24 @@ module Convection
|
|
40
41
|
when :update then "#{ key }: #{ theirs } => #{ ours }"
|
41
42
|
when :replace then "#{ key }: #{ theirs } => #{ ours }"
|
42
43
|
when :delete then key
|
44
|
+
when :retain then key
|
43
45
|
end
|
44
46
|
|
45
47
|
[action, message, color]
|
46
48
|
end
|
49
|
+
|
50
|
+
def <=>(other)
|
51
|
+
value = @key <=> other.key
|
52
|
+
return value if value != 0
|
53
|
+
|
54
|
+
value = @ours <=> other.ours
|
55
|
+
return value if value != 0
|
56
|
+
|
57
|
+
value = @theirs <=> other.theirs
|
58
|
+
return value if value != 0
|
59
|
+
|
60
|
+
@action <=> other.action
|
61
|
+
end
|
47
62
|
end
|
48
63
|
end
|
49
64
|
end
|
@@ -297,7 +297,45 @@ module Convection
|
|
297
297
|
end
|
298
298
|
|
299
299
|
def diff(other, stack_ = nil, retain: false)
|
300
|
-
|
300
|
+
# We want to accurately show when the DeletionPolicy is getting deleted and also when resources are going to be retained.
|
301
|
+
# Sample DeletionPolicy Removal output
|
302
|
+
# us-east-1 compare Compare local state of stack test-logs-deletion with remote template
|
303
|
+
# us-east-1 delete Resources.sgtestConvectionDeletion.DeletionPolicy
|
304
|
+
#
|
305
|
+
# Sample Mixed Retain/Delete Resources
|
306
|
+
# us-east-1 retain Resources.ELBLoggingPolicy.DependsOn.AWS::S3::BucketPolicy.0
|
307
|
+
# us-east-1 retain Resources.ELBLoggingPolicy.DeletionPolicy
|
308
|
+
# us-east-1 delete Resources.sgtestConvectionDeletion.Type
|
309
|
+
# us-east-1 delete Resources.sgtestConvectionDeletion.Properties.AWS::EC2::SecurityGroup.GroupDescription
|
310
|
+
# us-east-1 delete Resources.sgtestConvectionDeletion.Properties.AWS::EC2::SecurityGroup.VpcId
|
311
|
+
#
|
312
|
+
events = render(stack_, retain: retain).diff(other).map { |diff| Diff.new(diff[0], *diff[1]) }
|
313
|
+
|
314
|
+
# Top level events (changes to the resource directly) have keys with a format "Resources.{NAME}.{KEY}".
|
315
|
+
# So we can count the number of separators to find them.
|
316
|
+
top_level_events = events.select { |event| event.key.count('.') <= 2 }
|
317
|
+
|
318
|
+
# We know something's a deleted resource when it has a top level "Type" attribute.
|
319
|
+
type_suffix = '.Type'.freeze
|
320
|
+
deleted_resources = top_level_events.select do |event|
|
321
|
+
event.action == :delete && event.key.end_with?(type_suffix)
|
322
|
+
end
|
323
|
+
deleted_resources.map! { |event| event.key[0...-type_suffix.length] }
|
324
|
+
|
325
|
+
# We know something's a retainable resource when it has a top level "DeletionPolicy" attribute.
|
326
|
+
delete_policy_suffix = '.DeletionPolicy'.freeze
|
327
|
+
retainable_resources = top_level_events.select do |event|
|
328
|
+
event.action == :delete && event.key.end_with?(delete_policy_suffix) && event.theirs == 'Retain'
|
329
|
+
end
|
330
|
+
retainable_resources.map! { |event| event.key[0...-delete_policy_suffix.length] }
|
331
|
+
retainable_resources.keep_if { |name| deleted_resources.include?(name) }
|
332
|
+
|
333
|
+
events.each do |event|
|
334
|
+
retained = retainable_resources.any? { |name| event.action == :delete && event.key.start_with?(name) }
|
335
|
+
event.action = :retain if retained
|
336
|
+
end
|
337
|
+
|
338
|
+
events
|
301
339
|
end
|
302
340
|
|
303
341
|
def to_json(stack_ = nil, pretty = false, retain: false)
|
@@ -49,6 +49,79 @@ class Convection::Model::Template
|
|
49
49
|
end
|
50
50
|
end
|
51
51
|
|
52
|
+
describe '#diff' do
|
53
|
+
context 'when diffing resources with deletion_policy' do
|
54
|
+
it 'emits retain events when the entire resource is deleted' do
|
55
|
+
local = Convection.template do
|
56
|
+
end
|
57
|
+
|
58
|
+
remote = Convection.template do
|
59
|
+
resource 'Test' do
|
60
|
+
type 'Test'
|
61
|
+
property 'Key', 'Value'
|
62
|
+
deletion_policy 'Retain'
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
retained = [
|
67
|
+
Convection::Model::Diff.new('Resources.Test.Properties.Test.Key', nil, 'Value'),
|
68
|
+
Convection::Model::Diff.new('Resources.Test.DeletionPolicy', nil, 'Retain'),
|
69
|
+
Convection::Model::Diff.new('Resources.Test.Type', nil, 'Test')
|
70
|
+
]
|
71
|
+
retained.each { |event| event.action = :retain }
|
72
|
+
|
73
|
+
events = local.diff(remote.render)
|
74
|
+
expect(events.sort).to eq(retained.sort)
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'emits delete events when only part of the resource is deleted' do
|
78
|
+
local = Convection.template do
|
79
|
+
resource 'Test' do
|
80
|
+
type 'Test'
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
remote = Convection.template do
|
85
|
+
resource 'Test' do
|
86
|
+
type 'Test'
|
87
|
+
property 'Key', 'Value'
|
88
|
+
deletion_policy 'Retain'
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
deleted = [
|
93
|
+
Convection::Model::Diff.new('Resources.Test.Properties.Test.Key', nil, 'Value'),
|
94
|
+
Convection::Model::Diff.new('Resources.Test.DeletionPolicy', nil, 'Retain')
|
95
|
+
]
|
96
|
+
deleted.each { |event| event.action = :delete }
|
97
|
+
|
98
|
+
events = local.diff(remote.render)
|
99
|
+
expect(events.sort).to eq(deleted.sort)
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'emits delete events even when properties match Type and DeletePolicy' do
|
103
|
+
local = Convection.template do
|
104
|
+
end
|
105
|
+
|
106
|
+
remote = Convection.template do
|
107
|
+
resource 'Test' do
|
108
|
+
property 'Type', 'Test'
|
109
|
+
property 'DeletionPolicy', 'Retain'
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
deleted = [
|
114
|
+
Convection::Model::Diff.new('Resources.Test.Properties.Type', nil, 'Test'),
|
115
|
+
Convection::Model::Diff.new('Resources.Test.Properties.DeletionPolicy', nil, 'Retain')
|
116
|
+
]
|
117
|
+
deleted.each { |event| event.action = :delete }
|
118
|
+
|
119
|
+
events = local.diff(remote.render)
|
120
|
+
expect(events.sort).to eq(deleted.sort)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
52
125
|
subject do
|
53
126
|
template_json
|
54
127
|
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: 2.
|
4
|
+
version: 2.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Manero
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-09-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|