Skip to content

Commit 5668acf

Browse files
committed
use generic connection interface from latest pytest-mh
Latest version added an option to replace SSH connections with podman or docker, therefore a generic interface was created. Most notably, `host.ssh` was replaced with `host.conn`.
1 parent f0c03cb commit 5668acf

36 files changed

+362
-324
lines changed

docs/config.rst

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ Basic definition
1717
hosts:
1818
- hostname: <dns host name>
1919
role: <host role>
20-
ssh:
20+
conn:
21+
type: ssh
2122
host: <ssh host> (optional, defaults to host name)
2223
port: <ssh port> (optional, defaults to 22)
2324
username: <ssh username> (optional, defaults to "root")
@@ -41,11 +42,11 @@ domain has ``id`` attribute and defines the list of available hosts.
4142
* ``hostname``: DNS host name, it may not necessarily be resolvable from the
4243
machine that runs pytest
4344
* ``role``: host role
44-
* ``ssh.host``: ssh host to connect to (it may be a resolvable host name or an
45+
* ``conn.host``: ssh host to connect to (it may be a resolvable host name or an
4546
IP address), defaults to the value of ``hostname``
46-
* ``ssh.port``: ssh port, defaults to 22
47-
* ``ssh.username``: ssh username, defaults to ``root``
48-
* ``ssh.password``: ssh password for the user, defaults to ``Secret123``
47+
* ``conn.port``: ssh port, defaults to 22
48+
* ``conn.username``: ssh username, defaults to ``root``
49+
* ``conn.password``: ssh password for the user, defaults to ``Secret123``
4950
* ``config``: additional configuration, place for custom options, see
5051
:ref:`custom-config`
5152
* ``artifacts``: list of artifacts that are automatically downloaded, see

docs/guides/using-roles.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -461,10 +461,10 @@ needed, you can also run commands on the host directly:
461461
@pytest.mark.topology(KnownTopology.AD)
462462
def test_client(client: Client, ad: AD):
463463
# Commands are executed in bash on Linux systems
464-
client.host.ssh.run('echo "test"')
464+
client.host.conn.run('echo "test"')
465465
466466
# And in Powershell on Windows
467-
ad.host.ssh.run('Write-Output "test"')
467+
ad.host.conn.run('Write-Output "test"')
468468
469469
.. seealso::
470470

docs/guides/using-ssh.rst

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
Using SSH
22
#########
33

4-
You can use :class:`pytest_mh.ssh.SSHClient` to connect to any host as any
4+
You can use :class:`pytest_mh.conn.ssh.SSHClient` to connect to any host as any
55
user. It is not recommended to instantiate this class on yourself but you should
6-
rather use :meth:`pytest_mh.MultihostRole.ssh` to get the client
7-
object.
6+
rather use :meth:`pytest_mh.MultihostRole.ssh` to get the client object.
87

98
Once you establish SSH connections, you can run commands on the remote host in
109
both blocking and non-blocking mode.

requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
jc
22
pytest
33
python-ldap
4-
pytest-mh >= 1.0.17
4+
pytest-mh >= 1.0.18

sssd_test_framework/hosts/ad.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from pathlib import PureWindowsPath
66
from typing import Any
77

8-
from pytest_mh.ssh import SSHLog
8+
from pytest_mh.conn import ProcessLogLevel
99

1010
from .base import BaseDomainHost
1111

@@ -88,7 +88,7 @@ def naming_context(self) -> str:
8888
:rtype: str
8989
"""
9090
if not self.__naming_context:
91-
result = self.ssh.run("Write-Host (Get-ADRootDSE).rootDomainNamingContext")
91+
result = self.conn.run("Write-Host (Get-ADRootDSE).rootDomainNamingContext")
9292
nc = result.stdout.strip()
9393
if not nc:
9494
raise ValueError("Unable to find default naming context")
@@ -118,7 +118,7 @@ def backup(self) -> Any:
118118
"""
119119
self.logger.info("Creating backup of Active Directory")
120120

121-
result = self.ssh.run(
121+
result = self.conn.run(
122122
rf"""
123123
$basedn = '{self.naming_context}'
124124
$sitesdn = "cn=sites,cn=configuration,$basedn"
@@ -151,7 +151,7 @@ def backup(self) -> Any:
151151
152152
Write-Output $tmpdir.FullName
153153
""",
154-
log_level=SSHLog.Error,
154+
log_level=ProcessLogLevel.Error,
155155
)
156156

157157
return PureWindowsPath(result.stdout.strip())
@@ -185,7 +185,7 @@ def restore(self, backup_data: Any | None) -> None:
185185
backup_path = str(backup_data)
186186
self.logger.info(f"Restoring Active Directory from {backup_path}")
187187

188-
self.ssh.run(
188+
self.conn.run(
189189
rf"""
190190
$basedn = '{self.naming_context}'
191191
$sitesdn = "cn=sites,cn=configuration,$basedn"
@@ -253,5 +253,5 @@ def restore(self, backup_data: Any | None) -> None:
253253
# If we got here, make sure we exit with 0
254254
Exit 0
255255
""",
256-
log_level=SSHLog.Error,
256+
log_level=ProcessLogLevel.Error,
257257
)

sssd_test_framework/hosts/base.py

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
import ldap
1010
from ldap.ldapobject import ReconnectLDAPObject
1111
from pytest_mh import MultihostHost
12-
from pytest_mh.ssh import SSHPowerShellProcess
12+
from pytest_mh.conn import Powershell
1313
from pytest_mh.utils.fs import LinuxFileSystem
1414
from pytest_mh.utils.services import SystemdServices
1515

@@ -86,10 +86,10 @@ def remove_backup(self, backup_data: Any | None) -> None:
8686
else:
8787
raise TypeError(f"Only PurePath is supported as backup_data, got {type(backup_data)}")
8888

89-
if self.ssh.shell is SSHPowerShellProcess:
90-
self.ssh.exec(["Remove-Item", "-Force", "-Recurse", path])
89+
if isinstance(self.conn.shell, Powershell):
90+
self.conn.exec(["Remove-Item", "-Force", "-Recurse", path])
9191
else:
92-
self.ssh.exec(["rm", "-fr", path])
92+
self.conn.exec(["rm", "-fr", path])
9393

9494
@abstractmethod
9595
def start(self) -> None:
@@ -213,19 +213,22 @@ def __init__(self, *args, tls: bool = True, **kwargs) -> None:
213213
"""Bind password ``config.bindpw``, defaults to ``Secret123``"""
214214

215215
# Lazy properties.
216-
self.__conn: ReconnectLDAPObject | None = None
216+
self.__ldap_conn: ReconnectLDAPObject | None = None
217217
self.__naming_context: str | None = None
218218

219219
@property
220220
@retry(on=ldap.SERVER_DOWN)
221-
def conn(self) -> ReconnectLDAPObject:
221+
def ldap_conn(self) -> ReconnectLDAPObject:
222222
"""
223223
LDAP connection (``python-ldap`` library).
224224
225225
:rtype: ReconnectLDAPObject
226226
"""
227-
if not self.__conn:
228-
newconn = ReconnectLDAPObject(f"ldap://{self.ssh_host}")
227+
if not self.__ldap_conn:
228+
# Use host from SSH if possible, otherwise fallback to hostname
229+
host = getattr(self.conn, "host", self.hostname)
230+
231+
newconn = ReconnectLDAPObject(f"ldap://{host}")
229232
newconn.protocol_version = ldap.VERSION3
230233
newconn.set_option(ldap.OPT_REFERRALS, 0)
231234

@@ -235,9 +238,9 @@ def conn(self) -> ReconnectLDAPObject:
235238
newconn.start_tls_s()
236239

237240
newconn.simple_bind_s(self.binddn, self.bindpw)
238-
self.__conn = newconn
241+
self.__ldap_conn = newconn
239242

240-
return self.__conn
243+
return self.__ldap_conn
241244

242245
@property
243246
def naming_context(self) -> str:
@@ -249,7 +252,7 @@ def naming_context(self) -> str:
249252
"""
250253
if not self.__naming_context:
251254
attr = "defaultNamingContext"
252-
result = self.conn.search_s("", ldap.SCOPE_BASE, attrlist=[attr])
255+
result = self.ldap_conn.search_s("", ldap.SCOPE_BASE, attrlist=[attr])
253256
if len(result) != 1:
254257
raise ValueError(f"Unexpected number of results for rootDSE query: {len(result)}")
255258

@@ -265,9 +268,9 @@ def disconnect(self) -> None:
265268
"""
266269
Disconnect LDAP connection.
267270
"""
268-
if self.__conn is not None:
269-
self.__conn.unbind()
270-
self.__conn = None
271+
if self.__ldap_conn is not None:
272+
self.__ldap_conn.unbind()
273+
self.__ldap_conn = None
271274

272275
def ldap_result_to_dict(
273276
self, result: list[tuple[str, dict[str, list[bytes]]]]

sssd_test_framework/hosts/client.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from pathlib import PurePosixPath
66
from typing import Any
77

8-
from pytest_mh.ssh import SSHLog
8+
from pytest_mh.conn import ProcessLogLevel
99

1010
from .base import BaseBackupHost, BaseLinuxHost
1111

@@ -39,7 +39,7 @@ def features(self) -> dict[str, bool]:
3939
return self._features
4040

4141
self.logger.info(f"Detecting SSSD's features on {self.hostname}")
42-
result = self.ssh.run(
42+
result = self.conn.run(
4343
"""
4444
set -ex
4545
@@ -52,7 +52,7 @@ def features(self) -> dict[str, bool]:
5252
MANWIDTH=10000 man sssd.conf | grep -q "id_provider = ldap or id_provider = proxy" && \
5353
echo "limited_enumeration" || :
5454
""",
55-
log_level=SSHLog.Error,
55+
log_level=ProcessLogLevel.Error,
5656
)
5757

5858
# Set default values
@@ -91,7 +91,7 @@ def backup(self) -> Any:
9191
"""
9292
self.logger.info("Creating backup of SSSD client")
9393

94-
result = self.ssh.run(
94+
result = self.conn.run(
9595
"""
9696
set -ex
9797
@@ -110,7 +110,7 @@ def backup(self) -> Any:
110110
111111
echo $path
112112
""",
113-
log_level=SSHLog.Error,
113+
log_level=ProcessLogLevel.Error,
114114
)
115115

116116
return PurePosixPath(result.stdout_lines[-1].strip())
@@ -131,7 +131,7 @@ def restore(self, backup_data: Any | None) -> None:
131131
backup_path = str(backup_data)
132132

133133
self.logger.info(f"Restoring SSSD data from {backup_path}")
134-
self.ssh.run(
134+
self.conn.run(
135135
f"""
136136
set -ex
137137
@@ -149,5 +149,5 @@ def restore(self, backup_data: Any | None) -> None:
149149
restore "{backup_path}/logs" /var/log/sssd
150150
restore "{backup_path}/lib" /var/lib/sss
151151
""",
152-
log_level=SSHLog.Error,
152+
log_level=ProcessLogLevel.Error,
153153
)

sssd_test_framework/hosts/ipa.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from pathlib import PurePosixPath
66
from typing import Any
77

8-
from pytest_mh.ssh import SSHLog
8+
from pytest_mh.conn import ProcessLogLevel
99

1010
from ..misc.ssh import retry_command
1111
from .base import BaseDomainHost, BaseLinuxHost
@@ -79,15 +79,15 @@ def features(self) -> dict[str, bool]:
7979

8080
self.logger.info(f"Detecting features on {self.hostname}")
8181

82-
result = self.ssh.run(
82+
result = self.conn.run(
8383
"""
8484
set -ex
8585
8686
[ -f "/usr/libexec/sssd/passkey_child" ] && \
8787
ipa help user | grep user-add-passkey 1> /dev/null && \
8888
echo "passkey" || :
8989
""",
90-
log_level=SSHLog.Error,
90+
log_level=ProcessLogLevel.Error,
9191
)
9292

9393
# Set default values
@@ -104,7 +104,7 @@ def kinit(self) -> None:
104104
"""
105105
Obtain ``admin`` user Kerberos TGT.
106106
"""
107-
self.ssh.exec(["kinit", "admin"], input=self.adminpw)
107+
self.conn.exec(["kinit", "admin"], input=self.adminpw)
108108

109109
def start(self) -> None:
110110
self.svc.start("ipa.service")
@@ -126,7 +126,7 @@ def backup(self) -> Any:
126126
# Race condition: https://pagure.io/freeipa/issue/9584
127127
@retry_command(delay=0, match_stderr="Unable to add LDIF task: This entry already exists")
128128
def _backup():
129-
return self.ssh.run(
129+
return self.conn.run(
130130
"""
131131
set -ex
132132
@@ -148,7 +148,7 @@ def _backup():
148148
149149
echo $path
150150
""",
151-
log_level=SSHLog.Error,
151+
log_level=ProcessLogLevel.Error,
152152
)
153153

154154
self.logger.info("Creating backup of IPA server")
@@ -174,7 +174,7 @@ def restore(self, backup_data: Any | None) -> None:
174174
backup_path = str(backup_data)
175175
self.logger.info(f"Restoring IPA server from {backup_path}")
176176

177-
self.ssh.run(
177+
self.conn.run(
178178
f"""
179179
set -ex
180180
@@ -194,6 +194,6 @@ def restore(self, backup_data: Any | None) -> None:
194194
restore "{backup_path}/logs" /var/log/sssd
195195
restore "{backup_path}/lib" /var/lib/sss
196196
""",
197-
log_level=SSHLog.Error,
197+
log_level=ProcessLogLevel.Error,
198198
)
199199
self.svc.restart("sssd.service")

sssd_test_framework/hosts/kdc.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from pathlib import PurePosixPath
66
from typing import Any
77

8-
from pytest_mh.ssh import SSHLog
8+
from pytest_mh.conn import ProcessLogLevel
99

1010
from .base import BaseDomainHost, BaseLinuxHost
1111

@@ -62,14 +62,14 @@ def backup(self) -> Any:
6262
"""
6363
self.logger.info("Creating backup of KDC")
6464

65-
result = self.ssh.run(
65+
result = self.conn.run(
6666
"""
6767
set -e
6868
path=`mktemp`
6969
kdb5_util dump $path && rm -f "$path.dump_ok"
7070
echo $path
7171
""",
72-
log_level=SSHLog.Error,
72+
log_level=ProcessLogLevel.Error,
7373
)
7474
return PurePosixPath(result.stdout_lines[-1].strip())
7575

@@ -89,4 +89,4 @@ def restore(self, backup_data: Any | None) -> None:
8989
backup_path = str(backup_data)
9090
self.logger.info(f"Restoring KDC from {backup_path}")
9191

92-
self.ssh.run(f'kdb5_util load "{backup_path}"', log_level=SSHLog.Error)
92+
self.conn.run(f'kdb5_util load "{backup_path}"', log_level=ProcessLogLevel.Error)

0 commit comments

Comments
 (0)