# -*- coding: utf-8 -*- # Copyright (c) 2022, Felix Fontein (@felixfontein) # GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) # SPDX-License-Identifier: GPL-3.0-or-later # The data inside here is private to this collection. If you use this from outside the collection, # you are on your own. There can be random changes to its format even in bugfix releases! from __future__ import absolute_import, division, print_function __metaclass__ = type import re from ansible.module_utils.common.text.converters import to_text def validate_and_prepare_restrict(module, path_info): restrict = module.params['restrict'] if restrict is None: return None restrict_data = [] for rule in restrict: field = rule['field'] if field.startswith('!'): module.fail_json(msg='restrict: the field name "{0}" must not start with "!"'.format(field)) f = path_info.fields.get(field) if f is None: module.fail_json(msg='restrict: the field "{0}" does not exist for this path'.format(field)) new_rule = dict( field=field, match_disabled=rule['match_disabled'], invert=rule['invert'], ) if rule['values'] is not None: new_rule['values'] = rule['values'] if rule['regex'] is not None: regex = rule['regex'] try: new_rule['regex'] = re.compile(regex) new_rule['regex_source'] = regex except Exception as exc: module.fail_json(msg='restrict: invalid regular expression "{0}": {1}'.format(regex, exc)) restrict_data.append(new_rule) return restrict_data def _value_to_str(value): if value is None: return None value_str = to_text(value) if isinstance(value, bool): value_str = value_str.lower() return value_str def _test_rule_except_invert(value, rule): if value is None and rule['match_disabled']: return True if 'values' in rule and value in rule['values']: return True if 'regex' in rule and value is not None and rule['regex'].match(_value_to_str(value)): return True return False def restrict_entry_accepted(entry, path_info, restrict_data): if restrict_data is None: return True for rule in restrict_data: # Obtain field and value field = rule['field'] field_info = path_info.fields[field] value = entry.get(field) if value is None: value = field_info.default if field not in entry and field_info.absent_value: value = field_info.absent_value # Check matches_rule = _test_rule_except_invert(value, rule) if rule['invert']: matches_rule = not matches_rule if not matches_rule: return False return True def restrict_argument_spec(): return dict( restrict=dict( type='list', elements='dict', options=dict( field=dict(type='str', required=True), match_disabled=dict(type='bool', default=False), values=dict(type='list', elements='raw'), regex=dict(type='str'), invert=dict(type='bool', default=False), ), ), )