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)
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'))
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)
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)
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)
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'))
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)
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)
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)
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
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)
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)
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))
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
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
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)
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
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
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)
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))
# 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)
# 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):
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)
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)
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)
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)