From aae13bd85d09f31ecd5b65a72781e83806be48e3 Mon Sep 17 00:00:00 2001 From: Tom Mullaney <2078150+tpmullan@users.noreply.github.com> Date: Mon, 12 Sep 2022 18:38:03 +0000 Subject: [PATCH] Improved ssh config support in Paramiko backend The include statement is now supported when using paramiko as the backend --- testinfra/backend/paramiko.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/testinfra/backend/paramiko.py b/testinfra/backend/paramiko.py index 5e6599be..0a85721a 100644 --- a/testinfra/backend/paramiko.py +++ b/testinfra/backend/paramiko.py @@ -54,7 +54,7 @@ def __init__( self.timeout = int(timeout) super().__init__(self.host.name, *args, **kwargs) - def _load_ssh_config(self, client, cfg, ssh_config): + def _load_ssh_config(self, client, cfg, ssh_config, ssh_config_dir="~/.ssh"): for key, value in ssh_config.lookup(self.host.name).items(): if key == "hostname": cfg[key] = value @@ -74,6 +74,14 @@ def _load_ssh_config(self, client, cfg, ssh_config): cfg["gss_kex"] = value == "yes" elif key == "proxycommand": cfg["sock"] = paramiko.ProxyCommand(value) + elif key == "include": + new_config_path = os.path.join( + os.path.expanduser(ssh_config_dir), value + ) + with open(new_config_path) as f: + new_ssh_config = paramiko.SSHConfig() + new_ssh_config.parse(f) + self._load_ssh_config(client, cfg, new_ssh_config, ssh_config_dir) @cached_property def client(self): @@ -87,13 +95,17 @@ def client(self): "password": self.host.password, } if self.ssh_config: + ssh_config_dir = os.path.dirname(self.ssh_config) + with open(self.ssh_config) as f: ssh_config = paramiko.SSHConfig() ssh_config.parse(f) - self._load_ssh_config(client, cfg, ssh_config) + self._load_ssh_config(client, cfg, ssh_config, ssh_config_dir) else: # fallback reading ~/.ssh/config default_ssh_config = os.path.join(os.path.expanduser("~"), ".ssh", "config") + ssh_config_dir = os.path.dirname(default_ssh_config) + try: with open(default_ssh_config) as f: ssh_config = paramiko.SSHConfig() @@ -101,7 +113,7 @@ def client(self): except IOError: pass else: - self._load_ssh_config(client, cfg, ssh_config) + self._load_ssh_config(client, cfg, ssh_config, ssh_config_dir) if self.ssh_identity_file: cfg["key_filename"] = self.ssh_identity_file