#!/usr/bin/python3 # vi: ts=2 sw=2 et : ## Dependencies # pip install pyhocon # - https://github.com/chimpler/pyhocon from pyhocon import ConfigFactory from subprocess import Popen, PIPE, STDOUT import subprocess import sys import os import pty def di_syscall(cmd, workdir='.'): #print('[dbg] CMD: %s' % (cmd)) process = subprocess.run(cmd, capture_output=True, cwd=workdir) return (process.stdout.decode("utf-8").strip(), process.stderr.decode("utf-8").strip()) def di_syscall_follow(cmd): #print('[dbg] CMD: %s' % (cmd)) process = Popen(cmd, stdout=PIPE, stderr=STDOUT) try: while True: line = process.stdout.readline() if not line: break else: print(line.decode('utf-8').strip()) except KeyboardInterrupt: print('') def di_syscall_interactive(cmd): #print('[dbg] CMD: %s' % (cmd)) pty.spawn(cmd) def print_help_exit(): print('Use: [container.conf] command') exit() def create_default_config(): conf_d = {} conf_d['shell'] = 'sh' conf_d['upd-sig'] = 'HUP' return ConfigFactory.from_dict(conf_d) def get_config(path): if os.path.isfile(path): conf = ConfigFactory.parse_file(path) return conf else: return None # -------------------------- # class Container: def __init__(self, conf, workdir): self.conf = conf self.workdir = workdir def status(self): self.__require_exists() if self.is_run(): print('%s running' % (self.conf['title'])) else: print('%s container down' % (self.conf['title'])) out, err = di_syscall(['podman', 'logs', '--tail', '5', self.conf['name']]) if err: print(err) else: print(out) def start(self): if not self.is_run(): cmd = ['podman', 'run', '-d', '--name', self.conf['name']] for volume in self.conf['volumes']: cmd.append('--volume') cmd.append(volume) for publish in self.conf['ports']: cmd.append('--publish') cmd.append(publish) if self.conf.get('env', None) is not None: for env_name in self.conf['env'].keys(): cmd.append('--env') cmd.append('%s=%s' % (env_name, self.conf['env'][env_name])) cmd.append(self.conf['image']) if self.conf.get('cmd', None) is not None: for arg in self.conf['cmd']: cmd.append('%s' % arg) container_id, err = di_syscall(cmd, self.workdir) if err: print('ERROR') print(err) else: print('Container %s started [%s]' % (self.conf['title'], container_id)) else: print('%s is runned' % self.conf['title']) def stop(self): self.__require_exists() if self.is_run(): print('Stop %s container...' % (self.conf['title'])) cid, err = di_syscall(['podman', 'stop', self.conf['name']]) if err: print(err) print('Remove %s container...' % (self.conf['title'])) cid, err = di_syscall(['podman', 'rm', self.conf['name']]) if err: print(err) def logs(self): self.__require_exists() di_syscall_follow(['podman', 'logs', '--tail', '10', '-f', self.conf['name']]) def shell(self): self.__require_run() print('Enter shell in %s container...' % self.conf['title']) di_syscall_interactive(['podman', 'exec', '-it', self.conf['name'], self.conf['shell']]) def update(self): self.__require_run() print('Update config %s...' % self.conf['title']) di_syscall(['podman', 'kill', '--signal=%s' % self.conf['upg-sig'], self.conf['name']]) def is_run(self): return len(di_syscall(['podman', 'ps', '--filter', 'name=%s' % (self.conf['name']), '-q'])[0]) > 0 def is_exists(self): return len(di_syscall(['podman', 'ps', '--filter', 'name=%s' % (self.conf['name']), '-qa'])[0]) > 0 def __require_run(self): if not self.is_run(): print('%s not runned' % self.conf['title']) exit() def __require_exists(self): if not self.is_exists(): print('%s not exists' % self.conf['title']) exit() # -------------------------- # if len(sys.argv) == 1: print_help_exit() conf = None begin_index_commands = None workdir = None if os.path.isfile(sys.argv[1]): conf = get_config(sys.argv[1]) begin_index_commands = 2 workdir = os.path.dirname(sys.argv[1]) else: conf = get_config('container.conf') begin_index_commands = 1 workdir = '.' if conf is None: print_help_exit() conf = conf.with_fallback(create_default_config()) container = Container(conf, workdir) command = sys.argv[begin_index_commands] if command == 'start': container.start() elif command == 'status': container.status() elif command == 'stop': container.stop() elif command == 'logs': container.logs() elif command == 'restart': container.stop() container.start() elif command == 'shell': container.shell() elif command == 'update': container.update() else: print_help_exit()