mirror of
https://github.com/ansible-collections/community.general.git
synced 2026-04-19 15:21:27 +00:00
Factoids and push variables via setup are now available to be templated in command args
as well as template files. PLUS, variables are now expressed in playbooks without having to know about the setup task, which means playbooks are simpler to read now.
This commit is contained in:
@@ -24,6 +24,8 @@ import yaml
|
||||
import shlex
|
||||
import os
|
||||
|
||||
SETUP_CACHE={ 'foo' : {} }
|
||||
|
||||
#############################################
|
||||
|
||||
class PlayBook(object):
|
||||
@@ -150,7 +152,8 @@ class PlayBook(object):
|
||||
remote_pass=self.remote_pass,
|
||||
module_path=self.module_path,
|
||||
timeout=self.timeout,
|
||||
remote_user=remote_user
|
||||
remote_user=remote_user,
|
||||
setup_cache=SETUP_CACHE
|
||||
).run()
|
||||
|
||||
def _run_task(self, pattern=None, task=None, host_list=None,
|
||||
@@ -274,6 +277,7 @@ class PlayBook(object):
|
||||
|
||||
# get configuration information about the pattern
|
||||
pattern = pg['hosts']
|
||||
vars = pg.get('vars', {})
|
||||
tasks = pg['tasks']
|
||||
handlers = pg['handlers']
|
||||
user = pg.get('user', C.DEFAULT_REMOTE_USER)
|
||||
@@ -283,8 +287,35 @@ class PlayBook(object):
|
||||
if self.verbose:
|
||||
print "PLAY [%s] ****************************\n" % pattern
|
||||
|
||||
# run all the top level tasks, these get run on every node
|
||||
# first run the setup task on every node, which gets the variables
|
||||
# written to the JSON file and will also bubble facts back up via
|
||||
# magic in Runner()
|
||||
push_var_str=''
|
||||
for (k,v) in vars.items():
|
||||
push_var_str += "%s=%s " % (k,v)
|
||||
if user != 'root':
|
||||
push_var_str = "%s metadata=~/.ansible_setup" % (push_var_str)
|
||||
|
||||
# push any variables down to the system
|
||||
setup_results = ansible.runner.Runner(
|
||||
pattern=pattern,
|
||||
module_name='setup',
|
||||
module_args=push_var_str,
|
||||
host_list=self.host_list,
|
||||
forks=self.forks,
|
||||
module_path=self.module_path,
|
||||
timeout=self.timeout,
|
||||
remote_user=user,
|
||||
setup_cache=SETUP_CACHE
|
||||
).run()
|
||||
|
||||
# now for each result, load into the setup cache so we can
|
||||
# let runner template out future commands
|
||||
setup_ok = setup_results.get('contacted', {})
|
||||
for (host, result) in setup_ok.items():
|
||||
SETUP_CACHE[host] = result
|
||||
|
||||
# run all the top level tasks, these get run on every node
|
||||
for task in tasks:
|
||||
self._run_task(
|
||||
pattern=pattern,
|
||||
|
||||
@@ -29,9 +29,10 @@ import signal
|
||||
import os
|
||||
import ansible.constants as C
|
||||
import Queue
|
||||
import paramiko
|
||||
import random
|
||||
|
||||
import paramiko
|
||||
import jinja2
|
||||
|
||||
################################################
|
||||
|
||||
def noop(*args, **kwargs):
|
||||
@@ -62,6 +63,7 @@ class Runner(object):
|
||||
remote_user=C.DEFAULT_REMOTE_USER,
|
||||
remote_pass=C.DEFAULT_REMOTE_PASS,
|
||||
background=0,
|
||||
setup_cache={},
|
||||
verbose=False):
|
||||
|
||||
'''
|
||||
@@ -75,9 +77,10 @@ class Runner(object):
|
||||
remote_user -- who to login as (default root)
|
||||
remote_pass -- provide only if you don't want to use keys or ssh-agent
|
||||
background --- if non 0, run async, failing after X seconds, -1 == infinite
|
||||
setup_cache -- used only by playbook (complex explanation pending)
|
||||
'''
|
||||
|
||||
# save input values
|
||||
self.setup_cache = setup_cache
|
||||
|
||||
self.host_list, self.groups = self.parse_hosts(host_list)
|
||||
self.module_path = module_path
|
||||
@@ -91,6 +94,7 @@ class Runner(object):
|
||||
self.remote_pass = remote_pass
|
||||
self.background = background
|
||||
|
||||
|
||||
# hosts in each group name in the inventory file
|
||||
self._tmp_paths = {}
|
||||
|
||||
@@ -201,10 +205,17 @@ class Runner(object):
|
||||
|
||||
def _execute_module(self, conn, tmp, remote_module_path, module_args):
|
||||
'''
|
||||
runs a module that has already been transferred
|
||||
runs a module that has already been transferred, but first
|
||||
modifies the command using setup_cache variables (see playbook)
|
||||
'''
|
||||
args = [ str(x) for x in module_args ]
|
||||
args = " ".join(args)
|
||||
args = module_args
|
||||
if type(args) == list:
|
||||
args = [ str(x) for x in module_args ]
|
||||
args = " ".join(args)
|
||||
inject_vars = self.setup_cache.get(conn._host,{})
|
||||
template = jinja2.Template(args)
|
||||
args = template.render(inject_vars)
|
||||
|
||||
cmd = "%s %s" % (remote_module_path, args)
|
||||
result = self._exec_command(conn, cmd)
|
||||
self._delete_remote_files(conn, [ tmp ])
|
||||
@@ -217,6 +228,16 @@ class Runner(object):
|
||||
'''
|
||||
module = self._transfer_module(conn, tmp, self.module_name)
|
||||
result = self._execute_module(conn, tmp, module, self.module_args)
|
||||
# when running the setup module, which pushes vars to the host and ALSO
|
||||
# returns them (+factoids), store the variables that were returned such that commands
|
||||
# run AFTER setup use these variables for templating when executed
|
||||
# from playbooks
|
||||
if self.module_name == 'setup':
|
||||
host = conn._host
|
||||
try:
|
||||
var_result = json.loads(result)
|
||||
except:
|
||||
var_result = {}
|
||||
self._delete_remote_files(conn, tmp)
|
||||
return self._return_from_module(conn, host, result)
|
||||
|
||||
@@ -303,6 +324,7 @@ class Runner(object):
|
||||
# module, call the appropriate executor function
|
||||
|
||||
ok, conn = self._connect(host)
|
||||
conn._host = host
|
||||
if not ok:
|
||||
return [ host, False, conn ]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user