diff --git a/testinfra/backend/ssh.py b/testinfra/backend/ssh.py index 5c813952..9b7dfe41 100644 --- a/testinfra/backend/ssh.py +++ b/testinfra/backend/ssh.py @@ -26,6 +26,7 @@ def __init__( ssh_config=None, ssh_identity_file=None, timeout=10, + controlpath="", controlpersist=60, ssh_extra_args=None, *args, @@ -35,6 +36,7 @@ def __init__( self.ssh_config = ssh_config self.ssh_identity_file = ssh_identity_file self.timeout = int(timeout) + self.controlpath = controlpath self.controlpersist = int(controlpersist) self.ssh_extra_args = ssh_extra_args super().__init__(self.host.name, *args, **kwargs) @@ -74,6 +76,12 @@ def _build_ssh_command(self, command): self.controlpersist ) ) + if ( + "ControlMaster" in " ".join(cmd) + and self.controlpath + and ("controlpath" not in (self.ssh_extra_args or "").lower()) + ): + cmd.append("-o ControlPath={}".format(self.controlpath)) cmd.append("%s %s") cmd_args.extend([self.host.name, command]) return cmd, cmd_args diff --git a/testinfra/utils/ansible_runner.py b/testinfra/utils/ansible_runner.py index 3cbd7bf9..210da582 100644 --- a/testinfra/utils/ansible_runner.py +++ b/testinfra/utils/ansible_runner.py @@ -170,6 +170,16 @@ def get_config(name, default=None): ] ).strip() + control_path = config.get("ssh_connection", "control_path", fallback="", raw=True) + if control_path: + directory = config.get( + "persistent_connection", "control_path_dir", fallback="~/.ansible/cp" + ) + control_path = control_path % ({"directory": directory}) + # restore original "%%" + control_path = control_path.replace("%", "%%") + kwargs["controlpath"] = control_path + spec = "{}://".format(connection) # Fallback to user:password auth when identity file is not used