Skip to content

Commit 9e6741d

Browse files
cursor[bot]cursoragentblainekasten
authored
feat: expose GPU cluster add-on flags for headlamp and slurm web (#461)
* feat(cli): expose cluster add-on flags Co-authored-by: Blaine Kasten <blainekasten@gmail.com> * fix(cli): suppress negative add-on flag variants Co-authored-by: Blaine Kasten <blainekasten@gmail.com> * fix(cli): rename cluster add-on flags Co-authored-by: Blaine Kasten <blainekasten@gmail.com> --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Blaine Kasten <blainekasten@gmail.com>
1 parent 5da1f1b commit 9e6741d

3 files changed

Lines changed: 62 additions & 1 deletion

File tree

src/together/lib/cli/api/beta/clusters/create.py

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from together._utils._json import openapi_dumps
99
from together.lib.cli.utils.config import CLIConfigParameter
1010
from together.lib.cli.utils._console import console
11-
from together.types.beta.cluster_create_params import SharedVolume, ClusterCreateParams
11+
from together.types.beta.cluster_create_params import AddOn, SharedVolume, ClusterCreateParams
1212

1313
NameParameter = Annotated[Optional[str], Parameter(help="Name of the cluster")]
1414
NumGpusParameter = Annotated[Optional[int], Parameter(help="Number of GPUs to allocate in the cluster")]
@@ -32,6 +32,10 @@
3232
AutoScaleMaxGpusParameter = Annotated[Optional[int], Parameter(help="Maximum GPUs for auto-scaling")]
3333
CapacityPoolIDParameter = Annotated[Optional[str], Parameter(help="Capacity pool ID to use for the cluster")]
3434
InstallTraefikParameter = Annotated[Optional[bool], Parameter(help="Install Traefik ingress controller")]
35+
HeadlampParameter = Annotated[
36+
Optional[bool], Parameter(help="Enable the Headlamp Kubernetes dashboard add-on", negative=())
37+
]
38+
SlurmWebParameter = Annotated[Optional[bool], Parameter(help="Enable the Slurm Web add-on", negative=())]
3539
NumCapacityPoolGpusParameter = Annotated[
3640
Optional[int], Parameter(help="Number of GPUs to allocate from a capacity pool")
3741
]
@@ -60,6 +64,8 @@ async def create(
6064
auto_scale_max_gpus: AutoScaleMaxGpusParameter = None,
6165
capacity_pool_id: CapacityPoolIDParameter = None,
6266
install_traefik: InstallTraefikParameter = None,
67+
headlamp_addon: HeadlampParameter = None,
68+
slurm_web_addon: SlurmWebParameter = None,
6369
num_capacity_pool_gpus: NumCapacityPoolGpusParameter = None,
6470
num_preemptible_gpus: NumPreemptibleGpusParameter = None,
6571
num_reserved_gpus: NumReservedGpusParameter = None,
@@ -92,6 +98,25 @@ async def create(
9298
params["capacity_pool_id"] = capacity_pool_id
9399
if install_traefik is not None:
94100
params["install_traefik"] = install_traefik
101+
add_ons: list[AddOn] = []
102+
if headlamp_addon is not None:
103+
add_ons.append(
104+
{
105+
"add_on_type": "headlamp",
106+
"name": "headlamp",
107+
"config": {"headlamp": {"enabled": headlamp_addon}},
108+
}
109+
)
110+
if slurm_web_addon is not None:
111+
add_ons.append(
112+
{
113+
"add_on_type": "slurm_web",
114+
"name": "slurm_web",
115+
"config": {"slurm_web": {"enabled": slurm_web_addon}},
116+
}
117+
)
118+
if add_ons:
119+
params["add_ons"] = add_ons
95120
if num_capacity_pool_gpus is not None:
96121
params["num_capacity_pool_gpus"] = num_capacity_pool_gpus
97122
if num_preemptible_gpus is not None:

src/together/lib/cli/api/beta/clusters/update.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from together.lib.cli.utils.config import CLIConfigParameter
1111
from together.lib.cli.utils._console import console
1212
from together.lib.cli.components.loader import show_loading_status
13+
from together.types.beta.cluster_update_params import AddOn
1314

1415

1516
async def update(
@@ -34,15 +35,30 @@ async def update(
3435
Optional[str],
3536
Parameter(help="Timestamp at which the cluster should be decommissioned"),
3637
] = None,
38+
headlamp: Annotated[
39+
Optional[bool],
40+
Parameter(help="Enable or disable the Headlamp Kubernetes dashboard add-on"),
41+
] = None,
42+
slurm_web: Annotated[
43+
Optional[bool],
44+
Parameter(help="Enable or disable the Slurm Web add-on"),
45+
] = None,
3746
*,
3847
config: CLIConfigParameter,
3948
) -> None:
4049
"""Update a cluster."""
4150

51+
add_ons: list[AddOn] = []
52+
if headlamp is not None:
53+
add_ons.append({"name": "headlamp", "config": {"headlamp": {"enabled": headlamp}}})
54+
if slurm_web is not None:
55+
add_ons.append({"name": "slurm_web", "config": {"slurm_web": {"enabled": slurm_web}}})
56+
4257
await show_loading_status(
4358
"Updating cluster...",
4459
config.client.beta.clusters.update(
4560
cluster_id,
61+
add_ons=add_ons if add_ons else omit,
4662
num_gpus=num_gpus if num_gpus is not None else omit,
4763
cluster_type=cluster_type if cluster_type is not None else omit,
4864
num_capacity_pool_gpus=num_capacity_pool_gpus if num_capacity_pool_gpus is not None else omit,

tests/cli/test_beta_clusters.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -695,6 +695,8 @@ def test_create_accepts_new_cluster_params(self, respx_mock: MockRouter, cli_run
695695
"--capacity-pool-id",
696696
"pool-1",
697697
"--install-traefik",
698+
"--headlamp-addon",
699+
"--slurm-web-addon",
698700
"--num-capacity-pool-gpus",
699701
"8",
700702
"--num-preemptible-gpus",
@@ -722,6 +724,18 @@ def test_create_accepts_new_cluster_params(self, respx_mock: MockRouter, cli_run
722724
assert body["capacity_pool_id"] == "pool-1"
723725
assert "gpu_node_failover_enabled" not in body
724726
assert body["install_traefik"] is True
727+
assert body["add_ons"] == [
728+
{
729+
"add_on_type": "headlamp",
730+
"name": "headlamp",
731+
"config": {"headlamp": {"enabled": True}},
732+
},
733+
{
734+
"add_on_type": "slurm_web",
735+
"name": "slurm_web",
736+
"config": {"slurm_web": {"enabled": True}},
737+
},
738+
]
725739
assert body["num_capacity_pool_gpus"] == 8
726740
assert body["num_preemptible_gpus"] == 8
727741
assert body["num_reserved_gpus"] == 8
@@ -768,10 +782,16 @@ def test_update_accepts_new_cluster_params(self, respx_mock: MockRouter, cli_run
768782
"16",
769783
"--reservation-end-time",
770784
"2026-06-02T00:00:00Z",
785+
"--no-headlamp",
786+
"--slurm-web",
771787
],
772788
)
773789

774790
put_body = json.loads(cast(Call, put.calls[0]).request.content.decode())
791+
assert put_body["add_ons"] == [
792+
{"name": "headlamp", "config": {"headlamp": {"enabled": False}}},
793+
{"name": "slurm_web", "config": {"slurm_web": {"enabled": True}}},
794+
]
775795
assert put_body["num_preemptible_gpus"] == 8
776796
assert put_body["num_capacity_pool_gpus"] == 8
777797
assert put_body["num_reserved_gpus"] == 16

0 commit comments

Comments
 (0)