manifest_template.py 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. import jinja2
  2. import base64
  3. import yaml
  4. from typing import List, Optional
  5. from gpustack.utils.compat_importlib import pkg_resources
  6. from gpustack.schemas.clusters import ClusterRegistrationTokenPublic
  7. from gpustack.schemas.clusters import K8sVolumeMount
  8. from gpustack_runtime.detector import ManufacturerEnum
  9. class TemplateConfig(ClusterRegistrationTokenPublic):
  10. namespace: Optional[str] = None
  11. cluster_suffix: Optional[str] = None
  12. runtime_enum: Optional[ManufacturerEnum] = None
  13. runtime: Optional[str] = None
  14. k8s_volume_mounts: Optional[List[K8sVolumeMount]] = None
  15. def render(self) -> str:
  16. def b64encode(value):
  17. return base64.b64encode(value.encode("utf-8")).decode("utf-8")
  18. def to_yaml(value):
  19. if hasattr(value, "model_dump"):
  20. value = value.model_dump(by_alias=True, exclude_none=True)
  21. elif isinstance(value, list):
  22. value = [
  23. (
  24. v.model_dump(by_alias=True, exclude_none=True)
  25. if hasattr(v, "model_dump")
  26. else v
  27. )
  28. for v in value
  29. ]
  30. dumped = yaml.dump(value, default_flow_style=False)
  31. if dumped.endswith("...\n"):
  32. dumped = dumped[:-4]
  33. return dumped.strip()
  34. with pkg_resources.path("gpustack.k8s", "manifests.jinja") as manifest_path:
  35. with manifest_path.open(encoding="utf-8") as f:
  36. template_data = f.read()
  37. with pkg_resources.path("gpustack.k8s", "daemonset.jinja") as daemon_set_path:
  38. with daemon_set_path.open(encoding="utf-8") as f:
  39. daemon_set_data = f.read()
  40. env = jinja2.Environment()
  41. env.filters["b64encode"] = b64encode
  42. env.filters["to_yaml"] = to_yaml
  43. template = env.from_string(template_data)
  44. rendered = template.render(config=self)
  45. template_daemonset = env.from_string(daemon_set_data)
  46. daemon_set = template_daemonset.render(config=self)
  47. return "\n".join([rendered, daemon_set])
  48. def __init__(
  49. self, registration: Optional[ClusterRegistrationTokenPublic] = None, **data
  50. ):
  51. if registration is not None:
  52. base_data = registration.model_dump()
  53. base_data.update(data)
  54. super().__init__(**base_data)
  55. else:
  56. super().__init__(**data)
  57. if self.namespace is None and self.cluster_suffix is not None:
  58. self.namespace = f"gpustack-system-{self.cluster_suffix}"
  59. elif self.namespace is None:
  60. self.namespace = "gpustack-system"
  61. self.runtime = (
  62. self.runtime_enum.value if self.runtime_enum is not None else None
  63. )