Exemplo n.º 1
0
    def run(self, terms, variables, **kwargs):
        results = []

        for term in terms:
            try:
                self.reset()  # clear out things for this iteration
                try:
                    if not self.parse_simple_args(term):
                        self.parse_kv_args(parse_kv(term))
                except AssibleError:
                    raise
                except Exception as e:
                    raise AssibleError(
                        "unknown error parsing with_sequence arguments: %r. Error was: %s"
                        % (term, e))

                self.sanity_check()
                if self.stride != 0:
                    results.extend(self.generate_sequence())
            except AssibleError:
                raise
            except Exception as e:
                raise AssibleError("unknown error generating sequence: %s" % e)

        return results
Exemplo n.º 2
0
def load_extra_vars(loader):
    extra_vars = {}
    for extra_vars_opt in context.CLIARGS.get('extra_vars', tuple()):
        data = None
        extra_vars_opt = to_text(extra_vars_opt, errors='surrogate_or_strict')
        if extra_vars_opt is None or not extra_vars_opt:
            continue

        if extra_vars_opt.startswith(u"@"):
            # Argument is a YAML file (JSON is a subset of YAML)
            data = loader.load_from_file(extra_vars_opt[1:])
        elif extra_vars_opt[0] in [u'/', u'.']:
            raise AssibleOptionsError("Please prepend extra_vars filename '%s' with '@'" % extra_vars_opt)
        elif extra_vars_opt[0] in [u'[', u'{']:
            # Arguments as YAML
            data = loader.load(extra_vars_opt)
        else:
            # Arguments as Key-value
            data = parse_kv(extra_vars_opt)

        if isinstance(data, MutableMapping):
            extra_vars = combine_vars(extra_vars, data)
        else:
            raise AssibleOptionsError("Invalid extra vars data supplied. '%s' could not be made into a dictionary" % extra_vars_opt)

    return extra_vars
Exemplo n.º 3
0
    def _normalize_new_style_args(self, thing, action):
        '''
        deals with fuzziness in new style module invocations
        accepting key=value pairs and dictionaries, and returns
        a dictionary of arguments

        possible example inputs:
            'echo hi', 'shell'
            {'region': 'xyz'}, 'ec2'
        standardized outputs like:
            { _raw_params: 'echo hi', _uses_shell: True }
        '''

        if isinstance(thing, dict):
            # form is like: { xyz: { x: 2, y: 3 } }
            args = thing
        elif isinstance(thing, string_types):
            # form is like: copy: src=a dest=b
            check_raw = action in FREEFORM_ACTIONS
            args = parse_kv(thing, check_raw=check_raw)
        elif thing is None:
            # this can happen with modules which take no params, like ping:
            args = None
        else:
            raise AssibleParserError("unexpected parameter type in action: %s" % type(thing), obj=self._task_ds)
        return args
Exemplo n.º 4
0
    def _normalize_parameters(self, thing, action=None, additional_args=None):
        '''
        arguments can be fuzzy.  Deal with all the forms.
        '''

        additional_args = {} if additional_args is None else additional_args

        # final args are the ones we'll eventually return, so first update
        # them with any additional args specified, which have lower priority
        # than those which may be parsed/normalized next
        final_args = dict()
        if additional_args:
            if isinstance(additional_args, string_types):
                templar = Templar(loader=None)
                if templar.is_template(additional_args):
                    final_args['_variable_params'] = additional_args
                else:
                    raise AssibleParserError("Complex args containing variables cannot use bare variables (without Jinja2 delimiters), "
                                             "and must use the full variable style ('{{var_name}}')")
            elif isinstance(additional_args, dict):
                final_args.update(additional_args)
            else:
                raise AssibleParserError('Complex args must be a dictionary or variable string ("{{var}}").')

        # how we normalize depends if we figured out what the module name is
        # yet.  If we have already figured it out, it's a 'new style' invocation.
        # otherwise, it's not

        if action is not None:
            args = self._normalize_new_style_args(thing, action)
        else:
            (action, args) = self._normalize_old_style_args(thing)

            # this can occasionally happen, simplify
            if args and 'args' in args:
                tmp_args = args.pop('args')
                if isinstance(tmp_args, string_types):
                    tmp_args = parse_kv(tmp_args)
                args.update(tmp_args)

        # only internal variables can start with an underscore, so
        # we don't allow users to set them directly in arguments
        if args and action not in FREEFORM_ACTIONS:
            for arg in args:
                arg = to_text(arg)
                if arg.startswith('_assible_'):
                    raise AssibleError("invalid parameter specified for action '%s': '%s'" % (action, arg))

        # finally, update the args we're going to return with the ones
        # which were normalized above
        if args:
            final_args.update(args)

        return (action, final_args)
