from typing import Any from ...adapters import ( CERTIFICATES, PROXY_HOSTS, Capability, CapabilityOperation, DiscoveredObject, ) from ...npm_client import NpmClient _PROXY_HOST_FIELDS = ( "domain_names", "forward_scheme", "forward_host", "forward_port", "certificate_id", "ssl_forced", "caching_enabled", "block_exploits", "allow_websocket_upgrade", "http2_support", "hsts_enabled", "hsts_subdomains", "enabled", ) class Plugin: name = "npm" capabilities = frozenset( { Capability( PROXY_HOSTS, CapabilityOperation.DISCOVER, ), Capability( CERTIFICATES, CapabilityOperation.DISCOVER, ), } ) def __init__(self, config, endpoint): self.config = config self.endpoint = endpoint self.client = NpmClient(config, endpoint) @staticmethod def _local_key(row: dict[str, Any], label: str) -> str: local_id = row.get("id") if isinstance(local_id, bool) or not isinstance(local_id, int): raise RuntimeError( f"NPM {label} has invalid id: {local_id!r}" ) return str(local_id) def connect(self) -> None: self.client.login() def discover( self, object_type: str, ) -> list[DiscoveredObject]: if object_type == PROXY_HOSTS: return self._discover_proxy_hosts() if object_type == CERTIFICATES: return self._discover_certificates() raise RuntimeError( f"{self.endpoint.identity} cannot discover " f"object type {object_type!r}" ) def _discover_proxy_hosts(self) -> list[DiscoveredObject]: discovered: list[DiscoveredObject] = [] for row in self.client.proxy_hosts(): payload = { field: row.get(field) for field in _PROXY_HOST_FIELDS } discovered.append( DiscoveredObject( object_type=PROXY_HOSTS, local_key=self._local_key(row, "proxy host"), payload=payload, ) ) return discovered def _discover_certificates(self) -> list[DiscoveredObject]: discovered: list[DiscoveredObject] = [] for row in self.client.certificates(): meta = row.get("meta") if not isinstance(meta, dict): meta = {} payload = { "domain_names": list( row.get("domain_names") or [] ), "provider": str(row.get("provider") or ""), "nice_name": str(row.get("nice_name") or ""), "valid_from": row.get("valid_from"), "expires_on": row.get("expires_on"), "cluster_managed": ( meta.get("cluster_managed") is True ), "acme_renew": meta.get("acme_renew") is True, "dns_challenge": ( meta.get("dns_challenge") is True ), } discovered.append( DiscoveredObject( object_type=CERTIFICATES, local_key=self._local_key(row, "certificate"), payload=payload, ) ) return discovered def apply(self, action): raise RuntimeError( f"{self.endpoint.identity} does not support apply yet" ) def verify(self, object): raise RuntimeError( f"{self.endpoint.identity} does not support verify yet" )