Exemplo n.º 1
0
def json_query(data, expr):
    '''Query data using jmespath query language ( http://jmespath.org ). Example:
    - ansible.builtin.debug: msg="{{ instance | json_query(tagged_instances[*].block_device_mapping.*.volume_id') }}"
    '''
    if not HAS_LIB:
        raise AnsibleError('You need to install "jmespath" prior to running '
                           'json_query filter')

    # Hack to handle Ansible Unsafe text, AnsibleMapping and AnsibleSequence
    # See issue: https://github.com/ansible-collections/community.general/issues/320
    jmespath.functions.REVERSE_TYPES_MAP['string'] = jmespath.functions.REVERSE_TYPES_MAP['string'] + ('AnsibleUnicode', 'AnsibleUnsafeText', )
    jmespath.functions.REVERSE_TYPES_MAP['array'] = jmespath.functions.REVERSE_TYPES_MAP['array'] + ('AnsibleSequence', )
    jmespath.functions.REVERSE_TYPES_MAP['object'] = jmespath.functions.REVERSE_TYPES_MAP['object'] + ('AnsibleMapping', )
    try:
        return jmespath.search(expr, data)
    except jmespath.exceptions.JMESPathError as e:
        raise AnsibleFilterError('JMESPathError in json_query filter plugin:\n%s' % e)
    except Exception as e:
        # For older jmespath, we can get ValueError and TypeError without much info.
        raise AnsibleFilterError('Error in jmespath.search in json_query filter plugin:\n%s' % e)
def config_parameter(parameters, key, default=None, comment=False):
    if not isinstance(parameters, dict):
        raise AnsibleFilterError('manala_logrotate_config_parameter parameters expects a dict but was given a %s' % type(parameters))
    if not isinstance(key, string_types):
        raise AnsibleFilterError('manala_logrotate_config_parameter key expects a string but was given a %s' % type(key))
    result = ''
    value = parameters.get(key, default)
    if value is True:
        result = '%s' % key
    elif value is False:
        pass
    elif isinstance(value, string_types):
        result = '%s %s' % (key, value)
    elif isinstance(value, Number):
        result = '%s %s' % (key, value)
    else:
        AnsibleFilterError('manala_logrotate_config_parameter value of an unknown type %s' % type(value))
    if comment and key not in parameters:
        result = '#%s' % result
    return result
Exemplo n.º 3
0
def babylon_extract_parameter_vars(vars_dict):
    """
    Filter parameter variables from all values provided for provision.

    Most values will be included in the AnarchyGovernor as they are not
    parameters which are expected to be different with each requested
    environment.

    The `__meta__.catalag.parameters` provides a list of expected parameters
    along with data type validation that will be applied. Variables are
    converted to the types expected by the validation to prevent them from
    being rejected.
    """
    parameter_vars = dict()
    parameters = vars_dict.get('__meta__', {}).get('catalog', {}).get('parameters')

    # Cloud tags may passed as a YAML string which must be interpreted.
    # Strip out guid and uuid from cloud tags as these will conflict with Babylon assignment.
    if 'cloud_tags' in vars_dict and isinstance(vars_dict['cloud_tags'], str):
        vars_dict['cloud_tags'] = {
            k: v for k, v in yaml.safe_load(vars_dict['cloud_tags']).items() if k not in ('guid', 'uuid')
        }

    if parameters == None:
        # No parameters configured, so must pass all vars as parameter vars
        for varname, value in vars_dict.items():
            if varname not in ('__meta__', 'agnosticv_meta', 'guid', 'uuid'):
                parameter_vars[varname] = value
    else:
        # Pass parameter vars with expected type conversions
        for parameter in parameters:
            # Use explicit variable name for parameter if set, otherwise use parameter name as variable name
            # unless parameter sets an annotation.
            varname = parameter.get('variable', None if 'annotation' in parameter else parameter['name'])
            vartype = parameter.get('openAPIV3Schema', {}).get('type')
            if varname and varname in vars_dict:
                raw_value = vars_dict[varname]
                try:
                    if vartype == 'boolean':
                        parameter_vars[varname] = to_bool(raw_value)
                    elif vartype == 'integer':
                        parameter_vars[varname] = int(raw_value)
                    elif vartype == 'number':
                        parameter_vars[varname] = float(raw_value)
                    elif vartype == 'string':
                        parameter_vars[varname] = str(raw_value)
                    else:
                        parameter_vars[varname] = raw_value
                except ValueError:
                    raise AnsibleFilterError(
                        'Invalid value for {}: "{}" is cannot be parsed as {}'.format(varname, raw_value, vartype)
                    )

    return parameter_vars
