From 1d5c4ccbee0bf7f23cf8436db79cb74fd151f515 Mon Sep 17 00:00:00 2001 From: ldericher <40151420+ldericher@users.noreply.github.com> Date: Thu, 2 Dec 2021 17:08:14 +0100 Subject: [PATCH] Split instance.py --- kiwi_scp/commands/cli.py | 4 +- kiwi_scp/commands/cmd_build.py | 3 +- kiwi_scp/commands/cmd_cmd.py | 3 +- kiwi_scp/commands/cmd_disable.py | 3 +- kiwi_scp/commands/cmd_down.py | 4 +- kiwi_scp/commands/cmd_enable.py | 3 +- kiwi_scp/commands/cmd_list.py | 3 +- kiwi_scp/commands/cmd_logs.py | 4 +- kiwi_scp/commands/cmd_up.py | 4 +- kiwi_scp/instance.py | 132 +------------------------------ kiwi_scp/project.py | 69 ++++++++++++++++ kiwi_scp/service.py | 44 +++++++++++ kiwi_scp/services.py | 36 +++++++++ tests/test_project.py | 2 +- tests/test_service.py | 2 +- tests/test_services.py | 3 +- 16 files changed, 178 insertions(+), 141 deletions(-) create mode 100644 kiwi_scp/project.py create mode 100644 kiwi_scp/service.py create mode 100644 kiwi_scp/services.py diff --git a/kiwi_scp/commands/cli.py b/kiwi_scp/commands/cli.py index cb538bc..acd09b6 100644 --- a/kiwi_scp/commands/cli.py +++ b/kiwi_scp/commands/cli.py @@ -7,7 +7,9 @@ from typing import List, Iterable, Type, Optional, TypeVar import click -from ..instance import Instance, Project, Services +from ..instance import Instance +from ..project import Project +from ..services import Services from ..wstring import WParagraph, WAlignment _logger = logging.getLogger(__name__) diff --git a/kiwi_scp/commands/cmd_build.py b/kiwi_scp/commands/cmd_build.py index 57008a0..338f5b7 100644 --- a/kiwi_scp/commands/cmd_build.py +++ b/kiwi_scp/commands/cmd_build.py @@ -3,7 +3,8 @@ from typing import List from .cli import KiwiCommand, KiwiCommandType from .decorators import kiwi_command from ..executable import COMPOSE_EXE -from ..instance import Instance, Project +from ..instance import Instance +from ..project import Project @kiwi_command( diff --git a/kiwi_scp/commands/cmd_cmd.py b/kiwi_scp/commands/cmd_cmd.py index 58996f7..15cfdfa 100644 --- a/kiwi_scp/commands/cmd_cmd.py +++ b/kiwi_scp/commands/cmd_cmd.py @@ -5,7 +5,8 @@ import click from .cli import KiwiCommand, KiwiCommandType from .decorators import kiwi_command from ..executable import COMPOSE_EXE -from ..instance import Instance, Project +from ..instance import Instance +from ..project import Project @click.argument( diff --git a/kiwi_scp/commands/cmd_disable.py b/kiwi_scp/commands/cmd_disable.py index 6a146d0..8b6b2ef 100644 --- a/kiwi_scp/commands/cmd_disable.py +++ b/kiwi_scp/commands/cmd_disable.py @@ -3,7 +3,8 @@ import click from .cli import KiwiCommand, KiwiCommandType from .decorators import kiwi_command from .._constants import KIWI_CONF_NAME -from ..instance import Instance, Project +from ..instance import Instance +from ..project import Project @click.option( diff --git a/kiwi_scp/commands/cmd_down.py b/kiwi_scp/commands/cmd_down.py index b055328..960559a 100644 --- a/kiwi_scp/commands/cmd_down.py +++ b/kiwi_scp/commands/cmd_down.py @@ -5,7 +5,9 @@ import click from .cli import KiwiCommand, KiwiCommandType from .decorators import kiwi_command from ..executable import COMPOSE_EXE -from ..instance import Instance, Project, Services +from ..instance import Instance +from ..project import Project +from ..services import Services @click.option( diff --git a/kiwi_scp/commands/cmd_enable.py b/kiwi_scp/commands/cmd_enable.py index 9f7eadc..6f3676b 100644 --- a/kiwi_scp/commands/cmd_enable.py +++ b/kiwi_scp/commands/cmd_enable.py @@ -3,7 +3,8 @@ import click from .cli import KiwiCommand, KiwiCommandType from .decorators import kiwi_command from .._constants import KIWI_CONF_NAME -from ..instance import Instance, Project +from ..instance import Instance +from ..project import Project @click.option( diff --git a/kiwi_scp/commands/cmd_list.py b/kiwi_scp/commands/cmd_list.py index 5c98568..e07719a 100644 --- a/kiwi_scp/commands/cmd_list.py +++ b/kiwi_scp/commands/cmd_list.py @@ -4,7 +4,8 @@ import click from .cli import KiwiCommandType, KiwiCommand from .decorators import kiwi_command -from ..instance import Instance, Project +from ..instance import Instance +from ..project import Project @click.option( diff --git a/kiwi_scp/commands/cmd_logs.py b/kiwi_scp/commands/cmd_logs.py index f31a066..581c966 100644 --- a/kiwi_scp/commands/cmd_logs.py +++ b/kiwi_scp/commands/cmd_logs.py @@ -5,7 +5,9 @@ import click from .cli import KiwiCommand, KiwiCommandType from .decorators import kiwi_command from ..executable import COMPOSE_EXE -from ..instance import Instance, Project, Services +from ..instance import Instance +from ..project import Project +from ..services import Services @click.option( diff --git a/kiwi_scp/commands/cmd_up.py b/kiwi_scp/commands/cmd_up.py index 8485bdb..8764953 100644 --- a/kiwi_scp/commands/cmd_up.py +++ b/kiwi_scp/commands/cmd_up.py @@ -5,7 +5,9 @@ import click from .cli import KiwiCommand, KiwiCommandType from .decorators import kiwi_command from ..executable import COMPOSE_EXE -from ..instance import Instance, Project, Services +from ..instance import Instance +from ..project import Project +from ..services import Services @kiwi_command(short_help="Bring up kiwi services") diff --git a/kiwi_scp/instance.py b/kiwi_scp/instance.py index 3c7cd03..f5f63b6 100644 --- a/kiwi_scp/instance.py +++ b/kiwi_scp/instance.py @@ -1,136 +1,10 @@ -import functools -import re -import subprocess from pathlib import Path -from typing import Generator, List, Optional, Dict, Any +from typing import Generator import attr -from ruamel.yaml.comments import CommentedMap -from ._constants import COMPOSE_FILE_NAME, CONF_DIRECTORY_NAME -from .config import KiwiConfig, ProjectConfig -from .executable import COMPOSE_EXE -from .yaml import YAML - - -@attr.s -class Service: - name: str = attr.ib() - content: CommentedMap = attr.ib() - parent: "Project" = attr.ib() - - _RE_CONFDIR = re.compile(r"^\s*\$(?:CONFDIR|{CONFDIR})/+(.*)$", flags=re.UNICODE) - - @property - def configs(self) -> Generator[Path, None, None]: - if "volumes" not in self.content: - return - - for volume in self.content["volumes"]: - host_part = volume.split(":")[0] - cd_match = Service._RE_CONFDIR.match(host_part) - - if cd_match: - yield Path(cd_match.group(1)) - - def has_executable(self, exe_name: str) -> bool: - try: - # test if desired executable exists - COMPOSE_EXE.run( - ["exec", "-T", self.name, "/bin/sh", "-c", f"command -v {exe_name}"], - check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, - **self.parent.process_kwargs, - ) - return True - - except subprocess.CalledProcessError: - return False - - -@attr.s -class Services: - content: List[Service] = attr.ib() - - def __str__(self) -> str: - return YAML().dump({ - "services": { - service.name: service.content - for service in self.content - } - }).strip() - - def __bool__(self) -> bool: - return bool(self.content) - - @property - def names(self) -> Generator[str, None, None]: - return ( - service.name - for service in self.content - ) - - def filter_existing(self, service_names: List[str]) -> "Services": - return Services([ - service - for service in self.content - if service.name in service_names - ]) - - -@attr.s -class Project: - directory: Path = attr.ib() - parent: "Instance" = attr.ib() - - @staticmethod - @functools.lru_cache(maxsize=10) - def _parse_compose_file(directory: Path) -> CommentedMap: - with open(directory.joinpath(COMPOSE_FILE_NAME), "r") as cf: - return YAML().load(cf) - - @property - def name(self) -> str: - return self.directory.name - - @property - def config(self) -> Optional[ProjectConfig]: - return self.parent.config.get_project_config(self.name) - - @property - def process_kwargs(self) -> Dict[str, Any]: - directory: Path = self.directory - project_name: str = self.name - kiwi_hub_name: str = self.parent.config.network.name - target_root_dir: Path = self.parent.config.storage.directory - conf_dir: Path = target_root_dir.joinpath(CONF_DIRECTORY_NAME) - target_dir: Path = target_root_dir.joinpath(project_name) - - result: Dict[str, Any] = { - "cwd": str(directory), - "env": { - "COMPOSE_PROJECT_NAME": project_name, - "KIWI_HUB_NAME": kiwi_hub_name, - "TARGETROOT": str(target_root_dir), - "CONFDIR": str(conf_dir), - "TARGETDIR": str(target_dir), - }, - } - - result["env"].update(self.parent.config.environment) - - return result - - @property - def services(self) -> Services: - yml = Project._parse_compose_file(self.directory) - - return Services([ - Service( - name=name, - content=content, - parent=self, - ) for name, content in yml["services"].items() - ]) +from .config import KiwiConfig +from .project import Project @attr.s diff --git a/kiwi_scp/project.py b/kiwi_scp/project.py new file mode 100644 index 0000000..b6154a4 --- /dev/null +++ b/kiwi_scp/project.py @@ -0,0 +1,69 @@ +import functools +from pathlib import Path +from typing import Optional, Dict, Any + +import attr +from ruamel.yaml import CommentedMap + +from ._constants import COMPOSE_FILE_NAME, CONF_DIRECTORY_NAME +from .config import ProjectConfig +from .instance import Instance +from .service import Service +from .services import Services +from .yaml import YAML + + +@attr.s +class Project: + directory: Path = attr.ib() + parent: "Instance" = attr.ib() + + @staticmethod + @functools.lru_cache(maxsize=10) + def _parse_compose_file(directory: Path) -> CommentedMap: + with open(directory.joinpath(COMPOSE_FILE_NAME), "r") as cf: + return YAML().load(cf) + + @property + def name(self) -> str: + return self.directory.name + + @property + def config(self) -> Optional[ProjectConfig]: + return self.parent.config.get_project_config(self.name) + + @property + def process_kwargs(self) -> Dict[str, Any]: + directory: Path = self.directory + project_name: str = self.name + kiwi_hub_name: str = self.parent.config.network.name + target_root_dir: Path = self.parent.config.storage.directory + conf_dir: Path = target_root_dir.joinpath(CONF_DIRECTORY_NAME) + target_dir: Path = target_root_dir.joinpath(project_name) + + result: Dict[str, Any] = { + "cwd": str(directory), + "env": { + "COMPOSE_PROJECT_NAME": project_name, + "KIWI_HUB_NAME": kiwi_hub_name, + "TARGETROOT": str(target_root_dir), + "CONFDIR": str(conf_dir), + "TARGETDIR": str(target_dir), + }, + } + + result["env"].update(self.parent.config.environment) + + return result + + @property + def services(self) -> Services: + yml = Project._parse_compose_file(self.directory) + + return Services([ + Service( + name=name, + content=content, + parent=self, + ) for name, content in yml["services"].items() + ]) \ No newline at end of file diff --git a/kiwi_scp/service.py b/kiwi_scp/service.py new file mode 100644 index 0000000..ae282b1 --- /dev/null +++ b/kiwi_scp/service.py @@ -0,0 +1,44 @@ +import re +import subprocess +from pathlib import Path +from typing import Generator + +import attr +from ruamel.yaml import CommentedMap + +from .executable import COMPOSE_EXE +from .project import Project + + +@attr.s +class Service: + name: str = attr.ib() + content: CommentedMap = attr.ib() + parent: "Project" = attr.ib() + + _RE_CONFDIR = re.compile(r"^\s*\$(?:CONFDIR|{CONFDIR})/+(.*)$", flags=re.UNICODE) + + @property + def configs(self) -> Generator[Path, None, None]: + if "volumes" not in self.content: + return + + for volume in self.content["volumes"]: + host_part = volume.split(":")[0] + cd_match = Service._RE_CONFDIR.match(host_part) + + if cd_match: + yield Path(cd_match.group(1)) + + def has_executable(self, exe_name: str) -> bool: + try: + # test if desired executable exists + COMPOSE_EXE.run( + ["exec", "-T", self.name, "/bin/sh", "-c", f"command -v {exe_name}"], + check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, + **self.parent.process_kwargs, + ) + return True + + except subprocess.CalledProcessError: + return False \ No newline at end of file diff --git a/kiwi_scp/services.py b/kiwi_scp/services.py new file mode 100644 index 0000000..df8187b --- /dev/null +++ b/kiwi_scp/services.py @@ -0,0 +1,36 @@ +from typing import List, Generator + +import attr + +from kiwi_scp.service import Service +from kiwi_scp.yaml import YAML + + +@attr.s +class Services: + content: List[Service] = attr.ib() + + def __str__(self) -> str: + return YAML().dump({ + "services": { + service.name: service.content + for service in self.content + } + }).strip() + + def __bool__(self) -> bool: + return bool(self.content) + + @property + def names(self) -> Generator[str, None, None]: + return ( + service.name + for service in self.content + ) + + def filter_existing(self, service_names: List[str]) -> "Services": + return Services([ + service + for service in self.content + if service.name in service_names + ]) \ No newline at end of file diff --git a/tests/test_project.py b/tests/test_project.py index aef5915..f6fabff 100644 --- a/tests/test_project.py +++ b/tests/test_project.py @@ -4,7 +4,7 @@ import pytest from kiwi_scp._constants import COMPOSE_FILE_NAME from kiwi_scp.config import KiwiConfig -from kiwi_scp.instance import Project +from kiwi_scp.project import Project class TestDefault: diff --git a/tests/test_service.py b/tests/test_service.py index 1eb9e0a..9206374 100644 --- a/tests/test_service.py +++ b/tests/test_service.py @@ -2,7 +2,7 @@ from pathlib import Path from ruamel.yaml import CommentedMap -from kiwi_scp.instance import Service +from kiwi_scp.service import Service class TestDefault: diff --git a/tests/test_services.py b/tests/test_services.py index ff349ef..b6dd451 100644 --- a/tests/test_services.py +++ b/tests/test_services.py @@ -1,6 +1,7 @@ from ruamel.yaml import CommentedMap -from kiwi_scp.instance import Service, Services +from kiwi_scp.services import Services +from kiwi_scp.service import Service class TestServices: