from typing import Self, Never, Callable, Sequence from custtypes import Roles, Scopes, PathCollection, PathRoles from custtypes import Software, SoftwareRoles, ExecutedPath from custtypes import PacMans, UserName, GroupName, IdlePath from custtypes import ExecutedPath, AnsibleRoles from sshkey import SSHKeyCollection, SSHKeyType, SSHKey from whereami import PROJ_ROLES class App: def __init__(self, name: Software, role: SoftwareRoles = SoftwareRoles.client, paths: PathRoles | None = None): self.__name = name.name.lower().replace("_", "-") # @TODO create dict type hint for below data struct self.alt_names = dict() self.alt_names[PacMans.APT.name.lower()] = self.__name self.role = role.name.lower() if paths is not None: if Roles.EXE in paths: setattr(self, "_" + Roles.EXE.name.lower(), paths[Roles.EXE.name.lower()]) if Roles.CONF in paths: setattr(self, "_" + Roles.CONF.name.lower(), paths[Roles.CONF.name.lower()]) if Roles.DATA in paths: setattr(self, "_" + Roles.DATA.name.lower(), paths[Roles.DATA.name.lower()]) if Roles.MEM in paths: setattr(self, "_" + Roles.MEM.name.lower(), paths[Roles.MEM.name.lower()]) self.__parents: tuple[Self] | None = None self.__children: tuple[Self| None] = [] self.__api: str | None = None self.__current_filepath: IdlePath | ExecutedPath | None = None self.__content: str | None = None @property def conf_paths(self): if hasattr(self, "_" + Roles.CONF.name.lower()): return self._conf else: raise Exception @property def data_paths(self): if hasattr(self, "_" + Roles.DATA.name.lower()): return self._data else: raise Exception @property def exec_paths(self): if hasattr(self, "_" + Roles.EXE.name.lower()): return self._exe else: raise Exception @property def mem_paths(self): if hasattr(self, "_" + Roles.MEM.name.lower()): return self._mem else: raise Exception def get_paths(self, role: Roles = Roles.CONF): if hasattr(self, "_" + role.name.lower()): return getattr(self, "_" + role.name.lower()) else: raise Exception def append(self, datatype: Roles = Roles.CONF, scope: Scopes | None = None, path: IdlePath | ExecutedPath | str | PathCollection | None = None): if path is None: raise TypeError datatype = datatype.name.lower() if hasattr(self, "_" + datatype): paths = getattr(self, "_" + datatype) else: setattr(self, "_" + datatype, dict()) paths = getattr(self, "_" + datatype) if scope is not None: if isinstance(path, str): path: ExecutedPath = Path(path) if scope.name.lower() not in paths: paths[scope.name.lower()] = [] paths[scope.name.lower()].append(path) else: paths: PathCollection = path setattr(self, "_" + datatype, paths) def inherit(self, other): if other._App__children is None: other._App__children = tuple() if self not in other._App__children: other.adopt(self) self.__parents = (*self.__parents, other) def adopt(self, other: Self): if other._App__parents is None: other._App__parents = tuple() if self not in other._App__parent: other.inherit(self) self.__children = (*self.__children, other) def __enter__(self) -> dict | Sequence: self.__content = self.__current_filepath.read_text() return self.__content def __exit__(self, exc_type, exc_value, exc_traceback) -> None: # txt = yams.dump(self.__content) # self.__file.write(txt) # del txt self.__file.close() def __call__(self, path = str, mode = "r+", scope: Scopes = Scopes.PROJ, role: Roles = Roles.CONF, index: int = 0) -> Callable: if not hasattr(self, "_" + role.name.lower()): raise Exception else: config = getattr(self, "_" + role.name.lower()) conf_coll = config[scope.name.lower()] if isinstance(conf_coll, Sequence): conf_coll = conf_coll[index] if isinstance(conf_coll, str): conf_coll = Path(conf_coll) filepath = conf_coll / path self.__current_filepath = filepath self.__file = open(str(filepath), mode) return __enter__ # @TODO write below method to duplicate file or template in local to project role file/template def clone(self, source_scope: Scopes = Scopes.SYS, target_scope: Scopes = Scopes.PROJ, index: int = 0) -> Never: raise NotImplementedError def declare(self, **kwargs): for k, v in kwargs.items(): setattr(self, k, v) sshd_proj_files = map(lambda r: r / AnsibleRoles.bootstrap.name.lower() / "files" / "sshd_config.d", PROJ_ROLES) sshd_proj_files = list(filter(lambda p: p.exists(), sshd_proj_files)) sshd_proj_templates = map(lambda r: r / AnsibleRoles.bootstrap.name.lower() / "templates" / "sshd_config.d", PROJ_ROLES) sshd_proj_templates = list(filter(lambda p: p.exists(), sshd_proj_templates)) # @TODO rewrite below using DIR_ROOTS var from whereami module sshd_paths: PathRoles = { Roles.CONF.name.lower(): { Scopes.PROJ.name.lower(): sshd_proj_files + sshd_proj_templates } } sshd = App(Software.openssh_server, SoftwareRoles.server, sshd_paths)