Exemplo n.º 4
0
def max(environment, a, **kwargs):
    if HAS_MIN_MAX:
        return do_max(environment, a, **kwargs)
    else:
        if kwargs:
            raise AnsibleFilterError(
                "Ansible's max filter does not support any keyword arguments. "
                "You need Jinja2 2.10 or later that provides their version of the filter."
            )
        _max = __builtins__.get('max')
        return _max(a)
Exemplo n.º 5
0
def dynamic_roler_source_name(source):
    if 'name' in source:
        return source['name']
    m = re.search(r'/(\w+)(\.git)?$', source['src'])
    if m:
        return m.group(1)
    elif re.match('(\w+)\.(\w+)$', source['src']):
        return source['src']
    raise AnsibleFilterError(
        "Unable to determine source name from {}, name must be provided".
        format(source['src']))
Exemplo n.º 6
0
def match_key(subject_item, other_item, *key):
    if len(key) == 1:
        subject_key = other_key = key[0]
    elif len(key) == 2:
        subject_key, other_key = key
    else:
        raise AnsibleFilterError(
            'Too many keys to be matched ({} > 2)'.format(key))

    return (subject_key in subject_item and other_key in other_item
            and subject_item[subject_key] == other_item[other_key])
Exemplo n.º 7
0
def do_yaql(data, expression):
    try:
        import yaql
    except ImportError:
        raise AnsibleFilterError("The yaql filter plugin require yaql."
                                 " 'pip install yaql'")

    engine = yaql.factory.YaqlFactory().create()  # pylint: disable=E1101
    expression = engine(expression)
    result = expression.evaluate(data=data)
    return result
def config(config, exclude=[]):
    if not isinstance(config, dict):
        raise AnsibleFilterError('manala_supervisor_config expects a dict but was given a %s' % type(config))
    [config.pop(key, None) for key in exclude]
    result = ''
    for section, parameters in sorted(iteritems(config)):
        result += '[%s]%s\n\n' % (
            section,
            config_parameters(parameters)
        )
    return result.rsplit('\n', 1)[0]
Exemplo n.º 9
0
def _cut_ignorelist_directory(ignorelist):
    res = []
    for ignore in ignorelist:
        r1 = re.split(".*flash.?:/?", ignore)
        if not isinstance(r1, list) or len(r1) < 2:
            raise AnsibleFilterError(
                "Unexpected IgnoreList match. Check show version and show boot output."
            )
        r2 = re.split("/", r1[1])
        res.append(r2[0])
    return res
Exemplo n.º 10
0
def cleanfile(filelist, ignorelist, platform):
    if not filelist or not ignorelist or not platform:
        raise AnsibleFilterError(
            'FileList, IgnoreList, Platform must not be empty.')
    if not isinstance(filelist, list):
        raise AnsibleFilterError('FileList must be an array')
    if not isinstance(ignorelist, list):
        raise AnsibleFilterError('IgnoreList must be an array')

    result = []
    ignorelist_cutted = _cut_ignorelist_directory(ignorelist)

    for line in filelist:
        regex = r"[^ ]*$"
        matches = re.search(regex, line)
        filematch = matches.group()
        if _platform_check(filematch, platform):
            if _ignorelist_check(filematch, ignorelist_cutted):
                result.append(filematch)
    return result
Exemplo n.º 11
0
def hash_salt(password):

    split_password = password.split("$")
    if len(split_password) != 4:
        raise AnsibleFilterError(
            "Could not parse salt out password correctly from {0}".format(
                password
            )
        )
    else:
        return split_password[2]
def postfix_type_join(mylist):
    if not is_sequence(mylist):
        raise AnsibleFilterError("list required, got %s" % type(mylist))

    ret_list = []

    for item in mylist:
        s = "%s:%s" % (item['type'], item['dest'])
        ret_list.append(s)

    return ", ".join(ret_list)
