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.

Partial-Bug: #1870557
Change-Id: I952df4d4a7700eccdb2d49a7fba271518058771a
(cherry picked from commit c072a6bf9d)
This commit is contained in:
Alex Schultz 2019-12-20 14:24:38 -07:00
parent c33b720912
commit 67005aad2a
2 changed files with 38 additions and 1 deletions

View File

@ -42,7 +42,8 @@ class FilterModule(object):
'get_role_assignments': self.get_role_assignments,
'get_domain_id': self.get_domain_id,
'get_changed_containers': self.get_changed_containers,
'get_failed_containers': self.get_failed_containers
'get_failed_containers': self.get_failed_containers,
'recursive_get_key_from_dict': self.recursive_get_key_from_dict
}
def subsort(self, dict_to_sort, attribute, null_value=0):
@ -264,6 +265,22 @@ class FilterModule(object):
returned_list.append(value)
return 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

@ -687,6 +687,26 @@ class TestHelperFilters(tests_base.TestCase):
result = self.filters.get_key_from_dict(data, key='users')
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",