Skip to content

Commit 74b2b8e

Browse files
authored
Merge branch 'master' into add_puppet6_support
2 parents 6b5814d + 58b3fb7 commit 74b2b8e

File tree

5 files changed

+139
-1
lines changed

5 files changed

+139
-1
lines changed

doc/advanced-ignores.md

+10
Original file line numberDiff line numberDiff line change
@@ -222,3 +222,13 @@ File[/tmp/foo] =>
222222
In this case, the very important line was removed from the catalog, and you want to know about this. Ignoring `File[/tmp/foo]::parameters::content` would have suppressed this (because all changes to that attribute are ignored). Also ignoring `File[/tmp/foo]::parameters::content=~>This is the line in the new catalog that I do not care about$` would have also suppressed this (because the regular expression was matched for *one* of the lines). However, the two examples with `=&>` in this section would *not* have suppressed this change, because it is no longer the case that *all* changes in the file matched the regular expression.
223223

224224
:warning: All lines are stripped of leading and trailing spaces before the regular expression match is tried. This stripping of whitespace is done *only* for this comparison stage, and does not affect the display of any results.
225+
226+
#### Ignoring attributes which have identical elements but in arbitrary order
227+
228+
You can ignore attributes where both the values in both the old and new catalogs are arrays and the arrays
229+
contain identical elements but in arbitrary order. Basically, you can ignore a parameter where the values
230+
have set equality.
231+
232+
To ignore any parameters named `foo` with values having set equality, you would use:
233+
234+
--ignore 'My::Custom::Resource[*]::parameters::foo=s>='

lib/octocatalog-diff/catalog-diff/differ.rb