Exemplo n.º 13
0
    def genie_parser_diff(self, output1, output2, mode=None, exclude=None):
        if not PY3:
            raise AnsibleFilterError("Genie requires Python 3")

        if not HAS_GENIE:
            raise AnsibleFilterError("Genie not found. Run 'pip install genie'")

        if not HAS_PYATS:
            raise AnsibleFilterError("pyATS not found. Run 'pip install pyats'")

        supported_mode = ['add', 'remove', 'modified', None]
        if mode not in supported_mode:
            raise AnsibleFilterError("Mode '%s' is not supported. Specify %s." % (mode, supported_mode) )

        dd = Diff(output1, output2, mode=mode, exclude=exclude)
        dd.findDiff()
        diff = str(dd)
        diff_list = diff.split('\n')

        return diff_list
Exemplo n.º 14
0
def transpile_ignition_config(ignition_config):
    '''https://github.com/coreos/container-linux-config-transpiler'''
    try:
        bin_path = get_bin_path("ct", required=True, opt_dirs=None)
    except ValueError as e:
        raise AnsibleFilterError("ct needs to be installed: %s" % e.message)

    process = subprocess.Popen(["ct"],
                               stdout=subprocess.PIPE,
                               stderr=subprocess.PIPE,
                               stdin=subprocess.PIPE)
    out, err = process.communicate(input=_encode(ignition_config))
    return_code = process.returncode

    if return_code != 0:
        raise AnsibleFilterError(
            "transpilation failed with return code %d: %s (%s)" %
            (return_code, out, err))

    return _decode(out.strip())
Exemplo n.º 15
0
def jc(data, parser, quiet=True, raw=False):
    """Convert returned command output to JSON using the JC library

    Arguments:

        parser      required    (string) the correct parser for the input data (e.g. 'ifconfig')
                                see https://github.com/kellyjonbrazil/jc#parsers for latest list of parsers.
        quiet       optional    (bool) True to suppress warning messages (default is True)
        raw         optional    (bool) True to return pre-processed JSON (default is False)

    Returns:

        dictionary or list of dictionaries

    Example:

        - name: run date command
          hosts: ubuntu
          tasks:
          - shell: date
            register: result
          - set_fact:
              myvar: "{{ result.stdout | community.general.jc('date') }}"
          - debug:
              msg: "{{ myvar }}"

        produces:

        ok: [192.168.1.239] => {
            "msg": {
                "day": 9,
                "hour": 22,
                "minute": 6,
                "month": "Aug",
                "month_num": 8,
                "second": 22,
                "timezone": "UTC",
                "weekday": "Sun",
                "weekday_num": 1,
                "year": 2020
            }
        }
    """

    if not HAS_LIB:
        raise AnsibleError(
            'You need to install "jc" prior to running jc filter')

    try:
        jc_parser = importlib.import_module('jc.parsers.' + parser)
        return jc_parser.parse(data, quiet=quiet, raw=raw)

    except Exception as e:
        raise AnsibleFilterError('Error in jc filter plugin:  %s' % e)
Exemplo n.º 16
0
def path_join(paths):
    ''' takes a sequence or a string, and return a concatenation
        of the different members '''
    if isinstance(paths, string_types):
        return os.path.join(paths)
    elif is_sequence(paths):
        return os.path.join(*paths)
    else:
        raise AnsibleFilterError(
            "|path_join expects string or sequence, got %s instead." %
            type(paths))
Exemplo n.º 17
0
def combine(*terms, **kwargs):
    recursive = kwargs.get('recursive', False)
    if len(kwargs) > 1 or (len(kwargs) == 1 and 'recursive' not in kwargs):
        raise AnsibleFilterError("'recursive' is the only valid keyword argument")

    dicts = []
    for t in terms:
        if isinstance(t, MutableMapping):
            recursive_check_defined(t)
            dicts.append(t)
        elif isinstance(t, list):
            recursive_check_defined(t)
            dicts.append(combine(*t, **kwargs))
        else:
            raise AnsibleFilterError("|combine expects dictionaries, got " + repr(t))

    if recursive:
        return reduce(merge_hash, dicts)
    else:
        return dict(itertools.chain(*map(iteritems, dicts)))
Exemplo n.º 18
0
def mount_backup(item):
    '''Get the mount backup preference.
    Default is `False`.
    '''
    dump_value = item.get('mount', {}).get('backup', False)
    if dump_value is True:
        return '1'
    elif dump_value is False:
        return '0'
    else:
        raise AnsibleFilterError('Invalid mount backup: not boolean')
