Beispiel #1
0
    def run(self,
            conn,
            tmp,
            module_name,
            module_args,
            inject,
            complex_args=None,
            **kwargs):

        # the group_by module does not need to pay attention to check mode.
        # it always runs.

        args = {}
        if complex_args:
            args.update(complex_args)
        args.update(parse_kv(self.runner.module_args))
        if not 'key' in args:
            raise ae("'key' is a required argument.")

        vv("created 'group_by' ActionModule: key=%s" % (args['key']))

        inventory = self.runner.inventory

        result = {'changed': False}

        ### find all groups
        groups = {}

        for host in self.runner.host_set:

            data = inject['hostvars'][host]
            if not check_conditional(
                    template.template(self.runner.basedir,
                                      self.runner.conditional, data)):
                continue
            group_name = template.template(self.runner.basedir, args['key'],
                                           data)
            group_name = group_name.replace(' ', '-')
            if group_name not in groups:
                groups[group_name] = []
            groups[group_name].append(host)

        result['groups'] = groups

        ### add to inventory
        for group, hosts in groups.items():
            inv_group = inventory.get_group(group)
            if not inv_group:
                inv_group = ansible.inventory.Group(name=group)
                inventory.add_group(inv_group)
            for host in hosts:
                del self.runner.inventory._vars_per_host[host]
                inv_host = inventory.get_host(host)
                if not inv_host:
                    inv_host = ansible.inventory.Host(name=host)
                if inv_group not in inv_host.get_groups():
                    result['changed'] = True
                    inv_group.add_host(inv_host)

        return ReturnData(conn=conn, comm_ok=True, result=result)
Beispiel #2
0
    def run(self, conn, tmp, module_name, module_args, inject, complex_args=None, **kwargs):

        # note: the fail module does not need to pay attention to check mode
        # it always runs.

        args = {}
        if complex_args:
            args.update(complex_args)
        args.update(utils.parse_kv(module_args))

        msg = ''

        if 'msg' in args:
            msg = args['msg']

        if not 'that' in args:
            raise errors.AnsibleError('conditional required in "that" string')

        if not isinstance(args['that'], list):
            args['that'] = [ args['that'] ]

        for that in args['that']:
            result = utils.check_conditional(that, self.runner.basedir, inject, fail_on_undefined=True)
            if not result:
                return ReturnData(conn=conn, result=dict(failed=True, assertion=that, evaluated_to=result))

        return ReturnData(conn=conn, result=dict(msg='all assertions passed'))
Beispiel #3
0
    def run(self, conn, tmp, module_name, module_args, inject, complex_args=None, **kwargs):

        # the group_by module does not need to pay attention to check mode.
        # it always runs.

        args = {}
        if complex_args:
            args.update(complex_args)
        args.update(parse_kv(self.runner.module_args))
        if not 'key' in args:
            raise ae("'key' is a required argument.")

        vv("created 'group_by' ActionModule: key=%s"%(args['key']))

        inventory = self.runner.inventory

        result = {'changed': False}

        ### find all groups
        groups = {}

        for host in self.runner.host_set:
            data = {}
            data.update(inject)
            data.update(inject['hostvars'][host])
            conds = self.runner.conditional
            if type(conds) != list:
                conds = [ conds ]
            next_host = False
            for cond in conds:
                if not check_conditional(cond, self.runner.basedir, data, fail_on_undefined=self.runner.error_on_undefined_vars):
                    next_host = True
                    break
            if next_host:
                continue
            group_name = template.template(self.runner.basedir, args['key'], data)
            group_name = group_name.replace(' ','-')
            if group_name not in groups:
                groups[group_name] = []
            groups[group_name].append(host)

        result['groups'] = groups

        ### add to inventory
        for group, hosts in groups.items():
            inv_group = inventory.get_group(group)
            if not inv_group:
                inv_group = ansible.inventory.Group(name=group)
                inventory.add_group(inv_group)
            for host in hosts:
                del self.runner.inventory._vars_per_host[host]
                inv_host = inventory.get_host(host)
                if not inv_host:
                    inv_host = ansible.inventory.Host(name=host)
                if inv_group not in inv_host.get_groups():
                    result['changed'] = True
                    inv_group.add_host(inv_host)

        return ReturnData(conn=conn, comm_ok=True, result=result)
Beispiel #4
0
    def noop_on_check(self, inject):
        ''' Should the runner run in check mode or not ? '''

        # initialize self.always_run on first call
        if self.always_run is None:
            self.always_run = self.module_vars.get('always_run', False)
            self.always_run = check_conditional(
                self.always_run, self.basedir, inject, fail_on_undefined=True, jinja2=True)

        return (self.check and not self.always_run)
Beispiel #5
0
    def noop_on_check(self, inject):
        ''' Should the runner run in check mode or not ? '''

        # initialize self.always_run on first call
        if self.always_run is None:
            self.always_run = self.module_vars.get('always_run', False)
            self.always_run = check_conditional(
                self.always_run, self.basedir, inject, fail_on_undefined=True, jinja2=True)

        return (self.check and not self.always_run)
Beispiel #6
0
    def _executor_internal_inner(self,
                                 host,
                                 module_name,
                                 module_args,
                                 inject,
                                 port,
                                 is_chained=False):
        ''' decides how to invoke a module '''

        # special non-user/non-fact variables:
        # 'groups' variable is a list of host name in each group
        # 'hostvars' variable contains variables for each host name
        #  ... and is set elsewhere
        # 'inventory_hostname' is also set elsewhere
        inject['groups'] = self.inventory.groups_list()

        # allow module args to work as a dictionary
        # though it is usually a string
        new_args = ""
        if type(module_args) == dict:
            for (k, v) in module_args.iteritems():
                new_args = new_args + "%s='%s' " % (k, v)
            module_args = new_args

        conditional = utils.template(self.basedir, self.conditional, inject)
        if not utils.check_conditional(conditional):
            result = utils.jsonify(dict(skipped=True))
            self.callbacks.on_skipped(host, inject.get('item', None))
            return ReturnData(host=host, result=result)

        conn = None
        actual_host = host
        try:
            delegate_to = inject.get('delegate_to', None)
            alternative_host = inject.get('ansible_ssh_host', None)
            if delegate_to is not None:
                actual_host = delegate_to
            elif alternative_host is not None:
                actual_host = alternative_host
            conn = self.connector.connect(actual_host, port)
            if delegate_to is not None or alternative_host is not None:
                conn._delegate_for = host
        except errors.AnsibleConnectionFailed, e:
            result = dict(failed=True, msg="FAILED: %s" % str(e))
            return ReturnData(host=host, comm_ok=False, result=result)
Beispiel #7
0
    def run(self,
            conn,
            tmp,
            module_name,
            module_args,
            inject,
            complex_args=None,
            **kwargs):

        # note: the fail module does not need to pay attention to check mode
        # it always runs.

        args = {}
        if complex_args:
            args.update(complex_args)
        args.update(utils.parse_kv(module_args))

        msg = None
        if 'msg' in args:
            msg = args['msg']

        if not 'that' in args:
            raise errors.AnsibleError('conditional required in "that" string')

        if not isinstance(args['that'], list):
            args['that'] = [args['that']]

        for that in args['that']:
            test_result = utils.check_conditional(that,
                                                  self.runner.basedir,
                                                  inject,
                                                  fail_on_undefined=True)
            if not test_result:
                result = dict(
                    failed=True,
                    evaluated_to=test_result,
                    assertion=that,
                )
                if msg:
                    result['msg'] = msg
                return ReturnData(conn=conn, result=result)

        return ReturnData(conn=conn, result=dict(msg='all assertions passed'))
Beispiel #8
0
    def run(self, conn, tmp, module_name, module_args, inject):
        args = parse_kv(self.runner.module_args)
        if not 'key' in args:
            raise ae("'key' is a required argument.")

        vv("created 'group_by' ActionModule: key=%s"%(args['key']))

        inventory = self.runner.inventory

        result = {'changed': False}

        ### find all groups
        groups = {}
        for host in self.runner.host_set:
            data = inject['hostvars'][host]
            if not check_conditional(template(self.runner.basedir, self.runner.conditional, data)):
                continue
            group_name = template(self.runner.basedir, args['key'], data)
            group_name = group_name.replace(' ','-')
            if group_name not in groups:
                groups[group_name] = []
            groups[group_name].append(host)

        result['groups'] = groups

        ### add to inventory
        for group, hosts in groups.items():
            inv_group = inventory.get_group(group)
            if not inv_group:
                inv_group = ansible.inventory.Group(name=group)
                inventory.add_group(inv_group)
            for host in hosts:
                inv_host = inventory.get_host(host)
                if not inv_host:
                    inv_host = ansible.inventory.Host(name=host)
                if inv_group not in inv_host.get_groups():
                    result['changed'] = True
                    inv_group.add_host(inv_host)

        return ReturnData(conn=conn, comm_ok=True, result=result)
