diff options
Diffstat (limited to 'test/lib/ansible_test/_internal/become.py')
-rw-r--r-- | test/lib/ansible_test/_internal/become.py | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/test/lib/ansible_test/_internal/become.py b/test/lib/ansible_test/_internal/become.py new file mode 100644 index 0000000..e653959 --- /dev/null +++ b/test/lib/ansible_test/_internal/become.py @@ -0,0 +1,108 @@ +"""Become abstraction for interacting with test hosts.""" +from __future__ import annotations + +import abc +import shlex + +from .util import ( + get_subclasses, +) + + +class Become(metaclass=abc.ABCMeta): + """Base class for become implementations.""" + @classmethod + def name(cls) -> str: + """The name of this plugin.""" + return cls.__name__.lower() + + @property + @abc.abstractmethod + def method(self) -> str: + """The name of the Ansible become plugin that is equivalent to this.""" + + @abc.abstractmethod + def prepare_command(self, command: list[str]) -> list[str]: + """Return the given command, if any, with privilege escalation.""" + + +class Doas(Become): + """Become using 'doas'.""" + @property + def method(self) -> str: + """The name of the Ansible become plugin that is equivalent to this.""" + raise NotImplementedError('Ansible has no built-in doas become plugin.') + + def prepare_command(self, command: list[str]) -> list[str]: + """Return the given command, if any, with privilege escalation.""" + become = ['doas', '-n'] + + if command: + become.extend(['sh', '-c', shlex.join(command)]) + else: + become.extend(['-s']) + + return become + + +class DoasSudo(Doas): + """Become using 'doas' in ansible-test and then after bootstrapping use 'sudo' for other ansible commands.""" + @classmethod + def name(cls) -> str: + """The name of this plugin.""" + return 'doas_sudo' + + @property + def method(self) -> str: + """The name of the Ansible become plugin that is equivalent to this.""" + return 'sudo' + + +class Su(Become): + """Become using 'su'.""" + @property + def method(self) -> str: + """The name of the Ansible become plugin that is equivalent to this.""" + return 'su' + + def prepare_command(self, command: list[str]) -> list[str]: + """Return the given command, if any, with privilege escalation.""" + become = ['su', '-l', 'root'] + + if command: + become.extend(['-c', shlex.join(command)]) + + return become + + +class SuSudo(Su): + """Become using 'su' in ansible-test and then after bootstrapping use 'sudo' for other ansible commands.""" + @classmethod + def name(cls) -> str: + """The name of this plugin.""" + return 'su_sudo' + + @property + def method(self) -> str: + """The name of the Ansible become plugin that is equivalent to this.""" + return 'sudo' + + +class Sudo(Become): + """Become using 'sudo'.""" + @property + def method(self) -> str: + """The name of the Ansible become plugin that is equivalent to this.""" + return 'sudo' + + def prepare_command(self, command: list[str]) -> list[str]: + """Return the given command, if any, with privilege escalation.""" + become = ['sudo', '-in'] + + if command: + become.extend(['sh', '-c', shlex.join(command)]) + + return become + + +SUPPORTED_BECOME_METHODS = {cls.name(): cls for cls in get_subclasses(Become)} |