Exemplo n.º 5
0
def _parse_parameters(term):
    """Hacky parsing of params

    See https://github.com/assible/assible-modules-core/issues/1968#issuecomment-136842156
    and the first_found lookup For how we want to fix this later
    """
    first_split = term.split(' ', 1)
    if len(first_split) <= 1:
        # Only a single argument given, therefore it's a path
        relpath = term
        params = dict()
    else:
        relpath = first_split[0]
        params = parse_kv(first_split[1])
        if '_raw_params' in params:
            # Spaces in the path?
            relpath = u' '.join((relpath, params['_raw_params']))
            del params['_raw_params']

            # Check that we parsed the params correctly
            if not term.startswith(relpath):
                # Likely, the user had a non parameter following a parameter.
                # Reject this as a user typo
                raise AssibleError(
                    'Unrecognized value after key=value parameters given to password lookup'
                )
        # No _raw_params means we already found the complete path when
        # we split it initially

    # Check for invalid parameters.  Probably a user typo
    invalid_params = frozenset(params.keys()).difference(VALID_PARAMS)
    if invalid_params:
        raise AssibleError(
            'Unrecognized parameter(s) given to password lookup: %s' %
            ', '.join(invalid_params))

    # Set defaults
    params['length'] = int(params.get('length', DEFAULT_LENGTH))
    params['encrypt'] = params.get('encrypt', None)

    params['chars'] = params.get('chars', None)
    if params['chars']:
        tmp_chars = []
        if u',,' in params['chars']:
            tmp_chars.append(u',')
        tmp_chars.extend(
            c for c in params['chars'].replace(u',,', u',').split(u',') if c)
        params['chars'] = tmp_chars
    else:
        # Default chars for password
        params['chars'] = [u'ascii_letters', u'digits', u".,:-_"]

    return relpath, params
Exemplo n.º 6
0
    def _normalize_old_style_args(self, thing):
        '''
        deals with fuzziness in old-style (action/local_action) module invocations
        returns tuple of (module_name, dictionary_args)

        possible example inputs:
           { 'shell' : 'echo hi' }
           'shell echo hi'
           {'module': 'ec2', 'x': 1 }
        standardized outputs like:
           ('ec2', { 'x': 1} )
        '''

        action = None
        args = None

        if isinstance(thing, dict):
            # form is like:  action: { module: 'copy', src: 'a', dest: 'b' }
            thing = thing.copy()
            if 'module' in thing:
                action, module_args = self._split_module_string(thing['module'])
                args = thing.copy()
                check_raw = action in FREEFORM_ACTIONS
                args.update(parse_kv(module_args, check_raw=check_raw))
                del args['module']

        elif isinstance(thing, string_types):
            # form is like:  action: copy src=a dest=b
            (action, args) = self._split_module_string(thing)
            check_raw = action in FREEFORM_ACTIONS
            args = parse_kv(args, check_raw=check_raw)

        else:
            # need a dict or a string, so giving up
            raise AssibleParserError("unexpected parameter type in action: %s" % type(thing), obj=self._task_ds)

        return (action, args)
Exemplo n.º 7
0
    def run(self, terms, variables=None, **kwargs):

        ret = []

        for term in terms:
            kv = parse_kv(term)

            if '_raw_params' not in kv:
                raise AssibleError('Search key is required but was not found')

            key = kv['_raw_params']

            paramvals = {
                'col': "1",  # column to return
                'default': None,
                'delimiter': "TAB",
                'file': 'assible.csv',
                'encoding': 'utf-8',
            }

            # parameters specified?
            try:
                for name, value in kv.items():
                    if name == '_raw_params':
                        continue
                    if name not in paramvals:
                        raise AssibleAssertionError('%s not in paramvals' %
                                                    name)
                    paramvals[name] = value
            except (ValueError, AssertionError) as e:
                raise AssibleError(e)

            if paramvals['delimiter'] == 'TAB':
                paramvals['delimiter'] = "\t"

            lookupfile = self.find_file_in_search_path(variables, 'files',
                                                       paramvals['file'])
            var = self.read_csv(lookupfile, key, paramvals['delimiter'],
                                paramvals['encoding'], paramvals['default'],
                                paramvals['col'])
            if var is not None:
                if isinstance(var, MutableSequence):
                    for v in var:
                        ret.append(v)
                else:
                    ret.append(var)
        return ret