Beispiel #9
0
    def _executor_internal_inner(self, host, module_name, module_args, inject, port, is_chained=False):
        ''' decides how to invoke a module '''

        # special non-user/non-fact variables:
        # 'groups' variable is a list of host name in each group
        # 'hostvars' variable contains variables for each host name
        #  ... and is set elsewhere
        # 'inventory_hostname' is also set elsewhere
        inject['groups'] = self.inventory.groups_list()

        # allow module args to work as a dictionary
        # though it is usually a string
        new_args = ""
        if type(module_args) == dict:
            for (k,v) in module_args.iteritems():
                new_args = new_args + "%s='%s' " % (k,v)
            module_args = new_args

        conditional = utils.template(self.basedir, self.conditional, inject)
        if not utils.check_conditional(conditional):
            result = utils.jsonify(dict(skipped=True))
            self.callbacks.on_skipped(host, inject.get('item',None))
            return ReturnData(host=host, result=result)

        conn = None
        actual_host = host
        try:
            delegate_to = inject.get('delegate_to', None)
            alternative_host = inject.get('ansible_ssh_host', None)
            if delegate_to is not None:
                actual_host = delegate_to
            elif alternative_host is not None:
                actual_host = alternative_host
            conn = self.connector.connect(actual_host, port)
            if delegate_to is not None or alternative_host is not None:
                conn._delegate_for = host
        except errors.AnsibleConnectionFailed, e:
            result = dict(failed=True, msg="FAILED: %s" % str(e))
            return ReturnData(host=host, comm_ok=False, result=result)
Beispiel #10
0
    def _run_task(self, play, task, is_handler):
        ''' run a single task in the playbook and recursively run any subtasks.  '''

        ansible.callbacks.set_task(self.callbacks, task)
        ansible.callbacks.set_task(self.runner_callbacks, task)

        if task.role_name:
            name = '%s | %s' % (task.role_name, task.name)
        else:
            name = task.name

        try:
            # v1 HACK: we don't have enough information to template many names
            # at this point.  Rather than making this work for all cases in
            # v1, just make this degrade gracefully.  Will fix in v2
            name = template(play.basedir,
                            name,
                            task.module_vars,
                            lookup_fatal=False,
                            filter_fatal=False)
        except:
            pass

        self.callbacks.on_task_start(name, is_handler)
        if hasattr(self.callbacks, 'skip_task') and self.callbacks.skip_task:
            ansible.callbacks.set_task(self.callbacks, None)
            ansible.callbacks.set_task(self.runner_callbacks, None)
            return True

        # template ignore_errors
        # TODO: Is this needed here?  cond is templated again in
        # check_conditional after some more manipulations.
        # TODO: we don't have enough information here to template cond either
        # (see note on templating name above)
        cond = template(play.basedir,
                        task.ignore_errors,
                        task.module_vars,
                        expand_lists=False)
        task.ignore_errors = utils.check_conditional(
            cond,
            play.basedir,
            task.module_vars,
            fail_on_undefined=C.DEFAULT_UNDEFINED_VAR_BEHAVIOR)

        # load up an appropriate ansible runner to run the task in parallel
        include_failed = is_handler and play.force_handlers
        results = self._run_task_internal(task, include_failed=include_failed)

        # if no hosts are matched, carry on
        hosts_remaining = True
        if results is None:
            hosts_remaining = False
            results = {}

        contacted = results.get('contacted', {})
        self.stats.compute(results, ignore_errors=task.ignore_errors)

        def _register_play_vars(host, result):
            # when 'register' is used, persist the result in the vars cache
            # rather than the setup cache - vars should be transient between
            # playbook executions
            if 'stdout' in result and 'stdout_lines' not in result:
                result['stdout_lines'] = result['stdout'].splitlines()
            utils.update_hash(self.VARS_CACHE, host, {task.register: result})

        def _save_play_facts(host, facts):
            # saves play facts in SETUP_CACHE, unless the module executed was
            # set_fact, in which case we add them to the VARS_CACHE
            if task.module_name in ('set_fact', 'include_vars'):
                utils.update_hash(self.VARS_CACHE, host, facts)
            else:
                utils.update_hash(self.SETUP_CACHE, host, facts)

        # add facts to the global setup cache
        for host, result in contacted.iteritems():
            if 'results' in result:
                # task ran with_ lookup plugin, so facts are encapsulated in
                # multiple list items in the results key
                for res in result['results']:
                    if type(res) == dict:
                        facts = res.get('ansible_facts', {})
                        _save_play_facts(host, facts)
            else:
                # when facts are returned, persist them in the setup cache
                facts = result.get('ansible_facts', {})
                _save_play_facts(host, facts)

            # if requested, save the result into the registered variable name
            if task.register:
                _register_play_vars(host, result)

        # also have to register some failed, but ignored, tasks
        if task.ignore_errors and task.register:
            failed = results.get('failed', {})
            for host, result in failed.iteritems():
                _register_play_vars(host, result)

        # flag which notify handlers need to be run
        if task.notify and len(task.notify) > 0:
            for host, results in results.get('contacted', {}).iteritems():
                if results.get('changed', False):
                    for handler_name in task.notify:
                        self._flag_handler(
                            play,
                            template(play.basedir, handler_name,
                                     task.module_vars), host)

        ansible.callbacks.set_task(self.callbacks, None)
        ansible.callbacks.set_task(self.runner_callbacks, None)
        return hosts_remaining
            raise ae("'key' is a required argument.")

        vv("created 'group_by' ActionModule: key=%s"%(args['key']))

        inventory = self.runner.inventory

        result = {'changed': False}

        ### find all groups
        groups = {}

        for host in self.runner.host_set:
<<<<<<< HEAD

            data = inject['hostvars'][host]
            if not check_conditional(template.template(self.runner.basedir, self.runner.conditional, data)):
=======
            if not check_conditional(template.template(self.runner.basedir, self.runner.conditional, inject)):
>>>>>>> remote
                continue
            group_name = template.template(self.runner.basedir, args['key'], inject)
            group_name = group_name.replace(' ','-')
            if group_name not in groups:
                groups[group_name] = []
            groups[group_name].append(host)

        result['groups'] = groups

        ### add to inventory
        for group, hosts in groups.items():
            inv_group = inventory.get_group(group)
Beispiel #12
0
    def _run_task(self, play, task, is_handler):
        ''' run a single task in the playbook and recursively run any subtasks.  '''

        ansible.callbacks.set_task(self.callbacks, task)
        ansible.callbacks.set_task(self.runner_callbacks, task)

        if task.role_name:
            name = '%s | %s' % (task.role_name, task.name)
        else:
            name = task.name

        self.callbacks.on_task_start(
            template(play.basedir,
                     name,
                     task.module_vars,
                     lookup_fatal=False,
                     filter_fatal=False), is_handler)
        if hasattr(self.callbacks, 'skip_task') and self.callbacks.skip_task:
            ansible.callbacks.set_task(self.callbacks, None)
            ansible.callbacks.set_task(self.runner_callbacks, None)
            return True

        # template ignore_errors
        cond = template(play.basedir,
                        task.ignore_errors,
                        task.module_vars,
                        expand_lists=False)
        task.ignore_errors = utils.check_conditional(
            cond,
            play.basedir,
            task.module_vars,
            fail_on_undefined=C.DEFAULT_UNDEFINED_VAR_BEHAVIOR)

        # load up an appropriate ansible runner to run the task in parallel
        results = self._run_task_internal(task)

        # if no hosts are matched, carry on
        hosts_remaining = True
        if results is None:
            hosts_remaining = False
            results = {}

        contacted = results.get('contacted', {})
        self.stats.compute(results, ignore_errors=task.ignore_errors)

        # add facts to the global setup cache
        for host, result in contacted.iteritems():
            if 'results' in result:
                # task ran with_ lookup plugin, so facts are encapsulated in
                # multiple list items in the results key
                for res in result['results']:
                    if type(res) == dict:
                        facts = res.get('ansible_facts', {})
                        self.SETUP_CACHE[host].update(facts)
            else:
                facts = result.get('ansible_facts', {})
                self.SETUP_CACHE[host].update(facts)
            if task.register:
                if 'stdout' in result and 'stdout_lines' not in result:
                    result['stdout_lines'] = result['stdout'].splitlines()
                self.SETUP_CACHE[host][task.register] = result

        # also have to register some failed, but ignored, tasks
        if task.ignore_errors and task.register:
            failed = results.get('failed', {})
            for host, result in failed.iteritems():
                if 'stdout' in result and 'stdout_lines' not in result:
                    result['stdout_lines'] = result['stdout'].splitlines()
                self.SETUP_CACHE[host][task.register] = result

        # flag which notify handlers need to be run
        if len(task.notify) > 0:
            for host, results in results.get('contacted', {}).iteritems():
                if results.get('changed', False):
                    for handler_name in task.notify:
                        self._flag_handler(
                            play,
                            template(play.basedir, handler_name,
                                     task.module_vars), host)

        ansible.callbacks.set_task(self.callbacks, None)
        ansible.callbacks.set_task(self.runner_callbacks, None)
        return hosts_remaining