Exemplo n.º 19
0
def list_of_dict_key_value_elements_to_dict(mylist,
                                            key_name='key',
                                            value_name='value'):
    ''' takes a list of dicts with each having a 'key' and 'value' keys, and transforms the list into a dictionary,
        effectively as the reverse of dict2items '''

    if not is_sequence(mylist):
        raise AnsibleFilterError(
            "items2dict requires a list, got %s instead." % type(mylist))

    return dict((item[key_name], item[value_name]) for item in mylist)
def get_ovf_disk_size(data):
    try:
        root = ET.fromstring(data)
        for child in root:
            for element in child:
                if element.tag == "Disk":
                    return element.attrib.get(
                        "{http://schemas.dmtf.org/ovf/envelope/1/}size")
    except Exception as e:
        raise AnsibleFilterError(
            "Error in get_ovf_disk_size filter plugin:\n%s" % e)
Exemplo n.º 21
0
def dict_to_list_of_dict_key_value_elements(mydict, key_name='key', value_name='value'):
    ''' takes a dictionary and transforms it into a list of dictionaries,
        with each having a 'key' and 'value' keys that correspond to the keys and values of the original '''

    if not isinstance(mydict, MutableMapping):
        raise AnsibleFilterError("dict2items requires a dictionary, got %s instead." % type(mydict))

    ret = []
    for key in mydict:
        ret.append({key_name: key, value_name: mydict[key]})
    return ret
Exemplo n.º 22
0
def mandatory(a):
    from jinja2.runtime import Undefined

    ''' Make a variable mandatory '''
    if isinstance(a, Undefined):
        if a._undefined_name is not None:
            name = "'%s' " % to_text(a._undefined_name)
        else:
            name = ''
        raise AnsibleFilterError("Mandatory variable %snot defined." % name)
    return a
Exemplo n.º 23
0
def regex_escape(string, re_type='python'):
    string = to_text(string,
                     errors='surrogate_or_strict',
                     nonstring='simplerepr')
    '''Escape all regular expressions special characters from STRING.'''
    if re_type == 'python':
        return re.escape(string)
    elif re_type == 'posix_basic':
        # list of BRE special chars:
        # https://en.wikibooks.org/wiki/Regular_Expressions/POSIX_Basic_Regular_Expressions
        return regex_replace(string, r'([].[^$*\\])', r'\\\1')
    # TODO: implement posix_extended
    # It's similar to, but different from python regex, which is similar to,
    # but different from PCRE.  It's possible that re.escape would work here.
    # https://remram44.github.io/regex-cheatsheet/regex.html#programs
    elif re_type == 'posix_extended':
        raise AnsibleFilterError('Regex type (%s) not yet implemented' %
                                 re_type)
    else:
        raise AnsibleFilterError('Invalid regex type (%s)' % re_type)
Exemplo n.º 24
0
def auto_assign_ips(config):
    """
    Automatically assign ip addresses to the configuration, derived from
    the auto_assign_ranges provided in the configuration
    """
    # Make a copy of the config that we can safely modify
    c = copy.deepcopy(config)

    # If there is no ip to assign, return immediately
    subnets = c.get('auto_assign_ranges', [])
    if not subnets:
        return c

    # Assign an ip to the host
    pubkey = get_pubkey(c)
    address = c.get('address', [])
    if not isinstance(address, list):
        raise AnsibleFilterError(
            '|auto_assign_ips: "address" should be a list')
    for subnet in subnets:
        generated = gen_ip(pubkey, subnet=subnet, with_prefixlen=True)
        if generated not in address:
            address += [generated]
    c['address'] = address

    # Assign allowedips to the peers
    for peername, peervars in c.get('peers', dict()).items():
        allowedips = peervars.get('allowedips', [])
        if not isinstance(allowedips, list):
            raise AnsibleFilterError(
                '|auto_assign_ips: "allowedips" should be a list')

        for subnet in subnets:
            generated = gen_ip(peervars['pubkey'],
                               subnet=subnet,
                               with_maxprefixlen=True)
            if generated not in allowedips:
                allowedips += [generated]
        c['peers'][peername]['allowedips'] = allowedips

    return c
