Skip to content

Commit 1c106f7

Browse files
mitali401atihkin
andauthored
add list avzone and deploy de in avzone (#379)
* add list avzone and deploy de in avzone * added create endpoint with availability zone and list availability zones. still need to return availability zone per endpoint. --------- Co-authored-by: Nikitha Suryadevara <[email protected]>
1 parent 51db0c1 commit 1c106f7

File tree

2 files changed

+89
-0
lines changed

2 files changed

+89
-0
lines changed

src/together/cli/api/endpoints.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,10 @@ def endpoints(ctx: click.Context) -> None:
132132
type=int,
133133
help="Number of minutes of inactivity after which the endpoint will be automatically stopped. Set to 0 to disable.",
134134
)
135+
@click.option(
136+
"--availability-zone",
137+
help="Start endpoint in specified availability zone (e.g., us-central-4b)",
138+
)
135139
@click.option(
136140
"--wait",
137141
is_flag=True,
@@ -152,6 +156,7 @@ def create(
152156
no_speculative_decoding: bool,
153157
no_auto_start: bool,
154158
inactive_timeout: int | None,
159+
availability_zone: str | None,
155160
wait: bool,
156161
) -> None:
157162
"""Create a new dedicated inference endpoint."""
@@ -177,6 +182,7 @@ def create(
177182
disable_speculative_decoding=no_speculative_decoding,
178183
state="STOPPED" if no_auto_start else "STARTED",
179184
inactive_timeout=inactive_timeout,
185+
availability_zone=availability_zone,
180186
)
181187
except InvalidRequestError as e:
182188
print_api_error(e)
@@ -203,6 +209,8 @@ def create(
203209
click.echo(" Auto-start: disabled", err=True)
204210
if inactive_timeout is not None:
205211
click.echo(f" Inactive timeout: {inactive_timeout} minutes", err=True)
212+
if availability_zone:
213+
click.echo(f" Availability zone: {availability_zone}", err=True)
206214

207215
click.echo(f"Endpoint created successfully, id: {response.id}", err=True)
208216

@@ -449,3 +457,25 @@ def update(
449457

450458
click.echo("Successfully updated endpoint", err=True)
451459
click.echo(endpoint_id)
460+
461+
462+
@endpoints.command()
463+
@click.option("--json", is_flag=True, help="Print output in JSON format")
464+
@click.pass_obj
465+
@handle_api_errors
466+
def availability_zones(client: Together, json: bool) -> None:
467+
"""List all availability zones."""
468+
avzones = client.endpoints.list_avzones()
469+
470+
if not avzones:
471+
click.echo("No availability zones found", err=True)
472+
return
473+
474+
if json:
475+
import json as json_lib
476+
477+
click.echo(json_lib.dumps({"avzones": avzones}, indent=2))
478+
else:
479+
click.echo("Available zones:", err=True)
480+
for availability_zone in sorted(avzones):
481+
click.echo(f" {availability_zone}")

src/together/resources/endpoints.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ def create(
7676
disable_speculative_decoding: bool = True,
7777
state: Literal["STARTED", "STOPPED"] = "STARTED",
7878
inactive_timeout: Optional[int] = None,
79+
availability_zone: Optional[str] = None,
7980
) -> DedicatedEndpoint:
8081
"""
8182
Create a new dedicated endpoint.
@@ -90,6 +91,7 @@ def create(
9091
disable_speculative_decoding (bool, optional): Whether to disable speculative decoding. Defaults to False.
9192
state (str, optional): The desired state of the endpoint. Defaults to "STARTED".
9293
inactive_timeout (int, optional): The number of minutes of inactivity after which the endpoint will be automatically stopped. Set to 0 to disable automatic timeout.
94+
availability_zone (str, optional): Start endpoint in specified availability zone (e.g., us-central-4b).
9395
9496
Returns:
9597
DedicatedEndpoint: Object containing endpoint information
@@ -116,6 +118,9 @@ def create(
116118
if inactive_timeout is not None:
117119
data["inactive_timeout"] = inactive_timeout
118120

121+
if availability_zone is not None:
122+
data["availability_zone"] = availability_zone
123+
119124
response, _, _ = requestor.request(
120125
options=TogetherRequest(
121126
method="POST",
@@ -273,6 +278,31 @@ def list_hardware(self, model: Optional[str] = None) -> List[HardwareWithStatus]
273278

274279
return [HardwareWithStatus(**item) for item in response.data["data"]]
275280

281+
def list_avzones(self) -> List[str]:
282+
"""
283+
List all available availability zones.
284+
285+
Returns:
286+
List[str]: List of unique availability zones
287+
"""
288+
requestor = api_requestor.APIRequestor(
289+
client=self._client,
290+
)
291+
292+
response, _, _ = requestor.request(
293+
options=TogetherRequest(
294+
method="GET",
295+
url="clusters/availability-zones",
296+
),
297+
stream=False,
298+
)
299+
300+
assert isinstance(response, TogetherResponse)
301+
assert isinstance(response.data, dict)
302+
assert isinstance(response.data["avzones"], list)
303+
304+
return response.data["avzones"]
305+
276306

277307
class AsyncEndpoints:
278308
def __init__(self, client: TogetherClient) -> None:
@@ -340,6 +370,7 @@ async def create(
340370
disable_speculative_decoding: bool = True,
341371
state: Literal["STARTED", "STOPPED"] = "STARTED",
342372
inactive_timeout: Optional[int] = None,
373+
availability_zone: Optional[str] = None,
343374
) -> DedicatedEndpoint:
344375
"""
345376
Create a new dedicated endpoint.
@@ -380,6 +411,9 @@ async def create(
380411
if inactive_timeout is not None:
381412
data["inactive_timeout"] = inactive_timeout
382413

414+
if availability_zone is not None:
415+
data["availability_zone"] = availability_zone
416+
383417
response, _, _ = await requestor.arequest(
384418
options=TogetherRequest(
385419
method="POST",
@@ -538,3 +572,28 @@ async def list_hardware(
538572
assert isinstance(response.data["data"], list)
539573

540574
return [HardwareWithStatus(**item) for item in response.data["data"]]
575+
576+
async def list_avzones(self) -> List[str]:
577+
"""
578+
List all availability zones.
579+
580+
Returns:
581+
List[str]: List of unique availability zones
582+
"""
583+
requestor = api_requestor.APIRequestor(
584+
client=self._client,
585+
)
586+
587+
response, _, _ = await requestor.arequest(
588+
options=TogetherRequest(
589+
method="GET",
590+
url="clusters/availability-zones",
591+
),
592+
stream=False,
593+
)
594+
595+
assert isinstance(response, TogetherResponse)
596+
assert isinstance(response.data, dict)
597+
assert isinstance(response.data["avzones"], list)
598+
599+
return response.data["avzones"]

0 commit comments

Comments
 (0)