1
0
Fork 0
mirror of https://github.com/yavook/kiwi-scp.git synced 2024-11-25 05:53:00 +00:00
kiwi-scp/kiwi_scp/subcommands/shell.py

105 lines
3.1 KiB
Python
Raw Normal View History

2020-08-13 11:00:32 +00:00
# system
import logging
import subprocess
2021-09-22 01:06:43 +00:00
from ..config import LoadedConfig
2020-08-13 11:00:32 +00:00
# local
2020-08-19 15:21:38 +00:00
from ..subcommand import ServiceCommand
2020-08-13 11:00:32 +00:00
def _service_has_executable(project, service, exe_name):
2020-08-17 08:08:29 +00:00
"""
Test if service in project has an executable exe_name in its PATH.
Requires /bin/sh.
2020-08-17 08:08:29 +00:00
"""
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"command -v {exe_name}"],
2020-08-19 15:09:43 +00:00
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
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'
shells = ['/bin/sh', 'sh']
# load favorite shells from config
config = LoadedConfig.get()
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):
if _service_has_executable(project, service, shell):
2020-08-17 08:08:29 +00:00
# found working shell
logging.debug(f"Using shell '{shell}'")
return shell
2020-08-17 08:08:29 +00:00
elif i + 1 < len(shells):
2020-08-17 08:08:29 +00:00
# try next in list
2021-09-22 01:06:43 +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
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!")
return None
2020-08-20 12:15:38 +00:00
class ShellCommand(ServiceCommand):
"""kiwi shell"""
2020-08-17 08:08:29 +00:00
2020-08-13 11:00:32 +00:00
def __init__(self):
super().__init__(
2020-08-20 12:15:38 +00:00
'shell', 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
)
# -s argument: Select shell
2020-08-13 11:00:32 +00:00
self._sub_parser.add_argument(
'-s', '--shell', type=str,
2020-08-13 11:00:32 +00:00
help="shell to spawn"
)
2020-08-24 12:49:17 +00:00
# -u argument: Run as user
self._sub_parser.add_argument(
'-u', '--user', type=str,
help="container user to run shell"
)
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-24 12:49:17 +00:00
user_args = ['-u', args.user] if args.user else []
2020-08-17 08:08:29 +00:00
if shell is not None:
# spawn shell
2020-08-24 12:49:17 +00:00
project.compose_run(['exec', *user_args, service, shell])
2020-08-17 13:00:05 +00:00
return True
return False