Aggregate ssh arguments in PlayContext instead of the connection plugin

Using set_host_overrides() in the connection plugin to access the ssh
argument variables from the inventory didn't see group_vars/host_vars
settings, as noted earlier. Instead, we can set the correct values in
the PlayContext, which has access to all command-line options, task
settings, and variables.

The only downside of doing so is that the source of the settings is no
longer available in ssh.py, and therefore can't be logged. But the code
is simpler, and it actually works.

This change was suggested by @jimi-c in response to the FIXME in the
earlier commit.
This commit is contained in:
Abhijit Menon-Sen 2015-10-02 12:55:48 +05:30
parent 3ad9b4cba6
commit 1981bf2b95
2 changed files with 11 additions and 27 deletions

View file

@ -67,6 +67,10 @@ MAGIC_VARIABLE_MAPPING = dict(
become_pass = ('ansible_become_password','ansible_become_pass'), become_pass = ('ansible_become_password','ansible_become_pass'),
become_exe = ('ansible_become_exe',), become_exe = ('ansible_become_exe',),
become_flags = ('ansible_become_flags',), become_flags = ('ansible_become_flags',),
ssh_common_args = ('ansible_ssh_common_args',),
sftp_extra_args = ('ansible_sftp_extra_args',),
scp_extra_args = ('ansible_scp_extra_args',),
ssh_extra_args = ('ansible_ssh_extra_args',),
sudo = ('ansible_sudo',), sudo = ('ansible_sudo',),
sudo_user = ('ansible_sudo_user',), sudo_user = ('ansible_sudo_user',),
sudo_pass = ('ansible_sudo_password', 'ansible_sudo_pass'), sudo_pass = ('ansible_sudo_password', 'ansible_sudo_pass'),
@ -140,6 +144,7 @@ class PlayContext(Base):
_private_key_file = FieldAttribute(isa='string', default=C.DEFAULT_PRIVATE_KEY_FILE) _private_key_file = FieldAttribute(isa='string', default=C.DEFAULT_PRIVATE_KEY_FILE)
_timeout = FieldAttribute(isa='int', default=C.DEFAULT_TIMEOUT) _timeout = FieldAttribute(isa='int', default=C.DEFAULT_TIMEOUT)
_shell = FieldAttribute(isa='string') _shell = FieldAttribute(isa='string')
_ssh_args = FieldAttribute(isa='string', default=C.ANSIBLE_SSH_ARGS)
_ssh_common_args = FieldAttribute(isa='string') _ssh_common_args = FieldAttribute(isa='string')
_sftp_extra_args = FieldAttribute(isa='string') _sftp_extra_args = FieldAttribute(isa='string')
_scp_extra_args = FieldAttribute(isa='string') _scp_extra_args = FieldAttribute(isa='string')

View file

@ -33,7 +33,6 @@ from ansible import constants as C
from ansible.errors import AnsibleError, AnsibleConnectionFailure, AnsibleFileNotFound from ansible.errors import AnsibleError, AnsibleConnectionFailure, AnsibleFileNotFound
from ansible.plugins.connection import ConnectionBase from ansible.plugins.connection import ConnectionBase
from ansible.utils.path import unfrackpath, makedirs_safe from ansible.utils.path import unfrackpath, makedirs_safe
from ansible.utils.vars import combine_vars
SSHPASS_AVAILABLE = None SSHPASS_AVAILABLE = None
@ -48,21 +47,6 @@ class Connection(ConnectionBase):
super(Connection, self).__init__(*args, **kwargs) super(Connection, self).__init__(*args, **kwargs)
self.host = self._play_context.remote_addr self.host = self._play_context.remote_addr
for v in ['ssh_common_args', 'sftp_extra_args', 'scp_extra_args', 'ssh_extra_args']:
setattr(self, v, '')
def set_host_overrides(self, host):
# FIXME: The following can only use the variables set directly against
# the host ("hostname var=...") or the group ("[group:vars] ...") in the
# inventory file, but NOT those read from group_vars/host_vars files or
# any other source. That's clearly wrong, but we don't have access to a
# VariableManager here, so I don't know how to get at those settings.
vars = combine_vars(host.get_group_vars(), host.get_vars())
for v in ['ssh_common_args', 'sftp_extra_args', 'scp_extra_args', 'ssh_extra_args']:
name = 'ansible_%s' % v
if name in vars:
setattr(self, v, vars[name])
# The connection is created by running ssh/scp/sftp from the exec_command, # The connection is created by running ssh/scp/sftp from the exec_command,
# put_file, and fetch_file methods, so we don't need to do any connection # put_file, and fetch_file methods, so we don't need to do any connection
@ -169,8 +153,8 @@ class Connection(ConnectionBase):
# Next, we add [ssh_connection]ssh_args from ansible.cfg, or the default # Next, we add [ssh_connection]ssh_args from ansible.cfg, or the default
# Control* settings. # Control* settings.
if C.ANSIBLE_SSH_ARGS: if self._play_context.ssh_args:
args = self._split_args(C.ANSIBLE_SSH_ARGS) args = self._split_args(self._play_context.ssh_args)
self._add_args("ansible.cfg set ssh_args", args) self._add_args("ansible.cfg set ssh_args", args)
else: else:
args = ( args = (
@ -223,20 +207,15 @@ class Connection(ConnectionBase):
("-o", "ConnectTimeout={0}".format(self._play_context.timeout)) ("-o", "ConnectTimeout={0}".format(self._play_context.timeout))
) )
# If the inventory specifies either common or binary-specific arguments # Add in any common or binary-specific arguments from the PlayContext
# applicable to this host, or they are specified as an override on the # (i.e. inventory or task settings or overrides on the command line).
# command line, add them in now.
for opt in ['ssh_common_args', binary + '_extra_args']: for opt in ['ssh_common_args', binary + '_extra_args']:
if getattr(self._play_context, opt): if getattr(self._play_context, opt):
args = self._split_args(getattr(self._play_context, opt)) args = self._split_args(getattr(self._play_context, opt))
self._add_args("command-line added --%s" % opt.replace('_', '-'), args) self._add_args("PlayContext set %s" % opt, args)
elif getattr(self, opt):
args = self._split_args(getattr(self, opt))
self._add_args("inventory added ansible_%s" % opt, args)
# Check if ControlPersist is enabled (either by default, or using # Check if ControlPersist is enabled and add a ControlPath if one hasn't
# ssh_args or ssh_extra_args) and add a ControlPath if one hasn't
# already been set. # already been set.
controlpersist, controlpath = self._persistence_controls(self._command) controlpersist, controlpath = self._persistence_controls(self._command)