From 96905120698e3118d8bafaee5ebe8f83d2bbd607 Mon Sep 17 00:00:00 2001 From: Brian Coca Date: Thu, 25 Feb 2021 15:08:11 -0500 Subject: [PATCH] Pipe it to connections (#73688) * pipelining tweaks added 'defaults' entry for ini pipelining from ssh plugin --- changelogs/fragments/pipelinig_to_plugins.yml | 2 ++ lib/ansible/config/base.yml | 7 ++--- lib/ansible/plugins/connection/local.py | 11 +++++-- lib/ansible/plugins/connection/psrp.py | 2 ++ lib/ansible/plugins/connection/ssh.py | 13 ++------- lib/ansible/plugins/connection/winrm.py | 2 ++ .../doc_fragments/connection_pipelining.py | 29 +++++++++++++++++++ 7 files changed, 49 insertions(+), 17 deletions(-) create mode 100644 changelogs/fragments/pipelinig_to_plugins.yml create mode 100644 lib/ansible/plugins/doc_fragments/connection_pipelining.py diff --git a/changelogs/fragments/pipelinig_to_plugins.yml b/changelogs/fragments/pipelinig_to_plugins.yml new file mode 100644 index 00000000000..1794caaecb6 --- /dev/null +++ b/changelogs/fragments/pipelinig_to_plugins.yml @@ -0,0 +1,2 @@ +bugfixes: + - Restructured pipelining settings to be at the connection plugins leaving base config as global and for backwards compatiblity. diff --git a/lib/ansible/config/base.yml b/lib/ansible/config/base.yml index 66606eeef9b..439cf9c952a 100644 --- a/lib/ansible/config/base.yml +++ b/lib/ansible/config/base.yml @@ -109,16 +109,15 @@ ANSIBLE_PIPELINING: - "However this conflicts with privilege escalation (become). For example, when using 'sudo:' operations you must first disable 'requiretty' in /etc/sudoers on all managed hosts, which is why it is disabled by default." - This option is disabled if ``ANSIBLE_KEEP_REMOTE_FILES`` is enabled. + - This is a global option, each connection plugin can override either by having more specific options or not supporting pipelining at all. env: - name: ANSIBLE_PIPELINING - - name: ANSIBLE_SSH_PIPELINING ini: + - section: defaults + key: pipelining - section: connection key: pipelining - - section: ssh_connection - key: pipelining type: boolean - yaml: {key: plugins.connection.pipelining} ANSIBLE_SSH_ARGS: # TODO: move to ssh plugin default: -C -o ControlMaster=auto -o ControlPersist=60s diff --git a/lib/ansible/plugins/connection/local.py b/lib/ansible/plugins/connection/local.py index c6ec01d82d8..182e21cd7df 100644 --- a/lib/ansible/plugins/connection/local.py +++ b/lib/ansible/plugins/connection/local.py @@ -12,6 +12,8 @@ DOCUMENTATION = ''' - This connection plugin allows ansible to execute tasks on the Ansible 'controller' instead of on a remote host. author: ansible (@core) version_added: historical + extends_documentation_fragment: + - connection_pipelining notes: - The remote user is ignored, the user with which the ansible CLI was executed is used instead. ''' @@ -82,7 +84,7 @@ class Connection(ConnectionBase): master = None stdin = subprocess.PIPE - if sudoable and self.become and self.become.expect_prompt(): + if sudoable and self.become and self.become.expect_prompt() and not self.get_option('pipelining'): # Create a pty if sudoable for privlege escalation that needs it. # Falls back to using a standard pipe if this fails, which may # cause the command to fail in certain situations where we are escalating @@ -102,7 +104,7 @@ class Connection(ConnectionBase): stderr=subprocess.PIPE, ) - # if we created a master, we can close the other half of the pty now + # if we created a master, we can close the other half of the pty now, otherwise master is stdin if master is not None: os.close(stdin) @@ -138,7 +140,10 @@ class Connection(ConnectionBase): if not self.become.check_success(become_output): become_pass = self.become.get_option('become_pass', playcontext=self._play_context) - os.write(master, to_bytes(become_pass, errors='surrogate_or_strict') + b'\n') + if master is None: + p.stdin.write(to_bytes(become_pass, errors='surrogate_or_strict') + b'\n') + else: + os.write(master, to_bytes(become_pass, errors='surrogate_or_strict') + b'\n') fcntl.fcntl(p.stdout, fcntl.F_SETFL, fcntl.fcntl(p.stdout, fcntl.F_GETFL) & ~os.O_NONBLOCK) fcntl.fcntl(p.stderr, fcntl.F_SETFL, fcntl.fcntl(p.stderr, fcntl.F_GETFL) & ~os.O_NONBLOCK) diff --git a/lib/ansible/plugins/connection/psrp.py b/lib/ansible/plugins/connection/psrp.py index 9e73382d9b5..086897b38e0 100644 --- a/lib/ansible/plugins/connection/psrp.py +++ b/lib/ansible/plugins/connection/psrp.py @@ -15,6 +15,8 @@ description: version_added: "2.7" requirements: - pypsrp>=0.4.0 (Python library) +extends_documentation_fragment: + - connection_pipelining options: # transport options remote_addr: diff --git a/lib/ansible/plugins/connection/ssh.py b/lib/ansible/plugins/connection/ssh.py index 99f675cd0fe..29a218c090b 100644 --- a/lib/ansible/plugins/connection/ssh.py +++ b/lib/ansible/plugins/connection/ssh.py @@ -16,6 +16,8 @@ DOCUMENTATION = ''' a password manually to decrypt an ssh key when using this connection plugin (which is the default). The use of ``ssh-agent`` is highly recommended. author: ansible (@core) + extends_documentation_fragment: + - connection_pipelining version_added: historical options: host: @@ -190,23 +192,14 @@ DOCUMENTATION = ''' - name: ansible_user - name: ansible_ssh_user pipelining: - default: ANSIBLE_PIPELINING - description: - - Pipelining reduces the number of SSH operations required to execute a module on the remote server, - by executing many Ansible modules without actual file transfer. - - This can result in a very significant performance improvement when enabled. - - However this conflicts with privilege escalation (become). - For example, when using sudo operations you must first disable 'requiretty' in the sudoers file for the target hosts, - which is why this feature is disabled by default. env: - name: ANSIBLE_PIPELINING - name: ANSIBLE_SSH_PIPELINING ini: - - section: defaults + - section: connection key: pipelining - section: ssh_connection key: pipelining - type: boolean vars: - name: ansible_pipelining - name: ansible_ssh_pipelining diff --git a/lib/ansible/plugins/connection/winrm.py b/lib/ansible/plugins/connection/winrm.py index b4521f057ca..82bada26fcb 100644 --- a/lib/ansible/plugins/connection/winrm.py +++ b/lib/ansible/plugins/connection/winrm.py @@ -14,6 +14,8 @@ DOCUMENTATION = """ - This plugin allows extra arguments to be passed that are supported by the protocol but not explicitly defined here. They should take the form of variables declared with the following pattern `ansible_winrm_