Exemplo n.º 25
0
def to_time_unit(human_time, unit='ms', **kwargs):
    ''' Return a time unit from a human readable string '''
    unit = UNIT_TO_SHORT_FORM.get(unit, unit)
    if unit not in UNIT_FACTORS:
        available_units = sorted(
            list(UNIT_FACTORS.keys()) + list(UNIT_TO_SHORT_FORM.keys()))
        raise AnsibleFilterError(
            "to_time_unit() can not convert to the following unit: %s. "
            "Available units: %s" % (unit, ', '.join(available_units)))

    unit_factors = UNIT_FACTORS
    if 'year' in kwargs:
        unit_factors['y'] = unit_factors['y'][:-1] + [kwargs.pop('year')]
    if 'month' in kwargs:
        unit_factors['mo'] = unit_factors['mo'][:-1] + [kwargs.pop('month')]

    if kwargs:
        raise AnsibleFilterError(
            'to_time_unit() got unknown keyword arguments: %s' %
            ', '.join(kwargs.keys()))

    result = 0
    for h_time_string in human_time.split():
        res = re.match(r'(-?\d+)(\w+)', h_time_string)
        if not res:
            raise AnsibleFilterError(
                "to_time_unit() can not interpret following string: %s" %
                human_time)

        h_time_int = int(res.group(1))
        h_time_unit = res.group(2)

        h_time_unit = UNIT_TO_SHORT_FORM.get(h_time_unit, h_time_unit)
        if h_time_unit not in unit_factors:
            raise AnsibleFilterError(
                "to_time_unit() can not interpret following string: %s" %
                human_time)

        time_in_milliseconds = h_time_int * multiply(unit_factors[h_time_unit])
        result += time_in_milliseconds
    return round(result / multiply(unit_factors[unit]), 12)
Exemplo n.º 26
0
def to_uuid(string, namespace=UUID_NAMESPACE_ANSIBLE):
    uuid_namespace = namespace
    if not isinstance(uuid_namespace, uuid.UUID):
        try:
            uuid_namespace = uuid.UUID(namespace)
        except (AttributeError, ValueError) as e:
            raise AnsibleFilterError("Invalid value '%s' for 'namespace': %s" %
                                     (to_native(namespace), to_native(e)))
    # uuid.uuid5() requires bytes on Python 2 and bytes or text or Python 3
    return to_text(
        uuid.uuid5(uuid_namespace,
                   to_native(string, errors='surrogate_or_strict')))
Exemplo n.º 27
0
def recursive_check_defined(item):
    from jinja2.runtime import Undefined

    if isinstance(item, MutableMapping):
        for key in item:
            recursive_check_defined(item[key])
    elif isinstance(item, list):
        for i in item:
            recursive_check_defined(i)
    else:
        if isinstance(item, Undefined):
            raise AnsibleFilterError("{0} is undefined".format(item))
Exemplo n.º 28
0
 def from_ldif(cls, data):
     """Convert LDIF data to dictionary."""
     try:
         ldif_record_list = LDIFRecordList(StringIO(data))
         ldif_record_list.parse()
         returned = []
         for entry in ldif_record_list.all_records:
             returned.append([entry[0], cls.decode_values(entry[1])])
         return returned
     except Exception:
         raise AnsibleFilterError(
             'Invalid LDIF data for LDIFRecordList (%s)' % data)
Exemplo n.º 29
0
def config(parameters, exclude=[]):
    if not isinstance(parameters, dict):
        raise AnsibleFilterError(
            'manala_backup_manager_config expects a dict but was given a %s' %
            type(parameters))
    [parameters.pop(key, None) for key in exclude]
    result = ''
    for key in sorted(parameters):
        parameter = config_parameter(parameters, key)
        if parameter:
            result += '\n%s' % parameter
    return result
Exemplo n.º 30
0
def kms_decrypt(ciphertext, context=MISSING):
    try:
        decoded = base64.b64decode(ciphertext)
        plaintext = ''
        if context is MISSING:
            plaintext = kms.decrypt(CiphertextBlob=decoded).get('Plaintext')
        else:
            plaintext = kms.decrypt(CiphertextBlob=decoded,
                                    EncryptionContext=context).get('Plaintext')
        return plaintext.decode()
    except Exception as e:
        raise AnsibleFilterError(e)