Beispiel #13
0
            if 'item' in inject:
                result.result['item'] = inject['item']

            result.result['invocation'] = dict(module_args=module_args,
                                               module_name=module_name)

            changed_when = self.module_vars.get('changed_when')
            if changed_when is not None:
                register = self.module_vars.get('register')
                if register is not None:
                    if 'stdout' in data:
                        data['stdout_lines'] = data['stdout'].splitlines()
                    inject[register] = data
                data['changed'] = utils.check_conditional(
                    changed_when,
                    self.basedir,
                    inject,
                    fail_on_undefined=self.error_on_undefined_vars)

            if is_chained:
                # no callbacks
                return result
            if 'skipped' in data:
                self.callbacks.on_skipped(host)
            elif not result.is_successful():
                ignore_errors = self.module_vars.get('ignore_errors', False)
                self.callbacks.on_failed(host, data, ignore_errors)
            else:
                if self.diff:
                    self.callbacks.on_file_diff(conn.host, result.diff)
                self.callbacks.on_ok(host, data)
Beispiel #14
0
    def run(self, conn, tmp, module_name, module_args, inject, complex_args=None, **kwargs):

        # the group_by module does not need to pay attention to check mode.
        # it always runs.

        # module_args and complex_args have already been templated for the first host.
        # Use them here only to check that a key argument is provided.
        args = {}
        if complex_args:
            args.update(complex_args)
        args.update(parse_kv(module_args))
        if not 'key' in args:
            raise ae("'key' is a required argument.")

        vv("created 'group_by' ActionModule: key=%s"%(args['key']))

        inventory = self.runner.inventory

        result = {'changed': False}

        ### find all groups
        groups = {}

        for host in self.runner.host_set:
            data = {}
            data.update(inject)
            data.update(inject['hostvars'][host])
            conds = self.runner.conditional
            if type(conds) != list:
                conds = [ conds ]
            next_host = False
            for cond in conds:
                if not check_conditional(cond, self.runner.basedir, data, fail_on_undefined=self.runner.error_on_undefined_vars):
                    next_host = True
                    break
            if next_host:
                continue

            # Template original module_args and complex_args from runner for each host.
            host_module_args = template.template(self.runner.basedir, self.runner.module_args, data)
            host_complex_args = template.template(self.runner.basedir, self.runner.complex_args, data)
            host_args  = {}
            if host_complex_args:
                host_args.update(host_complex_args)
            host_args.update(parse_kv(host_module_args))

            group_name = host_args['key']
            group_name = group_name.replace(' ','-')
            if group_name not in groups:
                groups[group_name] = []
            groups[group_name].append(host)

        result['groups'] = groups

        ### add to inventory
        for group, hosts in groups.items():
            inv_group = inventory.get_group(group)
            if not inv_group:
                inv_group = ansible.inventory.Group(name=group)
                inventory.add_group(inv_group)
                inventory.get_group('all').add_child_group(inv_group)
                inv_group.vars = inventory.get_group_variables(group, update_cached=False, vault_password=inventory._vault_password)
            for host in hosts:
                if host in self.runner.inventory._vars_per_host:
                    del self.runner.inventory._vars_per_host[host]
                inv_host = inventory.get_host(host)
                if not inv_host:
                    inv_host = ansible.inventory.Host(name=host)
                if inv_group not in inv_host.get_groups():
                    result['changed'] = True
                    inv_group.add_host(inv_host)

        return ReturnData(conn=conn, comm_ok=True, result=result)
Beispiel #15
0
    def _executor_internal(self, host, new_stdin):
        ''' executes any module one or more times '''

        host_variables = self.inventory.get_variables(host)
        host_connection = host_variables.get('ansible_connection', self.transport)
        if host_connection in [ 'paramiko', 'ssh', 'accelerate' ]:
            port = host_variables.get('ansible_ssh_port', self.remote_port)
            if port is None:
                port = C.DEFAULT_REMOTE_PORT
        else:
            # fireball, local, etc
            port = self.remote_port

        inject = {}
        inject = utils.combine_vars(inject, self.default_vars)
        inject = utils.combine_vars(inject, host_variables)
        inject = utils.combine_vars(inject, self.module_vars)
        inject = utils.combine_vars(inject, self.setup_cache[host])
        inject.setdefault('ansible_ssh_user', self.remote_user)
        inject['hostvars'] = HostVars(self.setup_cache, self.inventory)
        inject['group_names'] = host_variables.get('group_names', [])
        inject['groups']      = self.inventory.groups_list()
        inject['vars']        = self.module_vars
        inject['defaults']    = self.default_vars
        inject['environment'] = self.environment
        inject['playbook_dir'] = self.basedir

        if self.inventory.basedir() is not None:
            inject['inventory_dir'] = self.inventory.basedir()

        if self.inventory.src() is not None:
            inject['inventory_file'] = self.inventory.src()

        # allow with_foo to work in playbooks...
        items = None
        items_plugin = self.module_vars.get('items_lookup_plugin', None)

        if items_plugin is not None and items_plugin in utils.plugins.lookup_loader:

            basedir = self.basedir
            if '_original_file' in inject:
                basedir = os.path.dirname(inject['_original_file'])
                filesdir = os.path.join(basedir, '..', 'files')
                if os.path.exists(filesdir):
                    basedir = filesdir

            items_terms = self.module_vars.get('items_lookup_terms', '')
            items_terms = template.template(basedir, items_terms, inject)
            items = utils.plugins.lookup_loader.get(items_plugin, runner=self, basedir=basedir).run(items_terms, inject=inject)
            if type(items) != list:
                raise errors.AnsibleError("lookup plugins have to return a list: %r" % items)

            if len(items) and utils.is_list_of_strings(items) and self.module_name in [ 'apt', 'yum', 'pkgng' ]:
                # hack for apt, yum, and pkgng so that with_items maps back into a single module call
                use_these_items = []
                for x in items:
                    inject['item'] = x
                    if not self.conditional or utils.check_conditional(self.conditional, self.basedir, inject, fail_on_undefined=self.error_on_undefined_vars):
                        use_these_items.append(x)
                inject['item'] = ",".join(use_these_items)
                items = None

        # logic to replace complex args if possible
        complex_args = self.complex_args

        # logic to decide how to run things depends on whether with_items is used
        if items is None:
            if isinstance(complex_args, basestring):
                complex_args = template.template(self.basedir, complex_args, inject, convert_bare=True)
                complex_args = utils.safe_eval(complex_args)
                if type(complex_args) != dict:
                    raise errors.AnsibleError("args must be a dictionary, received %s" % complex_args)
            return self._executor_internal_inner(host, self.module_name, self.module_args, inject, port, complex_args=complex_args)
        elif len(items) > 0:

            # executing using with_items, so make multiple calls
            # TODO: refactor

            if self.background > 0:
                raise errors.AnsibleError("lookup plugins (with_*) cannot be used with async tasks")

            aggregrate = {}
            all_comm_ok = True
            all_changed = False
            all_failed = False
            results = []
            for x in items:
                inject['item'] = x

                # TODO: this idiom should be replaced with an up-conversion to a Jinja2 template evaluation
                if isinstance(self.complex_args, basestring):
                    complex_args = template.template(self.basedir, self.complex_args, inject, convert_bare=True)
                    complex_args = utils.safe_eval(complex_args)
                    if type(complex_args) != dict:
                        raise errors.AnsibleError("args must be a dictionary, received %s" % complex_args)
                result = self._executor_internal_inner(
                     host,
                     self.module_name,
                     self.module_args,
                     inject,
                     port,
                     complex_args=complex_args
                )
                results.append(result.result)
                if result.comm_ok == False:
                    all_comm_ok = False
                    all_failed = True
                    break
                for x in results:
                    if x.get('changed') == True:
                        all_changed = True
                    if (x.get('failed') == True) or ('failed_when_result' in x and [x['failed_when_result']] or [('rc' in x) and (x['rc'] != 0)])[0]:
                        all_failed = True
                        break
            msg = 'All items completed'
            if all_failed:
                msg = "One or more items failed."
            rd_result = dict(failed=all_failed, changed=all_changed, results=results, msg=msg)
            if not all_failed:
                del rd_result['failed']
            return ReturnData(host=host, comm_ok=all_comm_ok, result=rd_result)
        else:
            self.callbacks.on_skipped(host, None)
            return ReturnData(host=host, comm_ok=True, result=dict(changed=False, skipped=True))
