Add recursive get key from dict

The docker_config (and other data) that we have in tripleo is a complex
dict but we need a way to fetch a specific key from a larget structure.
This change adds a filter called recursive_get_key_from_dict which will
traverse all the dictionaries in a given dataset and return a list
containing all the values of the requested key.

Change-Id: I952df4d4a7700eccdb2d49a7fba271518058771a
This commit is contained in:
Alex Schultz 2019-12-20 14:24:38 -07:00
parent 97fd9db251
commit c072a6bf9d
2 changed files with 38 additions and 1 deletions

View File

@ -29,7 +29,8 @@ class FilterModule(object):
'haskey': self.haskey,
'list_of_keys': self.list_of_keys,
'container_exec_cmd': self.container_exec_cmd,
'get_key_from_dict': self.get_key_from_dict
'get_key_from_dict': self.get_key_from_dict,
'recursive_get_key_from_dict': self.recursive_get_key_from_dict
}
def subsort(self, dict_to_sort, attribute, null_value=0):
@ -218,6 +219,22 @@ class FilterModule(object):
returned_list.append(value)
return sorted(returned_list)
def recursive_get_key_from_dict(self, data, key):
"""Recursively return values for keys in a dict
This filter will traverse all the dictionaries in the provided
dictionary and return any values for a specified key. This is useful
if you have a complex dictionary containing dynamic keys but want to
fetch a commonly named key.
"""
val = []
if key in data:
val.append(data.get(key))
for k, v in data.items():
if isinstance(v, dict):
val.extend(self.recursive_get_key_from_dict(v, key))
return val
def list_or_dict_arg(self, data, cmd, key, arg):
"""Utility to build a command and its argument with list or dict data.

View File

@ -367,6 +367,26 @@ class TestHelperFilters(tests_base.TestCase):
default='service')
self.assertEqual(result, expected_list)
def test_recursive_get_key_from_dict(self):
data = {
'step': {'container': {'name': 'foo', 'image': 'bar'},
'other_container': {'name': 'meh', 'image': 'baz'}
}
}
expected_list = ['bar', 'baz']
result = self.filters.recursive_get_key_from_dict(data, 'image')
self.assertEqual(result, expected_list)
def test_recursive_get_key_from_dict_multiple_levels(self):
data = {
'a': {'b': {'val': 1},
'c': {'val': 2, 'd': {'val': 3}}
}
}
expected_list = [1, 2, 3]
result = self.filters.recursive_get_key_from_dict(data, 'val')
self.assertEqual(result, expected_list)
def test_container_exec_cmd(self):
data = {
"action": "exec",