Massive QoL reworks
This commit is contained in:
parent
f94db364d7
commit
9da09d56cf
12 changed files with 93 additions and 89 deletions
|
@ -20,20 +20,11 @@ def set_verbosity(logger, handler, verbosity):
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
kiwi.Parser().get_parser().add_argument(
|
|
||||||
'-v', '--verbosity',
|
|
||||||
action='count', default=0
|
|
||||||
)
|
|
||||||
|
|
||||||
args = kiwi.Parser().get_args()
|
|
||||||
|
|
||||||
log_handler = logging.StreamHandler()
|
log_handler = logging.StreamHandler()
|
||||||
logging.getLogger().addHandler(log_handler)
|
logging.getLogger().addHandler(log_handler)
|
||||||
set_verbosity(logging.getLogger(), log_handler, args.verbosity)
|
set_verbosity(logging.getLogger(), log_handler, kiwi.verbosity())
|
||||||
|
|
||||||
logging.debug(f"main CLI args: {args}")
|
kiwi.run()
|
||||||
|
|
||||||
kiwi.Runner().run(args.command)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
|
@ -1,7 +1,17 @@
|
||||||
from .core import Parser
|
from .parser import Parser
|
||||||
from .runner import Runner
|
from .runner import Runner
|
||||||
|
|
||||||
|
|
||||||
|
def verbosity():
|
||||||
|
_ = Runner()
|
||||||
|
return Parser().get_args().verbosity
|
||||||
|
|
||||||
|
|
||||||
|
def run():
|
||||||
|
Runner().run()
|
||||||
|
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
'Parser',
|
'verbosity',
|
||||||
'Runner'
|
'run'
|
||||||
]
|
]
|
||||||
|
|
4
src/kiwi/_constants.py
Normal file
4
src/kiwi/_constants.py
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
import os
|
||||||
|
|
||||||
|
KIWI_ROOT = os.getenv('KIWI_ROOT', ".")
|
||||||
|
KIWI_CONF_NAME = os.getenv('KIWI_CONF_NAME', "kiwi.yml")
|
|
@ -3,12 +3,13 @@ import re
|
||||||
import os
|
import os
|
||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
from .core import KIWI_ROOT, KIWI_CONF_NAME
|
from ._constants import KIWI_ROOT, KIWI_CONF_NAME
|
||||||
|
|
||||||
###########
|
###########
|
||||||
# CONSTANTS
|
# CONSTANTS
|
||||||
|
|
||||||
DEFAULT_KIWI_CONF_NAME = f"{KIWI_ROOT}/default.kiwi.yml"
|
HEADER_KIWI_CONF_NAME = f"{KIWI_ROOT}/kiwi_header.yml"
|
||||||
|
DEFAULT_KIWI_CONF_NAME = f"{KIWI_ROOT}/kiwi_default.yml"
|
||||||
VERSION_TAG_NAME = f"{KIWI_ROOT}/version-tag"
|
VERSION_TAG_NAME = f"{KIWI_ROOT}/version-tag"
|
||||||
|
|
||||||
|
|
||||||
|
@ -42,11 +43,9 @@ class Config:
|
||||||
# insert newline before every main key
|
# insert newline before every main key
|
||||||
yml_string = re.sub(r'^(\S)', r'\n\1', yml_string, flags=re.MULTILINE)
|
yml_string = re.sub(r'^(\S)', r'\n\1', yml_string, flags=re.MULTILINE)
|
||||||
|
|
||||||
# extract header comment from default config
|
# load header comment from file
|
||||||
with open(DEFAULT_KIWI_CONF_NAME, 'r') as stream:
|
with open(HEADER_KIWI_CONF_NAME, 'r') as stream:
|
||||||
yml_header = stream.read().strip()
|
yml_string = stream.read() + yml_string
|
||||||
yml_header = re.sub(r'^[^#].*', r'', yml_header, flags=re.MULTILINE).strip()
|
|
||||||
yml_string = "{}\n{}".format(yml_header, yml_string)
|
|
||||||
|
|
||||||
return yml_string
|
return yml_string
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,4 @@
|
||||||
import argparse
|
import argparse
|
||||||
import os
|
|
||||||
|
|
||||||
###########
|
|
||||||
# CONSTANTS
|
|
||||||
|
|
||||||
KIWI_ROOT = os.getenv('KIWI_ROOT', ".")
|
|
||||||
KIWI_CONF_NAME = os.getenv('KIWI_CONF_NAME', "kiwi.yml")
|
|
||||||
|
|
||||||
|
|
||||||
class Parser:
|
class Parser:
|
||||||
|
@ -17,6 +10,11 @@ class Parser:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.__parser = argparse.ArgumentParser(description='kiwi-config')
|
self.__parser = argparse.ArgumentParser(description='kiwi-config')
|
||||||
|
|
||||||
|
self.__parser.add_argument(
|
||||||
|
'-v', '--verbosity',
|
||||||
|
action='count', default=0
|
||||||
|
)
|
||||||
|
|
||||||
self.__subparsers = self.__parser.add_subparsers()
|
self.__subparsers = self.__parser.add_subparsers()
|
||||||
self.__subparsers.required = True
|
self.__subparsers.required = True
|
||||||
self.__subparsers.dest = 'command'
|
self.__subparsers.dest = 'command'
|
|
@ -1,3 +1,7 @@
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from .config import LoadedConfig
|
||||||
|
from .parser import Parser
|
||||||
from .subcommands import *
|
from .subcommands import *
|
||||||
|
|
||||||
###########
|
###########
|
||||||
|
@ -18,10 +22,14 @@ class Runner:
|
||||||
for cmd in SUBCOMMANDS:
|
for cmd in SUBCOMMANDS:
|
||||||
self.__commands.append(cmd())
|
self.__commands.append(cmd())
|
||||||
|
|
||||||
def run(self, command_name):
|
def run(self):
|
||||||
|
config = LoadedConfig.get()
|
||||||
|
args = Parser().get_args()
|
||||||
|
|
||||||
for cmd in self.__commands:
|
for cmd in self.__commands:
|
||||||
if str(cmd) == command_name:
|
if str(cmd) == args.command:
|
||||||
cmd.run()
|
logging.debug(f"Running '{cmd}' with args: {args}")
|
||||||
|
cmd.run(config, args)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
@ -34,7 +42,3 @@ class Runner:
|
||||||
|
|
||||||
def __getattr__(self, item):
|
def __getattr__(self, item):
|
||||||
return getattr(self.__instance, item)
|
return getattr(self.__instance, item)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == 'kiwi.runner':
|
|
||||||
_ = Runner()
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ import logging
|
||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
from ..core import Parser
|
from ..parser import Parser
|
||||||
from ..config import LoadedConfig
|
from ..config import LoadedConfig
|
||||||
|
|
||||||
|
|
||||||
|
@ -28,16 +28,16 @@ def get_exe_key(exe_name):
|
||||||
|
|
||||||
class SubCommand:
|
class SubCommand:
|
||||||
__name = None
|
__name = None
|
||||||
_parser = None
|
_sub_parser = None
|
||||||
|
|
||||||
def __init__(self, name, **kwargs):
|
def __init__(self, name, **kwargs):
|
||||||
self.__name = name
|
self.__name = name
|
||||||
self._parser = Parser().get_subparsers().add_parser(name, **kwargs)
|
self._sub_parser = Parser().get_subparsers().add_parser(name, **kwargs)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.__name
|
return self.__name
|
||||||
|
|
||||||
def run(self):
|
def run(self, config, args):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,15 +1,19 @@
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from ..core import KIWI_CONF_NAME, Parser
|
from .._constants import KIWI_CONF_NAME
|
||||||
from ..config import DefaultConfig, LoadedConfig
|
from ..config import DefaultConfig
|
||||||
|
|
||||||
from ._utils import SubCommand, is_executable, find_exe_file, get_exe_key
|
from ._utils import SubCommand, is_executable, find_exe_file, get_exe_key
|
||||||
|
|
||||||
|
|
||||||
def user_input(config, key, prompt):
|
def user_input(config, key, prompt):
|
||||||
# prompt user as per argument
|
# prompt user as per argument
|
||||||
result = input("{} [{}] ".format(prompt, config[key])).strip()
|
try:
|
||||||
|
result = input("{} [{}] ".format(prompt, config[key])).strip()
|
||||||
|
except EOFError:
|
||||||
|
print()
|
||||||
|
result = None
|
||||||
|
|
||||||
# store result if present
|
# store result if present
|
||||||
if result:
|
if result:
|
||||||
|
@ -38,38 +42,41 @@ class InitCommand(SubCommand):
|
||||||
description="Create a new kiwi-config instance"
|
description="Create a new kiwi-config instance"
|
||||||
)
|
)
|
||||||
|
|
||||||
self._parser.add_argument(
|
self._sub_parser.add_argument(
|
||||||
'-f', '--force',
|
'-f', '--force',
|
||||||
action='store_true',
|
action='store_true',
|
||||||
help=f"use default values even if {KIWI_CONF_NAME} is present"
|
help=f"use default values even if {KIWI_CONF_NAME} is present"
|
||||||
)
|
)
|
||||||
|
|
||||||
def run(self):
|
def run(self, config, args):
|
||||||
logging.info(f"Initializing kiwi-config instance in '{os.getcwd()}'")
|
logging.info(f"Initializing kiwi-config instance in '{os.getcwd()}'")
|
||||||
|
|
||||||
if Parser().get_args().force and os.path.isfile(KIWI_CONF_NAME):
|
if args.force and os.path.isfile(KIWI_CONF_NAME):
|
||||||
logging.warning(f"Overwriting existing '{KIWI_CONF_NAME}'!")
|
logging.warning(f"Overwriting existing '{KIWI_CONF_NAME}'!")
|
||||||
config = DefaultConfig.get()
|
config = DefaultConfig.get()
|
||||||
else:
|
|
||||||
config = LoadedConfig.get()
|
|
||||||
|
|
||||||
# version
|
try:
|
||||||
user_input(config, 'version', "Enter kiwi-config version for this instance")
|
# version
|
||||||
|
user_input(config, 'version', "Enter kiwi-config version for this instance")
|
||||||
|
|
||||||
# runtime
|
# runtime
|
||||||
user_input(config, 'runtime:storage', "Enter local directory for service data")
|
user_input(config, 'runtime:storage', "Enter local directory for service data")
|
||||||
|
|
||||||
# markers
|
# markers
|
||||||
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")
|
||||||
|
|
||||||
# network
|
# network
|
||||||
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")
|
||||||
|
|
||||||
# executables
|
# executables
|
||||||
user_input_exe(config, 'docker')
|
user_input_exe(config, 'docker')
|
||||||
user_input_exe(config, 'docker-compose')
|
user_input_exe(config, 'docker-compose')
|
||||||
user_input_exe(config, 'sudo')
|
user_input_exe(config, 'sudo')
|
||||||
|
|
||||||
config.save()
|
config.save()
|
||||||
|
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
print()
|
||||||
|
logging.warning(f"'{self}' aborted, input discarded.")
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from ..config import LoadedConfig
|
|
||||||
from ..core import Parser
|
|
||||||
|
|
||||||
from ._utils import SubCommand, DockerCommand
|
from ._utils import SubCommand, DockerCommand
|
||||||
|
|
||||||
|
|
||||||
|
@ -13,26 +10,23 @@ class LogsCommand(SubCommand):
|
||||||
description="Show logs of a project or service(s) of a project"
|
description="Show logs of a project or service(s) of a project"
|
||||||
)
|
)
|
||||||
|
|
||||||
self._parser.add_argument(
|
self._sub_parser.add_argument(
|
||||||
'-f', '--follow', action='store_true',
|
'-f', '--follow', action='store_true',
|
||||||
help="output appended data as log grows"
|
help="output appended data as log grows"
|
||||||
)
|
)
|
||||||
|
|
||||||
self._parser.add_argument(
|
self._sub_parser.add_argument(
|
||||||
'project', type=str,
|
'project', type=str,
|
||||||
help="select a project in this instance"
|
help="select a project in this instance"
|
||||||
)
|
)
|
||||||
|
|
||||||
self._parser.add_argument(
|
self._sub_parser.add_argument(
|
||||||
'services', metavar='service', nargs='*', type=str,
|
'services', metavar='service', nargs='*', type=str,
|
||||||
help="select service(s) in a project"
|
help="select service(s) in a project"
|
||||||
)
|
)
|
||||||
|
|
||||||
def run(self):
|
def run(self, config, args):
|
||||||
config = LoadedConfig.get()
|
project_name = args.project
|
||||||
cli_args = Parser().get_args()
|
|
||||||
|
|
||||||
project_name = cli_args.project
|
|
||||||
project_marker = config['markers:project']
|
project_marker = config['markers:project']
|
||||||
project_dir = f'{project_name}{project_marker}'
|
project_dir = f'{project_name}{project_marker}'
|
||||||
|
|
||||||
|
@ -41,22 +35,22 @@ class LogsCommand(SubCommand):
|
||||||
'COMPOSE_PROJECT_NAME': project_name
|
'COMPOSE_PROJECT_NAME': project_name
|
||||||
}
|
}
|
||||||
|
|
||||||
args = ['logs', '-t']
|
process_args = ['logs', '-t']
|
||||||
if cli_args.follow:
|
if args.follow:
|
||||||
args = [*args, '-f', '--tail=10']
|
process_args = [*process_args, '-f', '--tail=10']
|
||||||
|
|
||||||
if cli_args.services:
|
if args.services:
|
||||||
args = [*args, *cli_args.services]
|
process_args = [*process_args, *args.services]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if cli_args.follow:
|
if args.follow:
|
||||||
DockerCommand('docker-compose').run(
|
DockerCommand('docker-compose').run(
|
||||||
args,
|
process_args,
|
||||||
cwd=project_dir, env=environment
|
cwd=project_dir, env=environment
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
DockerCommand('docker-compose').run_less(
|
DockerCommand('docker-compose').run_less(
|
||||||
args,
|
process_args,
|
||||||
cwd=project_dir, env=environment
|
cwd=project_dir, env=environment
|
||||||
)
|
)
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
from ..config import LoadedConfig
|
|
||||||
|
|
||||||
from ._utils import SubCommand
|
from ._utils import SubCommand
|
||||||
|
|
||||||
|
|
||||||
|
@ -10,6 +8,5 @@ class ShowCommand(SubCommand):
|
||||||
description="Show effective kiwi.yml"
|
description="Show effective kiwi.yml"
|
||||||
)
|
)
|
||||||
|
|
||||||
def run(self):
|
def run(self, config, args):
|
||||||
config = LoadedConfig.get()
|
|
||||||
print(config)
|
print(config)
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
######################################
|
|
||||||
# kiwi-config instance configuration #
|
|
||||||
######################################
|
|
||||||
version:
|
version:
|
||||||
runtime:
|
runtime:
|
||||||
storage: /var/kiwi
|
storage: /var/kiwi
|
3
src/kiwi_header.yml
Normal file
3
src/kiwi_header.yml
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
######################################
|
||||||
|
# kiwi-config instance configuration #
|
||||||
|
######################################
|
Loading…
Reference in a new issue