2020-08-13 11:00:32 +00:00
|
|
|
# system
|
|
|
|
import logging
|
|
|
|
import subprocess
|
|
|
|
|
|
|
|
# local
|
2020-08-19 15:21:38 +00:00
|
|
|
from ..subcommand import ServiceCommand
|
2020-08-19 14:10:56 +00:00
|
|
|
from ..config import LoadedConfig
|
2020-08-13 11:00:32 +00:00
|
|
|
|
2020-08-19 14:10:56 +00:00
|
|
|
|
|
|
|
def _service_has_executable(project, service, exe_name):
|
2020-08-17 08:08:29 +00:00
|
|
|
"""
|
2020-08-19 14:10:56 +00:00
|
|
|
Test if service in project has an executable exe_name in its PATH.
|
2020-08-17 08:08:29 +00:00
|
|
|
Requires /bin/sh and which.
|
|
|
|
"""
|
|
|
|
|
2020-08-13 11:00:32 +00:00
|
|
|
try:
|
|
|
|
# test if desired shell exists
|
2020-08-19 15:09:43 +00:00
|
|
|
project.compose_run(
|
|
|
|
['exec', service, '/bin/sh', '-c', f"which {exe_name}"],
|
|
|
|
check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL
|
|
|
|
)
|
2020-08-13 11:00:32 +00:00
|
|
|
return True
|
|
|
|
|
2020-08-17 08:08:29 +00:00
|
|
|
except subprocess.CalledProcessError as e:
|
2020-08-13 11:00:32 +00:00
|
|
|
# fallback
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
2020-08-19 14:10:56 +00:00
|
|
|
def _find_shell(args, project, service):
|
|
|
|
"""find first working shell (provided by config and args) in service in project"""
|
2020-08-17 08:08:29 +00:00
|
|
|
|
|
|
|
# builtin shells: as a last resort, fallback to '/bin/sh' and 'sh'
|
2020-08-15 02:06:25 +00:00
|
|
|
shells = ['/bin/sh', 'sh']
|
|
|
|
|
|
|
|
# load favorite shells from config
|
2020-08-19 14:10:56 +00:00
|
|
|
config = LoadedConfig.get()
|
2020-08-15 02:06:25 +00:00
|
|
|
if config['runtime:shells']:
|
|
|
|
shells = [*config['runtime:shells'], *shells]
|
|
|
|
|
|
|
|
# consider shell from args
|
|
|
|
if args.shell:
|
|
|
|
shells = [args.shell, *shells]
|
|
|
|
|
|
|
|
logging.debug(f"Shells priority: {shells}")
|
|
|
|
|
|
|
|
# actually try shells
|
|
|
|
for i, shell in enumerate(shells):
|
2020-08-19 14:10:56 +00:00
|
|
|
if _service_has_executable(project, service, shell):
|
2020-08-17 08:08:29 +00:00
|
|
|
# found working shell
|
2020-08-15 02:06:25 +00:00
|
|
|
logging.debug(f"Using shell '{shell}'")
|
|
|
|
return shell
|
2020-08-17 08:08:29 +00:00
|
|
|
|
2020-08-15 02:06:25 +00:00
|
|
|
elif i + 1 < len(shells):
|
2020-08-17 08:08:29 +00:00
|
|
|
# try next in list
|
2020-08-15 02:06:25 +00:00
|
|
|
logging.info(f"Shell '{shell}' not found in container, trying '{shells[i+1]}'")
|
2020-08-17 08:08:29 +00:00
|
|
|
|
|
|
|
elif args.shell:
|
|
|
|
# not found, user suggestion provided
|
|
|
|
logging.warning(f"Could not find any working shell in this container. "
|
|
|
|
f"Launching provided '{args.shell}' nevertheless. "
|
|
|
|
f"Don't get mad if this fails!")
|
|
|
|
return args.shell
|
|
|
|
|
2020-08-15 02:06:25 +00:00
|
|
|
else:
|
|
|
|
# not found, search exhausted
|
2020-08-17 08:08:29 +00:00
|
|
|
logging.error(f"Could not find any working shell among '{shells}' in this container. "
|
|
|
|
f"Please suggest a shell using the '-s SHELL' command line option!")
|
2020-08-15 02:06:25 +00:00
|
|
|
return None
|
|
|
|
|
|
|
|
|
2020-08-15 00:06:55 +00:00
|
|
|
class ShCommand(ServiceCommand):
|
2020-08-17 08:08:29 +00:00
|
|
|
"""kiwi sh"""
|
|
|
|
|
2020-08-13 11:00:32 +00:00
|
|
|
def __init__(self):
|
|
|
|
super().__init__(
|
2020-08-17 10:58:18 +00:00
|
|
|
'sh', num_projects=1, num_services=1,
|
2020-08-19 14:23:52 +00:00
|
|
|
action="Spawning shell in",
|
2020-08-13 12:26:49 +00:00
|
|
|
description="Spawn shell inside a project's service"
|
2020-08-13 11:00:32 +00:00
|
|
|
)
|
|
|
|
|
2020-08-17 10:58:18 +00:00
|
|
|
# -s argument: Select shell
|
2020-08-13 11:00:32 +00:00
|
|
|
self._sub_parser.add_argument(
|
2020-08-15 02:06:25 +00:00
|
|
|
'-s', '--shell', type=str,
|
2020-08-13 11:00:32 +00:00
|
|
|
help="shell to spawn"
|
|
|
|
)
|
|
|
|
|
2020-08-19 14:10:56 +00:00
|
|
|
def _run_services(self, runner, args, project, services):
|
|
|
|
service = services[0]
|
|
|
|
shell = _find_shell(args, project, service)
|
2020-08-13 11:00:32 +00:00
|
|
|
|
2020-08-17 08:08:29 +00:00
|
|
|
if shell is not None:
|
2020-08-15 02:06:25 +00:00
|
|
|
# spawn shell
|
2020-08-19 15:09:43 +00:00
|
|
|
project.compose_run(['exec', service, shell])
|
2020-08-17 13:00:05 +00:00
|
|
|
return True
|
|
|
|
|
|
|
|
return False
|