diff --git a/container.conf b/container.conf new file mode 100644 index 0000000..fa0d971 --- /dev/null +++ b/container.conf @@ -0,0 +1,16 @@ +{ + name: tools--phpmyadmin + title: phpMyAdmin + image: phpmyadmin:5.1.1-apache + ports: [ + 0.0.0.0:9091:80 + ] + volumes: [ + /etc/timezone:/etc/timezone:ro + /etc/localtime:/etc/localtime:ro + ] + env: { + PMA_ARBITRARY: 1 + } +} + diff --git a/ctl b/ctl deleted file mode 100755 index 49b265d..0000000 --- a/ctl +++ /dev/null @@ -1,51 +0,0 @@ -#!/bin/bash -# vi: set tabstop=4 shiftwidth=4 expandtab : -ROOTDIR=$(cd "$(dirname "$0")" && pwd) -cd $ROOTDIR -declare -A MAP_COMMAND - -# === Log ==================================================================== # -CW="\033[1;37m" # White -CG="\033[0;32m" # Green -CY="\033[0;33m" # Yellow -NC="\033[0m" # Reset - -function log { - local II="${CW}╡${CG}ctl${CW}╞${NC}" - echo -e "${II} $@" -} - -log "${CY}Container Control Script ${CG}b20220114-0500${NC}" - -# === Import ================================================================= # -for V in $(ls $ROOTDIR/ctl.d/*.sh) -do - . $V -done - -# === Main =================================================================== # -function main { - local args=($@) - local command=${args[0]} - - if [[ -n $command ]] - then - for cmd in $(echo "${!MAP_COMMAND[@]}") - do - if [ $command = $cmd ] - then - ${MAP_COMMAND[$cmd]} ${args[@]:1} - return - fi - done - fi - - print_help -} - -function print_help { - local vvv=$(echo "${!MAP_COMMAND[@]}" | tr ' ' "\n" | sort | tr "\n" ',' | sed 's/,/, /g') - log "Use: ${vvv:: -2}" -} - -main $@ diff --git a/ctl.d/10-module-container.sh b/ctl.d/10-module-container.sh deleted file mode 100644 index 498bcb7..0000000 --- a/ctl.d/10-module-container.sh +++ /dev/null @@ -1,129 +0,0 @@ -#!/bin/bash -# vi: set tabstop=4 shiftwidth=4 expandtab : - -declare -A M_CONTAINER - -M_CONTAINER['name']='' -M_CONTAINER['title']='(NULL)' -M_CONTAINER['shell']=sh -M_CONTAINER['upd-sig']=HUP - -# -# Статус работы контейнера -# -MAP_COMMAND['status']=fn_container_status -function fn_container_status { - if [ $(fn_container_check) = 1 ] - then - log "${M_CONTAINERP['title']} running" - podman logs --tail 5 ${M_CONTAINER['name']} - elif [ $(fn_container_check2) = 1 ] - then - log "${M_CONTAINER['title']} container down" - else - log "${M_CONTAINER['title']} not running" - fi -} - -# -# Остановка контейнера -# -MAP_COMMAND['stop']=fn_container_stop -function fn_container_stop { - if [ $(fn_container_check) = 1 ] - then - log "Stop ${M_CONTAINER['title']} container..." - podman stop ${M_CONTAINER['name']} - fi - - if [ $(fn_container_check2) = 1 ] - then - log "Remove ${M_CONTAINER['title']} container..." - local container_id=$(podman rm ${M_CONTAINER['name']}) - log $conainer_id - # TODO здесь необходимо выполнить проверку на - # - включен ли модуль network - # - остались ли после удаления контейнера сетевые файлы - # - Если да, то запустить процесс зачистки... - # - ...файлов - # - ...nftables - # - Если нет, просто завершить работу - else - log "${M_CONTAINER['title']} not runned." - fi -} - -# -# Перезапуск контейнера -# -MAP_COMMAND['restart']=fn_container_restart -function fn_container_restart { - fn_container_stop && fn_container_start -} - -# -# Логи контейнера -# -MAP_COMMAND['logs']=fn_container_logs -function fn_logs { - if [ $(fn_container_check2) = 1 ] - then - podman logs --tail 10 -f ${M_CONTAINER['name']} - else - log "${M_CONTAINER['title']} not exists" - fi -} - -# -# Войти в shell контейнера -# -MAP_COMMAND['shell']=fn_container_shell -function fn_container_shell { - if [ $(fn_container_check) = 1 ] - then - log "Enter shell in ${M_CONTAINER['title']} container..." - podman exec -it ${M_CONTAINER['name']} ${M_CONTAINER['shell']} - else - log "${M_CONTAINER['title']} not runned." - fi -} - -# -# Послать сигнал обновления конфигов. -# Предназначено для запущенный в контейнере программ. -# -MAP_COMMAND['update']=fn_container_update_config -function fn_container_update_config { - if [ $(fn_container_check) = 1 ] - then - log "Update config ${M_CONTAINER['title']}..." - podman kill --signal=${M_CONTAINER['upd-sig']} ${M_CONTAINER['name']} - else - log "${M_CONTAINER['title']} not runned." - fi -} - -# -# Статус работы контейнера -# -function fn_container_check { - if [[ -n $(podman ps --filter "name=${M_CONTAINER['name']}" -q) ]] - then - echo 1 - else - echo 0 - fi -} - -# -# Статус существования контейнера -# -function fn_container_check2 { - if [[ -n $(podman ps --filter "name=${M_CONTAINER['name']}" -qa) ]] - then - echo 1 - else - echo 0 - fi -} - diff --git a/ctl.d/11-pma.sh b/ctl.d/11-pma.sh deleted file mode 100644 index c44a103..0000000 --- a/ctl.d/11-pma.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/bash -# vi: set tabstop=4 shiftwidth=4 expandtab : - -M_CONTAINER['name']='tools--phpmyadmin' -M_CONTAINER['title']='phpMyAdmin' -M_CONTAINER['host']=0.0.0.0 -M_CONTAINER['port']=9091 - -MAP_COMMAND['start']=fn_container_start -function fn_container_start { - if [ $(fn_container_check) = 1 ] - then - log "${M_CONTAINER['title']} is runned." - elif [ $(fn_container_check2) = 1 ] - then - log "${M_CONTAINER['title']} container is down. Need restart." - else - log "Start ${M_CONTAINER['title']} container..." - local container_id=$(podman run -d \ - --name "${M_CONTAINER['name']}" \ - --volume /etc/timezone:/etc/timezone:ro \ - --volume /etc/localtime:/etc/localtime:ro \ - --publish "${M_CONTAINER['host']}:${M_CONTAINER['port']}:8080" \ - --env 'PMA_ARBITRARY=1' \ - phpmyadmin:5.1.1-apache - ) - log $conainer_id - fi -} - diff --git a/ctl.d/21-pma-backup.sh b/ctl.d/21-pma-backup.sh deleted file mode 100644 index af05c97..0000000 --- a/ctl.d/21-pma-backup.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/bash -# vi: set tabstop=4 shiftwidth=4 expandtab : - -MAP_COMMAND['backup']=fn_backup -function fn_backup { - local basename=$(basename "$(cd "$(dirname "$0")" && pwd)") - local archive=${basename}-$(date +%Y%m%d) - - log 'Backup...' - tar -cf - -- \ - ctrl.d/ \ - ctl \ - | 7z a -bso0 -si ${archive}.tar.7z - log "$(du -sh ${archive}.tar.7z)" -} diff --git a/ctl.py b/ctl.py new file mode 100755 index 0000000..213cc77 --- /dev/null +++ b/ctl.py @@ -0,0 +1,175 @@ +#!/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): + #print('[dbg] CMD: %s' % (cmd)) + process = subprocess.run(cmd, capture_output=True) + return (process.stdout.decode("utf-8").strip(), process.stderr.decode("utf-8").strip()) + + +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): + self.conf = conf + + + def status(self): + self.__require_exists() + + if self.is_run(): + print('%s running' % (self.conf['title'])) + out, err = di_syscall(['podman', 'logs', '--tail', '5', self.conf['name']]) + if err: print(err) + else: + print('%s container down' % (self.conf['title'])) + out, err = di_syscall(['podman', 'logs', '--tail', '5', self.conf['name']]) + if err: print(err) + + + 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) + 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']) + + container_id, err = di_syscall(cmd) + 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_interactive(['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() + +begin_index_commands = 2 +conf = get_config(sys.argv[1]) +if conf is None: + conf = get_config('container.conf') + if conf is None: + print_help_exit() + else: + begin_index_commands = 1 +conf = conf.with_fallback(create_default_config()) + +container = Container(conf) +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() +