1
0
Fork 0
mirror of https://github.com/yavook/kiwi-scp.git synced 2024-11-22 04:43:00 +00:00

YML executable paths, "logs" subcommand

This commit is contained in:
Jörn-Michael Miehe 2020-08-08 19:41:11 +02:00
parent 1214137005
commit 3e1d9510dc
14 changed files with 182 additions and 46 deletions

1
example/Makefile Symbolic link
View file

@ -0,0 +1 @@
../Makefile

View file

@ -2,6 +2,6 @@ export SUFFIX_PROJECT=.project
export SUFFIX_DOWN=.down export SUFFIX_DOWN=.down
export DOCKERNET=kiwinet export DOCKERNET=kiwinet
export DOCKERCIDR=10.13.37.0/24 export DOCKERCIDR=10.22.46.0/24
export TARGETROOT=/var/kiwi export TARGETROOT=/var/kiwi

View file

@ -0,0 +1,15 @@
version: "2"
networks:
# reachable from outside
default:
driver: bridge
# interconnects projects
kiwihub:
external:
name: $DOCKERNET
services:
hello-world:
image: alpine:latest
command: sh -c 'while :; do echo Hello World; sleep 10; done'

22
example/kiwi.yml Normal file
View file

@ -0,0 +1,22 @@
######################################
# kiwi-config instance configuration #
######################################
version: '0.1'
runtime:
storage: /var/kiwi
env: null
markers:
project: .project
down: .down
network:
name: kiwinet
cidr: 10.22.46.0/24
executables:
docker: /usr/bin/docker
docker-compose: /usr/local/bin/docker-compose
sudo: /usr/bin/sudo

View file

@ -1 +0,0 @@
version: '0.1'

View file

@ -2,12 +2,16 @@
# kiwi-config instance configuration # # kiwi-config instance configuration #
###################################### ######################################
version: version:
runtime:
storage: /var/kiwi
env: null
markers: markers:
project: .project project: .project
down: .down down: .down
network: network:
name: kiwinet name: kiwinet
cidr: 10.22.46.0/24 cidr: 10.22.46.0/24
runtime: executables:
storage: /var/kiwi docker: null
env: null docker-compose: null
sudo: null

View file

@ -9,6 +9,7 @@ from .core import KIWI_ROOT, KIWI_CONF_NAME
# CONSTANTS # CONSTANTS
DEFAULT_KIWI_CONF_NAME = KIWI_ROOT + "/default.kiwi.yml" DEFAULT_KIWI_CONF_NAME = KIWI_ROOT + "/default.kiwi.yml"
VERSION_TAG_NAME = KIWI_ROOT + "/version-tag"
class Config: class Config:
@ -49,35 +50,39 @@ class Config:
return yml_string return yml_string
def __update_from_file(self, filename): def _update_from_file(self, filename):
with open(filename, 'r') as stream: with open(filename, 'r') as stream:
try: try:
self.__yml_content.update(yaml.safe_load(stream)) self.__yml_content.update(yaml.safe_load(stream))
except yaml.YAMLError as exc: except yaml.YAMLError as exc:
logging.error(exc) logging.error(exc)
def __save_to_file(self, filename): def save(self):
with open(filename, 'w') as stream: with open(KIWI_CONF_NAME, 'w') as stream:
stream.write(str(self)) stream.write(str(self))
@classmethod
def default(cls):
result = cls()
result.__update_from_file(DEFAULT_KIWI_CONF_NAME)
with open(KIWI_ROOT + "/version-tag", 'r') as stream: class DefaultConfig(Config):
result.__yml_content["version"] = stream.read().strip() __instance = None
return result
@classmethod @classmethod
def load(cls): def get(cls):
result = cls.default() if cls.__instance is None:
cls.__instance = cls()
cls.__instance._update_from_file(DEFAULT_KIWI_CONF_NAME)
with open(VERSION_TAG_NAME, 'r') as stream:
cls.__instance["version"] = stream.read().strip()
return cls.__instance
class LoadedConfig(Config):
@classmethod
def get(cls):
result = DefaultConfig.get()
if os.path.isfile(KIWI_CONF_NAME): if os.path.isfile(KIWI_CONF_NAME):
result.__update_from_file(KIWI_CONF_NAME) result._update_from_file(KIWI_CONF_NAME)
return result return result
def save(self):
self.__save_to_file(KIWI_CONF_NAME)

View file

@ -7,7 +7,8 @@ from .subcommands import *
class Runner: class Runner:
__commands: List[SubCommand] = [ __commands: List[SubCommand] = [
InitCommand, InitCommand,
ShowCommand ShowCommand,
LogsCommand
] ]
@classmethod @classmethod

View file

@ -1,6 +1,12 @@
from .subcommand import SubCommand from ._utils import SubCommand
from .init import InitCommand from .init import InitCommand
from .show import ShowCommand from .show import ShowCommand
from .logs import LogsCommand
__all__ = ['SubCommand', 'InitCommand', 'ShowCommand'] __all__ = [
'SubCommand',
'InitCommand',
'ShowCommand',
'LogsCommand'
]

View file

@ -0,0 +1,53 @@
import subprocess
from ..config import LoadedConfig
class SubCommand:
@classmethod
def get_cmd(cls):
pass
@classmethod
def setup(cls):
pass
@classmethod
def run(cls):
pass
class Docker:
__requires_root = None
@classmethod
def __check_requires_root(cls):
if cls.__requires_root is None:
try:
config = LoadedConfig.get()
subprocess.run(
[config['executables:docker'], 'ps'],
check=True,
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL
)
cls.__requires_root = False
except subprocess.CalledProcessError:
cls.__requires_root = True
return cls.__requires_root
@classmethod
def run_command(cls, program, args, cwd=None, env=None):
config = LoadedConfig.get()
cmd = [config['executables:' + program], *args]
if cls.__check_requires_root():
cmd = [config['executables:sudo'], *cmd]
print(cmd)
return subprocess.run(
cmd,
# stdout=subprocess.PIPE,
# stderr=subprocess.PIPE,
cwd=cwd, env=env
)

View file

@ -1,10 +1,10 @@
import logging import logging
import os import os
from kiwi.core import KIWI_CONF_NAME, Parser from ..core import KIWI_CONF_NAME, Parser
from kiwi.config import Config from ..config import DefaultConfig
from .subcommand import SubCommand from ._utils import SubCommand
def user_input(config, key, prompt): def user_input(config, key, prompt):
@ -16,6 +16,25 @@ def user_input(config, key, prompt):
config[key] = result config[key] = result
def find_exe(program_name):
for path in os.environ["PATH"].split(os.pathsep):
exe_file = os.path.join(path, program_name)
if os.path.isfile(exe_file) and os.access(exe_file, os.X_OK):
return exe_file
return None
def user_input_exe(config, program_name):
exe_file = find_exe(program_name)
key = 'executables:' + program_name
if exe_file is not None:
config[key] = exe_file
else:
user_input(config, key, "Enter path to '{}' executable".format(program_name))
class InitCommand(SubCommand): class InitCommand(SubCommand):
__parser = None __parser = None
@ -30,19 +49,23 @@ class InitCommand(SubCommand):
@classmethod @classmethod
def run(cls): def run(cls):
config = Config.default() config = DefaultConfig.get()
if os.path.isfile(KIWI_CONF_NAME): if os.path.isfile(KIWI_CONF_NAME):
logging.warning("Overwriting existing '%s'!", KIWI_CONF_NAME) logging.warning("Overwriting existing '%s'!", KIWI_CONF_NAME)
user_input(config, 'version', "Choose kiwi-config version") user_input(config, 'version', "Choose kiwi-config version")
user_input(config, 'runtime:storage', "Enter main directory for local data")
user_input(config, 'markers:project', "Enter marker string for project directories") user_input(config, 'markers:project', "Enter marker string for project directories")
user_input(config, 'markers:down', "Enter marker string for disabled projects") user_input(config, 'markers:down', "Enter marker string for disabled projects")
user_input(config, 'network:name', "Enter name for local docker network") user_input(config, 'network:name', "Enter name for local docker network")
user_input(config, 'network:cidr', "Enter CIDR block for local docker network") user_input(config, 'network:cidr', "Enter CIDR block for local docker network")
user_input(config, 'runtime:storage', "Enter main directory for local data") user_input_exe(config, 'docker')
user_input_exe(config, 'docker-compose')
user_input_exe(config, 'sudo')
config.save() config.save()

View file

@ -0,0 +1,19 @@
from ..core import Parser
from ._utils import SubCommand, Docker
class LogsCommand(SubCommand):
__parser = None
@classmethod
def get_cmd(cls):
return 'logs'
@classmethod
def setup(cls):
cls.__parser = Parser.get_subparsers().add_parser(cls.get_cmd(), help="Show logs of a project")
@classmethod
def run(cls):
print(Docker.run_command('docker-compose', ['logs', '-tf', '--tail=10'], cwd='hello-world.project', env={'COMPOSE_PROJECT_NAME': 'hello-world'}))

View file

@ -1,7 +1,7 @@
from kiwi.config import Config from ..config import LoadedConfig
from kiwi.core import Parser from ..core import Parser
from .subcommand import SubCommand from ._utils import SubCommand
class ShowCommand(SubCommand): class ShowCommand(SubCommand):
@ -17,5 +17,5 @@ class ShowCommand(SubCommand):
@classmethod @classmethod
def run(cls): def run(cls):
config = Config.load() config = LoadedConfig.get()
print(config) print(config)

View file

@ -1,12 +0,0 @@
class SubCommand:
@classmethod
def get_cmd(cls):
pass
@classmethod
def setup(cls):
pass
@classmethod
def run(cls):
pass