Skip to content

Commit 8712742

Browse files
committed
chroot / means no chroot
1 parent 251173f commit 8712742

File tree

4 files changed

+32
-20
lines changed

4 files changed

+32
-20
lines changed

exec_helpers/_ssh_client_base.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1323,11 +1323,11 @@ def get_result(remote: "SSHClientBase") -> exec_result.ExecResult:
13231323
# pylint: disable=protected-access
13241324
cmd_for_log: str = remote._mask_command(cmd=command, log_mask_re=log_mask_re)
13251325

1326+
target_path: typing.Optional[str] = kwargs.get("chroot_path", remote._chroot_path)
1327+
chroot_info: str = "" if not target_path or target_path == "/" else f" (with chroot to: {target_path!r})"
1328+
13261329
remote.logger.log(
1327-
level=log_level,
1328-
msg=f"Executing command"
1329-
f"{'' if not remote._chroot_path else f' (with chroot to: {remote._chroot_path})'}:\n"
1330-
f"{cmd_for_log!r}\n",
1330+
level=log_level, msg=f"Executing command{chroot_info}:\n{cmd_for_log!r}\n",
13311331
)
13321332
async_result: SshExecuteAsyncResult = remote._execute_async(
13331333
command,

exec_helpers/api.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -236,10 +236,11 @@ def _prepare_command(self, cmd: str, chroot_path: typing.Optional[str] = None) -
236236
:param chroot_path: path to make chroot for execution
237237
:return: final command, includes chroot, if required
238238
"""
239-
if any((chroot_path, self._chroot_path)):
240-
target_path: str = shlex.quote(chroot_path if chroot_path else self._chroot_path) # type: ignore
239+
target_path: typing.Optional[str] = chroot_path if chroot_path else self._chroot_path
240+
if target_path and target_path != "/":
241+
chroot_dst: str = shlex.quote(target_path.strip())
241242
quoted_command = shlex.quote(cmd)
242-
return f'chroot {target_path} sh -c {shlex.quote(f"eval {quoted_command}")}'
243+
return f'chroot {chroot_dst} sh -c {shlex.quote(f"eval {quoted_command}")}'
243244
return cmd
244245

245246
@abc.abstractmethod
@@ -363,10 +364,11 @@ def execute(
363364
cmd_for_log: str = self._mask_command(cmd=command, log_mask_re=log_mask_re)
364365
log_level: int = logging.INFO if verbose else logging.DEBUG
365366

367+
target_path: typing.Optional[str] = kwargs.get("chroot_path", self._chroot_path)
368+
chroot_info: str = "" if not target_path or target_path == "/" else f" (with chroot to: {target_path!r})"
369+
366370
self.logger.log(
367-
level=log_level,
368-
msg=f"Executing command{'' if not self._chroot_path else f' (with chroot to: {self._chroot_path})'}:\n"
369-
f"{cmd_for_log!r}\n",
371+
level=log_level, msg=f"Executing command{chroot_info}:\n{cmd_for_log!r}\n",
370372
)
371373

372374
async_result: ExecuteAsyncResult = self._execute_async(

exec_helpers/async_api/api.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -220,10 +220,11 @@ async def execute( # type: ignore
220220
cmd_for_log: str = self._mask_command(cmd=command, log_mask_re=log_mask_re)
221221
log_level: int = logging.INFO if verbose else logging.DEBUG
222222

223+
target_path: typing.Optional[str] = kwargs.get("chroot_path", self._chroot_path)
224+
chroot_info: str = "" if not target_path or target_path == "/" else f" (with chroot to: {target_path!r})"
225+
223226
self.logger.log(
224-
level=log_level,
225-
msg=f"Executing command{'' if not self._chroot_path else f' (with chroot to: {self._chroot_path})'}:\n"
226-
f"{cmd_for_log!r}\n",
227+
level=log_level, msg=f"Executing command{chroot_info}:\n{cmd_for_log!r}\n",
227228
)
228229

229230
async_result: api.ExecuteAsyncResult = await self._execute_async(

test/test_ssh_client_execute_async_special.py

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -218,30 +218,30 @@ def test_010_check_stdin_closed(paramiko_ssh_client, chan_makefile, auto_add_pol
218218

219219
def test_011_execute_async_chroot_cmd(ssh, ssh_transport_channel):
220220
"""Command-only chroot path."""
221-
ssh._execute_async(command, chroot_path="/")
221+
ssh._execute_async(command, chroot_path="/mnt")
222222
ssh_transport_channel.assert_has_calls(
223223
(
224224
mock.call.makefile_stderr("rb"),
225-
mock.call.exec_command(f'chroot / sh -c {shlex.quote(f"eval {quoted_command}")}\n'),
225+
mock.call.exec_command(f'chroot /mnt sh -c {shlex.quote(f"eval {quoted_command}")}\n'),
226226
)
227227
)
228228

229229

230230
def test_012_execute_async_chroot_context(ssh, ssh_transport_channel):
231231
"""Context-managed chroot path."""
232-
with ssh.chroot("/"):
232+
with ssh.chroot("/mnt"):
233233
ssh._execute_async(command)
234234
ssh_transport_channel.assert_has_calls(
235235
(
236236
mock.call.makefile_stderr("rb"),
237-
mock.call.exec_command(f'chroot / sh -c {shlex.quote(f"eval {quoted_command}")}\n'),
237+
mock.call.exec_command(f'chroot /mnt sh -c {shlex.quote(f"eval {quoted_command}")}\n'),
238238
)
239239
)
240240

241241

242242
def test_013_execute_async_no_chroot_context(ssh, ssh_transport_channel):
243243
"""Context-managed chroot path override."""
244-
ssh._chroot_path = "/"
244+
ssh._chroot_path = "/mnt"
245245

246246
with ssh.chroot(None):
247247
ssh._execute_async(command)
@@ -250,12 +250,12 @@ def test_013_execute_async_no_chroot_context(ssh, ssh_transport_channel):
250250

251251
def test_012_execute_async_chroot_path(ssh, ssh_transport_channel):
252252
"""Command-only chroot path."""
253-
with ssh.chroot(pathlib.Path("/")):
253+
with ssh.chroot(pathlib.Path("/mnt")):
254254
ssh._execute_async(command)
255255
ssh_transport_channel.assert_has_calls(
256256
(
257257
mock.call.makefile_stderr("rb"),
258-
mock.call.exec_command(f'chroot / sh -c {shlex.quote(f"eval {quoted_command}")}\n'),
258+
mock.call.exec_command(f'chroot /mnt sh -c {shlex.quote(f"eval {quoted_command}")}\n'),
259259
)
260260
)
261261

@@ -266,3 +266,12 @@ def test_013_execute_async_chroot_path_invalid_type(ssh, ssh_transport_channel):
266266
with ssh.chroot(...):
267267
ssh._execute_async(command)
268268
assert str(exc.value) == f"path={...!r} is not instance of Optional[Union[str, pathlib.Path]]"
269+
270+
271+
def test_014_execute_async_no_chroot_root(ssh, ssh_transport_channel):
272+
"""Context-managed chroot path override."""
273+
ssh._chroot_path = "/mnt"
274+
275+
with ssh.chroot("/"):
276+
ssh._execute_async(command)
277+
ssh_transport_channel.assert_has_calls((mock.call.makefile_stderr("rb"), mock.call.exec_command(f"{command}\n")))

0 commit comments

Comments
 (0)