Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 6fa1e51

Browse files
author
Brice Figureau
committedMay 14, 2020
(#223) display diff for nested arrays of objects
When using octocatalog-diff with puppet resources with deep nested datastructures such as nested arrays of objects, octocatalog- diff would not display diffs when array elements are modified,added or removed. In fact, it turns out `dig_out_key` doesn't descend into arrays index that hashdiff can produce, like for instance: testtype::test::parameters::testparam::another-one::an-array[0]::env `dig_out_key` would stop at `an-array` because it doesn't know that's and array index it should try to descend into. This patch adds the functionality for `dig_out_key` to follow array index and descend into those nested structure.
1 parent 8d4b413 commit 6fa1e51

File tree

2 files changed

+83
-3
lines changed

2 files changed

+83
-3
lines changed
 

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

+8-3
Original file line numberDiff line numberDiff line change
@@ -622,9 +622,14 @@ def hashdiff_nested_changes(hashdiff_add_remove, remaining1, remaining2)
622622
def dig_out_key(hash_in, key_array)
623623
return hash_in if key_array.empty?
624624
return hash_in unless hash_in.is_a?(Hash)
625-
return nil unless hash_in.key?(key_array[0])
626-
next_key = key_array.shift
627-
dig_out_key(hash_in[next_key], key_array)
625+
key_without_index = key_array[0].sub(/\[\d+\]/, '')
626+
return nil unless hash_in.key?(key_without_index)
627+
full_key = key_array.shift
628+
next_obj = hash_in[key_without_index]
629+
# jump into array index if needed
630+
md = full_key.match(/\[(\d+)\]/)
631+
next_obj = next_obj[md[1].to_i] if md
632+
dig_out_key(next_obj, key_array)
628633
end
629634

630635
# This is a helper for the constructor, verifying that the incoming catalog is an expected

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

+75
Original file line numberDiff line numberDiff line change
@@ -1414,6 +1414,81 @@
14141414
fileref = { 'file' => '/var/tmp/foo', 'line' => 5 }
14151415
expect(result[0]).to eq(['!', "Class\fOpenssl::Package\fparameters\fcommon-array", [1, 2, 3], [1, 5, 25], fileref, fileref])
14161416
end
1417+
1418+
it 'should return array with proper results for deeply nested arrays of hashes' do
1419+
hashdiff_add_remove = [
1420+
"Class\fOpenssl::Package\fparameters\fobject\farray[0]\fcommon-array"
1421+
]
1422+
1423+
empty_puppet_catalog_json = File.read(OctocatalogDiff::Spec.fixture_path('catalogs/catalog-empty.json'))
1424+
empty_puppet_catalog = OctocatalogDiff::Catalog.create(json: empty_puppet_catalog_json)
1425+
obj = OctocatalogDiff::CatalogDiff::Differ.new({}, empty_puppet_catalog, empty_puppet_catalog)
1426+
1427+
arr1 = [
1428+
{
1429+
'name' => 'test', 'value' => 'abc'
1430+
},
1431+
{
1432+
'name' => 'test2', 'value' => 'def'
1433+
}
1434+
]
1435+
cat1 = [
1436+
{
1437+
'type' => 'Class',
1438+
'title' => 'Openssl::Package',
1439+
'parameters' => {
1440+
'object' => {
1441+
'array' => [
1442+
{
1443+
'common-array' => arr1
1444+
}
1445+
]
1446+
}
1447+
},
1448+
'file' => '/var/tmp/foo',
1449+
'line' => 5
1450+
}
1451+
]
1452+
1453+
arr2 = [
1454+
{
1455+
'name' => 'test', 'value' => 'abc'
1456+
},
1457+
{
1458+
'name' => 'test2', 'value' => 'def'
1459+
},
1460+
{
1461+
'name' => 'test3', 'value' => 'ghj'
1462+
}
1463+
]
1464+
cat2 = [
1465+
{
1466+
'type' => 'Class',
1467+
'title' => 'Openssl::Package',
1468+
'parameters' => {
1469+
'object' => {
1470+
'array' => [
1471+
{
1472+
'common-array' => arr2
1473+
}
1474+
]
1475+
}
1476+
},
1477+
'file' => '/var/tmp/foo',
1478+
'line' => 5
1479+
}
1480+
]
1481+
1482+
remaining1 = obj.send(:resources_as_hashes_with_serialized_keys, cat1)
1483+
remaining2 = obj.send(:resources_as_hashes_with_serialized_keys, cat2)
1484+
1485+
result = obj.send(:hashdiff_nested_changes, hashdiff_add_remove, remaining1, remaining2)
1486+
expect(result).to be_a_kind_of(Array)
1487+
expect(result.size).to eq(1)
1488+
1489+
fileref = { 'file' => '/var/tmp/foo', 'line' => 5 }
1490+
expect(result[0]).to eq(['!', "Class\fOpenssl::Package\fparameters\fobject\farray[0]\fcommon-array", arr1, arr2, fileref, fileref])
1491+
end
14171492
end
14181493

14191494
describe '#regexp_operator_match?' do

0 commit comments

Comments
 (0)
Please sign in to comment.