Beispiel #16
0
    def _run_task(self, play, task, is_handler):
        ''' run a single task in the playbook and recursively run any subtasks.  '''

        ansible.callbacks.set_task(self.callbacks, task)
        ansible.callbacks.set_task(self.runner_callbacks, task)

        if task.role_name:
            name = '%s | %s' % (task.role_name, task.name)
        else:
            name = task.name

        self.callbacks.on_task_start(template(play.basedir, name, task.module_vars, lookup_fatal=False, filter_fatal=False), is_handler)
        if hasattr(self.callbacks, 'skip_task') and self.callbacks.skip_task:
            ansible.callbacks.set_task(self.callbacks, None)
            ansible.callbacks.set_task(self.runner_callbacks, None)
            return True

        # template ignore_errors
        cond = template(play.basedir, task.ignore_errors, task.module_vars, expand_lists=False)
        task.ignore_errors =  utils.check_conditional(cond, play.basedir, task.module_vars, fail_on_undefined=C.DEFAULT_UNDEFINED_VAR_BEHAVIOR)

        # load up an appropriate ansible runner to run the task in parallel
        results = self._run_task_internal(task)

        # if no hosts are matched, carry on
        hosts_remaining = True
        if results is None:
            hosts_remaining = False
            results = {}

        contacted = results.get('contacted', {})
        self.stats.compute(results, ignore_errors=task.ignore_errors)

        def _register_play_vars(host, result):
            # when 'register' is used, persist the result in the vars cache
            # rather than the setup cache - vars should be transient between
            # playbook executions
            if 'stdout' in result and 'stdout_lines' not in result:
                result['stdout_lines'] = result['stdout'].splitlines()
            utils.update_hash(self.VARS_CACHE, host, {task.register: result})

        def _save_play_facts(host, facts):
            # saves play facts in SETUP_CACHE, unless the module executed was
            # set_fact, in which case we add them to the VARS_CACHE
            if task.module_name == 'set_fact':
                utils.update_hash(self.VARS_CACHE, host, facts)
            else:
                utils.update_hash(self.SETUP_CACHE, host, facts)

        # add facts to the global setup cache
        for host, result in contacted.iteritems():
            if 'results' in result:
                # task ran with_ lookup plugin, so facts are encapsulated in
                # multiple list items in the results key
                for res in result['results']:
                    if type(res) == dict:
                        facts = res.get('ansible_facts', {})
                        _save_play_facts(host, facts)
            else:
                # when facts are returned, persist them in the setup cache
                facts = result.get('ansible_facts', {})
                _save_play_facts(host, facts)

            # if requested, save the result into the registered variable name
            if task.register:
                _register_play_vars(host, result)

        # also have to register some failed, but ignored, tasks
        if task.ignore_errors and task.register:
            failed = results.get('failed', {})
            for host, result in failed.iteritems():
                _register_play_vars(host, result)

        # flag which notify handlers need to be run
        if len(task.notify) > 0:
            for host, results in results.get('contacted',{}).iteritems():
                if results.get('changed', False):
                    for handler_name in task.notify:
                        self._flag_handler(play, template(play.basedir, handler_name, task.module_vars), host)

        ansible.callbacks.set_task(self.callbacks, None)
        ansible.callbacks.set_task(self.runner_callbacks, None)
        return hosts_remaining
Beispiel #17
0
    def _get_vars(self):
        ''' load the vars section from a play, accounting for all sorts of variable features
        including loading from yaml files, prompting, and conditional includes of the first
        file found in a list. '''

        if self.vars is None:
            self.vars = {}

        if type(self.vars) not in [dict, list]:
            raise errors.AnsibleError(
                "'vars' section must contain only key/value pairs")

        vars = self.playbook.global_vars

        # translate a list of vars into a dict
        if type(self.vars) == list:
            for item in self.vars:
                if getattr(item, 'items', None) is None:
                    raise errors.AnsibleError(
                        "expecting a key-value pair in 'vars' section")
                k, v = item.items()[0]
                vars[k] = v
        else:
            vars.update(self.vars)

        if type(self.vars_prompt) == list:
            for var in self.vars_prompt:
                if not 'name' in var:
                    raise errors.AnsibleError(
                        "'vars_prompt' item is missing 'name:'")

                vname = var['name']
                prompt = utils.template(None,
                                        "%s: " % var.get("prompt", vname),
                                        self.vars)
                private = var.get("private", True)

                confirm = var.get("confirm", False)
                encrypt = var.get("encrypt", None)
                salt_size = var.get("salt_size", None)
                salt = var.get("salt", None)
                conditional = var.get("only_if", 'True')

                if utils.check_conditional(conditional):
                    vars[vname] = self.playbook.callbacks.on_vars_prompt(
                        vname, private, prompt, encrypt, confirm, salt_size,
                        salt)

        elif type(self.vars_prompt) == dict:
            for (vname, prompt) in self.vars_prompt.iteritems():
                prompt_msg = "%s: " % prompt
                vars[vname] = self.playbook.callbacks.on_vars_prompt(
                    varname=vname, private=False, prompt=prompt_msg)

        else:
            raise errors.AnsibleError(
                "'vars_prompt' section is malformed, see docs")

        results = self.playbook.extra_vars.copy()
        results.update(vars)
        return results
Beispiel #18
0
    def _executor_internal_inner(self, host, module_name, module_args, inject, port, is_chained=False, complex_args=None):
        ''' decides how to invoke a module '''


        # allow module args to work as a dictionary
        # though it is usually a string
        new_args = ""
        if type(module_args) == dict:
            for (k,v) in module_args.iteritems():
                new_args = new_args + "%s='%s' " % (k,v)
            module_args = new_args

        # module_name may be dynamic (but cannot contain {{ ansible_ssh_user }})
        module_name  = template.template(self.basedir, module_name, inject)

        if module_name in utils.plugins.action_loader:
            if self.background != 0:
                raise errors.AnsibleError("async mode is not supported with the %s module" % module_name)
            handler = utils.plugins.action_loader.get(module_name, self)
        elif self.background == 0:
            handler = utils.plugins.action_loader.get('normal', self)
        else:
            handler = utils.plugins.action_loader.get('async', self)

        if type(self.conditional) != list:
            self.conditional = [ self.conditional ]

        for cond in self.conditional:

            if not utils.check_conditional(cond, self.basedir, inject, fail_on_undefined=self.error_on_undefined_vars):
                result = utils.jsonify(dict(changed=False, skipped=True))
                self.callbacks.on_skipped(host, inject.get('item',None))
                return ReturnData(host=host, result=result)

        if getattr(handler, 'setup', None) is not None:
            handler.setup(module_name, inject)
        conn = None
        actual_host = inject.get('ansible_ssh_host', host)
        # allow ansible_ssh_host to be templated
        actual_host = template.template(self.basedir, actual_host, inject, fail_on_undefined=True)
        actual_port = port
        actual_user = inject.get('ansible_ssh_user', self.remote_user)
        actual_pass = inject.get('ansible_ssh_pass', self.remote_pass)
        actual_transport = inject.get('ansible_connection', self.transport)
        actual_private_key_file = inject.get('ansible_ssh_private_key_file', self.private_key_file)

        if self.accelerate and actual_transport != 'local':
            #Fix to get the inventory name of the host to accelerate plugin
            if inject.get('ansible_ssh_host', None):
                self.accelerate_inventory_host = host
            else:
                self.accelerate_inventory_host = None
            # if we're using accelerated mode, force the
            # transport to accelerate
            actual_transport = "accelerate"
            if not self.accelerate_port:
                self.accelerate_port = C.ACCELERATE_PORT

        if actual_transport in [ 'paramiko', 'ssh', 'accelerate' ]:
            actual_port = inject.get('ansible_ssh_port', port)

        # the delegated host may have different SSH port configured, etc
        # and we need to transfer those, and only those, variables
        delegate_to = inject.get('delegate_to', None)
        if delegate_to is not None:
            delegate_to = template.template(self.basedir, delegate_to, inject)
            inject = inject.copy()
            interpreters = []
            for i in inject:
                if i.startswith("ansible_") and i.endswith("_interpreter"):
                    interpreters.append(i)
            for i in interpreters:
                del inject[i]
            port = C.DEFAULT_REMOTE_PORT
            try:
                delegate_info = inject['hostvars'][delegate_to]
                actual_host = delegate_info.get('ansible_ssh_host', delegate_to)
                # allow ansible_ssh_host to be templated
                actual_host = template.template(self.basedir, actual_host, inject, fail_on_undefined=True)
                actual_port = delegate_info.get('ansible_ssh_port', port)
                actual_user = delegate_info.get('ansible_ssh_user', actual_user)
                actual_pass = delegate_info.get('ansible_ssh_pass', actual_pass)
                actual_private_key_file = delegate_info.get('ansible_ssh_private_key_file', self.private_key_file)
                actual_transport = delegate_info.get('ansible_connection', self.transport)
                for i in delegate_info:
                    if i.startswith("ansible_") and i.endswith("_interpreter"):
                        inject[i] = delegate_info[i]
            except errors.AnsibleError:
                actual_host = delegate_to
                actual_port = port

        # user/pass may still contain variables at this stage
        actual_user = template.template(self.basedir, actual_user, inject)
        actual_pass = template.template(self.basedir, actual_pass, inject)

        # make actual_user available as __magic__ ansible_ssh_user variable
        inject['ansible_ssh_user'] = actual_user

        try:
            if actual_transport == 'accelerate':
                # for accelerate, we stuff both ports into a single
                # variable so that we don't have to mangle other function
                # calls just to accomodate this one case
                actual_port = [actual_port, self.accelerate_port]
            elif actual_port is not None:
                actual_port = int(template.template(self.basedir, actual_port, inject))
        except ValueError, e:
            result = dict(failed=True, msg="FAILED: Configured port \"%s\" is not a valid port, expected integer" % actual_port)
            return ReturnData(host=host, comm_ok=False, result=result)
