def main():
    path_choices = sorted([
        join_path(path) for path, path_info in PATHS.items()
        if get_backend(path_info) is not None
    ])
    module_args = dict(
        path=dict(type='str', required=True, choices=path_choices),
        data=dict(type='list', elements='dict', required=True),
        handle_absent_entries=dict(type='str',
                                   choices=['ignore', 'remove'],
                                   default='ignore'),
        handle_entries_content=dict(
            type='str',
            choices=['ignore', 'remove', 'remove_as_much_as_possible'],
            default='ignore'),
        ensure_order=dict(type='bool', default=False),
    )
    module_args.update(api_argument_spec())

    module = AnsibleModule(
        argument_spec=module_args,
        supports_check_mode=True,
    )
    if module.params['ensure_order'] and module.params[
            'handle_absent_entries'] == 'ignore':
        module.fail_json(
            msg='ensure_order=true requires handle_absent_entries=remove')

    if not HAS_ORDEREDDICT:
        # This should never happen for Python 2.7+
        module.fail_json(msg=missing_required_lib('ordereddict'))

    check_has_library(module)
    api = create_api(module)

    path = split_path(module.params['path'])
    path_info = PATHS.get(tuple(path))
    backend = get_backend(path_info)
    if path_info is None or backend is None:
        module.fail_json(msg='Path /{path} is not yet supported'.format(
            path='/'.join(path)))

    backend(module, api, path, path_info)
Example #2
0
def main():
    module_args = dict(
        path=dict(type='str',
                  required=True,
                  choices=sorted([
                      join_path(path) for path in PATHS
                      if PATHS[path].fully_understood
                  ])),
        unfiltered=dict(type='bool', default=False),
        handle_disabled=dict(type='str',
                             choices=['exclamation', 'null-value', 'omit'],
                             default='exclamation'),
        hide_defaults=dict(type='bool', default=True),
        include_dynamic=dict(type='bool', default=False),
    )
    module_args.update(api_argument_spec())

    module = AnsibleModule(
        argument_spec=module_args,
        supports_check_mode=True,
    )

    check_has_library(module)
    api = create_api(module)

    path = split_path(module.params['path'])
    path_info = PATHS.get(tuple(path))
    if path_info is None:
        module.fail_json(msg='Path /{path} is not yet supported'.format(
            path='/'.join(path)))

    handle_disabled = module.params['handle_disabled']
    hide_defaults = module.params['hide_defaults']
    include_dynamic = module.params['include_dynamic']
    try:
        api_path = compose_api_path(api, path)

        result = []
        unfiltered = module.params['unfiltered']
        for entry in api_path:
            if not include_dynamic:
                if entry.get('dynamic', False):
                    continue
            if not unfiltered:
                for k in list(entry):
                    if k == '.id':
                        continue
                    if k == 'dynamic' and include_dynamic:
                        continue
                    if k not in path_info.fields:
                        entry.pop(k)
            if handle_disabled != 'omit':
                for k in path_info.fields:
                    if k not in entry:
                        if handle_disabled == 'exclamation':
                            k = '!%s' % k
                        entry[k] = None
            for k, field_info in path_info.fields.items():
                if hide_defaults:
                    if field_info.default is not None and entry.get(
                            k) == field_info.default:
                        entry.pop(k)
                if field_info.absent_value and k not in entry:
                    entry[k] = field_info.absent_value
            result.append(entry)

        module.exit_json(result=result)
    except (LibRouterosError, UnicodeEncodeError) as e:
        module.fail_json(msg=to_native(e))
