portals.py 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. from typing import TYPE_CHECKING
  2. import copy
  3. if TYPE_CHECKING:
  4. from render import Render
  5. try:
  6. from .error import RenderError
  7. from .validations import valid_portal_scheme_or_raise, valid_http_path_or_raise, valid_port_or_raise
  8. except ImportError:
  9. from error import RenderError
  10. from validations import valid_portal_scheme_or_raise, valid_http_path_or_raise, valid_port_or_raise
  11. class Portals:
  12. def __init__(self, render_instance: "Render"):
  13. self._render_instance = render_instance
  14. self._portals: set[Portal] = set()
  15. def add(self, port: dict, config: dict | None = None):
  16. config = copy.deepcopy((config or {}))
  17. port = copy.deepcopy((port or {}))
  18. # If its not published, portal does not make sense
  19. if port.get("bind_mode", "") != "published":
  20. return
  21. name = config.get("name", "Web UI")
  22. if name in [p._name for p in self._portals]:
  23. raise RenderError(f"Portal [{name}] already added")
  24. host = config.get("host", None)
  25. host_ips = port.get("host_ips", [])
  26. if not isinstance(host_ips, list):
  27. raise RenderError("Expected [host_ips] to be a list of strings")
  28. # Remove wildcard IPs
  29. if "::" in host_ips:
  30. host_ips.remove("::")
  31. if "0.0.0.0" in host_ips:
  32. host_ips.remove("0.0.0.0")
  33. # If host is not set, use the first host_ip (if it exists)
  34. if not host and len(host_ips) >= 1:
  35. host = host_ips[0]
  36. config["host"] = host
  37. if not config.get("port"):
  38. config["port"] = port.get("port_number", 0)
  39. self._portals.add(Portal(name, config))
  40. def render(self):
  41. return [p.render() for _, p in sorted([(p._name, p) for p in self._portals])]
  42. class Portal:
  43. def __init__(self, name: str, config: dict):
  44. self._name = name
  45. self._scheme = valid_portal_scheme_or_raise(config.get("scheme", "http"))
  46. self._host = config.get("host", "0.0.0.0") or "0.0.0.0"
  47. self._port = valid_port_or_raise(config.get("port", 0))
  48. self._path = valid_http_path_or_raise(config.get("path", "/"))
  49. def render(self):
  50. return {
  51. "name": self._name,
  52. "scheme": self._scheme,
  53. "host": self._host,
  54. "port": self._port,
  55. "path": self._path,
  56. }