Beispiel #19
0
            if 'item' in inject:
                result.result['item'] = inject['item']

            result.result['invocation'] = dict(
                module_args=module_args,
                module_name=module_name
            )

            changed_when = self.module_vars.get('changed_when')
            if changed_when is not None:
                register = self.module_vars.get('register')
                if  register is not None:
                    if 'stdout' in data:
                        data['stdout_lines'] = data['stdout'].splitlines()
                    inject[register] = data
                data['changed'] = utils.check_conditional(changed_when, self.basedir, inject, fail_on_undefined=self.error_on_undefined_vars)

            if is_chained:
                # no callbacks
                return result
            if 'skipped' in data:
                self.callbacks.on_skipped(host)
            elif not result.is_successful():
                ignore_errors = self.module_vars.get('ignore_errors', False)
                self.callbacks.on_failed(host, data, ignore_errors)
            else:
                if self.diff:
                    self.callbacks.on_file_diff(conn.host, result.diff)
                self.callbacks.on_ok(host, data)
        return result
Beispiel #20
0
    def _run_task(self, play, task, is_handler):
        ''' run a single task in the playbook and recursively run any subtasks.  '''

        ansible.callbacks.set_task(self.callbacks, task)
        ansible.callbacks.set_task(self.runner_callbacks, task)

        if task.role_name:
            name = '%s | %s' % (task.role_name, task.name)
        else:
            name = task.name

        self.callbacks.on_task_start(template(play.basedir, name, task.module_vars, lookup_fatal=False, filter_fatal=False), is_handler)
        if hasattr(self.callbacks, 'skip_task') and self.callbacks.skip_task:
            ansible.callbacks.set_task(self.callbacks, None)
            ansible.callbacks.set_task(self.runner_callbacks, None)
            return True

        # template ignore_errors
        cond = template(play.basedir, task.ignore_errors, task.module_vars, expand_lists=False)
        task.ignore_errors =  utils.check_conditional(cond , play.basedir, task.module_vars, fail_on_undefined=C.DEFAULT_UNDEFINED_VAR_BEHAVIOR)

        # load up an appropriate ansible runner to run the task in parallel
        results = self._run_task_internal(task)

        # if no hosts are matched, carry on
        hosts_remaining = True
        if results is None:
            hosts_remaining = False
            results = {}

        contacted = results.get('contacted', {})
        self.stats.compute(results, ignore_errors=task.ignore_errors)

        # add facts to the global setup cache
        for host, result in contacted.iteritems():
            if 'results' in result:
                # task ran with_ lookup plugin, so facts are encapsulated in
                # multiple list items in the results key
                for res in result['results']:
                    if type(res) == dict:
                        facts = res.get('ansible_facts', {})
                        self.SETUP_CACHE[host].update(facts)
            else:
                facts = result.get('ansible_facts', {})
                self.SETUP_CACHE[host].update(facts)
            # extra vars need to always trump - so update  again following the facts
            self.SETUP_CACHE[host].update(self.extra_vars)
            if task.register:
                if 'stdout' in result and 'stdout_lines' not in result:
                    result['stdout_lines'] = result['stdout'].splitlines()
                self.SETUP_CACHE[host][task.register] = result

        # also have to register some failed, but ignored, tasks
        if task.ignore_errors and task.register:
            failed = results.get('failed', {})
            for host, result in failed.iteritems():
                if 'stdout' in result and 'stdout_lines' not in result:
                    result['stdout_lines'] = result['stdout'].splitlines()
                self.SETUP_CACHE[host][task.register] = result

        # flag which notify handlers need to be run
        if len(task.notify) > 0:
            for host, results in results.get('contacted',{}).iteritems():
                if results.get('changed', False):
                    for handler_name in task.notify:
                        self._flag_handler(play, template(play.basedir, handler_name, task.module_vars), host)

        ansible.callbacks.set_task(self.callbacks, None)
        ansible.callbacks.set_task(self.runner_callbacks, None)
        return hosts_remaining
Beispiel #21
0
    def run(self, conn, tmp, module_name, module_args, inject, complex_args=None, **kwargs):

        # the group_by module does not need to pay attention to check mode.
        # it always runs.

        # module_args and complex_args have already been templated for the first host.
        # Use them here only to check that a key argument is provided.
        args = {}
        if complex_args:
            args.update(complex_args)
        args.update(parse_kv(module_args))

        name = args.get('name', None)
        #if not 'nam' in args:
        #    raise ae("'key' is a required argument.")

        #vv("created 'create_group' ActionModule: name=%s"%(args['name']))

        inventory = self.runner.inventory

        result = {'changed': False}

        ### find all groups
        groups = {}

        def add_host_to_group(groups, group_name, host):
            if group_name not in groups:
                groups[group_name] = []
            groups[group_name].append(host)


        for host in self.runner.host_set:
            data = {}
            data.update(inject)
            data.update(inject['hostvars'][host])
            conds = self.runner.conditional
            if type(conds) != list:
                conds = [ conds ]
            next_host = False
            for cond in conds:
                if not check_conditional(cond, self.runner.basedir, data, fail_on_undefined=self.runner.error_on_undefined_vars):
                    next_host = True
                    break
            if next_host:
                continue

            # Template original module_args and complex_args from runner for each host.
            # TODO - Decide whether we need to evaluate at this stage or not.
            host_module_args = template.template(self.runner.basedir, self.runner.module_args, data)
            host_complex_args = template.template(self.runner.basedir, self.runner.complex_args, data)
            host_args  = {}
            if host_complex_args:
                host_args.update(host_complex_args)
            host_args.update(parse_kv(host_module_args))

            group_name = host_args.get('name', None)
            group_name = group_name.replace(' ','-')
            prefix = host_args.get('prefix', None)
            when = host_args.get('when', None)

            if prefix:
                for k, v in data.iteritems():
                    if k.startswith(prefix) and v:
                        add_host_to_group(groups, k, host)
            elif when:
                try:
                    if check_conditional(when, self.runner.basedir, data):
                        add_host_to_group(groups, group_name, host)
                except ae as e:
                    # Error evaluating the conditional - we ignore as its likely a missing variable.
                    pass
            elif name:
                add_host_to_group(groups, group_name, host)


        result['groups'] = groups

        ### add to inventory
        group_names = []
        for group, hosts in groups.items():
            inv_group = inventory.get_group(group)
            group_names.append(group)
            if not inv_group:
                inv_group = ansible.inventory.Group(name=group)
                inventory.add_group(inv_group)
            for host in hosts:
                if host in self.runner.inventory._vars_per_host:
                    del self.runner.inventory._vars_per_host[host]
                inv_host = inventory.get_host(host)
                if not inv_host:
                    inv_host = ansible.inventory.Host(name=host)
                if inv_group not in inv_host.get_groups():
                    result['changed'] = True
                    inv_group.add_host(inv_host)

        if name:
            inject['item'] = name
        elif group_names:
            count = len(group_names)
            if count == 1:
                inject['item'] = group_names[0]
            else:
                inject['item'] = ' %d groups' % count

        return ReturnData(conn=conn, comm_ok=True, result=result)
    def run(self, conn, tmp, module_name, module_args, inject,
            complex_args=None, **kwargs):

        if not self.runner.is_playbook:
            raise errors.AnsibleError("in current versions of ansible, "
                                      "aeriscloud_service is only usable "
                                      "in playbooks")

        # load up options
        options = {}
        if complex_args:
            options.update(complex_args)
        options.update(utils.parse_kv(module_args))

        res = self.create_aeriscloud_directory(conn, tmp, inject)
        if not res.is_successful():
            return res

        data = {
            'services': []
        }

        for service in options['services']:
            if 'when' in service \
                    and not utils.check_conditional(service['when'],
                                                    self.runner.basedir,
                                                    inject):
                continue
            if 'path' in service and 'protocol' not in service:
                service['protocol'] = 'http'
            if 'path' not in service:
                service['path'] = ''
            if 'protocol' not in service:
                service['protocol'] = 'tcp'
            data['services'].append(service)

        template = jinja2.Template("""{%- for service in services -%}
{{ service['name'] }},{{ service['port'] }},{{ service['path'] }},{{ service['protocol'] }}
{% endfor %}""")

        resultant = template.render(data)

        dest = os.path.join('/etc/aeriscloud.d', options['name'])
        module_args = ''
        options = {
            'path': dest,
            'mode': 0644,
            'owner': 'root',
            'group': 'root',
            'state': 'file'
        }

        local_checksum = utils.checksum_s(resultant)
        remote_checksum = self.runner._remote_checksum(conn, tmp, dest, inject)

        if remote_checksum in ('0', '2', '3', '4'):
            # Note: 1 means the file is not present which is fine; template
            # will create it
            result = dict(failed=True, msg="failed to checksum remote file."
                                           " Checksum error code: %s" % remote_checksum)
            return ReturnData(conn=conn, comm_ok=True, result=result)

        if local_checksum != remote_checksum:

            # template is different from the remote value

            # if showing diffs, we need to get the remote value
            dest_contents = ''

            if self.runner.diff:
                # using persist_files to keep the temp directory around to avoid needing to grab another
                dest_result = self.runner._execute_module(conn, tmp, 'slurp',
                                                          "path=%s" % dest,
                                                          inject=inject,
                                                          persist_files=True)
                if 'content' in dest_result.result:
                    dest_contents = dest_result.result['content']
                    if dest_result.result['encoding'] == 'base64':
                        dest_contents = base64.b64decode(dest_contents)
                    else:
                        raise Exception(
                            "unknown encoding, failed: %s" % dest_result.result)

            xfered = self.runner._transfer_str(conn, tmp, 'source', resultant)

            # fix file permissions when the copy is done as a different user
            if self.runner.become and self.runner.become_user != 'root':
                self.runner._remote_chmod(conn, 'a+r', xfered, tmp)

            # run the copy module
            new_module_args = dict(
                src=xfered,
                dest=dest,
                follow=True,
            )
            module_args_tmp = utils.merge_module_args(module_args,
                                                      new_module_args)

            if self.runner.noop_on_check(inject):
                return ReturnData(conn=conn, comm_ok=True,
                                  result=dict(changed=True),
                                  diff=dict(before_header=dest,
                                            after_header='',
                                            before=dest_contents,
                                            after=resultant))
            else:
                res = self.runner._execute_module(conn, tmp, 'copy',
                                                  module_args_tmp,
                                                  inject=inject,
                                                  complex_args=None)
                if res.result.get('changed', False):
                    res.diff = dict(before=dest_contents, after=resultant)
                return res
        else:
            # when running the file module based on the template data, we do
            # not want the source filename (the name of the template) to be used,
            # since this would mess up links, so we clear the src param and tell
            # the module to follow links.  When doing that, we have to set
            # original_basename to the template just in case the dest is
            # a directory.
            module_args = ''
            new_module_args = dict(
                src=None,
                follow=True,
            )
            # be sure to inject the check mode param into the module args and
            # rely on the file module to report its changed status
            if self.runner.noop_on_check(inject):
                new_module_args['CHECKMODE'] = True
            options.update(new_module_args)
            return self.runner._execute_module(conn, tmp, 'file', module_args,
                                               inject=inject,
                                               complex_args=options)
Beispiel #23
0
    def _executor_internal(self, host, new_stdin):
        ''' executes any module one or more times '''

        host_variables = self.inventory.get_variables(host)
        host_connection = host_variables.get('ansible_connection', self.transport)
        if host_connection in [ 'paramiko', 'paramiko_alt', 'ssh', 'ssh_old', 'accelerate', 'tx' ]:
            port = host_variables.get('ansible_ssh_port', self.remote_port)
            if port is None:
                port = C.DEFAULT_REMOTE_PORT
        else:
            # fireball, local, etc
            port = self.remote_port

        inject = {}
        inject = utils.combine_vars(inject, self.default_vars)
        inject = utils.combine_vars(inject, host_variables)
        inject = utils.combine_vars(inject, self.module_vars)
        inject = utils.combine_vars(inject, self.setup_cache[host])
        inject.setdefault('ansible_ssh_user', self.remote_user)
        inject['hostvars'] = HostVars(self.setup_cache, self.inventory)
        inject['group_names'] = host_variables.get('group_names', [])
        inject['groups']      = self.inventory.groups_list()
        inject['vars']        = self.module_vars
        inject['defaults']    = self.default_vars
        inject['environment'] = self.environment
        inject['playbook_dir'] = self.basedir

        if self.inventory.basedir() is not None:
            inject['inventory_dir'] = self.inventory.basedir()

        if self.inventory.src() is not None:
            inject['inventory_file'] = self.inventory.src()

        # allow with_foo to work in playbooks...
        items = None
        items_plugin = self.module_vars.get('items_lookup_plugin', None)

        if items_plugin is not None and items_plugin in utils.plugins.lookup_loader:

            basedir = self.basedir
            if '_original_file' in inject:
                basedir = os.path.dirname(inject['_original_file'])
                filesdir = os.path.join(basedir, '..', 'files')
                if os.path.exists(filesdir):
                    basedir = filesdir

            items_terms = self.module_vars.get('items_lookup_terms', '')
            items_terms = template.template(basedir, items_terms, inject)
            items = utils.plugins.lookup_loader.get(items_plugin, runner=self, basedir=basedir).run(items_terms, inject=inject)
            if type(items) != list:
                raise errors.AnsibleError("lookup plugins have to return a list: %r" % items)

            if len(items) and utils.is_list_of_strings(items) and self.module_name in [ 'apt', 'yum', 'pkgng' ]:
                # hack for apt, yum, and pkgng so that with_items maps back into a single module call
                use_these_items = []
                for x in items:
                    inject['item'] = x
                    if not self.conditional or utils.check_conditional(self.conditional, self.basedir, inject, fail_on_undefined=self.error_on_undefined_vars):
                        use_these_items.append(x)
                inject['item'] = ",".join(use_these_items)
                items = None

        # logic to replace complex args if possible
        complex_args = self.complex_args

        # logic to decide how to run things depends on whether with_items is used
        if items is None:
            if isinstance(complex_args, basestring):
                complex_args = template.template(self.basedir, complex_args, inject, convert_bare=True)
                complex_args = utils.safe_eval(complex_args)
                if type(complex_args) != dict:
                    raise errors.AnsibleError("args must be a dictionary, received %s" % complex_args)
            return self._executor_internal_inner(host, self.module_name, self.module_args, inject, port, complex_args=complex_args)
        elif len(items) > 0:

            # executing using with_items, so make multiple calls
            # TODO: refactor

            if self.background > 0:
                raise errors.AnsibleError("lookup plugins (with_*) cannot be used with async tasks")

            aggregrate = {}
            all_comm_ok = True
            all_changed = False
            all_failed = False
            results = []
            for x in items:
                inject['item'] = x

                # TODO: this idiom should be replaced with an up-conversion to a Jinja2 template evaluation
                if isinstance(self.complex_args, basestring):
                    complex_args = template.template(self.basedir, self.complex_args, inject, convert_bare=True)
                    complex_args = utils.safe_eval(complex_args)
                    if type(complex_args) != dict:
                        raise errors.AnsibleError("args must be a dictionary, received %s" % complex_args)
                result = self._executor_internal_inner(
                     host,
                     self.module_name,
                     self.module_args,
                     inject,
                     port,
                     complex_args=complex_args
                )
                results.append(result.result)
                if result.comm_ok == False:
                    all_comm_ok = False
                    all_failed = True
                    break
                for x in results:
                    if x.get('changed') == True:
                        all_changed = True
                    if (x.get('failed') == True) or ('failed_when_result' in x and [x['failed_when_result']] or [('rc' in x) and (x['rc'] != 0)])[0]:
                        all_failed = True
                        break
            msg = 'All items completed'
            if all_failed:
                msg = "One or more items failed."
            rd_result = dict(failed=all_failed, changed=all_changed, results=results, msg=msg)
            if not all_failed:
                del rd_result['failed']
            return ReturnData(host=host, comm_ok=all_comm_ok, result=rd_result)
        else:
            self.callbacks.on_skipped(host, None)
            return ReturnData(host=host, comm_ok=True, result=dict(changed=False, skipped=True))
Beispiel #24
0
        # render module_args and complex_args templates
        try:
            module_args = template.template(self.basedir, module_args, inject, fail_on_undefined=self.error_on_undefined_vars)
            complex_args = template.template(self.basedir, complex_args, inject, fail_on_undefined=self.error_on_undefined_vars)
        except jinja2.exceptions.UndefinedError, e:
            raise errors.AnsibleUndefinedVariable("One or more undefined variables: %s" % str(e))


        result = handler.run(conn, tmp, module_name, module_args, inject, complex_args)
        # Code for do until feature
        until = self.module_vars.get('until', None)
        if until is not None and result.comm_ok:
            inject[self.module_vars.get('register')] = result.result
            cond = template.template(self.basedir, until, inject, expand_lists=False)
            if not utils.check_conditional(cond,  self.basedir, inject, fail_on_undefined=self.error_on_undefined_vars):
                retries = self.module_vars.get('retries')
                delay   = self.module_vars.get('delay')
                for x in range(1, int(retries) + 1):
                    # template the delay, cast to float and sleep
                    delay = template.template(self.basedir, delay, inject, expand_lists=False)
                    delay = float(delay)
                    time.sleep(delay)
                    tmp = ''
                    if self._early_needs_tmp_path(module_name, handler):
                        tmp = self._make_tmp_path(conn)
                    result = handler.run(conn, tmp, module_name, module_args, inject, complex_args)
                    result.result['attempts'] = x
                    vv("Result from run %i is: %s" % (x, result.result))
                    inject[self.module_vars.get('register')] = result.result
                    cond = template.template(self.basedir, until, inject, expand_lists=False)