Exemplo n.º 8
0
    def _preprocess_import(self, ds, new_ds, k, v):
        '''
        Splits the playbook import line up into filename and parameters
        '''

        if v is None:
            raise AssibleParserError("playbook import parameter is missing",
                                     obj=ds)
        elif not isinstance(v, string_types):
            raise AssibleParserError(
                "playbook import parameter must be a string indicating a file path, got %s instead"
                % type(v),
                obj=ds)

        # The import_playbook line must include at least one item, which is the filename
        # to import. Anything after that should be regarded as a parameter to the import
        items = split_args(v)
        if len(items) == 0:
            raise AssibleParserError(
                "import_playbook statements must specify the file name to import",
                obj=ds)
        else:
            new_ds['import_playbook'] = items[0].strip()
            if len(items) > 1:
                display.warning(
                    'Additional parameters in import_playbook statements are not supported. This will be an error in version 2.14'
                )
                # rejoin the parameter portion of the arguments and
                # then use parse_kv() to get a dict of params back
                params = parse_kv(" ".join(items[1:]))
                if 'tags' in params:
                    new_ds['tags'] = params.pop('tags')
                if 'vars' in new_ds:
                    raise AssibleParserError(
                        "import_playbook parameters cannot be mixed with 'vars' entries for import statements",
                        obj=ds)
                new_ds['vars'] = params
Exemplo n.º 9
0
    def _play_ds(self, pattern, async_val, poll):
        check_raw = context.CLIARGS['module_name'] in C.MODULE_REQUIRE_ARGS

        mytask = {
            'action': {
                'module':
                context.CLIARGS['module_name'],
                'args':
                parse_kv(context.CLIARGS['module_args'], check_raw=check_raw)
            }
        }

        # avoid adding to tasks that don't support it, unless set, then give user an error
        if context.CLIARGS['module_name'] not in ('include_role',
                                                  'include_tasks') and any(
                                                      frozenset(
                                                          (async_val, poll))):
            mytask['async_val'] = async_val
            mytask['poll'] = poll

        return dict(name="Assible Ad-Hoc",
                    hosts=pattern,
                    gather_facts='no',
                    tasks=[mytask])
Exemplo n.º 10
0
def test_parse_kv(args, expected):
    assert parse_kv(args) == expected
Exemplo n.º 11
0
    def default(self, arg, forceshell=False):
        """ actually runs modules """
        if arg.startswith("#"):
            return False

        if not self.cwd:
            display.error("No host found")
            return False

        if arg.split()[0] in self.modules:
            module = arg.split()[0]
            module_args = ' '.join(arg.split()[1:])
        else:
            module = 'shell'
            module_args = arg

        if forceshell is True:
            module = 'shell'
            module_args = arg

        result = None
        try:
            check_raw = module in ('command', 'shell', 'script', 'raw')
            play_ds = dict(
                name="Assible Shell",
                hosts=self.cwd,
                gather_facts='no',
                tasks=[
                    dict(action=dict(module=module,
                                     args=parse_kv(module_args,
                                                   check_raw=check_raw)))
                ],
                remote_user=self.remote_user,
                become=self.become,
                become_user=self.become_user,
                become_method=self.become_method,
                check_mode=self.check_mode,
                diff=self.diff,
            )
            play = Play().load(play_ds,
                               variable_manager=self.variable_manager,
                               loader=self.loader)
        except Exception as e:
            display.error(u"Unable to build command: %s" % to_text(e))
            return False

        try:
            cb = 'minimal'  # FIXME: make callbacks configurable
            # now create a task queue manager to execute the play
            self._tqm = None
            try:
                self._tqm = TaskQueueManager(
                    inventory=self.inventory,
                    variable_manager=self.variable_manager,
                    loader=self.loader,
                    passwords=self.passwords,
                    stdout_callback=cb,
                    run_additional_callbacks=C.DEFAULT_LOAD_CALLBACK_PLUGINS,
                    run_tree=False,
                    forks=self.forks,
                )

                result = self._tqm.run(play)
            finally:
                if self._tqm:
                    self._tqm.cleanup()
                if self.loader:
                    self.loader.cleanup_all_tmp_files()

            if result is None:
                display.error("No hosts found")
                return False
        except KeyboardInterrupt:
            display.error('User interrupted execution')
            return False
        except Exception as e:
            display.error(to_text(e))
            # FIXME: add traceback in very very verbose mode
            return False