201 lines
4.8 KiB
Python
Executable File
201 lines
4.8 KiB
Python
Executable File
#!/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()
|
|
|