diff --git a/lib/ansible/playbook.py b/lib/ansible/playbook.py index a74847cd9b..0eb0e4d685 100755 --- a/lib/ansible/playbook.py +++ b/lib/ansible/playbook.py @@ -113,14 +113,19 @@ class PlayBook(object): # include: some.yml a=2 b=3 c=4 include_tokens = task['include'].split() path = utils.path_dwim(dirname, include_tokens[0]) - inject_vars = self._get_vars(play, dirname) + play_vars = self._get_vars(play, dirname) + include_vars = {} for i,x in enumerate(include_tokens): if x.find("=") != -1: (k,v) = x.split("=") - inject_vars[k] = v + include_vars[k] = v + inject_vars = play_vars.copy() + inject_vars.update(include_vars) included = utils.template_from_file(path, inject_vars) included = utils.parse_yaml(included) for x in included: + if len(include_vars): + x["vars"] = include_vars new_tasks.append(x) # ***************************************************** @@ -266,7 +271,7 @@ class PlayBook(object): # ***************************************************** - def _run_module(self, pattern, host_list, module, args, remote_user, + def _run_module(self, pattern, host_list, module, args, vars, remote_user, async_seconds, async_poll_interval, only_if, sudo): ''' run a particular module step in a playbook ''' @@ -277,7 +282,7 @@ class PlayBook(object): module_args=args, host_list=hosts, forks=self.forks, remote_pass=self.remote_pass, module_path=self.module_path, timeout=self.timeout, remote_user=remote_user, - remote_port=self.remote_port, + remote_port=self.remote_port, module_vars=vars, setup_cache=SETUP_CACHE, basedir=self.basedir, conditional=only_if, callbacks=self.runner_callbacks, extra_vars=self.extra_vars, debug=self.debug, sudo=sudo @@ -309,6 +314,9 @@ class PlayBook(object): module_name = tokens[0] module_args = tokens[1] + # include task specific vars + module_vars = task.get('vars') + # tasks can be direct (run on all nodes matching # the pattern) or conditional, where they ran # as the result of a change handler on a subset @@ -319,7 +327,7 @@ class PlayBook(object): # load up an appropriate ansible runner to # run the task in parallel results = self._run_module(pattern, host_list, module_name, - module_args, remote_user, async_seconds, + module_args, module_vars, remote_user, async_seconds, async_poll_interval, only_if, sudo) self.stats.compute(results) diff --git a/lib/ansible/runner.py b/lib/ansible/runner.py index 0218ea2406..b2cf3518b9 100755 --- a/lib/ansible/runner.py +++ b/lib/ansible/runner.py @@ -74,8 +74,8 @@ class Runner(object): remote_user=C.DEFAULT_REMOTE_USER, remote_pass=C.DEFAULT_REMOTE_PASS, remote_port=C.DEFAULT_REMOTE_PORT, background=0, basedir=None, setup_cache=None, transport='paramiko', conditional='True', groups={}, callbacks=None, verbose=False, - debug=False, sudo=False, extra_vars=None): - + debug=False, sudo=False, extra_vars=None, module_vars=None): + if setup_cache is None: setup_cache = {} if basedir is None: @@ -101,6 +101,7 @@ class Runner(object): self.forks = int(forks) self.pattern = pattern self.module_args = module_args + self.module_vars = module_vars self.extra_vars = extra_vars self.timeout = timeout self.debug = debug @@ -267,7 +268,7 @@ class Runner(object): # ***************************************************** - def _transfer_argsfile(self, conn, tmp, args_str): + def _transfer_str(self, conn, tmp, name, args_str): ''' transfer arguments as a single file to be fed to the module. ''' args_fd, args_file = tempfile.mkstemp() @@ -276,7 +277,7 @@ class Runner(object): args_fo.flush() args_fo.close() - args_remote = os.path.join(tmp, 'arguments') + args_remote = os.path.join(tmp, name) conn.put_file(args_file, args_remote) os.unlink(args_file) @@ -355,7 +356,7 @@ class Runner(object): module_name_tail = remote_module_path.split("/")[-1] client_executed_str = "%s %s" % (module_name_tail, args.strip()) - argsfile = self._transfer_argsfile(conn, tmp, args) + argsfile = self._transfer_str(conn, tmp, 'arguments', args) if async_jid is None: cmd = "%s %s" % (remote_module_path, argsfile) else: @@ -498,8 +499,16 @@ class Runner(object): # install the template module template_module = self._transfer_module(conn, tmp, 'template') + # transfer module vars + if self.module_vars: + vars = utils.bigjson(self.module_vars) + vars_path = self._transfer_str(conn, tmp, 'module_vars', vars) + vars_arg=" vars=%s"%(vars_path) + else: + vars_arg="" + # run the template module - args = "src=%s dest=%s metadata=%s" % (temppath, dest, metadata) + args = "src=%s dest=%s metadata=%s%s" % (temppath, dest, metadata, vars_arg) (result1, err, executed) = self._execute_module(conn, tmp, template_module, args) (host, ok, data, err) = self._return_from_module(conn, host, result1, err, executed) @@ -637,13 +646,13 @@ class Runner(object): prc.start() workers.append(prc) - try: - for worker in workers: - worker.join() - except KeyboardInterrupt: - for worker in workers: - worker.terminate() - worker.join() + try: + for worker in workers: + worker.join() + except KeyboardInterrupt: + for worker in workers: + worker.terminate() + worker.join() results = [] while not result_queue.empty(): diff --git a/library/template b/library/template index 3421f497cc..0b13422d5a 100755 --- a/library/template +++ b/library/template @@ -48,7 +48,7 @@ for x in items: source = params['src'] dest = params['dest'] metadata = params.get('metadata', '/etc/ansible/setup') - +module_vars = params.get('vars') # raise an error if there is no template metadata if not os.path.exists(metadata): @@ -71,6 +71,19 @@ except: }) sys.exit(1) +if module_vars: + try: + f = open(module_vars) + vars = json.loads(f.read()) + data.update(vars) + f.close() + except: + print json.dumps({ + "failed" : 1, + "msg" : "Failed to parse/load %s." % module_vars + }) + sys.exit(1) + if not os.path.exists(source): print json.dumps({ "failed" : 1,