Merge pull request 'Miscellaneous ssh fixes.' (#3487) from misc-fixes into main

Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3487
This commit is contained in:
Mic92
2025-05-04 08:51:31 +00:00
2 changed files with 18 additions and 14 deletions

View File

@@ -244,12 +244,12 @@ class TimeTable:
# Print in default color # Print in default color
print(f"Took {v} for command: '{k}'") print(f"Took {v} for command: '{k}'")
def add(self, cmd: str, time: float) -> None: def add(self, cmd: str, duration: float) -> None:
with self.lock: with self.lock:
if cmd in self.table: if cmd in self.table:
self.table[cmd] += time self.table[cmd] += duration
else: else:
self.table[cmd] = time self.table[cmd] = duration
TIME_TABLE = None TIME_TABLE = None
@@ -259,7 +259,7 @@ if os.environ.get("CLAN_CLI_PERF"):
@dataclass @dataclass
class RunOpts: class RunOpts:
input: bytes | None = None input: IO[bytes] | bytes | None = None
stdout: IO[bytes] | None = None stdout: IO[bytes] | None = None
stderr: IO[bytes] | None = None stderr: IO[bytes] | None = None
env: dict[str, str] | None = None env: dict[str, str] | None = None
@@ -329,7 +329,7 @@ def run(
if options.requires_root_perm: if options.requires_root_perm:
cmd = cmd_with_root(cmd, options.graphical_perm) cmd = cmd_with_root(cmd, options.graphical_perm)
if options.input: if options.input and isinstance(options.input, bytes):
if any(not ch.isprintable() for ch in options.input.decode("ascii", "replace")): if any(not ch.isprintable() for ch in options.input.decode("ascii", "replace")):
filtered_input = "<<binary_blob>>" filtered_input = "<<binary_blob>>"
else: else:
@@ -344,7 +344,7 @@ def run(
start = timeit.default_timer() start = timeit.default_timer()
with ExitStack() as stack: with ExitStack() as stack:
stdin = subprocess.PIPE if options.input is not None else None stdin = subprocess.PIPE if isinstance(options.input, bytes) else options.input
process = stack.enter_context( process = stack.enter_context(
subprocess.Popen( subprocess.Popen(
cmd, cmd,
@@ -364,13 +364,18 @@ def run(
else: else:
stack.enter_context(terminate_process_group(process)) stack.enter_context(terminate_process_group(process))
if isinstance(options.input, bytes):
input_bytes = options.input
else:
input_bytes = None
stdout_buf, stderr_buf = handle_io( stdout_buf, stderr_buf = handle_io(
process, process,
options.log, options.log,
prefix=options.prefix, prefix=options.prefix,
msg_color=options.msg_color, msg_color=options.msg_color,
timeout=options.timeout, timeout=options.timeout,
input_bytes=options.input, input_bytes=input_bytes,
stdout=options.stdout, stdout=options.stdout,
stderr=options.stderr, stderr=options.stderr,
) )
@@ -418,6 +423,3 @@ def run_no_stdout(
cmd, cmd,
opts, opts,
) )
# type: ignore

View File

@@ -124,6 +124,9 @@ class Host:
if extra_env is None: if extra_env is None:
extra_env = {} extra_env = {}
if opts is None:
opts = RunOpts()
# If we are not root and we need to become root, prepend sudo # If we are not root and we need to become root, prepend sudo
sudo = "" sudo = ""
if become_root and self.user != "root": if become_root and self.user != "root":
@@ -134,11 +137,10 @@ class Host:
for k, v in extra_env.items(): for k, v in extra_env.items():
env_vars.append(f"{shlex.quote(k)}={shlex.quote(v)}") env_vars.append(f"{shlex.quote(k)}={shlex.quote(v)}")
if opts is None: if opts.prefix is None:
opts = RunOpts()
else:
opts.needs_user_terminal = True
opts.prefix = self.command_prefix opts.prefix = self.command_prefix
# always set needs_user_terminal to True because ssh asks for passwords
opts.needs_user_terminal = True
if opts.cwd is not None: if opts.cwd is not None:
msg = "cwd is not supported for remote commands" msg = "cwd is not supported for remote commands"