2022-01-27 16:57:15 +00:00
|
|
|
import subprocess
|
2022-01-27 14:26:10 +00:00
|
|
|
from pathlib import Path
|
2022-01-27 16:57:15 +00:00
|
|
|
from typing import List, Generator, Optional, TYPE_CHECKING, TypeVar, Union
|
2021-12-02 16:08:14 +00:00
|
|
|
|
|
|
|
import attr
|
|
|
|
|
2022-01-27 16:57:15 +00:00
|
|
|
from .rootkit import Rootkit
|
2022-01-24 17:06:11 +00:00
|
|
|
from .yaml import YAML
|
2021-12-02 16:08:14 +00:00
|
|
|
|
2022-01-27 14:26:10 +00:00
|
|
|
if TYPE_CHECKING:
|
2022-01-27 16:57:15 +00:00
|
|
|
from .project import Project
|
2022-01-27 14:26:10 +00:00
|
|
|
from .service import Service
|
|
|
|
|
2021-12-02 16:08:14 +00:00
|
|
|
|
|
|
|
@attr.s
|
|
|
|
class Services:
|
2022-01-27 14:26:10 +00:00
|
|
|
content: List["Service"] = attr.ib()
|
2021-12-02 16:08:14 +00:00
|
|
|
|
|
|
|
def __str__(self) -> str:
|
|
|
|
return YAML().dump({
|
|
|
|
"services": {
|
|
|
|
service.name: service.content
|
|
|
|
for service in self.content
|
2022-01-27 16:57:15 +00:00
|
|
|
},
|
|
|
|
"configs": [
|
|
|
|
str(config)
|
|
|
|
for config in self.configs
|
|
|
|
],
|
2021-12-02 16:08:14 +00:00
|
|
|
}).strip()
|
|
|
|
|
|
|
|
def __bool__(self) -> bool:
|
|
|
|
return bool(self.content)
|
|
|
|
|
2022-01-27 14:26:10 +00:00
|
|
|
@property
|
2022-01-27 16:57:15 +00:00
|
|
|
def parent_project(self) -> Optional["Project"]:
|
2022-01-27 14:26:10 +00:00
|
|
|
if not self:
|
|
|
|
return
|
|
|
|
|
2022-01-27 16:57:15 +00:00
|
|
|
return self.content[0].parent_project
|
2022-01-27 14:26:10 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
def configs(self) -> Generator[Path, None, None]:
|
|
|
|
for service in self.content:
|
|
|
|
yield from service.configs
|
|
|
|
|
2022-01-27 16:57:15 +00:00
|
|
|
def copy_configs(self) -> None:
|
|
|
|
path_str_list = TypeVar("path_str_list", Union[Path, str], List[Union[Path, str]])
|
|
|
|
|
|
|
|
def prefix_path(path: path_str_list, prefix: Path) -> path_str_list:
|
|
|
|
if isinstance(path, Path):
|
|
|
|
return prefix.absolute().joinpath(path)
|
|
|
|
|
|
|
|
elif isinstance(path, str):
|
|
|
|
return prefix_path(Path(path), prefix)
|
|
|
|
|
|
|
|
elif isinstance(path, list):
|
|
|
|
return [prefix_path(p, prefix) for p in path]
|
|
|
|
|
|
|
|
project = self.parent_project
|
|
|
|
|
|
|
|
if project is None:
|
|
|
|
return
|
|
|
|
|
|
|
|
instance = project.parent_instance
|
|
|
|
cfgs = list(self.configs)
|
|
|
|
|
|
|
|
local_cfgs = prefix_path(cfgs, instance.config_directory)
|
|
|
|
storage_cfgs = prefix_path(cfgs, instance.storage_config_directory)
|
|
|
|
storage_dirs = [path.parent for path in storage_cfgs]
|
|
|
|
|
|
|
|
Rootkit("rsync").run([
|
|
|
|
"mkdir", "-p", storage_dirs
|
|
|
|
], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
|
|
|
|
|
|
|
Rootkit("rsync").run([
|
|
|
|
"rsync", "-rpt", list(zip(local_cfgs, storage_cfgs))
|
|
|
|
], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
2022-01-24 17:07:19 +00:00
|
|
|
|
2021-12-02 16:08:14 +00:00
|
|
|
@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
|
2022-01-24 17:06:11 +00:00
|
|
|
])
|