Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions doc/advanced-ignores.md
Original file line number Diff line number Diff line change
Expand Up @@ -222,3 +222,13 @@ File[/tmp/foo] =>
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.

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

#### Ignoring attributes which have identical elements but in arbitrary order

You can ignore attributes where both the values in both the old and new catalogs are arrays and the arrays
contain identical elements but in arbitrary order. Basically, you can ignore a parameter where the values
have set equality.

To ignore any parameters named `foo` with values having set equality, you would use:

--ignore 'My::Custom::Resource[*]::parameters::foo=s>='
6 changes: 5 additions & 1 deletion lib/octocatalog-diff/catalog-diff/differ.rb
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,8 @@ def attr_match_rule?(rule, attrib, old_val, new_val)
# =-> Attribute must have been removed and equal this
# =~> Change must match regexp (one line of change matching is sufficient)
# =&> Change must match regexp (all lines of change MUST match regexp)
if rule_attr =~ /\A(.+?)(=[\-\+~&]?>)(.+)/m
# =s> Change must be array and contain identical elements, ignoring order
if rule_attr =~ /\A(.+?)(=[\-\+~&s]?>)(.+)/m
rule_attr = Regexp.last_match(1)
operator = Regexp.last_match(2)
value = Regexp.last_match(3)
Expand All @@ -361,6 +362,9 @@ def attr_match_rule?(rule, attrib, old_val, new_val)
raise RegexpError, "Invalid ignore regexp for #{key}: #{exc.message}"
end
matcher = ->(x, y) { regexp_operator_match?(operator, my_regex, x, y) }
elsif operator == '=s>'
raise ArgumentError, "Invalid ignore option for =s>, must be '='" unless value == '='
matcher = ->(x, y) { x.is_a?(Array) && y.is_a?(Array) && Set.new(x) == Set.new(y) }
end
end

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"document_type": "Catalog",
"data": {
"tags": ["settings"],
"name": "my.rspec.node",
"version": "production",
"environment": "production",
"resources": [
{
"type": "Myres",
"title": "res1",
"file": "/environments/production/modules/foo/manifests/init.pp",
"line": 10,
"exported": false,
"parameters": {
"set1": ["one", "two", "three"],
"set2": ["a", "b"]
}
}
],
"classes": [
"settings"
]
},
"metadata": {
"api_version": 1
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"document_type": "Catalog",
"data": {
"tags": ["settings"],
"name": "my.rspec.node",
"version": "production",
"environment": "production",
"resources": [
{
"type": "Myres",
"title": "res1",
"file": "/environments/production/modules/foo/manifests/init.pp",
"line": 10,
"exported": false,
"parameters": {
"set1": ["three", "two", "one"],
"set2": ["a", "b", "c"],
"set3": [1, 2, 3]
}
}
],
"classes": [
"settings"
]
},
"metadata": {
"api_version": 1
}
}
67 changes: 67 additions & 0 deletions spec/octocatalog-diff/tests/catalog-diff/differ_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1234,6 +1234,73 @@
end
end

context 'ignoring changes in sets' do
describe '#ignore' do
before(:all) do
@c1 = OctocatalogDiff::Catalog.create(json: OctocatalogDiff::Spec.fixture_read('catalogs/ignore-parameter-set-1.json'))
@c2 = OctocatalogDiff::Catalog.create(json: OctocatalogDiff::Spec.fixture_read('catalogs/ignore-parameter-set-2.json'))
@set1 = [
'!',
"Myres\fres1\fparameters\fset1",
%w(one two three),
%w(three two one)
]
@set2 = [
'!',
"Myres\fres1\fparameters\fset2",
%w(a b),
%w(a b c)
]
@set3 = [
'!',
"Myres\fres1\fparameters\fset3",
nil,
[1, 2, 3]
]
end

it 'should not filter out a change when attribute does not match' do
opts = {}
testobj = OctocatalogDiff::CatalogDiff::Differ.new(opts, @c1, @c2)
testobj.ignore(type: 'Myres', title: 'res1', attr: "parameters\fmode")
result = testobj.diff
expect(OctocatalogDiff::Spec.array_contains_partial_array?(result, @set1)).to eq(true)
expect(OctocatalogDiff::Spec.array_contains_partial_array?(result, @set2)).to eq(true)
expect(OctocatalogDiff::Spec.array_contains_partial_array?(result, @set3)).to eq(true)
end

it 'should filter out a change when two arrays have set equality' do
opts = {}
testobj = OctocatalogDiff::CatalogDiff::Differ.new(opts, @c1, @c2)
testobj.ignore(type: 'Myres', title: 'res1', attr: "parameters\fset1=s>=")
result = testobj.diff
expect(OctocatalogDiff::Spec.array_contains_partial_array?(result, @set1)).to eq(false)
expect(OctocatalogDiff::Spec.array_contains_partial_array?(result, @set2)).to eq(true)
expect(OctocatalogDiff::Spec.array_contains_partial_array?(result, @set3)).to eq(true)
end

it 'should not filter out a change when two arrays are not equivalent sets' do
opts = {}
testobj = OctocatalogDiff::CatalogDiff::Differ.new(opts, @c1, @c2)
testobj.ignore(type: 'Myres', title: 'res1', attr: "parameters\fset2=s>=")
result = testobj.diff
expect(OctocatalogDiff::Spec.array_contains_partial_array?(result, @set1)).to eq(true)
expect(OctocatalogDiff::Spec.array_contains_partial_array?(result, @set2)).to eq(true)
expect(OctocatalogDiff::Spec.array_contains_partial_array?(result, @set3)).to eq(true)
end

it 'should not filter out a change when one array is not specified' do
opts = {}
testobj = OctocatalogDiff::CatalogDiff::Differ.new(opts, @c1, @c2)
testobj.ignore(type: 'Myres', title: 'res1', attr: "parameters\fset3=s>=")
result = testobj.diff
expect(OctocatalogDiff::Spec.array_contains_partial_array?(result, @set1)).to eq(true)
expect(OctocatalogDiff::Spec.array_contains_partial_array?(result, @set2)).to eq(true)
expect(OctocatalogDiff::Spec.array_contains_partial_array?(result, @set3)).to eq(true)
end
end
end

describe '#ignore_match?' do
let(:resource) { { type: 'Apple', title: 'delicious', attr: "parameters\fcolor" } }
let(:testobj) { described_class.allocate }
Expand Down