Merge "Move metadata filtering logic to utils.py"
This commit is contained in:
commit
42f33e5581
@ -1143,3 +1143,101 @@ else:
|
|||||||
for x, y in zip(first, second):
|
for x, y in zip(first, second):
|
||||||
result |= ord(x) ^ ord(y)
|
result |= ord(x) ^ ord(y)
|
||||||
return result == 0
|
return result == 0
|
||||||
|
|
||||||
|
|
||||||
|
def filter_and_format_resource_metadata(resource_type, resource_list,
|
||||||
|
search_filts, metadata_type=None):
|
||||||
|
"""Get all metadata for a list of resources after filtering.
|
||||||
|
|
||||||
|
Search_filts is a list of dictionaries, where the values in the dictionary
|
||||||
|
can be string or regex string, or a list of strings/regex strings.
|
||||||
|
|
||||||
|
Let's call a dict a 'filter block' and an item in the dict
|
||||||
|
a 'filter'. A tag is returned if it matches ALL the filters in
|
||||||
|
a filter block. If more than one values are specified for a
|
||||||
|
filter, a tag is returned if it matches ATLEAST ONE value of the filter. If
|
||||||
|
more than one filter blocks are specified, the tag should match ALL the
|
||||||
|
filter blocks.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
search_filts = [{'key': ['key1', 'key2'], 'value': 'val1'},
|
||||||
|
{'value': 'val2'}]
|
||||||
|
|
||||||
|
The filter translates to 'match any tag for which':
|
||||||
|
((key=key1 AND value=val1) OR (key=key2 AND value=val1)) AND
|
||||||
|
(value=val2)
|
||||||
|
|
||||||
|
This example filter will never match a tag.
|
||||||
|
|
||||||
|
:param resource_type: The resource type as a string, e.g. 'instance'
|
||||||
|
:param resource_list: List of resource objects
|
||||||
|
:param search_filts: Filters to filter metadata to be returned. Can be
|
||||||
|
dict (e.g. {'key': 'env', 'value': 'prod'}, or a list of dicts
|
||||||
|
(e.g. [{'key': 'env'}, {'value': 'beta'}]. Note that the values
|
||||||
|
of the dict can be regular expressions.
|
||||||
|
:param metadata_type: Provided to search for a specific metadata type
|
||||||
|
(e.g. 'system_metadata')
|
||||||
|
|
||||||
|
:returns: List of dicts where each dict is of the form {'key':
|
||||||
|
'somekey', 'value': 'somevalue', 'instance_id':
|
||||||
|
'some-instance-uuid-aaa'} if resource_type is 'instance'.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if isinstance(search_filts, dict):
|
||||||
|
search_filts = [search_filts]
|
||||||
|
|
||||||
|
def _get_id(resource):
|
||||||
|
if resource_type == 'instance':
|
||||||
|
return resource.get('uuid')
|
||||||
|
|
||||||
|
def _match_any(pattern_list, string):
|
||||||
|
if isinstance(pattern_list, str):
|
||||||
|
pattern_list = [pattern_list]
|
||||||
|
return any([re.match(pattern, string)
|
||||||
|
for pattern in pattern_list])
|
||||||
|
|
||||||
|
def _filter_metadata(resource, search_filt, input_metadata):
|
||||||
|
ids = search_filt.get('resource_id', [])
|
||||||
|
keys_filter = search_filt.get('key', [])
|
||||||
|
values_filter = search_filt.get('value', [])
|
||||||
|
output_metadata = {}
|
||||||
|
|
||||||
|
if ids and _get_id(resource) not in ids:
|
||||||
|
return {}
|
||||||
|
|
||||||
|
for k, v in six.iteritems(input_metadata):
|
||||||
|
# Both keys and value defined -- AND
|
||||||
|
if (keys_filter and values_filter and
|
||||||
|
not _match_any(keys_filter, k) and
|
||||||
|
not _match_any(values_filter, v)):
|
||||||
|
continue
|
||||||
|
# Only keys or value is defined
|
||||||
|
elif ((keys_filter and not _match_any(keys_filter, k)) or
|
||||||
|
(values_filter and not _match_any(values_filter, v))):
|
||||||
|
continue
|
||||||
|
|
||||||
|
output_metadata[k] = v
|
||||||
|
return output_metadata
|
||||||
|
|
||||||
|
formatted_metadata_list = []
|
||||||
|
for res in resource_list:
|
||||||
|
|
||||||
|
if resource_type == 'instance':
|
||||||
|
# NOTE(rushiagr): metadata_type should be 'metadata' or
|
||||||
|
# 'system_metadata' if resource_type is instance. Defaulting to
|
||||||
|
# 'metadata' if not specified.
|
||||||
|
if metadata_type is None:
|
||||||
|
metadata_type = 'metadata'
|
||||||
|
metadata = res.get(metadata_type, {})
|
||||||
|
|
||||||
|
for filt in search_filts:
|
||||||
|
# By chaining the input to the output, the filters are
|
||||||
|
# ANDed together
|
||||||
|
metadata = _filter_metadata(res, filt, metadata)
|
||||||
|
|
||||||
|
for (k, v) in metadata.items():
|
||||||
|
formatted_metadata_list.append({'key': k, 'value': v,
|
||||||
|
'%s_id' % resource_type: _get_id(res)})
|
||||||
|
|
||||||
|
return formatted_metadata_list
|
||||||
|
Loading…
Reference in New Issue
Block a user