Skip to content

Commit cf0684f

Browse files
committed
Move command run log to execute
Simplify code
1 parent c113869 commit cf0684f

File tree

9 files changed

+27
-67
lines changed

9 files changed

+27
-67
lines changed

exec_helpers/_log_templates.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@
1616

1717
"""Text templates for logging."""
1818

19-
CMD_EXEC: str = "Executing command:\n{cmd!r}\n"
20-
2119
CMD_WAIT_ERROR: str = (
2220
"Wait for {result.cmd!r} during {timeout!s}s: no return code!\n"
2321
"\tSTDOUT:\n"

exec_helpers/_ssh_client_base.py

Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -603,8 +603,6 @@ def _execute_async( # pylint: disable=arguments-differ
603603
stdin: typing.Union[bytes, str, bytearray, None] = None,
604604
open_stdout: bool = True,
605605
open_stderr: bool = True,
606-
verbose: bool = False,
607-
log_mask_re: typing.Optional[str] = None,
608606
*,
609607
chroot_path: typing.Optional[str] = None,
610608
get_pty: bool = False,
@@ -622,11 +620,6 @@ def _execute_async( # pylint: disable=arguments-differ
622620
:type open_stdout: bool
623621
:param open_stderr: open STDERR stream for read
624622
:type open_stderr: bool
625-
:param verbose: produce verbose log record on command call
626-
:type verbose: bool
627-
:param log_mask_re: regex lookup rule to mask command for logger.
628-
all MATCHED groups will be replaced by '<*masked*>'
629-
:type log_mask_re: typing.Optional[str]
630623
:param chroot_path: chroot path override
631624
:type chroot_path: typing.Optional[str]
632625
:param get_pty: Get PTY for connection
@@ -656,12 +649,6 @@ def _execute_async( # pylint: disable=arguments-differ
656649
.. versionchanged:: 3.2.0 Expose pty options as optional keyword-only arguments
657650
.. versionchanged:: 4.1.0 support chroot
658651
"""
659-
cmd_for_log: str = self._mask_command(cmd=command, log_mask_re=log_mask_re)
660-
661-
self.logger.log(
662-
level=logging.INFO if verbose else logging.DEBUG, msg=_log_templates.CMD_EXEC.format(cmd=cmd_for_log)
663-
)
664-
665652
chan: paramiko.Channel = self._ssh.get_transport().open_session()
666653

667654
if get_pty:
@@ -950,7 +937,7 @@ def execute_through_host(
950937
with self.proxy_to( # type: ignore
951938
host=hostname, port=port, auth=auth, verbose=verbose, ssh_config=self.ssh_config, keepalive=False
952939
) as conn:
953-
return conn.execute(
940+
return conn(
954941
command,
955942
timeout=timeout,
956943
open_stdout=open_stdout,
@@ -972,6 +959,7 @@ def execute_together(
972959
raise_on_err: bool = True,
973960
*,
974961
stdin: typing.Union[bytes, str, bytearray, None] = None,
962+
verbose: bool = False,
975963
log_mask_re: typing.Optional[str] = None,
976964
exception_class: "typing.Type[exceptions.ParallelCallProcessError]" = exceptions.ParallelCallProcessError,
977965
**kwargs: typing.Any,
@@ -990,6 +978,8 @@ def execute_together(
990978
:type raise_on_err: bool
991979
:param stdin: pass STDIN text to the process
992980
:type stdin: typing.Union[bytes, str, bytearray, None]
981+
:param verbose: produce verbose log record on command call
982+
:type verbose: bool
993983
:param log_mask_re: regex lookup rule to mask command for logger.
994984
all MATCHED groups will be replaced by '<*masked*>'
995985
:type log_mask_re: typing.Optional[str]
@@ -1016,17 +1006,20 @@ def get_result(remote: "SSHClientBase") -> exec_result.ExecResult:
10161006
:param remote: SSH connection instance
10171007
:return: execution result
10181008
"""
1019-
async_result: SshExecuteAsyncResult = remote._execute_async( # pylint: disable=protected-access
1009+
# pylint: disable=protected-access
1010+
cmd_for_log: str = remote._mask_command(cmd=command, log_mask_re=log_mask_re)
1011+
1012+
remote.logger.log(
1013+
level=logging.INFO if verbose else logging.DEBUG, msg=f"Executing command:\n{cmd_for_log!r}\n"
1014+
)
1015+
async_result: SshExecuteAsyncResult = remote._execute_async(
10201016
command, stdin=stdin, log_mask_re=log_mask_re, **kwargs
10211017
)
1018+
# pylint: enable=protected-access
10221019

10231020
async_result.interface.status_event.wait(timeout)
10241021
exit_code = async_result.interface.recv_exit_status()
10251022

1026-
# pylint: disable=protected-access
1027-
cmd_for_log: str = remote._mask_command(cmd=command, log_mask_re=log_mask_re)
1028-
# pylint: enable=protected-access
1029-
10301023
res = exec_result.ExecResult(cmd=cmd_for_log, stdin=stdin, started=async_result.started)
10311024
res.read_stdout(src=async_result.stdout)
10321025
res.read_stderr(src=async_result.stderr)

exec_helpers/api.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -246,8 +246,6 @@ def _execute_async(
246246
stdin: typing.Union[bytes, str, bytearray, None] = None,
247247
open_stdout: bool = True,
248248
open_stderr: bool = True,
249-
verbose: bool = False,
250-
log_mask_re: typing.Optional[str] = None,
251249
*,
252250
chroot_path: typing.Optional[str] = None,
253251
**kwargs: typing.Any,
@@ -262,11 +260,6 @@ def _execute_async(
262260
:type open_stdout: bool
263261
:param open_stderr: open STDERR stream for read
264262
:type open_stderr: bool
265-
:param verbose: produce verbose log record on command call
266-
:type verbose: bool
267-
:param log_mask_re: regex lookup rule to mask command for logger.
268-
all MATCHED groups will be replaced by '<*masked*>'
269-
:type log_mask_re: typing.Optional[str]
270263
:param chroot_path: chroot path override
271264
:type chroot_path: typing.Optional[str]
272265
:param kwargs: additional parameters for call.
@@ -287,6 +280,7 @@ def _execute_async(
287280
.. versionchanged:: 1.2.0 stdin data
288281
.. versionchanged:: 2.1.0 Use typed NamedTuple as result
289282
.. versionchanged:: 4.1.0 support chroot
283+
.. versionchanged:: 6.0.0 command start log moved to execute, verbose and log_mask_re removed as unused
290284
"""
291285

292286
@abc.abstractmethod
@@ -357,6 +351,10 @@ def execute(
357351
.. versionchanged:: 1.2.0 default timeout 1 hour
358352
.. versionchanged:: 2.1.0 Allow parallel calls
359353
"""
354+
cmd_for_log: str = self._mask_command(cmd=command, log_mask_re=log_mask_re)
355+
356+
self.logger.log(level=logging.INFO if verbose else logging.DEBUG, msg=f"Executing command:\n{cmd_for_log!r}\n")
357+
360358
async_result: ExecuteAsyncResult = self._execute_async(
361359
command, verbose=verbose, log_mask_re=log_mask_re, stdin=stdin, **kwargs
362360
)

exec_helpers/async_api/api.py

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -141,8 +141,6 @@ async def _execute_async( # type: ignore
141141
stdin: typing.Union[str, bytes, bytearray, None] = None,
142142
open_stdout: bool = True,
143143
open_stderr: bool = True,
144-
verbose: bool = False,
145-
log_mask_re: typing.Optional[str] = None,
146144
*,
147145
chroot_path: typing.Optional[str] = None,
148146
**kwargs: typing.Any,
@@ -157,11 +155,6 @@ async def _execute_async( # type: ignore
157155
:type open_stdout: bool
158156
:param open_stderr: open STDERR stream for read
159157
:type open_stderr: bool
160-
:param verbose: produce verbose log record on command call
161-
:type verbose: bool
162-
:param log_mask_re: regex lookup rule to mask command for logger.
163-
all MATCHED groups will be replaced by '<*masked*>'
164-
:type log_mask_re: typing.Optional[str]
165158
:param chroot_path: chroot path override
166159
:type chroot_path: typing.Optional[str]
167160
:param kwargs: additional parameters for call.
@@ -209,6 +202,10 @@ async def execute( # type: ignore
209202
:rtype: ExecResult
210203
:raises ExecHelperTimeoutError: Timeout exceeded
211204
"""
205+
cmd_for_log: str = self._mask_command(cmd=command, log_mask_re=log_mask_re)
206+
207+
self.logger.log(level=logging.INFO if verbose else logging.DEBUG, msg=f"Executing command:\n{cmd_for_log!r}\n")
208+
212209
async_result: api.ExecuteAsyncResult = await self._execute_async(
213210
command, verbose=verbose, log_mask_re=log_mask_re, stdin=stdin, **kwargs
214211
)

exec_helpers/async_api/subprocess_runner.py

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -169,8 +169,6 @@ async def _execute_async( # type: ignore
169169
stdin: typing.Union[str, bytes, bytearray, None] = None,
170170
open_stdout: bool = True,
171171
open_stderr: bool = True,
172-
verbose: bool = False,
173-
log_mask_re: typing.Optional[str] = None,
174172
*,
175173
chroot_path: typing.Optional[str] = None,
176174
cwd: typing.Optional[typing.Union[str, bytes]] = None,
@@ -189,11 +187,6 @@ async def _execute_async( # type: ignore
189187
:type open_stdout: bool
190188
:param open_stderr: open STDERR stream for read
191189
:type open_stderr: bool
192-
:param verbose: produce verbose log record on command call
193-
:type verbose: bool
194-
:param log_mask_re: regex lookup rule to mask command for logger.
195-
all MATCHED groups will be replaced by '<*masked*>'
196-
:type log_mask_re: typing.Optional[str]
197190
:param chroot_path: chroot path override
198191
:type chroot_path: typing.Optional[str]
199192
:param cwd: Sets the current directory before the child is executed.
@@ -215,12 +208,6 @@ async def _execute_async( # type: ignore
215208
)
216209
:raises OSError: impossible to process STDIN
217210
"""
218-
cmd_for_log: str = self._mask_command(cmd=command, log_mask_re=log_mask_re)
219-
220-
self.logger.log(
221-
level=logging.INFO if verbose else logging.DEBUG, msg=_log_templates.CMD_EXEC.format(cmd=cmd_for_log)
222-
)
223-
224211
started = datetime.datetime.utcnow()
225212

226213
process: asyncio.subprocess.Process = await asyncio.create_subprocess_shell( # pylint: disable=no-member

exec_helpers/subprocess_runner.py

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -188,8 +188,6 @@ def _execute_async( # pylint: disable=arguments-differ
188188
stdin: typing.Union[str, bytes, bytearray, None] = None,
189189
open_stdout: bool = True,
190190
open_stderr: bool = True,
191-
verbose: bool = False,
192-
log_mask_re: typing.Optional[str] = None,
193191
*,
194192
chroot_path: typing.Optional[str] = None,
195193
cwd: typing.Optional[typing.Union[str, bytes]] = None,
@@ -208,11 +206,6 @@ def _execute_async( # pylint: disable=arguments-differ
208206
:type open_stdout: bool
209207
:param open_stderr: open STDERR stream for read
210208
:type open_stderr: bool
211-
:param verbose: produce verbose log record on command call
212-
:type verbose: bool
213-
:param log_mask_re: regex lookup rule to mask command for logger.
214-
all MATCHED groups will be replaced by '<*masked*>'
215-
:type log_mask_re: typing.Optional[str]
216209
:param chroot_path: chroot path override
217210
:type chroot_path: typing.Optional[str]
218211
:param cwd: Sets the current directory before the child is executed.
@@ -239,12 +232,6 @@ def _execute_async( # pylint: disable=arguments-differ
239232
.. versionchanged:: 3.2.0 Expose cwd and env as optional keyword-only arguments
240233
.. versionchanged:: 4.1.0 support chroot
241234
"""
242-
cmd_for_log: str = self._mask_command(cmd=command, log_mask_re=log_mask_re)
243-
244-
self.logger.log(
245-
level=logging.INFO if verbose else logging.DEBUG, msg=_log_templates.CMD_EXEC.format(cmd=cmd_for_log)
246-
)
247-
248235
started = datetime.datetime.utcnow()
249236

250237
process = subprocess.Popen(

test/async_api/test_subprocess.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,6 @@ async def test_001_execute_async(create_subprocess_shell, logger, run_parameters
252252
if stdin is not None:
253253
res.interface.stdin.write.assert_called_once_with(stdin)
254254
res.interface.stdin.drain.assert_awaited_once()
255-
logger.log.assert_called_once_with(level=logging.DEBUG, msg=command_log)
256255

257256

258257
async def test_002_execute(create_subprocess_shell, logger, exec_result, run_parameters) -> None:
@@ -261,6 +260,7 @@ async def test_002_execute(create_subprocess_shell, logger, exec_result, run_par
261260
res = await runner.execute(command, stdin=run_parameters["stdin"])
262261
assert isinstance(res, exec_helpers.async_api.ExecResult)
263262
assert res == exec_result
263+
assert logger.mock_calls[0] == mock.call.log(level=logging.DEBUG, msg=command_log)
264264
assert logger.mock_calls[-1] == mock.call.log(
265265
level=logging.DEBUG, msg=f"Command {res.cmd!r} exit code: {res.exit_code!s}"
266266
)

test/test_ssh_client_execute.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ def execute(mocker, exec_result):
249249
return mocker.patch("exec_helpers.ssh_client.SSHClient.execute", name="execute", return_value=exec_result)
250250

251251

252-
def test_001_execute_async(ssh, paramiko_ssh_client, ssh_transport_channel, chan_makefile, run_parameters, get_logger):
252+
def test_001_execute_async(ssh, paramiko_ssh_client, ssh_transport_channel, chan_makefile, run_parameters):
253253
open_stdout = run_parameters["open_stdout"]
254254
open_stderr = run_parameters["open_stderr"]
255255
get_pty = run_parameters.get("get_pty", False)
@@ -316,11 +316,9 @@ def test_001_execute_async(ssh, paramiko_ssh_client, ssh_transport_channel, chan
316316
if stdin:
317317
res.stdin.write.assert_called_with(stdin.encode("utf-8"))
318318
res.stdin.flush.assert_called_once()
319-
log = get_logger(ssh.__class__.__name__).getChild(f"{host}:{port}")
320-
log.log.assert_called_once_with(level=logging.DEBUG, msg=command_log)
321319

322320

323-
def test_002_execute(ssh, ssh_transport_channel, exec_result, run_parameters) -> None:
321+
def test_002_execute(ssh, ssh_transport_channel, exec_result, run_parameters, get_logger) -> None:
324322
kwargs = {}
325323
if "get_pty" in run_parameters:
326324
kwargs["get_pty"] = run_parameters["get_pty"]
@@ -339,6 +337,8 @@ def test_002_execute(ssh, ssh_transport_channel, exec_result, run_parameters) ->
339337
assert isinstance(res, exec_helpers.ExecResult)
340338
assert res == exec_result
341339
ssh_transport_channel.assert_has_calls((mock.call.status_event.is_set(),))
340+
log = get_logger(ssh.__class__.__name__).getChild(f"{host}:22")
341+
assert log.mock_calls[0] == mock.call.log(level=logging.DEBUG, msg=command_log)
342342

343343

344344
def test_003_context_manager(ssh, exec_result, run_parameters, mocker) -> None:

test/test_subprocess.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,6 @@ def test_001_execute_async(popen, subprocess_logger, run_parameters) -> None:
226226
if stdin is not None:
227227
res.interface.stdin.write.assert_called_once_with(stdin)
228228
res.interface.stdin.close.assert_called_once()
229-
subprocess_logger.log.assert_called_once_with(level=logging.DEBUG, msg=command_log)
230229

231230

232231
def test_002_execute(popen, subprocess_logger, exec_result, run_parameters) -> None:
@@ -241,6 +240,7 @@ def test_002_execute(popen, subprocess_logger, exec_result, run_parameters) -> N
241240
assert isinstance(res, exec_helpers.ExecResult)
242241
assert res == exec_result
243242
popen().wait.assert_called_once_with(timeout=default_timeout)
243+
assert subprocess_logger.mock_calls[0] == mock.call.log(level=logging.DEBUG, msg=command_log)
244244

245245

246246
def test_003_context_manager(mocker, popen, subprocess_logger, exec_result, run_parameters) -> None:

0 commit comments

Comments
 (0)