Beispiel #25
0
        # render module_args and complex_args templates
        try:
            module_args = template.template(self.basedir, module_args, inject, fail_on_undefined=self.error_on_undefined_vars)
            complex_args = template.template(self.basedir, complex_args, inject, fail_on_undefined=self.error_on_undefined_vars)
        except jinja2.exceptions.UndefinedError, e:
            raise errors.AnsibleUndefinedVariable("One or more undefined variables: %s" % str(e))


        result = handler.run(conn, tmp, module_name, module_args, inject, complex_args)
        # Code for do until feature
        until = self.module_vars.get('until', None)
        if until is not None and result.comm_ok:
            inject[self.module_vars.get('register')] = result.result
            cond = template.template(self.basedir, until, inject, expand_lists=False)
            if not utils.check_conditional(cond,  self.basedir, inject, fail_on_undefined=self.error_on_undefined_vars):
                retries = self.module_vars.get('retries')
                delay   = self.module_vars.get('delay')
                for x in range(1, retries + 1):
                    time.sleep(delay)
                    tmp = ''
                    if getattr(handler, 'NEEDS_TMPPATH', True):
                        tmp = self._make_tmp_path(conn)
                    result = handler.run(conn, tmp, module_name, module_args, inject, complex_args)
                    result.result['attempts'] = x
                    vv("Result from run %i is: %s" % (x, result.result))
                    inject[self.module_vars.get('register')] = result.result
                    cond = template.template(self.basedir, until, inject, expand_lists=False)
                    if utils.check_conditional(cond, self.basedir, inject, fail_on_undefined=self.error_on_undefined_vars):
                        break
                if result.result['attempts'] == retries and not utils.check_conditional(cond, self.basedir, inject, fail_on_undefined=self.error_on_undefined_vars):
Beispiel #26
0
    def run(self,
            conn,
            tmp,
            module_name,
            module_args,
            inject,
            complex_args=None,
            **kwargs):

        # the group_by module does not need to pay attention to check mode.
        # it always runs.

        # module_args and complex_args have already been templated for the first host.
        # Use them here only to check that a key argument is provided.
        args = {}
        if complex_args:
            args.update(complex_args)
        args.update(parse_kv(module_args))
        if not 'key' in args:
            raise ae("'key' is a required argument.")

        vv("created 'group_by' ActionModule: key=%s" % (args['key']))

        inventory = self.runner.inventory

        result = {'changed': False}

        ### find all groups
        groups = {}

        for host in self.runner.host_set:
            data = {}
            data.update(inject)
            data.update(inject['hostvars'][host])
            conds = self.runner.conditional
            if type(conds) != list:
                conds = [conds]
            next_host = False
            for cond in conds:
                if not check_conditional(
                        cond,
                        self.runner.basedir,
                        data,
                        fail_on_undefined=self.runner.error_on_undefined_vars):
                    next_host = True
                    break
            if next_host:
                continue

            # Template original module_args and complex_args from runner for each host.
            host_module_args = template.template(self.runner.basedir,
                                                 self.runner.module_args, data)
            host_complex_args = template.template(self.runner.basedir,
                                                  self.runner.complex_args,
                                                  data)
            host_args = {}
            if host_complex_args:
                host_args.update(host_complex_args)
            host_args.update(parse_kv(host_module_args))

            group_name = host_args['key']
            group_name = group_name.replace(' ', '-')
            if group_name not in groups:
                groups[group_name] = []
            groups[group_name].append(host)

        result['groups'] = groups

        ### add to inventory
        for group, hosts in groups.items():
            inv_group = inventory.get_group(group)
            if not inv_group:
                inv_group = ansible.inventory.Group(name=group)
                inventory.add_group(inv_group)
            for host in hosts:
                if host in self.runner.inventory._vars_per_host:
                    del self.runner.inventory._vars_per_host[host]
                inv_host = inventory.get_host(host)
                if not inv_host:
                    inv_host = ansible.inventory.Host(name=host)
                if inv_group not in inv_host.get_groups():
                    result['changed'] = True
                    inv_group.add_host(inv_host)

        return ReturnData(conn=conn, comm_ok=True, result=result)
Beispiel #27
0
    def _executor_internal_inner(self, host, module_name, module_args, inject, port, is_chained=False, complex_args=None):
        ''' decides how to invoke a module '''

        # late processing of parameterized sudo_user (with_items,..)
        if self.sudo_user_var is not None:
            self.sudo_user = template.template(self.basedir, self.sudo_user_var, inject)

        # allow module args to work as a dictionary
        # though it is usually a string
        new_args = ""
        if type(module_args) == dict:
            for (k,v) in module_args.iteritems():
                new_args = new_args + "%s='%s' " % (k,v)
            module_args = new_args

        # module_name may be dynamic (but cannot contain {{ ansible_ssh_user }})
        module_name  = template.template(self.basedir, module_name, inject)

        if module_name in utils.plugins.action_loader:
            if self.background != 0:
                raise errors.AnsibleError("async mode is not supported with the %s module" % module_name)
            handler = utils.plugins.action_loader.get(module_name, self)
        elif self.background == 0:
            handler = utils.plugins.action_loader.get('normal', self)
        else:
            handler = utils.plugins.action_loader.get('async', self)

        if type(self.conditional) != list:
            self.conditional = [ self.conditional ]

        for cond in self.conditional:

            if not utils.check_conditional(cond, self.basedir, inject, fail_on_undefined=self.error_on_undefined_vars):
                result = utils.jsonify(dict(changed=False, skipped=True))
                self.callbacks.on_skipped(host, inject.get('item',None))
                return ReturnData(host=host, result=result)

        if getattr(handler, 'setup', None) is not None:
            handler.setup(module_name, inject)
        conn = None
        actual_host = inject.get('ansible_ssh_host', host)
        # allow ansible_ssh_host to be templated
        actual_host = template.template(self.basedir, actual_host, inject, fail_on_undefined=True)
        actual_port = port
        actual_user = inject.get('ansible_ssh_user', self.remote_user)
        actual_pass = inject.get('ansible_ssh_pass', self.remote_pass)
        actual_transport = inject.get('ansible_connection', self.transport)
        actual_private_key_file = inject.get('ansible_ssh_private_key_file', self.private_key_file)

        if self.accelerate and actual_transport != 'local':
            #Fix to get the inventory name of the host to accelerate plugin
            if inject.get('ansible_ssh_host', None):
                self.accelerate_inventory_host = host
            else:
                self.accelerate_inventory_host = None
            # if we're using accelerated mode, force the
            # transport to accelerate
            actual_transport = "accelerate"
            if not self.accelerate_port:
                self.accelerate_port = C.ACCELERATE_PORT

        if actual_transport in [ 'paramiko', 'ssh', 'accelerate' ]:
            actual_port = inject.get('ansible_ssh_port', port)

        # the delegated host may have different SSH port configured, etc
        # and we need to transfer those, and only those, variables
        delegate_to = inject.get('delegate_to', None)
        if delegate_to is not None:
            delegate_to = template.template(self.basedir, delegate_to, inject)
            inject = inject.copy()
            interpreters = []
            for i in inject:
                if i.startswith("ansible_") and i.endswith("_interpreter"):
                    interpreters.append(i)
            for i in interpreters:
                del inject[i]
            port = C.DEFAULT_REMOTE_PORT
            try:
                delegate_info = inject['hostvars'][delegate_to]
                actual_host = delegate_info.get('ansible_ssh_host', delegate_to)
                # allow ansible_ssh_host to be templated
                actual_host = template.template(self.basedir, actual_host, inject, fail_on_undefined=True)
                actual_port = delegate_info.get('ansible_ssh_port', port)
                actual_user = delegate_info.get('ansible_ssh_user', actual_user)
                actual_pass = delegate_info.get('ansible_ssh_pass', actual_pass)
                actual_private_key_file = delegate_info.get('ansible_ssh_private_key_file', self.private_key_file)
                actual_transport = delegate_info.get('ansible_connection', self.transport)
                for i in delegate_info:
                    if i.startswith("ansible_") and i.endswith("_interpreter"):
                        inject[i] = delegate_info[i]
            except errors.AnsibleError:
                actual_host = delegate_to
                actual_port = port

        # user/pass may still contain variables at this stage
        actual_user = template.template(self.basedir, actual_user, inject)
        actual_pass = template.template(self.basedir, actual_pass, inject)

        # make actual_user available as __magic__ ansible_ssh_user variable
        inject['ansible_ssh_user'] = actual_user

        try:
            if actual_transport == 'accelerate':
                # for accelerate, we stuff both ports into a single
                # variable so that we don't have to mangle other function
                # calls just to accomodate this one case
                actual_port = [actual_port, self.accelerate_port]
            elif actual_port is not None:
                actual_port = int(template.template(self.basedir, actual_port, inject))
        except ValueError, e:
            result = dict(failed=True, msg="FAILED: Configured port \"%s\" is not a valid port, expected integer" % actual_port)
            return ReturnData(host=host, comm_ok=False, result=result)
