Skip to content
Snippets Groups Projects
Commit 4134424b authored by Martin Mareš's avatar Martin Mareš
Browse files

More commands

parent 600c0cd8
Branches
No related tags found
No related merge requests found
- colors
- status: do not exit on non-zero return code
- "shc CONTAINER start" vs. "shc CONTAINER shell"
......@@ -25,10 +25,12 @@ def progress(msg: str) -> None:
print(msg, file=sys.stderr, end="", flush=True)
def run_command(args: List[str], *rest, **kwargs) -> None:
res = subprocess.run(args, *rest, **kwargs)
def run_command(cmd: List[str], *args, **kwargs) -> None:
if verbose:
print('RUN: ' + " ".join(cmd))
res = subprocess.run(cmd, *args, **kwargs)
if res.returncode != 0:
die('Command failed: ' + " ".join(args))
sys.exit(res.returncode)
def load_config() -> GlobalConfig:
......@@ -131,7 +133,7 @@ def cmd_init(args: argparse.Namespace) -> None:
except KeyError:
progress('creating\n')
run_command(
['adduser', '--system', '--group', '--gecos', f'Container {name}', '--disabled-password', cc.user_name],
['adduser', '--system', '--group', '--gecos', f'Container {name}', '--disabled-password', cc.user_name]
)
pwd = getpwnam(cc.user_name)
uid = pwd.pw_uid
......@@ -145,7 +147,7 @@ def cmd_init(args: argparse.Namespace) -> None:
progress('allocating\n')
sur = subuids.alloc_range(cc.user_name, 65536)
run_command(
['usermod', '--add-subuids', f'{sur.first}-{sur.first + sur.count - 1}', cc.user_name],
['usermod', '--add-subuids', f'{sur.first}-{sur.first + sur.count - 1}', cc.user_name]
)
progress('Subgid range: ')
......@@ -157,7 +159,7 @@ def cmd_init(args: argparse.Namespace) -> None:
progress('allocating\n')
sgr = subgids.alloc_range(cc.user_name, 65536)
run_command(
['usermod', '--add-subgids', f'{sgr.first}-{sgr.first + sgr.count - 1}', cc.user_name],
['usermod', '--add-subgids', f'{sgr.first}-{sgr.first + sgr.count - 1}', cc.user_name]
)
progress(f'Using user {cc.user_name}, uid {uid}, subuids {sur.first}+{sur.count}, subgids {sgr.first}+{sgr.count}\n')
......@@ -190,7 +192,7 @@ def cmd_init(args: argparse.Namespace) -> None:
def service_action(cc: ContainerConfig, action: str) -> None:
run_command(
['systemctl', action, f'shc@{cc.container}.service'],
['systemctl', action, f'shc@{cc.container}.service']
)
......@@ -202,13 +204,13 @@ def cmd_create(args: argparse.Namespace) -> None:
ip = socket.gethostbyname(name)
run_command(
['podman', 'pull', cc.image],
['podman', 'pull', cc.image]
)
service_action(cc, 'stop')
run_command(
['podman', 'rm', '-if', name],
['podman', 'rm', '-if', name]
)
run_command(
......@@ -243,6 +245,38 @@ def cmd_status(args: argparse.Namespace) -> None:
service_action(cc, 'status')
def cmd_disable(args: argparse.Namespace) -> None:
cc = setup_container(args, False)
service_action(cc, 'disable')
def cmd_enable(args: argparse.Namespace) -> None:
cc = setup_container(args, False)
service_action(cc, 'enable')
def cmd_shell(args: argparse.Namespace) -> None:
cc = setup_container(args, False)
run_command(
['podman', 'exec', '-it', cc.container, '/bin/bash']
)
def cmd_exec(args: argparse.Namespace) -> None:
cc = setup_container(args, False)
cmd = ['podman', 'exec']
if args.tty is not None:
cmd.extend(['--interactive', '--tty'])
if args.user is not None:
cmd.extend(['--user', args.user])
cmd.append(cc.container)
cmd.extend(args.arg)
run_command(cmd)
def parse_int_list(s: str) -> List[int]:
return list(map(int, s.split(',')))
......@@ -252,6 +286,7 @@ parser = argparse.ArgumentParser(
)
parser.add_argument('--as-user', type=int, metavar='UID', help='user ID of requesting user')
parser.add_argument('--as-groups', type=parse_int_list, metavar='GID,...', help='group IDs of requesting user (primary first)')
parser.add_argument('--verbose', '-v', default=False, action='store_true', help='be chatty and explain what is going on')
subparsers = parser.add_subparsers(help='action to perform', dest='action', required=True, metavar='ACTION')
init_parser = subparsers.add_parser('init', help='initialize a new container', description='Initialize a new container. Should be called by root.')
......@@ -260,6 +295,21 @@ init_parser.add_argument('name', help='name of the container')
create_parser = subparsers.add_parser('create', help='create a container from an image', description='Create a container from an image.')
create_parser.add_argument('name', help='name of the container')
create_parser = subparsers.add_parser('disable', help='disable automatic startup of a container', description='Disable automatic startup of a container.')
create_parser.add_argument('name', help='name of the container')
create_parser = subparsers.add_parser('enable', help='enable automatic startup of a container', description='Enable automatic startup of a container.')
create_parser.add_argument('name', help='name of the container')
create_parser = subparsers.add_parser('exec', help='execute a command within a container', description='Execute a command within a container.')
create_parser.add_argument('name', help='name of the container')
create_parser.add_argument('arg', nargs='+', help='command and its arguments')
create_parser.add_argument('--tty', '-t', default=False, action='store_true', help='stdio will be attached to a pseudo-terminal')
create_parser.add_argument('--user', '-u', metavar='USER[:GROUP]', help='user/group to run the command under (default: root)')
start_parser = subparsers.add_parser('shell', help='run a shell inside a container', description='Run a shell inside a container')
start_parser.add_argument('name', help='name of the container')
start_parser = subparsers.add_parser('start', help='start a container', description='Start a container')
start_parser.add_argument('name', help='name of the container')
......@@ -270,10 +320,15 @@ stop_parser = subparsers.add_parser('stop', help='stop a container', description
stop_parser.add_argument('name', help='name of the container')
args = parser.parse_args()
verbose = args.verbose
actions = {
'create': cmd_create,
'disable': cmd_disable,
'enable': cmd_enable,
'exec': cmd_exec,
'init': cmd_init,
'shell': cmd_shell,
'start': cmd_start,
'status': cmd_status,
'stop': cmd_stop,
......
......@@ -100,5 +100,5 @@ class ContainerConfig:
wu.raise_error(f'Unknown group {name}')
self.allowed_groups.add(grp.gr_gid)
self.pid_file = f'/run/{self.container}.pid'
self.pid_file = f'/run/shc/{self.container}.pid'
self.user_name = self.container
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment