Move delegate_to out of runner module_vars to prevent bleeding across runs

Previously, the delegate_to value was stored in the module_vars of runner,
which could lead to bleeding that value across runs and incorrect hosts
being delegated to. This patch moves the value to a local variable in
the Runner class with some related refactoring of _compute_delegate() in
Runner (since the value is no longer required to be a parameter).

Fixes #8705
This commit is contained in:
James Cammarata 2014-09-16 20:51:00 -05:00
parent 5ec8c28d2a
commit c3612e08f9
2 changed files with 27 additions and 38 deletions

View file

@ -450,9 +450,8 @@ class PlaybookRunnerCallbacks(DefaultRunnerCallbacks):
self._async_notified = {}
def on_unreachable(self, host, results):
delegate_to = self.runner.module_vars.get('delegate_to')
if delegate_to:
host = '%s -> %s' % (host, delegate_to)
if self.runner.delegate_to:
host = '%s -> %s' % (host, self.runner.delegate_to)
item = None
if type(results) == dict:
@ -465,9 +464,8 @@ class PlaybookRunnerCallbacks(DefaultRunnerCallbacks):
super(PlaybookRunnerCallbacks, self).on_unreachable(host, results)
def on_failed(self, host, results, ignore_errors=False):
delegate_to = self.runner.module_vars.get('delegate_to')
if delegate_to:
host = '%s -> %s' % (host, delegate_to)
if self.runner.delegate_to:
host = '%s -> %s' % (host, self.runner.delegate_to)
results2 = results.copy()
results2.pop('invocation', None)
@ -500,9 +498,8 @@ class PlaybookRunnerCallbacks(DefaultRunnerCallbacks):
super(PlaybookRunnerCallbacks, self).on_failed(host, results, ignore_errors=ignore_errors)
def on_ok(self, host, host_result):
delegate_to = self.runner.module_vars.get('delegate_to')
if delegate_to:
host = '%s -> %s' % (host, delegate_to)
if self.runner.delegate_to:
host = '%s -> %s' % (host, self.runner.delegate_to)
item = host_result.get('item', None)
@ -542,9 +539,8 @@ class PlaybookRunnerCallbacks(DefaultRunnerCallbacks):
super(PlaybookRunnerCallbacks, self).on_ok(host, host_result)
def on_skipped(self, host, item=None):
delegate_to = self.runner.module_vars.get('delegate_to')
if delegate_to:
host = '%s -> %s' % (host, delegate_to)
if self.runner.delegate_to:
host = '%s -> %s' % (host, self.runner.delegate_to)
if constants.DISPLAY_SKIPPED_HOSTS:
msg = ''

View file

@ -181,6 +181,7 @@ class Runner(object):
self.always_run = None
self.connector = connection.Connector(self)
self.conditional = conditional
self.delegate_to = None
self.module_name = module_name
self.forks = int(forks)
self.pattern = pattern
@ -312,16 +313,13 @@ class Runner(object):
# *****************************************************
def _compute_delegate(self, host, password, remote_inject):
def _compute_delegate(self, password, remote_inject):
""" Build a dictionary of all attributes for the delegate host """
delegate = {}
# allow delegated host to be templated
delegate['host'] = template.template(self.basedir, host,
remote_inject, fail_on_undefined=True)
delegate['inject'] = remote_inject.copy()
# set any interpreters
@ -333,36 +331,33 @@ class Runner(object):
del delegate['inject'][i]
port = C.DEFAULT_REMOTE_PORT
this_host = delegate['host']
# get the vars for the delegate by its name
try:
this_info = delegate['inject']['hostvars'][this_host]
this_info = delegate['inject']['hostvars'][self.delegate_to]
except:
# make sure the inject is empty for non-inventory hosts
this_info = {}
# get the real ssh_address for the delegate
# and allow ansible_ssh_host to be templated
delegate['ssh_host'] = template.template(self.basedir,
this_info.get('ansible_ssh_host', this_host),
this_info, fail_on_undefined=True)
delegate['ssh_host'] = template.template(
self.basedir,
this_info.get('ansible_ssh_host', self.delegate_to),
this_info,
fail_on_undefined=True
)
delegate['port'] = this_info.get('ansible_ssh_port', port)
delegate['user'] = self._compute_delegate_user(this_host, delegate['inject'])
delegate['user'] = self._compute_delegate_user(self.delegate_to, delegate['inject'])
delegate['pass'] = this_info.get('ansible_ssh_pass', password)
delegate['private_key_file'] = this_info.get('ansible_ssh_private_key_file',
self.private_key_file)
delegate['private_key_file'] = this_info.get('ansible_ssh_private_key_file', self.private_key_file)
delegate['transport'] = this_info.get('ansible_connection', self.transport)
delegate['sudo_pass'] = this_info.get('ansible_sudo_pass', self.sudo_pass)
# Last chance to get private_key_file from global variables.
# this is useful if delegated host is not defined in the inventory
if delegate['private_key_file'] is None:
delegate['private_key_file'] = remote_inject.get(
'ansible_ssh_private_key_file', None)
delegate['private_key_file'] = remote_inject.get('ansible_ssh_private_key_file', None)
if delegate['private_key_file'] is not None:
delegate['private_key_file'] = os.path.expanduser(delegate['private_key_file'])
@ -642,11 +637,6 @@ class Runner(object):
# fireball, local, etc
port = self.remote_port
# template this one is available, callbacks use this
delegate_to = self.module_vars.get('delegate_to')
if delegate_to:
self.module_vars['delegate_to'] = template.template(self.basedir, delegate_to, inject)
if self.inventory.basedir() is not None:
inject['inventory_dir'] = self.inventory.basedir()
@ -846,9 +836,12 @@ class Runner(object):
# 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 = self._compute_delegate(delegate_to, actual_pass, inject)
self.delegate_to = inject.get('delegate_to', None)
if self.delegate_to:
self.delegate_to = template.template(self.basedir, self.delegate_to, inject)
if self.delegate_to is not None:
delegate = self._compute_delegate(actual_pass, inject)
actual_transport = delegate['transport']
actual_host = delegate['ssh_host']
actual_port = delegate['port']
@ -880,7 +873,7 @@ class Runner(object):
try:
conn = self.connector.connect(actual_host, actual_port, actual_user, actual_pass, actual_transport, actual_private_key_file)
if delegate_to or host != actual_host:
if self.delegate_to or host != actual_host:
conn.delegate = host
default_shell = getattr(conn, 'default_shell', '')