mirror of
https://github.com/ansible-collections/community.general.git
synced 2025-07-22 12:50:22 -07:00
Feature filter replace_keys (#8446)
* Add filter replace_keys. * Update examples and integration tests. * Fix examples and copyright. * Update documentation, examples and integration tests. * Implement #8445. Add filter replace_keys * Fix documentation formatting. * Fix documentation. * Fix type(target). Formatting improved. * Instead of a dictionary, _keys_filter_target_dict returns a list * No target testing in _keys_filter_params * Interface changed _keys_filter_params(data, matching_parameter) * If there are items with equal C(before) the B(first) one will be used. * Update remove_keys. Interface changed _keys_filter_params(data, matching_parameter) * The target can't be empty also in _keys_filter_target_dict * Update plugins/filter/replace_keys.py Co-authored-by: Felix Fontein <felix@fontein.de> * Update plugins/filter/replace_keys.py Co-authored-by: Felix Fontein <felix@fontein.de> * Update plugins/filter/replace_keys.py Co-authored-by: Felix Fontein <felix@fontein.de> * Test attributes before and after are strings in the iteration of target. * Update plugins/filter/replace_keys.py Co-authored-by: Felix Fontein <felix@fontein.de> --------- Co-authored-by: Felix Fontein <felix@fontein.de>
This commit is contained in:
parent
2574cb0dea
commit
1d61541951
10 changed files with 397 additions and 35 deletions
|
@ -13,11 +13,10 @@ from ansible.module_utils.six import string_types
|
|||
from ansible.module_utils.common._collections_compat import Mapping, Sequence
|
||||
|
||||
|
||||
def _keys_filter_params(data, target, matching_parameter):
|
||||
def _keys_filter_params(data, matching_parameter):
|
||||
"""test parameters:
|
||||
* data must be a list of dictionaries. All keys must be strings.
|
||||
* target must be a non-empty sequence.
|
||||
* matching_parameter is member of a list.
|
||||
* data must be a list of dictionaries. All keys must be strings.
|
||||
* matching_parameter is member of a list.
|
||||
"""
|
||||
|
||||
mp = matching_parameter
|
||||
|
@ -37,30 +36,32 @@ def _keys_filter_params(data, target, matching_parameter):
|
|||
msg = "Top level keys must be strings. keys: %s"
|
||||
raise AnsibleFilterError(msg % elem.keys())
|
||||
|
||||
if not isinstance(target, Sequence):
|
||||
msg = ("The target must be a string or a list. target is %s.")
|
||||
raise AnsibleFilterError(msg % target)
|
||||
|
||||
if len(target) == 0:
|
||||
msg = ("The target can't be empty.")
|
||||
raise AnsibleFilterError(msg)
|
||||
|
||||
if mp not in ml:
|
||||
msg = ("The matching_parameter must be one of %s. matching_parameter is %s")
|
||||
msg = "The matching_parameter must be one of %s. matching_parameter=%s"
|
||||
raise AnsibleFilterError(msg % (ml, mp))
|
||||
|
||||
return
|
||||
|
||||
|
||||
def _keys_filter_target_str(target, matching_parameter):
|
||||
"""test:
|
||||
* If target is list all items are strings
|
||||
* If matching_parameter=regex target is a string or list with single string
|
||||
convert and return:
|
||||
* tuple of unique target items, or
|
||||
* tuple with single item, or
|
||||
* compiled regex if matching_parameter=regex
|
||||
"""
|
||||
Test:
|
||||
* target is a non-empty string or list.
|
||||
* If target is list all items are strings.
|
||||
* target is a string or list with single string if matching_parameter=regex.
|
||||
Convert target and return:
|
||||
* tuple of unique target items, or
|
||||
* tuple with single item, or
|
||||
* compiled regex if matching_parameter=regex.
|
||||
"""
|
||||
|
||||
if not isinstance(target, Sequence):
|
||||
msg = "The target must be a string or a list. target is %s."
|
||||
raise AnsibleFilterError(msg % type(target))
|
||||
|
||||
if len(target) == 0:
|
||||
msg = "The target can't be empty."
|
||||
raise AnsibleFilterError(msg)
|
||||
|
||||
if isinstance(target, list):
|
||||
for elem in target:
|
||||
|
@ -73,15 +74,14 @@ def _keys_filter_target_str(target, matching_parameter):
|
|||
r = target
|
||||
else:
|
||||
if len(target) > 1:
|
||||
msg = ("Single item is required in the target list if matching_parameter is regex.")
|
||||
msg = "Single item is required in the target list if matching_parameter=regex."
|
||||
raise AnsibleFilterError(msg)
|
||||
else:
|
||||
r = target[0]
|
||||
try:
|
||||
tt = re.compile(r)
|
||||
except re.error:
|
||||
msg = ("The target must be a valid regex if matching_parameter is regex."
|
||||
" target is %s")
|
||||
msg = "The target must be a valid regex if matching_parameter=regex. target is %s"
|
||||
raise AnsibleFilterError(msg % r)
|
||||
elif isinstance(target, string_types):
|
||||
tt = (target, )
|
||||
|
@ -92,17 +92,50 @@ def _keys_filter_target_str(target, matching_parameter):
|
|||
|
||||
|
||||
def _keys_filter_target_dict(target, matching_parameter):
|
||||
"""test:
|
||||
* target is a list of dictionaries
|
||||
* ...
|
||||
"""
|
||||
Test:
|
||||
* target is a list of dictionaries with attributes 'after' and 'before'.
|
||||
* Attributes 'before' must be valid regex if matching_parameter=regex.
|
||||
* Otherwise, the attributes 'before' must be strings.
|
||||
Convert target and return:
|
||||
* iterator that aggregates attributes 'before' and 'after', or
|
||||
* iterator that aggregates compiled regex of attributes 'before' and 'after' if matching_parameter=regex.
|
||||
"""
|
||||
|
||||
# TODO: Complete and use this in filter replace_keys
|
||||
if not isinstance(target, list):
|
||||
msg = "The target must be a list. target is %s."
|
||||
raise AnsibleFilterError(msg % (target, type(target)))
|
||||
|
||||
if isinstance(target, list):
|
||||
for elem in target:
|
||||
if not isinstance(elem, Mapping):
|
||||
msg = "The target items must be dictionary. %s is %s"
|
||||
raise AnsibleFilterError(msg % (elem, type(elem)))
|
||||
if len(target) == 0:
|
||||
msg = "The target can't be empty."
|
||||
raise AnsibleFilterError(msg)
|
||||
|
||||
return
|
||||
for elem in target:
|
||||
if not isinstance(elem, Mapping):
|
||||
msg = "The target items must be dictionaries. %s is %s"
|
||||
raise AnsibleFilterError(msg % (elem, type(elem)))
|
||||
if not all(k in elem for k in ('before', 'after')):
|
||||
msg = "All dictionaries in target must include attributes: after, before."
|
||||
raise AnsibleFilterError(msg)
|
||||
if not isinstance(elem['before'], string_types):
|
||||
msg = "The attributes before must be strings. %s is %s"
|
||||
raise AnsibleFilterError(msg % (elem['before'], type(elem['before'])))
|
||||
if not isinstance(elem['after'], string_types):
|
||||
msg = "The attributes after must be strings. %s is %s"
|
||||
raise AnsibleFilterError(msg % (elem['after'], type(elem['after'])))
|
||||
|
||||
before = [d['before'] for d in target]
|
||||
after = [d['after'] for d in target]
|
||||
|
||||
if matching_parameter == 'regex':
|
||||
try:
|
||||
tr = map(re.compile, before)
|
||||
tz = list(zip(tr, after))
|
||||
except re.error:
|
||||
msg = ("The attributes before must be valid regex if matching_parameter=regex."
|
||||
" Not all items are valid regex in: %s")
|
||||
raise AnsibleFilterError(msg % before)
|
||||
else:
|
||||
tz = list(zip(before, after))
|
||||
|
||||
return tz
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue