12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273 |
- from typing import TYPE_CHECKING
- import copy
- if TYPE_CHECKING:
- from render import Render
- try:
- from .error import RenderError
- from .validations import valid_portal_scheme_or_raise, valid_http_path_or_raise, valid_port_or_raise
- except ImportError:
- from error import RenderError
- from validations import valid_portal_scheme_or_raise, valid_http_path_or_raise, valid_port_or_raise
- class Portals:
- def __init__(self, render_instance: "Render"):
- self._render_instance = render_instance
- self._portals: set[Portal] = set()
- def add(self, port: dict, config: dict | None = None):
- config = copy.deepcopy((config or {}))
- port = copy.deepcopy((port or {}))
- # If its not published, portal does not make sense
- if port.get("bind_mode", "") != "published":
- return
- name = config.get("name", "Web UI")
- if name in [p._name for p in self._portals]:
- raise RenderError(f"Portal [{name}] already added")
- host = config.get("host", None)
- host_ips = port.get("host_ips", [])
- if not isinstance(host_ips, list):
- raise RenderError("Expected [host_ips] to be a list of strings")
- # Remove wildcard IPs
- if "::" in host_ips:
- host_ips.remove("::")
- if "0.0.0.0" in host_ips:
- host_ips.remove("0.0.0.0")
- # If host is not set, use the first host_ip (if it exists)
- if not host and len(host_ips) >= 1:
- host = host_ips[0]
- config["host"] = host
- if not config.get("port"):
- config["port"] = port.get("port_number", 0)
- self._portals.add(Portal(name, config))
- def render(self):
- return [p.render() for _, p in sorted([(p._name, p) for p in self._portals])]
- class Portal:
- def __init__(self, name: str, config: dict):
- self._name = name
- self._scheme = valid_portal_scheme_or_raise(config.get("scheme", "http"))
- self._host = config.get("host", "0.0.0.0") or "0.0.0.0"
- self._port = valid_port_or_raise(config.get("port", 0))
- self._path = valid_http_path_or_raise(config.get("path", "/"))
- def render(self):
- return {
- "name": self._name,
- "scheme": self._scheme,
- "host": self._host,
- "port": self._port,
- "path": self._path,
- }
|