You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ansible/test/lib/ansible_test/_internal/commands/shell/__init__.py

91 lines
2.3 KiB
Python

"""Open a shell prompt inside an ansible-test environment."""
from __future__ import annotations
import os
import typing as t
from ...util import (
ApplicationError,
display,
)
from ...config import (
ShellConfig,
)
from ...executor import (
Delegate,
)
from ...connections import (
Connection,
LocalConnection,
SshConnection,
)
from ...host_profiles import (
ControllerProfile,
PosixProfile,
SshTargetHostProfile,
)
from ...provisioning import (
prepare_profiles,
)
from ...host_configs import (
ControllerConfig,
OriginConfig,
)
def command_shell(args): # type: (ShellConfig) -> None
"""Entry point for the `shell` command."""
if args.raw and isinstance(args.targets[0], ControllerConfig):
raise ApplicationError('The --raw option has no effect on the controller.')
host_state = prepare_profiles(args, skip_setup=args.raw) # shell
if args.delegate:
raise Delegate(host_state=host_state)
if args.raw and not isinstance(args.controller, OriginConfig):
display.warning('The --raw option will only be applied to the target.')
target_profile = t.cast(SshTargetHostProfile, host_state.target_profiles[0])
if isinstance(target_profile, ControllerProfile):
# run the shell locally unless a target was requested
con = LocalConnection(args) # type: Connection
else:
# a target was requested, connect to it over SSH
con = target_profile.get_controller_target_connections()[0]
if isinstance(con, SshConnection) and args.raw:
cmd = [] # type: t.List[str]
elif isinstance(target_profile, PosixProfile):
cmd = []
if args.raw:
shell = 'sh' # shell required for non-ssh connection
else:
shell = 'bash'
python = target_profile.python # make sure the python interpreter has been initialized before opening a shell
display.info(f'Target Python {python.version} is at: {python.path}')
optional_vars = (
'TERM', # keep backspace working
)
env = {name: os.environ[name] for name in optional_vars if name in os.environ}
if env:
cmd = ['/usr/bin/env'] + [f'{name}={value}' for name, value in env.items()]
cmd += [shell, '-i']
else:
cmd = []
con.run(cmd)