Add loader and sceanrio runner interfaces, add support for local scenario

Signed-off-by: Andrey Berezin <a.berezin@yadro.com>
This commit is contained in:
Andrey Berezin 2023-06-26 16:45:34 +03:00 committed by Andrey Berezin
parent 13ea25bff5
commit 182bd6ab36
19 changed files with 786 additions and 384 deletions

View file

@ -7,7 +7,23 @@ class SudoInspector(CommandInspector):
If command is already prepended with sudo, then has no effect.
"""
def inspect(self, command: str) -> str:
def inspect(self, original_command: str, command: str) -> str:
if not command.startswith("sudo"):
return f"sudo {command}"
return command
class SuInspector(CommandInspector):
"""Allows to run command as another user via sudo su call
If command is already prepended with sudo su, then has no effect.
"""
def __init__(self, user: str) -> None:
self.user = user
def inspect(self, original_command: str, command: str) -> str:
if not original_command.startswith("sudo su"):
cmd = original_command.replace('"', '\\"').replace("\$", "\\\\\\$")
return f'sudo su - {self.user} -c "{cmd}"'
return original_command

View file

@ -22,11 +22,12 @@ class CommandInspector(ABC):
"""Interface of inspector that processes command text before execution."""
@abstractmethod
def inspect(self, command: str) -> str:
def inspect(self, original_command: str, command: str) -> str:
"""Transforms command text and returns modified command.
Args:
command: Command to transform with this inspector.
original_command: Untransformed command to transform with this inspector. Depending on type of the inspector it might be required to modify original command
Returns:
Transformed command text.
@ -47,6 +48,7 @@ class CommandOptions:
check: Controls whether to check return code of the command. Set to False to
ignore non-zero return codes.
no_log: Do not print output to logger if True.
extra_inspectors: Exctra command inspectors to process command
"""
interactive_inputs: Optional[list[InteractiveInput]] = None
@ -54,6 +56,7 @@ class CommandOptions:
timeout: Optional[int] = None
check: bool = True
no_log: bool = False
extra_inspectors: Optional[list[CommandInspector]] = None
def __post_init__(self):
if self.timeout is None:

View file

@ -24,8 +24,10 @@ class LocalShell(Shell):
# If no options were provided, use default options
options = options or CommandOptions()
for inspector in self.command_inspectors:
command = inspector.inspect(command)
original_command = command
extra_inspectors = options.extra_inspectors if options.extra_inspectors else []
for inspector in [*self.command_inspectors, *extra_inspectors]:
command = inspector.inspect(original_command, command)
logger.info(f"Executing command: {command}")
if options.interactive_inputs:

View file

@ -126,8 +126,10 @@ class SSHShell(Shell):
def exec(self, command: str, options: Optional[CommandOptions] = None) -> CommandResult:
options = options or CommandOptions()
for inspector in self.command_inspectors:
command = inspector.inspect(command)
original_command = command
extra_inspectors = options.extra_inspectors if options.extra_inspectors else []
for inspector in [*self.command_inspectors, *extra_inspectors]:
command = inspector.inspect(original_command, command)
if options.interactive_inputs:
result = self._exec_interactive(command, options)