+5-1
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,8 @@ def attr_match_rule?(rule, attrib, old_val, new_val)
340340
# =-> Attribute must have been removed and equal this
341341
# =~> Change must match regexp (one line of change matching is sufficient)
342342
# =&> Change must match regexp (all lines of change MUST match regexp)
343-
if rule_attr =~ /\A(.+?)(=[\-\+~&]?>)(.+)/m
343+
# =s> Change must be array and contain identical elements, ignoring order
344+
if rule_attr =~ /\A(.+?)(=[\-\+~&s]?>)(.+)/m
344345
rule_attr = Regexp.last_match(1)
345346
operator = Regexp.last_match(2)
346347
value = Regexp.last_match(3)
@@ -361,6 +362,9 @@ def attr_match_rule?(rule, attrib, old_val, new_val)
361362
raise RegexpError, "Invalid ignore regexp for #{key}: #{exc.message}"
362363
end
363364
matcher = ->(x, y) { regexp_operator_match?(operator, my_regex, x, y) }
365+
elsif operator == '=s>'
366+
raise ArgumentError, "Invalid ignore option for =s>, must be '='" unless value == '='
367+
matcher = ->(x, y) { x.is_a?(Array) && y.is_a?(Array) && Set.new(x) == Set.new(y) }
364368
end
365369
end
366370

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{
2+
"document_type": "Catalog",
3+
"data": {
4+
"tags": ["settings"],
5+
"name": "my.rspec.node",
6+
"version": "production",
7+
"environment": "production",
8+
"resources": [
9+
{
10+
"type": "Myres",
11+
"title": "res1",
12+
"file": "/environments/production/modules/foo/manifests/init.pp",
13+
"line": 10,
14+
"exported": false,
15+
"parameters": {
16+
"set1": ["one", "two", "three"],
17+
"set2": ["a", "b"]
18+
}
19+
}
20+
],
21+
"classes": [
22+
"settings"
23+
]
24+
},
25+
"metadata": {
26+
"api_version": 1
27+
}
28+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{
2+
"document_type": "Catalog",
3+
"data": {
4+
"tags": ["settings"],
5+
"name": "my.rspec.node",
6+
"version": "production",
7+
"environment": "production",
8+
"resources": [
9+
{
10+
"type": "Myres",
11+
"title": "res1",
12+
"file": "/environments/production/modules/foo/manifests/init.pp",
13+
"line": 10,
14+
"exported": false,
15+
"parameters": {
16+
"set1": ["three", "two", "one"],
17+
"set2": ["a", "b", "c"],
18+
"set3": [1, 2, 3]
19+
}
20+
}
21+
],
22+
"classes": [
23+
"settings"
24+
]
25+
},
26+
"metadata": {
27+
"api_version": 1
28+
}
29+
}

spec/octocatalog-diff/tests/catalog-diff/differ_spec.rb

+67
Original file line numberDiff line numberDiff line change
@@ -1234,6 +1234,73 @@
12341234
end
12351235
end
12361236

1237+
context 'ignoring changes in sets' do
1238+
describe '#ignore' do
1239+
before(:all) do
1240+
@c1 = OctocatalogDiff::Catalog.create(json: OctocatalogDiff::Spec.fixture_read('catalogs/ignore-parameter-set-1.json'))
1241+
@c2 = OctocatalogDiff::Catalog.create(json: OctocatalogDiff::Spec.fixture_read('catalogs/ignore-parameter-set-2.json'))
1242+
@set1 = [
1243+
'!',
1244+
"Myres\fres1\fparameters\fset1",
1245+
%w(one two three),
1246+
%w(three two one)
1247+
]
1248+
@set2 = [
1249+
'!',
1250+
"Myres\fres1\fparameters\fset2",
1251+
%w(a b),
1252+
%w(a b c)
1253+
]
1254+
@set3 = [
1255+
'!',
1256+
"Myres\fres1\fparameters\fset3",
1257+
nil,
1258+
[1, 2, 3]
1259+
]
1260+
end
1261+
1262+
it 'should not filter out a change when attribute does not match' do
1263+
opts = {}
1264+
testobj = OctocatalogDiff::CatalogDiff::Differ.new(opts, @c1, @c2)
1265+
testobj.ignore(type: 'Myres', title: 'res1', attr: "parameters\fmode")
1266+
result = testobj.diff
1267+
expect(OctocatalogDiff::Spec.array_contains_partial_array?(result, @set1)).to eq(true)
1268+
expect(OctocatalogDiff::Spec.array_contains_partial_array?(result, @set2)).to eq(true)
1269+
expect(OctocatalogDiff::Spec.array_contains_partial_array?(result, @set3)).to eq(true)
1270+
end
1271+
1272+
it 'should filter out a change when two arrays have set equality' do
1273+
opts = {}
1274+
testobj = OctocatalogDiff::CatalogDiff::Differ.new(opts, @c1, @c2)
1275+
testobj.ignore(type: 'Myres', title: 'res1', attr: "parameters\fset1=s>=")
1276+
result = testobj.diff
1277+
expect(OctocatalogDiff::Spec.array_contains_partial_array?(result, @set1)).to eq(false)
1278+
expect(OctocatalogDiff::Spec.array_contains_partial_array?(result, @set2)).to eq(true)
1279+
expect(OctocatalogDiff::Spec.array_contains_partial_array?(result, @set3)).to eq(true)
1280+
end
1281+
1282+
it 'should not filter out a change when two arrays are not equivalent sets' do
1283+
opts = {}
1284+
testobj = OctocatalogDiff::CatalogDiff::Differ.new(opts, @c1, @c2)
1285+
testobj.ignore(type: 'Myres', title: 'res1', attr: "parameters\fset2=s>=")
1286+
result = testobj.diff
1287+
expect(OctocatalogDiff::Spec.array_contains_partial_array?(result, @set1)).to eq(true)
1288+
expect(OctocatalogDiff::Spec.array_contains_partial_array?(result, @set2)).to eq(true)
1289+
expect(OctocatalogDiff::Spec.array_contains_partial_array?(result, @set3)).to eq(true)
1290+
end
1291+
1292+
it 'should not filter out a change when one array is not specified' do
1293+
opts = {}
1294+
testobj = OctocatalogDiff::CatalogDiff::Differ.new(opts, @c1, @c2)
1295+
testobj.ignore(type: 'Myres', title: 'res1', attr: "parameters\fset3=s>=")
1296+
result = testobj.diff
1297+
expect(OctocatalogDiff::Spec.array_contains_partial_array?(result, @set1)).to eq(true)
1298+
expect(OctocatalogDiff::Spec.array_contains_partial_array?(result, @set2)).to eq(true)
1299+
expect(OctocatalogDiff::Spec.array_contains_partial_array?(result, @set3)).to eq(true)
1300+
end
1301+
end
1302+
end
1303+
12371304
describe '#ignore_match?' do
12381305
let(:resource) { { type: 'Apple', title: 'delicious', attr: "parameters\fcolor" } }
12391306
let(:testobj) { described_class.allocate }

0 commit comments

Comments
 (0)