Example #3
0
    def __init__(self):
        module_args = dict(
            path=dict(type='str', required=True),
            add=dict(type='str'),
            remove=dict(type='str'),
            update=dict(type='str'),
            cmd=dict(type='str'),
            query=dict(type='str'),
            extended_query=dict(
                type='dict',
                options=dict(
                    attributes=dict(type='list', elements='str',
                                    required=True),
                    where=dict(
                        type='list',
                        elements='dict',
                        options={
                            'attribute':
                            dict(type='str'),
                            'is':
                            dict(type='str',
                                 choices=[
                                     "==", "!=", ">", "<", "in", "eq", "not",
                                     "more", "less"
                                 ]),
                            'value':
                            dict(type='raw'),
                            'or':
                            dict(type='list',
                                 elements='dict',
                                 options={
                                     'attribute':
                                     dict(type='str', required=True),
                                     'is':
                                     dict(type='str',
                                          choices=[
                                              "==", "!=", ">", "<", "in", "eq",
                                              "not", "more", "less"
                                          ],
                                          required=True),
                                     'value':
                                     dict(type='raw', required=True),
                                 }),
                        },
                        required_together=[('attribute', 'is', 'value')],
                        mutually_exclusive=[('attribute', 'or')],
                        required_one_of=[('attribute', 'or')],
                    ),
                )),
        )
        module_args.update(api_argument_spec())

        self.module = AnsibleModule(
            argument_spec=module_args,
            supports_check_mode=False,
            mutually_exclusive=(('add', 'remove', 'update', 'cmd', 'query',
                                 'extended_query'), ),
        )

        check_has_library(self.module)

        self.api = create_api(self.module)

        self.path = self.module.params['path'].split()
        self.add = self.module.params['add']
        self.remove = self.module.params['remove']
        self.update = self.module.params['update']
        self.arbitrary = self.module.params['cmd']

        self.where = None
        self.query = self.module.params['query']
        self.extended_query = self.module.params['extended_query']

        self.result = dict(message=[])

        # create api base path
        self.api_path = self.api_add_path(self.api, self.path)

        # api calls
        try:
            if self.add:
                self.api_add()
            elif self.remove:
                self.api_remove()
            elif self.update:
                self.api_update()
            elif self.query:
                self.check_query()
                self.api_query()
            elif self.extended_query:
                self.check_extended_query()
                self.api_extended_query()
            elif self.arbitrary:
                self.api_arbitrary()
            else:
                self.api_get_all()
        except UnicodeEncodeError as exc:
            self.module.fail_json(
                msg='Error while encoding text: {error}'.format(error=exc))
Example #4
0
def main():
    argument_spec = dict(gather_subset=dict(
        default=['all'],
        type='list',
        elements='str',
    ))
    argument_spec.update(api_argument_spec())

    module = AnsibleModule(argument_spec=argument_spec,
                           supports_check_mode=True)
    check_has_library(module)
    api = create_api(module)

    gather_subset = module.params['gather_subset']

    runable_subsets = set()
    exclude_subsets = set()

    for subset in gather_subset:
        if subset == 'all':
            runable_subsets.update(VALID_SUBSETS)
            continue

        if subset.startswith('!'):
            subset = subset[1:]
            if subset == 'all':
                exclude_subsets.update(VALID_SUBSETS)
                continue
            exclude = True
        else:
            exclude = False

        if subset not in VALID_SUBSETS:
            module.fail_json(msg='Bad subset: %s' % subset)

        if exclude:
            exclude_subsets.add(subset)
        else:
            runable_subsets.add(subset)

    if not runable_subsets:
        runable_subsets.update(VALID_SUBSETS)

    runable_subsets.difference_update(exclude_subsets)
    runable_subsets.add('default')

    facts = {}
    facts['gather_subset'] = sorted(runable_subsets)

    instances = []
    for key in runable_subsets:
        instances.append(FACT_SUBSETS[key](module, api))

    for inst in instances:
        inst.populate()
        facts.update(inst.facts)

    ansible_facts = {}
    for key, value in iteritems(facts):
        key = 'ansible_net_%s' % key
        ansible_facts[key] = value

    module.exit_json(ansible_facts=ansible_facts, warnings=warnings)
Example #5
0
def main():
    module_args = dict(
        path=dict(type='str', required=True),
        find=dict(type='dict', required=True),
        values=dict(type='dict', required=True),
        require_matches_min=dict(type='int', default=0),
        require_matches_max=dict(type='int'),
        allow_no_matches=dict(type='bool'),
    )
    module_args.update(api_argument_spec())

    module = AnsibleModule(
        argument_spec=module_args,
        supports_check_mode=True,
    )
    if module.params['allow_no_matches'] is None:
        module.params[
            'allow_no_matches'] = module.params['require_matches_min'] <= 0

    find = module.params['find']
    for key, value in sorted(find.items()):
        if key.startswith('!'):
            key = key[1:]
            if value not in (None, ''):
                module.fail_json(
                    msg=
                    'The value for "!{key}" in `find` must not be non-trivial!'
                    .format(key=key))
            if key in find:
                module.fail_json(
                    msg='`find` must not contain both "{key}" and "!{key}"!'.
                    format(key=key))
    values = module.params['values']
    for key, value in sorted(values.items()):
        if key.startswith('!'):
            key = key[1:]
            if value not in (None, ''):
                module.fail_json(
                    msg=
                    'The value for "!{key}" in `values` must not be non-trivial!'
                    .format(key=key))
            if key in values:
                module.fail_json(
                    msg='`values` must not contain both "{key}" and "!{key}"!'.
                    format(key=key))

    check_has_library(module)
    api = create_api(module)

    path = split_path(module.params['path'])

    api_path = compose_api_path(api, path)

    old_data = list(api_path)
    new_data = [entry.copy() for entry in old_data]

    # Find matching entries
    matching_entries = []
    for index, entry in enumerate(new_data):
        matches = True
        for key, value in find.items():
            if key.startswith('!'):
                # Allow to specify keys that should not be present by prepending '!'
                key = key[1:]
                value = None
            current_value = entry.get(key)
            if key in DISABLED_MEANS_EMPTY_STRING and value == '' and current_value is None:
                current_value = value
            if current_value != value:
                matches = False
                break
        if matches:
            matching_entries.append((index, entry))

    # Check whether the correct amount of entries was found
    if matching_entries:
        if len(matching_entries) < module.params['require_matches_min']:
            module.fail_json(
                msg='Found %d entries, but expected at least %d' %
                (len(matching_entries), module.params['require_matches_min']))
        if module.params['require_matches_max'] is not None and len(
                matching_entries) > module.params['require_matches_max']:
            module.fail_json(
                msg='Found %d entries, but expected at most %d' %
                (len(matching_entries), module.params['require_matches_max']))
    elif not module.params['allow_no_matches']:
        module.fail_json(msg='Found no entries, but allow_no_matches=false')

    # Identify entries to update
    modifications = []
    for index, entry in matching_entries:
        modification = {}
        for key, value in values.items():
            if key.startswith('!'):
                # Allow to specify keys to remove by prepending '!'
                key = key[1:]
                value = None
            current_value = entry.get(key)
            if key in DISABLED_MEANS_EMPTY_STRING and value == '' and current_value is None:
                current_value = value
            if current_value != value:
                if value is None:
                    disable_key = '!%s' % key
                    if key in DISABLED_MEANS_EMPTY_STRING:
                        disable_key = key
                    modification[disable_key] = ''
                    entry.pop(key, None)
                else:
                    modification[key] = value
                    entry[key] = value
        if modification:
            if '.id' in entry:
                modification['.id'] = entry['.id']
            modifications.append(modification)

    # Apply changes
    if not module.check_mode and modifications:
        for modification in modifications:
            try:
                api_path.update(**modification)
            except (LibRouterosError, UnicodeEncodeError) as e:
                module.fail_json(
                    msg='Error while modifying for .id={id}: {error}'.format(
                        id=modification['.id'],
                        error=to_native(e),
                    ))
        new_data = list(api_path)

    # Produce return value
    more = {}
    if module._diff:
        # Only include the matching values
        more['diff'] = {
            'before': {
                'values':
                [old_data[index] for index, entry in matching_entries],
            },
            'after': {
                'values': [entry for index, entry in matching_entries],
            },
        }
    module.exit_json(changed=bool(modifications),
                     old_data=old_data,
                     new_data=new_data,
                     match_count=len(matching_entries),
                     modify_count=len(modifications),
                     **more)