mirror of
ssh://git.janware.com/janware/proj/jw-pkg
synced 2026-04-24 17:23:36 +02:00
lib.SSHClient.run_cmd(): Align prototype with EC
Align the prototype of SSHClient.run_cmd() to ExecContext.run(). This is a push towards making the SSHClient code an ExceContext, too. Some arguments still log a warning or outright raise NotImplementedError. Signed-off-by: Jan Lindemann <jan@janware.com>
This commit is contained in:
parent
666f778e05
commit
989e2c93e3
1 changed files with 39 additions and 6 deletions
|
|
@ -5,6 +5,7 @@ from typing import Any
|
||||||
import os, abc, shlex, sys
|
import os, abc, shlex, sys
|
||||||
|
|
||||||
from .util import run_cmd
|
from .util import run_cmd
|
||||||
|
from .log import *
|
||||||
from .ExecContext import Result
|
from .ExecContext import Result
|
||||||
|
|
||||||
class SSHClient(abc.ABC):
|
class SSHClient(abc.ABC):
|
||||||
|
|
@ -38,10 +39,38 @@ class SSHClient(abc.ABC):
|
||||||
|
|
||||||
async def run_cmd(
|
async def run_cmd(
|
||||||
self,
|
self,
|
||||||
cmd: list[str],
|
args: list[str],
|
||||||
output_encoding: str|None = None,
|
wd: str|None = None,
|
||||||
|
throw: bool = True,
|
||||||
|
verbose: bool = False,
|
||||||
|
cmd_input: str|None = None,
|
||||||
|
env: dict[str, str]|None = None,
|
||||||
|
title: str=None,
|
||||||
|
output_encoding: str|None = None, # None => unchanged; "bytes" => return raw bytes
|
||||||
) -> Result:
|
) -> Result:
|
||||||
stdout_b, stderr_b, status = await self._run_cmd(cmd)
|
|
||||||
|
if wd is not None:
|
||||||
|
args = ['cd', wd, '&&', *args]
|
||||||
|
|
||||||
|
if verbose:
|
||||||
|
log(WARNING, f'Verbose SSH commands are not yet implemented')
|
||||||
|
|
||||||
|
interactive = (
|
||||||
|
cmd_input == "mode:interactive"
|
||||||
|
or (cmd_input == "mode:auto" and sys.stdin.isatty())
|
||||||
|
)
|
||||||
|
|
||||||
|
if interactive:
|
||||||
|
raise NotImplementedError('Interactive SSH is not yet implemented')
|
||||||
|
|
||||||
|
if env is not None:
|
||||||
|
raise NotImplementedError('Passing an environment to SSH commands is not yet implemented')
|
||||||
|
|
||||||
|
stdout_b, stderr_b, status = await self._run_cmd(args, cmd_input=cmd_input)
|
||||||
|
|
||||||
|
if throw and status:
|
||||||
|
raise Exception(f'SSH command returned error {status}')
|
||||||
|
|
||||||
if output_encoding == 'bytes':
|
if output_encoding == 'bytes':
|
||||||
return stdout_b, stderr_b, status
|
return stdout_b, stderr_b, status
|
||||||
|
|
||||||
|
|
@ -49,6 +78,7 @@ class SSHClient(abc.ABC):
|
||||||
output_encoding = sys.stdout.encoding or "utf-8"
|
output_encoding = sys.stdout.encoding or "utf-8"
|
||||||
stdout_s = stdout_b.decode(output_encoding, errors="replace") if stdout_b is not None else None
|
stdout_s = stdout_b.decode(output_encoding, errors="replace") if stdout_b is not None else None
|
||||||
stderr_s = stderr_b.decode(output_encoding, errors="replace") if stderr_b is not None else None
|
stderr_s = stderr_b.decode(output_encoding, errors="replace") if stderr_b is not None else None
|
||||||
|
|
||||||
return stdout_s, stderr_s, status
|
return stdout_s, stderr_s, status
|
||||||
|
|
||||||
class SSHClientInternal(SSHClient): # export
|
class SSHClientInternal(SSHClient): # export
|
||||||
|
|
@ -79,8 +109,10 @@ class SSHClientInternal(SSHClient): # export
|
||||||
def __scp(self):
|
def __scp(self):
|
||||||
return SCPClient(self.__ssh.get_transport())
|
return SCPClient(self.__ssh.get_transport())
|
||||||
|
|
||||||
async def _run_cmd(self, cmd: list[str]) -> Result:
|
async def _run_cmd(self, cmd: list[str], cmd_input: str|None) -> Result:
|
||||||
stdin, stdout, stderr = self.__ssh.exec_command(shlex.join(cmd), timeout=self.__timeout)
|
stdin, stdout, stderr = self.__ssh.exec_command(shlex.join(cmd), timeout=self.__timeout)
|
||||||
|
if cmd_input is not None:
|
||||||
|
stdin.write(cmd_input)
|
||||||
exit_status = stdout.channel.recv_exit_status()
|
exit_status = stdout.channel.recv_exit_status()
|
||||||
return stdout.read(), stderr.read(), exit_status
|
return stdout.read(), stderr.read(), exit_status
|
||||||
|
|
||||||
|
|
@ -113,9 +145,10 @@ class SSHClientCmd(SSHClient): # export
|
||||||
self.__askpass_orig[key] = os.getenv(key)
|
self.__askpass_orig[key] = os.getenv(key)
|
||||||
os.environ[key] = val
|
os.environ[key] = val
|
||||||
|
|
||||||
async def _run_cmd(self, cmd: list[str]) -> Result:
|
async def _run_cmd(self, cmd: list[str], cmd_input: str|None) -> Result:
|
||||||
self.__init_askpass()
|
self.__init_askpass()
|
||||||
return await run_cmd(['ssh', self.hostname, shlex.join(cmd)], output_encoding='bytes')
|
return await run_cmd(['ssh', self.hostname, shlex.join(cmd)],
|
||||||
|
output_encoding='bytes', cmd_input=cmd_input)
|
||||||
|
|
||||||
def ssh_client(*args, **kwargs) -> SSHClient: # export
|
def ssh_client(*args, **kwargs) -> SSHClient: # export
|
||||||
try:
|
try:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue