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

abandoned utils.misc for project handling

This commit is contained in:
Jörn-Michael Miehe 2020-08-19 11:58:13 +02:00
parent 0cf934965e
commit 267f85fa8d
9 changed files with 182 additions and 204 deletions

View file

@ -2,7 +2,7 @@
import logging
# local
from .utils.misc import get_first_project_name, get_services, list_projects
from .utils.project import Projects
# parent
from ..parser import Parser
@ -16,12 +16,13 @@ class SubCommand:
# command parser
_sub_parser = None
def __init__(self, name, **kwargs):
def __init__(self, name, add_parser=True, **kwargs):
self.__name = name
self._sub_parser = Parser().get_subparsers().add_parser(
name,
**kwargs
)
if add_parser:
self._sub_parser = Parser().get_subparsers().add_parser(
name,
**kwargs
)
def __str__(self):
return self.__name
@ -34,9 +35,9 @@ class SubCommand:
class ProjectCommand(SubCommand):
"""this command concerns a project in current instance"""
def __init__(self, name, num_projects, **kwargs):
def __init__(self, name, num_projects, add_parser=True, **kwargs):
super().__init__(
name,
name, add_parser=add_parser,
**kwargs
)
@ -54,9 +55,9 @@ class ProjectCommand(SubCommand):
class ServiceCommand(ProjectCommand):
"""this command concerns service(s) in a project"""
def __init__(self, name, num_projects, num_services, **kwargs):
def __init__(self, name, num_projects, num_services, add_parser=True, **kwargs):
super().__init__(
name, num_projects=num_projects,
name, num_projects=num_projects, add_parser=add_parser,
**kwargs
)
@ -76,9 +77,9 @@ class FlexCommand(ServiceCommand):
__action = None
def __init__(self, name, action='', **kwargs):
def __init__(self, name, action='', add_parser=True, **kwargs):
super().__init__(
name, num_projects='?', num_services='*',
name, num_projects='?', num_services='*', add_parser=add_parser,
**kwargs
)
@ -91,8 +92,8 @@ class FlexCommand(ServiceCommand):
def _run_instance(self, runner, config, args):
result = True
for project_name in list_projects(config):
args.projects = project_name
for project in Projects.from_args(args):
args.projects = project.get_name()
result &= runner.run(str(self))
return result
@ -104,19 +105,18 @@ class FlexCommand(ServiceCommand):
pass
def run(self, runner, config, args):
project_name = get_first_project_name(args)
services = get_services(args)
if project_name is None:
projects = Projects.from_args(args)
if not projects:
# no project given, run for entire instance
logging.info(f"{self.__action} this instance")
return self._run_instance(runner, config, args)
if not services:
project = projects[0]
if args is None or 'services' not in args or not args.services:
# no services given, run for whole project
logging.info(f"{self.__action} project '{project_name}'")
logging.info(f"{self.__action} project '{project.get_name()}'")
return self._run_project(runner, config, args)
# run for service(s) inside project
logging.info(f"{self.__action} services {services} in project '{project_name}'")
return self._run_services(runner, config, args, services)
logging.info(f"{self.__action} services {args.services} in project '{project.get_name()}'")
return self._run_services(runner, config, args, args.services)

View file

@ -5,7 +5,7 @@ import subprocess
# local
from ._subcommand import SubCommand
from .utils.misc import list_projects, get_project_dir
from .utils.project import Projects
from .utils.rootkit import Rootkit, prefix_path_mnt
# parent
@ -22,13 +22,11 @@ class ConfCopyCommand(SubCommand):
)
def run(self, runner, config, args):
conf_dirs = []
for project_name in list_projects(config):
project_conf = f"{get_project_dir(config, project_name)}/{CONF_DIRECTORY_NAME}"
if os.path.isdir(project_conf):
conf_dirs.append(project_conf)
conf_dirs = [
project.conf_dir_name()
for project in Projects.all()
if project.is_enabled()
]
if conf_dirs:
# add target directory
@ -76,14 +74,11 @@ class ConfCleanCommand(SubCommand):
def run(self, runner, config, args):
result = True
# down all projects with config directories
affected_projects = []
for project_name in list_projects(config):
project_conf = f"{get_project_dir(config, project_name)}/{CONF_DIRECTORY_NAME}"
if os.path.isdir(project_conf):
affected_projects.append(project_name)
affected_projects = [
project.conf_dir_name()
for project in Projects.all()
if project.has_configs()
]
for project_name in affected_projects:
args.projects = project_name
@ -91,7 +86,7 @@ class ConfCleanCommand(SubCommand):
# cleanly sync configs
result &= runner.run('conf-purge')
result &= runner.run('conf-purge')
result &= runner.run('conf-copy')
# bring projects back up
for project_name in affected_projects:

View file

@ -1,5 +1,5 @@
# local
from .utils.project import Project
from .utils.project import Projects
from ._subcommand import ProjectCommand
@ -13,9 +13,7 @@ class DisableCommand(ProjectCommand):
)
def run(self, runner, config, args):
result = True
for project in Project.from_args(args):
result = project.disable()
return result
return all([
project.disable()
for project in Projects.from_args(args)
])

View file

@ -1,5 +1,5 @@
# local
from .utils.project import Project
from .utils.project import Projects
from ._subcommand import ProjectCommand
@ -13,9 +13,7 @@ class EnableCommand(ProjectCommand):
)
def run(self, runner, config, args):
result = True
for project in Project.from_args(args):
result = project.enable()
return result
return all([
project.enable()
for project in Projects.from_args(args)
])

View file

@ -2,11 +2,12 @@
import logging
import os
import subprocess
import yaml
# local
from ._subcommand import FlexCommand
from .utils.dockercommand import DockerCommand
from .utils.misc import list_projects, get_first_project_name, get_project_dir
from .utils.project import Projects
def _print_list(strings):
@ -31,35 +32,61 @@ class ListCommand(FlexCommand):
)
def _run_instance(self, runner, config, args):
print(f"Projects in instance {os.getcwd()}:")
print("")
print(f"kiwi-config instance at '{os.getcwd()}'")
print("#########")
projects = Projects.all()
_print_list(list_projects(config))
enableds = [
project.get_name()
for project in projects
if project.is_enabled()
]
if enableds:
print(f"Enabled projects:")
_print_list(enableds)
disableds = [
project.get_name()
for project in projects
if project.is_disabled()
]
if disableds:
print(f"Disabled projects:")
_print_list(disableds)
return True
def _run_project(self, runner, config, args):
project_name = get_first_project_name(args)
print(f"Services in project '{project_name}':")
print("")
project = Projects.from_args(args)[0]
if not project.exists():
logging.error(f"Project '{project.get_name()}' not found")
return False
print(f"Services in project '{project.get_name()}':")
print("#########")
ps = DockerCommand('docker-compose').run(
config, args, ['config', '--services'],
stdout=subprocess.PIPE
)
_print_list(ps.stdout)
_print_list(ps.stdout)
return True
def _run_services(self, runner, config, args, services):
import yaml
project = Projects.from_args(args)[0]
project_name = get_first_project_name(args)
project_dir = get_project_dir(config, project_name)
print(f"Configuration of services {services} in project '{project_name}':")
print("")
if not project.exists():
logging.error(f"Project '{project.get_name()}' not found")
return False
with open(os.path.join(project_dir, 'docker-compose.yml'), 'r') as stream:
print(f"Configuration of services {services} in project '{project.get_name()}':")
print("#########")
with open(project.compose_file_name(), 'r') as stream:
try:
docker_compose_yml = yaml.safe_load(stream)

View file

@ -4,7 +4,7 @@ import os
import shutil
# local
from .utils.misc import get_project_names, get_project_dir, get_project_down_dir
from .utils.project import Projects
from ._subcommand import ProjectCommand
# parent
@ -22,18 +22,16 @@ class NewCommand(ProjectCommand):
def run(self, runner, config, args):
result = True
projects = Projects.from_args(args)
for project_name in get_project_names(args):
project_dir = get_project_dir(config, project_name)
project_down_dir = get_project_down_dir(config, project_name)
if os.path.isdir(project_dir) or os.path.isdir(project_down_dir):
logging.error(f"Project '{project_name}' exists in this instance!")
for project in projects:
if project.exists():
logging.error(f"Project '{project.get_name()}' exists in this instance!")
result = False
else:
logging.info(f"Creating project '{project_name}'")
os.mkdir(project_dir)
shutil.copy(DEFAULT_DOCKER_COMPOSE_NAME, os.path.join(project_dir, "docker-compose.yml"))
logging.info(f"Creating project '{project.get_name()}'")
os.mkdir(project.enabled_dir_name())
shutil.copy(DEFAULT_DOCKER_COMPOSE_NAME, project.compose_file_name())
return result

View file

@ -5,18 +5,24 @@ import subprocess
# local
from .executable import Executable
from .misc import get_project_dir, get_first_project_name
from .project import Projects
# parent
from ..._constants import CONF_DIRECTORY_NAME
from ...parser import Parser
from ...config import LoadedConfig
def _update_kwargs(config, args, **kwargs):
def _update_kwargs(**kwargs):
config = LoadedConfig.get()
projects = Projects.from_args(Parser().get_args())
# project given in args: command affects a project in this instance
project_name = get_first_project_name(args)
if project_name is not None:
if projects:
project = projects[0]
# execute command in project directory
kwargs['cwd'] = get_project_dir(config, project_name)
kwargs['cwd'] = project.dir_name()
# ensure there is an environment
if 'env' not in kwargs:
@ -24,10 +30,10 @@ def _update_kwargs(config, args, **kwargs):
# create environment variables for docker commands
kwargs['env'].update({
'COMPOSE_PROJECT_NAME': project_name,
'COMPOSE_PROJECT_NAME': project.get_name(),
'KIWI_HUB_NAME': config['network:name'],
'CONFDIR': os.path.join(config['runtime:storage'], CONF_DIRECTORY_NAME),
'TARGETDIR': os.path.join(config['runtime:storage'], get_project_dir(config, project_name))
'TARGETDIR': project.target_dir_name()
})
logging.debug(f"kwargs updated: {kwargs}")
@ -53,7 +59,7 @@ class DockerCommand(Executable):
raise PermissionError("Cannot access docker, please get into the docker group or run as root!")
def run(self, config, args, process_args, **kwargs):
kwargs = _update_kwargs(config, args, **kwargs)
kwargs = _update_kwargs(**kwargs)
# equivalent to 'super().run' but agnostic of nested class construct
return super().__getattr__("run")(
@ -62,7 +68,7 @@ class DockerCommand(Executable):
)
def run_less(self, config, args, process_args, **kwargs):
kwargs = _update_kwargs(config, args, **kwargs)
kwargs = _update_kwargs(**kwargs)
return super().__getattr__("run_less")(
process_args, config,

View file

@ -1,76 +1,3 @@
import os
def get_project_names(args):
"""get project names from CLI args"""
if args is not None and 'projects' in args:
if isinstance(args.projects, list):
if args.projects:
return args.projects
else:
return None
elif isinstance(args.projects, str):
return [args.projects]
return None
def get_first_project_name(args):
"""get first project name from CLI args"""
names = get_project_names(args)
if names is not None:
return names[0]
return None
def get_services(args):
"""get services list from CLI args"""
if args is not None and 'services' in args:
return args.services
return None
def get_project_dir(config, project_name):
"""get project directory"""
return f"{project_name}{config['markers:project']}"
def get_project_down_dir(config, project_name):
"""get project directory"""
return f"{get_project_dir(config, project_name)}{config['markers:down']}"
def get_target_dir(config, project_name):
"""get project's target directory"""
return os.path.join(config['runtime:storage'], get_project_dir(config, project_name))
def list_projects(config):
"""list projects in current instance"""
# complete dir listing
content = os.listdir()
# filter directories
dirs = [d for d in content if os.path.isdir(d)]
# filter suffix
project_dirs = [p for p in dirs if p.endswith(config['markers:project'])]
# remove suffix
projects = [p[:-len(config['markers:project'])] for p in project_dirs]
return projects
def _surround(string, bang):
midlane = f"{bang * 3} {string} {bang * 3}"
sidelane = bang*len(midlane)
@ -86,6 +13,7 @@ def _emphasize(lines):
else:
return lines
def are_you_sure(prompt, default="no"):
if default.lower() == 'yes':
suffix = "[YES|no]"

View file

@ -1,79 +1,58 @@
import logging
import os
from kiwi._constants import CONF_DIRECTORY_NAME
from kiwi.config import LoadedConfig
from ..._constants import CONF_DIRECTORY_NAME
from ...config import LoadedConfig
class Project:
__name = None
__config = None
def __init__(self, name):
self.__name = name
self.__config = LoadedConfig.get()
@classmethod
def from_names(cls, names):
return [cls(name) for name in names]
@classmethod
def all(cls):
# current directory content
content = os.listdir()
# filter subdirectories
dirs = [dir_name for dir_name in content if os.path.isdir(dir_name)]
# filter by suffix
project_dirs = [dir_name for dir_name in dirs if dir_name.endswith(cls.__config['markers:project'])]
# remove suffix
project_names = [project_name[:-len(cls.__config['markers:project'])] for project_name in project_dirs]
return cls.from_names(project_names)
@classmethod
def from_args(cls, args):
if args is not None and 'projects' in args:
if isinstance(args.projects, list) and args.projects:
return cls.from_names(args.projects)
elif isinstance(args.projects, str):
return cls.from_names([args.projects])
return []
def get_name(self):
return self.__name
def dir_name(self):
return f"{self.__name}{self.__config['markers:project']}"
if self.is_enabled():
return self.enabled_dir_name()
elif self.is_disabled():
return self.disabled_dir_name()
else:
return None
def down_dir_name(self):
return f"{self.dir_name()}{self.__config['markers:down']}"
def enabled_dir_name(self):
return f"{self.__name}{LoadedConfig.get()['markers:project']}"
def disabled_dir_name(self):
return f"{self.enabled_dir_name()}{LoadedConfig.get()['markers:down']}"
def conf_dir_name(self):
return os.path.join(self.dir_name(), CONF_DIRECTORY_NAME)
def compose_file_name(self):
return os.path.join(self.dir_name(), 'docker-compose.yml')
def target_dir_name(self):
return os.path.join(self.__config['runtime:storage'], self.dir_name())
return os.path.join(LoadedConfig.get()['runtime:storage'], self.enabled_dir_name())
def exists(self):
return os.path.isdir(self.dir_name()) or os.path.isdir(self.down_dir_name())
return os.path.isdir(self.enabled_dir_name()) or os.path.isdir(self.disabled_dir_name())
def is_enabled(self):
return os.path.isdir(self.dir_name())
return os.path.isdir(self.enabled_dir_name())
def is_disabled(self):
return os.path.isdir(self.down_dir_name())
return os.path.isdir(self.disabled_dir_name())
def has_configs(self):
return os.path.isdir(self.dir_name())
return os.path.isdir(self.conf_dir_name())
def enable(self):
if self.is_disabled():
logging.info(f"Enabling project '{self.get_name()}'")
os.rename(self.down_dir_name(), self.dir_name())
os.rename(self.dir_name(), self.enabled_dir_name())
elif self.is_enabled():
logging.warning(f"Project '{self.get_name()}' is enabled!")
@ -87,7 +66,7 @@ class Project:
def disable(self):
if self.is_enabled():
logging.info(f"Disabling project '{self.get_name()}'")
os.rename(self.dir_name(), self.down_dir_name())
os.rename(self.dir_name(), self.disabled_dir_name())
elif self.is_disabled():
logging.warning(f"Project '{self.get_name()}' is disabled!")
@ -96,4 +75,53 @@ class Project:
logging.warning(f"Project '{self.get_name()}' not found in instance!")
return False
return True
return True
def _extract_project_name(file_name):
config = LoadedConfig.get()
enabled_suffix = config['markers:project']
disabled_suffix = f"{enabled_suffix}{config['markers:down']}"
if os.path.isdir(file_name):
# all subdirectories
if file_name.endswith(enabled_suffix):
# enabled projects
return file_name[:-len(enabled_suffix)]
elif file_name.endswith(disabled_suffix):
# disabled projects
return file_name[:-len(disabled_suffix)]
return None
class Projects:
__projects = None
def __init__(self, names):
self.__projects = [
Project(name)
for name in names if isinstance(name, str)
]
def __getitem__(self, item):
return self.__projects[item]
@classmethod
def all(cls):
return cls([
_extract_project_name(file_name)
for file_name in os.listdir()
])
@classmethod
def from_args(cls, args):
if args is not None and 'projects' in args:
if isinstance(args.projects, list) and args.projects:
return cls(args.projects)
elif isinstance(args.projects, str):
return cls([args.projects])
return []