From 9d3ce193e8f7865314a53f656a2173b61ac8bce92c14c4c056f9df13a97a729b Mon Sep 17 00:00:00 2001 From: Christian Camper Date: Mon, 15 Dec 2025 01:03:25 -0600 Subject: [PATCH] sync --- src/compose/cfg/get.py | 61 +++++++++++++++++++++-- src/compose/compose/entity.py | 31 ++++++------ src/compose/net/entities.py | 32 ++++++------ src/compose/service/entity.py | 92 +++++++++++------------------------ 4 files changed, 117 insertions(+), 99 deletions(-) diff --git a/src/compose/cfg/get.py b/src/compose/cfg/get.py index 58e9b77..34fb454 100644 --- a/src/compose/cfg/get.py +++ b/src/compose/cfg/get.py @@ -3,9 +3,9 @@ from typing import cast from compose.cfg.entity import CfgData, CfgDataYaml, OrgData from compose.compose.entity import VolYaml -from compose.service.entity import Service +from compose.service.entity import Service, T_Compose from compose.service.factory import services_yaml_factory -from compose.util import read_yml +from compose.util import get_replace_name, read_yml def cfg_get_orgs(data: CfgDataYaml) -> Iterator[OrgData]: @@ -16,10 +16,63 @@ def cfg_get_orgs(data: CfgDataYaml) -> Iterator[OrgData]: ) +def _get_sec_opts( + data: T_Compose, +) -> frozenset[str]: + sec_opts = frozenset( + "no-new-privileges:true", + ) + sec = data.get("security_opt") + if not sec: + return sec_opts + return sec_opts.union(sec) + + +def _get_labels( + data: T_Compose, +) -> frozenset[str] | None: + org_name = get_replace_name("org_name") + url = get_replace_name("url") + traefik_labels = frozenset( + ( + f"traefik.http.routers.{org_name}.rule=Host(`{url}`)", + f"traefik.http.routers.{org_name}.entrypoints=websecure", + f"traefik.docker.network={org_name}_proxy", + f"traefik.http.routers.{org_name}.tls.certresolver=le", + ) + ) + labels = data.get("labels") + if not labels: + return + if "traefik.enable=true" not in labels: + return frozenset(labels) + return traefik_labels.union(labels) + + def cfg_get_services(cfg_data: CfgData) -> Iterator[tuple[str, Service]]: for path in cfg_data.services: - _dict = services_yaml_factory(path) - yield path.stem, Service.from_dict(_dict) + data = services_yaml_factory(path) + # yield path.stem, Service.from_dict(data) + # @classmethod + command = data.get("command") + volumes = data.get("volumes") + entry = data.get("entrypoint") + + service = Service( + tuple(command) if command else None, + get_replace_name("org_name"), + tuple(entry) if entry else None, + data.get("environment"), + data["image"], + _get_labels(data), + None, + Service.get_nets(data), + "unless-stopped", + _get_sec_opts(data), + data.get("user"), + frozenset(volumes) if volumes else None, + ) + yield path.stem, service def cfg_get_volumes(cfg_data: CfgData) -> Iterator[tuple[str, VolYaml]]: diff --git a/src/compose/compose/entity.py b/src/compose/compose/entity.py index 9168f20..c27e4a3 100644 --- a/src/compose/compose/entity.py +++ b/src/compose/compose/entity.py @@ -1,11 +1,10 @@ from dataclasses import asdict, dataclass -from typing import Literal, NotRequired, Self, TypedDict, final +from typing import Literal, NotRequired, TypedDict, final from compose.cfg import T_YamlDict from compose.cfg.entity import CfgData from compose.net.entities import Net, NetTraefik, NetYaml from compose.service.entity import Service, ServiceYaml, TraefikService -from compose.service.get import services_get_networks from compose.util import to_yaml type VolYaml = dict[str, T_YamlDict] @@ -26,25 +25,25 @@ class Compose: networks: Net | None volumes: VolYaml | None - @classmethod - def from_dict(cls, cfg: CfgData, data: ComposeYaml) -> Self: - # services = dict[str, ComposeService]() - services = dict(_get_services_dict(data)) - # vols = frozenset(_get_volumes_dict(data)) - return cls( - cfg, - services, - services_get_networks(services.values()), - data.get("volumes"), - ) + # @classmethod + # def from_dict(cls, cfg: CfgData, data: ComposeYaml) -> Self: + # # services = dict[str, ComposeService]() + # services = dict(_get_services_dict(data)) + # # vols = frozenset(_get_volumes_dict(data)) + # return cls( + # cfg, + # services, + # services_get_networks(services.values()), + # data.get("volumes"), + # ) def as_yaml(self) -> str: return to_yaml(asdict(self)) -def _get_services_dict(data: ComposeYaml): - for k, v in data["services"].items(): - yield k, Service.from_dict(v) +# def _get_services_dict(data: ComposeYaml): +# for k, v in data["services"].items(): +# yield k, Service.from_dict(v) # def _get_volumes_dict(data: ComposeYaml) -> Iterator[VolYaml]: diff --git a/src/compose/net/entities.py b/src/compose/net/entities.py index 015eefa..108703a 100644 --- a/src/compose/net/entities.py +++ b/src/compose/net/entities.py @@ -1,5 +1,5 @@ from dataclasses import dataclass -from typing import NotRequired, Self, TypedDict, final +from typing import NotRequired, TypedDict, final type NetTraefik = dict[str, NetArgs] @@ -15,12 +15,12 @@ class NetArgs: name: str external: bool | None - @classmethod - def from_dict(cls, data: NetArgsYaml) -> Self: - return cls( - data["name"], - data.get("external"), - ) + # @classmethod + # def from_dict(cls, data: NetArgsYaml) -> Self: + # return cls( + # data["name"], + # data.get("external"), + # ) class NetYaml(TypedDict): @@ -34,12 +34,12 @@ class Net: internal: NetArgs | None proxy: NetArgs | None - @classmethod - def from_class(cls, data: NetYaml) -> Self: - internal = data.get("internal") - if internal is not None: - internal = NetArgs.from_dict(internal) - proxy = data.get("proxy") - if proxy is not None: - proxy = NetArgs.from_dict(proxy) - return cls(internal, proxy) + # @classmethod + # def from_dict(cls, data: NetYaml) -> Self: + # internal = data.get("internal") + # if internal is not None: + # internal = NetArgs.from_dict(internal) + # proxy = data.get("proxy") + # if proxy is not None: + # proxy = NetArgs.from_dict(proxy) + # return cls(internal, proxy) diff --git a/src/compose/service/entity.py b/src/compose/service/entity.py index 8ea2bce..5a47acc 100644 --- a/src/compose/service/entity.py +++ b/src/compose/service/entity.py @@ -1,9 +1,8 @@ from abc import ABCMeta, abstractmethod from dataclasses import dataclass -from typing import Literal, NotRequired, Self, TypedDict, TypeVar, overload, override +from typing import Literal, NotRequired, TypedDict, TypeVar, overload, override from compose.cfg import T_Primitive -from compose.util import get_replace_name type T_NetAbc = str | Literal["proxy", "internal"] TCo_NetABC = TypeVar("TCo_NetABC", bound=T_NetAbc, covariant=True) @@ -57,35 +56,35 @@ class ServiceAbc[T_net: T_NetAbc, T_Yaml: T_Compose](metaclass=ABCMeta): user: str | None volumes: frozenset[str] | None - @classmethod - def from_dict(cls, data: T_Yaml) -> Self: - command = data.get("command") - volumes = data.get("volumes") - entry = data.get("entrypoint") - name = data.get("container_name") - if name is None: - raise KeyError - return cls( - tuple(command) if command else None, - name, - tuple(entry) if entry else None, - data.get("environment"), - data["image"], - _get_labels(data), - None, - cls.get_nets(data), - "unless-stopped", - _get_sec_opts(data), - data.get("user"), - frozenset(volumes) if volumes else None, - ) + # @classmethod + # def from_dict(cls, data: T_Yaml) -> Self: + # command = data.get("command") + # volumes = data.get("volumes") + # entry = data.get("entrypoint") + # name = data.get("container_name") + # if name is None: + # raise KeyError + # return cls( + # tuple(command) if command else None, + # name, + # tuple(entry) if entry else None, + # data.get("environment"), + # data["image"], + # _get_labels(data), + # None, + # cls.get_nets(data), + # "unless-stopped", + # _get_sec_opts(data), + # data.get("user"), + # frozenset(volumes) if volumes else None, + # ) - def is_valid(self) -> bool: - attrs = (self.container_name, self.restart, self.logging) - for attr in attrs: - if attr is None: - return False - return True + # def is_valid(self) -> bool: + # attrs = (self.container_name, self.restart, self.logging) + # for attr in attrs: + # if attr is None: + # return False + # return True @staticmethod @abstractmethod @@ -127,36 +126,3 @@ def _get_nets( if nets is None: return return frozenset(nets) - - -def _get_sec_opts( - data: T_Compose, -) -> frozenset[str]: - sec_opts = frozenset( - "no-new-privileges:true", - ) - sec = data.get("security_opt") - if not sec: - return sec_opts - return sec_opts.union(sec) - - -def _get_labels( - data: T_Compose, -) -> frozenset[str] | None: - org_name = get_replace_name("org_name") - url = get_replace_name("url") - traefik_labels = frozenset( - ( - f"traefik.http.routers.{org_name}.rule=Host(`{url}`)", - f"traefik.http.routers.{org_name}.entrypoints=websecure", - f"traefik.docker.network={org_name}_proxy", - f"traefik.http.routers.{org_name}.tls.certresolver=le", - ) - ) - labels = data.get("labels") - if not labels: - return - if "traefik.enable=true" not in labels: - return frozenset(labels) - return traefik_labels.union(labels)