Beispiel #28
0
    def _executor_internal_inner(self,
                                 host,
                                 module_name,
                                 module_args,
                                 inject,
                                 port,
                                 is_chained=False):
        ''' decides how to invoke a module '''

        # special non-user/non-fact variables:
        # 'groups' variable is a list of host name in each group
        # 'hostvars' variable contains variables for each host name
        #  ... and is set elsewhere
        # 'inventory_hostname' is also set elsewhere
        inject['groups'] = self.inventory.groups_list()

        # allow module args to work as a dictionary
        # though it is usually a string
        new_args = ""
        if type(module_args) == dict:
            for (k, v) in module_args.iteritems():
                new_args = new_args + "%s='%s' " % (k, v)
            module_args = new_args

        conditional = utils.template(self.basedir, self.conditional, inject)
        if not utils.check_conditional(conditional):
            result = utils.jsonify(dict(skipped=True))
            self.callbacks.on_skipped(host, inject.get('item', None))
            return ReturnData(host=host, result=result)

        conn = None
        actual_host = inject.get('ansible_ssh_host', host)
        actual_port = port
        if self.transport in ['paramiko', 'ssh']:
            actual_port = inject.get('ansible_ssh_port', port)

        # the delegated host may have different SSH port configured, etc
        # and we need to transfer those, and only those, variables
        delegate_to = inject.get('delegate_to', None)
        if delegate_to is not None:
            delegate_to = utils.template(self.basedir, delegate_to, inject)
            inject = inject.copy()
            interpreters = []
            for i in inject:
                if i.startswith("ansible_") and i.endswith("_interpreter"):
                    interpreters.append(i)
            for i in interpreters:
                del inject[i]
            port = C.DEFAULT_REMOTE_PORT
            try:
                delegate_info = inject['hostvars'][delegate_to]
                actual_host = delegate_info.get('ansible_ssh_host',
                                                delegate_to)
                actual_port = delegate_info.get('ansible_ssh_port', port)
                for i in delegate_info:
                    if i.startswith("ansible_") and i.endswith("_interpreter"):
                        inject[i] = delegate_info[i]
            except errors.AnsibleError:
                actual_host = delegate_to
                actual_port = port

        try:
            if actual_port is not None:
                actual_port = int(actual_port)
            conn = self.connector.connect(actual_host, actual_port)
            if delegate_to or host != actual_host:
                conn.delegate = host

        except errors.AnsibleConnectionFailed, e:
            result = dict(failed=True, msg="FAILED: %s" % str(e))
            return ReturnData(host=host, comm_ok=False, result=result)
    def _executor_internal_inner(self,
                                 host,
                                 module_name,
                                 module_args,
                                 inject,
                                 port,
                                 is_chained=False,
                                 complex_args=None):
        ''' decides how to invoke a module '''

        # allow module args to work as a dictionary
        # though it is usually a string
        new_args = ""
        if type(module_args) == dict:
            for (k, v) in module_args.iteritems():
                new_args = new_args + "%s='%s' " % (k, v)
            module_args = new_args

        module_name = utils.template(self.basedir, module_name, inject)
        module_args = utils.template(self.basedir, module_args, inject)
        complex_args = utils.template(self.basedir, complex_args, inject)

        if module_name in utils.plugins.action_loader:
            if self.background != 0:
                raise errors.AnsibleError(
                    "async mode is not supported with the %s module" %
                    module_name)
            handler = utils.plugins.action_loader.get(module_name, self)
        elif self.background == 0:
            handler = utils.plugins.action_loader.get('normal', self)
        else:
            handler = utils.plugins.action_loader.get('async', self)

        conditional = utils.template(self.basedir,
                                     self.conditional,
                                     inject,
                                     expand_lists=False)
        if not utils.check_conditional(conditional):
            result = utils.jsonify(dict(skipped=True))
            self.callbacks.on_skipped(host, inject.get('item', None))
            return ReturnData(host=host, result=result)

        conn = None
        actual_host = inject.get('ansible_ssh_host', host)
        actual_port = port
        actual_user = inject.get('ansible_ssh_user', self.remote_user)
        actual_pass = inject.get('ansible_ssh_pass', self.remote_pass)
        actual_transport = inject.get('ansible_connection', self.transport)
        if actual_transport in ['paramiko', 'ssh']:
            actual_port = inject.get('ansible_ssh_port', port)

        # the delegated host may have different SSH port configured, etc
        # and we need to transfer those, and only those, variables
        delegate_to = inject.get('delegate_to', None)
        if delegate_to is not None:
            delegate_to = utils.template(self.basedir, delegate_to, inject)
            inject = inject.copy()
            interpreters = []
            for i in inject:
                if i.startswith("ansible_") and i.endswith("_interpreter"):
                    interpreters.append(i)
            for i in interpreters:
                del inject[i]
            port = C.DEFAULT_REMOTE_PORT
            try:
                delegate_info = inject['hostvars'][delegate_to]
                actual_host = delegate_info.get('ansible_ssh_host',
                                                delegate_to)
                actual_port = delegate_info.get('ansible_ssh_port', port)
                actual_user = delegate_info.get('ansible_ssh_user',
                                                actual_user)
                actual_pass = delegate_info.get('ansible_ssh_pass',
                                                actual_pass)
                actual_transport = delegate_info.get('ansible_connection',
                                                     self.transport)
                for i in delegate_info:
                    if i.startswith("ansible_") and i.endswith("_interpreter"):
                        inject[i] = delegate_info[i]
            except errors.AnsibleError:
                actual_host = delegate_to
                actual_port = port

        actual_user = utils.template(self.basedir, actual_user, inject)
        actual_pass = utils.template(self.basedir, actual_pass, inject)

        try:
            if actual_port is not None:
                actual_port = int(actual_port)
        except ValueError, e:
            result = dict(
                failed=True,
                msg=
                "FAILED: Configured port \"%s\" is not a valid port, expected integer"
                % actual_port)
            return ReturnData(host=host, comm_ok=False, result=result)
Beispiel #30
0
    def _executor_internal_inner(self, host, module_name, module_args, inject, port, is_chained=False):
        ''' decides how to invoke a module '''

        # allow module args to work as a dictionary
        # though it is usually a string
        new_args = ""
        if type(module_args) == dict:
            for (k,v) in module_args.iteritems():
                new_args = new_args + "%s='%s' " % (k,v)
            module_args = new_args

        module_name = utils.template(self.basedir, module_name, inject)
        module_args = utils.template(self.basedir, module_args, inject, expand_lists=True)

        if module_name in utils.plugins.action_loader:
            if self.background != 0:
                raise errors.AnsibleError("async mode is not supported with the %s module" % module_name)
            handler = utils.plugins.action_loader.get(module_name, self)
        elif self.background == 0:
            handler = utils.plugins.action_loader.get('normal', self)
        else:
            handler = utils.plugins.action_loader.get('async', self)

        conditional = utils.template(self.basedir, self.conditional, inject)
        if not getattr(handler, 'BYPASS_HOST_LOOP', False) and not utils.check_conditional(conditional):
            result = utils.jsonify(dict(skipped=True))
            self.callbacks.on_skipped(host, inject.get('item',None))
            return ReturnData(host=host, result=result)

        conn = None
        actual_host = inject.get('ansible_ssh_host', host)
        actual_port = port
        if self.transport in [ 'paramiko', 'ssh' ]:
            actual_port = inject.get('ansible_ssh_port', port)

        # the delegated host may have different SSH port configured, etc
        # and we need to transfer those, and only those, variables
        delegate_to = inject.get('delegate_to', None)
        if delegate_to is not None:
            delegate_to = utils.template(self.basedir, delegate_to, inject)
            inject = inject.copy()
            interpreters = []
            for i in inject:
                if i.startswith("ansible_") and i.endswith("_interpreter"):
                    interpreters.append(i)
            for i in interpreters:
                del inject[i]
            port = C.DEFAULT_REMOTE_PORT
            try:
                delegate_info = inject['hostvars'][delegate_to]
                actual_host = delegate_info.get('ansible_ssh_host', delegate_to)
                actual_port = delegate_info.get('ansible_ssh_port', port)
                for i in delegate_info:
                    if i.startswith("ansible_") and i.endswith("_interpreter"):
                        inject[i] = delegate_info[i]
            except errors.AnsibleError:
                actual_host = delegate_to
                actual_port = port

        try:
            if actual_port is not None:
                actual_port = int(actual_port)
        except ValueError, e:
            result = dict(failed=True, msg="FAILED: Configured port \"%s\" is not a valid port, expected integer" % actual_port)
            return ReturnData(host=host, comm_ok=False, result=result)