Skip to content

Commit 54e7e6f

Browse files
Wrappers around autogen client for docker image batch jobs (#93)
* things to fill in * untested bundle stuff * batch job stuff + docs, also untested * aaa * wrong function mb * fix some bugs * mypy pls * comment the jank
1 parent bc84370 commit 54e7e6f

File tree

2 files changed

+323
-0
lines changed

2 files changed

+323
-0
lines changed

launch/client.py

Lines changed: 263 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,12 @@
3131
from launch.api_client.model.create_batch_job_v1_request import (
3232
CreateBatchJobV1Request,
3333
)
34+
from launch.api_client.model.create_docker_image_batch_job_bundle_v1_request import (
35+
CreateDockerImageBatchJobBundleV1Request,
36+
)
37+
from launch.api_client.model.create_docker_image_batch_job_v1_request import (
38+
CreateDockerImageBatchJobV1Request,
39+
)
3440
from launch.api_client.model.create_model_bundle_v1_request import (
3541
CreateModelBundleV1Request,
3642
)
@@ -61,6 +67,9 @@
6167
from launch.api_client.model.triton_enhanced_runnable_image_flavor import (
6268
TritonEnhancedRunnableImageFlavor,
6369
)
70+
from launch.api_client.model.update_docker_image_batch_job_v1_request import (
71+
UpdateDockerImageBatchJobV1Request,
72+
)
6473
from launch.api_client.model.update_model_endpoint_v1_request import (
6574
UpdateModelEndpointV1Request,
6675
)
@@ -73,6 +82,11 @@
7382
SCALE_LAUNCH_ENDPOINT,
7483
SCALE_LAUNCH_V1_ENDPOINT,
7584
)
85+
from launch.docker_image_batch_job_bundle import (
86+
CreateDockerImageBatchJobBundleResponse,
87+
DockerImageBatchJobBundleResponse,
88+
ListDockerImageBatchJobBundleResponse,
89+
)
7690
from launch.find_packages import find_packages_from_imports, get_imports
7791
from launch.hooks import PostInferenceHooks
7892
from launch.make_batch_file import (
@@ -2074,6 +2088,255 @@ def get_batch_async_response(self, batch_job_id: str) -> Dict[str, Any]:
20742088
resp = json.loads(response.response.data)
20752089
return resp
20762090

2091+
def create_docker_image_batch_job_bundle(
2092+
self,
2093+
*,
2094+
name: str,
2095+
image_repository: str,
2096+
image_tag: str,
2097+
command: List[str],
2098+
env: Optional[Dict[str, str]],
2099+
mount_location: Optional[str],
2100+
cpus: Optional[int] = None,
2101+
memory: Optional[str] = None,
2102+
gpus: Optional[int] = None,
2103+
gpu_type: Optional[str] = None,
2104+
storage: Optional[str] = None,
2105+
) -> CreateDockerImageBatchJobBundleResponse:
2106+
"""
2107+
For self hosted mode only.
2108+
2109+
Creates a Docker Image Batch Job Bundle.
2110+
2111+
Parameters:
2112+
name:
2113+
A user-defined name for the bundle. Does not need to be unique.
2114+
image_repository:
2115+
The (short) repository of your image. For example, if your image is located at
2116+
123456789012.dkr.ecr.us-west-2.amazonaws.com/repo:tag, and your version of Launch
2117+
is configured to look at 123456789012.dkr.ecr.us-west-2.amazonaws.com for Docker Images,
2118+
you would pass the value `repo` for the `image_repository` parameter.
2119+
image_tag:
2120+
The tag of your image inside of the repo. In the example above, you would pass
2121+
the value `tag` for the `image_tag` parameter.
2122+
command:
2123+
The command to run inside the docker image.
2124+
env:
2125+
A dictionary of environment variables to inject into your docker image.
2126+
mount_location:
2127+
A location in the filesystem where you would like a json-formatted file, controllable
2128+
on runtime, to be mounted. This allows behavior to be specified on runtime.
2129+
(Specifically, the contents of this file can be read via `json.load()` inside of the
2130+
user-defined code.)
2131+
cpus:
2132+
Optional default value for the number of cpus to give the job.
2133+
memory:
2134+
Optional default value for the amount of memory to give the job.
2135+
gpus:
2136+
Optional default value for the number of gpus to give the job.
2137+
gpu_type:
2138+
Optional default value for the type of gpu to give the job.
2139+
storage:
2140+
Optional default value for the amount of disk to give the job.
2141+
"""
2142+
with ApiClient(self.configuration) as api_client:
2143+
api_instance = DefaultApi(api_client)
2144+
# Raw dictionary since it's not the entire request and we can get away with this
2145+
# Also having it be a CreateDockerImageBatchJobResourceRequest runs into problems
2146+
# if no values are specified
2147+
resource_requests = dict_not_none(
2148+
cpus=cpus,
2149+
memory=memory,
2150+
gpus=gpus,
2151+
gpu_type=gpu_type,
2152+
storage=storage,
2153+
)
2154+
create_docker_image_batch_job_bundle_request = CreateDockerImageBatchJobBundleV1Request(
2155+
**dict_not_none(
2156+
name=name,
2157+
image_repository=image_repository,
2158+
image_tag=image_tag,
2159+
command=command,
2160+
env=env,
2161+
mount_location=mount_location,
2162+
resource_requests=resource_requests,
2163+
)
2164+
)
2165+
response = api_instance.create_docker_image_batch_job_bundle_v1_docker_image_batch_job_bundles_post(
2166+
body=create_docker_image_batch_job_bundle_request, skip_deserialization=True
2167+
)
2168+
resp = CreateDockerImageBatchJobBundleResponse.parse_raw(response.response.data)
2169+
return resp
2170+
2171+
def get_docker_image_batch_job_bundle(
2172+
self, docker_image_batch_job_bundle_id: str
2173+
) -> DockerImageBatchJobBundleResponse:
2174+
"""
2175+
For self hosted mode only. Gets information for a single batch job bundle with a given id.
2176+
"""
2177+
with ApiClient(self.configuration) as api_client:
2178+
api_instance = DefaultApi(api_client)
2179+
path_params = frozendict({"docker_image_batch_job_bundle_id": docker_image_batch_job_bundle_id})
2180+
response = api_instance.get_docker_image_batch_job_model_bundle_v1_docker_image_batch_job_bundles_docker_image_batch_job_bundle_id_get( # type: ignore # noqa: E501
2181+
path_params=path_params,
2182+
skip_deserialization=True,
2183+
)
2184+
resp = DockerImageBatchJobBundleResponse.parse_raw(response.response.data)
2185+
2186+
return resp
2187+
2188+
def get_latest_docker_image_batch_job_bundle(self, bundle_name: str) -> DockerImageBatchJobBundleResponse:
2189+
"""
2190+
For self hosted mode only. Gets information for the latest batch job bundle with a given name.
2191+
"""
2192+
with ApiClient(self.configuration) as api_client:
2193+
api_instance = DefaultApi(api_client)
2194+
query_params = frozendict({"bundle_name": bundle_name})
2195+
response = api_instance.get_latest_docker_image_batch_job_bundle_v1_docker_image_batch_job_bundles_latest_get( # type: ignore # noqa: E501
2196+
query_params=query_params,
2197+
skip_deserialization=True,
2198+
)
2199+
resp = DockerImageBatchJobBundleResponse.parse_raw(response.response.data)
2200+
2201+
return resp
2202+
2203+
def list_docker_image_batch_job_bundles(
2204+
self, bundle_name: Optional[str] = None, order_by: Optional[Literal["newest", "oldest"]] = None
2205+
) -> ListDockerImageBatchJobBundleResponse:
2206+
"""
2207+
For self hosted mode only. Gets information for multiple bundles.
2208+
2209+
Parameters:
2210+
bundle_name: The name of the bundles to retrieve. If not specified, this will retrieve all
2211+
bundles.
2212+
order_by: Either "newest", "oldest", or not specified. Specify to sort by newest/oldest.
2213+
"""
2214+
with ApiClient(self.configuration) as api_client:
2215+
api_instance = DefaultApi(api_client)
2216+
query_params = frozendict(dict_not_none(bundle_name=bundle_name, order_by=order_by))
2217+
response = api_instance.list_docker_image_batch_job_model_bundles_v1_docker_image_batch_job_bundles_get( # type: ignore # noqa: E501
2218+
query_params=query_params,
2219+
skip_deserialization=True,
2220+
)
2221+
resp = ListDockerImageBatchJobBundleResponse.parse_raw(response.response.data)
2222+
2223+
return resp
2224+
2225+
def create_docker_image_batch_job(
2226+
self,
2227+
*,
2228+
labels: Dict[str, str],
2229+
docker_image_batch_job_bundle: Optional[Union[str, DockerImageBatchJobBundleResponse]] = None,
2230+
docker_image_batch_job_bundle_name: Optional[str] = None,
2231+
job_config: Optional[Dict[str, Any]] = None,
2232+
cpus: Optional[int] = None,
2233+
memory: Optional[str] = None,
2234+
gpus: Optional[int] = None,
2235+
gpu_type: Optional[str] = None,
2236+
storage: Optional[str] = None,
2237+
):
2238+
"""
2239+
For self hosted mode only.
2240+
Parameters:
2241+
docker_image_batch_job_bundle: Specifies the docker image bundle to use for the batch job.
2242+
Either the string id of a docker image bundle, or a
2243+
DockerImageBatchJobBundleResponse object.
2244+
Only one of docker_image_batch_job_bundle and docker_image_batch_job_bundle_name
2245+
can be specified.
2246+
docker_image_batch_job_bundle_name: The name of a batch job bundle. If specified,
2247+
Launch will use the most recent bundle with that name owned by the current user.
2248+
Only one of docker_image_batch_job_bundle and docker_image_batch_job_bundle_name
2249+
can be specified.
2250+
labels: Kubernetes labels that are present on the batch job.
2251+
job_config: A JSON-serializable python object that will get passed to the batch job,
2252+
specifically as the contents of a file mounted at `mount_location` inside the bundle.
2253+
You can call python's `json.load()` on the file to retrieve the contents.
2254+
cpus: Optional override for the number of cpus to give to your job. Either the default
2255+
must be specified in the bundle, or this must be specified.
2256+
memory: Optional override for the amount of memory to give to your job. Either the default
2257+
must be specified in the bundle, or this must be specified.
2258+
gpus: Optional number of gpus to give to the bundle. If not specified in the bundle or
2259+
here, will be interpreted as 0 gpus.
2260+
gpu_type: Optional type of gpu. If the final number of gpus is positive, must be specified
2261+
either in the bundle or here.
2262+
storage: Optional reserved amount of disk to give to your batch job. If not specified,
2263+
your job may be evicted if it is using too much disk.
2264+
"""
2265+
2266+
assert (docker_image_batch_job_bundle is None) ^ (
2267+
docker_image_batch_job_bundle_name is None
2268+
), "Exactly one of docker_image_batch_job_bundle and docker_image_batch_job_bundle_name must be specified"
2269+
2270+
if docker_image_batch_job_bundle is not None and isinstance(
2271+
docker_image_batch_job_bundle, DockerImageBatchJobBundleResponse
2272+
):
2273+
docker_image_batch_job_bundle_id: Optional[str] = docker_image_batch_job_bundle.id
2274+
else:
2275+
docker_image_batch_job_bundle_id = docker_image_batch_job_bundle
2276+
2277+
with ApiClient(self.configuration) as api_client:
2278+
api_instance = DefaultApi(api_client)
2279+
# Raw dictionary since it's not the entire request and we can get away with this
2280+
# Also having it be a CreateDockerImageBatchJobResourceRequest runs into problems
2281+
# if no values are specified
2282+
resource_requests = dict_not_none(
2283+
cpus=cpus,
2284+
memory=memory,
2285+
gpus=gpus,
2286+
gpu_type=gpu_type,
2287+
storage=storage,
2288+
)
2289+
create_docker_image_batch_job_request = CreateDockerImageBatchJobV1Request(
2290+
**dict_not_none(
2291+
docker_image_batch_job_bundle_id=docker_image_batch_job_bundle_id,
2292+
docker_image_batch_job_bundle_name=docker_image_batch_job_bundle_name,
2293+
job_config=job_config,
2294+
labels=labels,
2295+
resource_requests=resource_requests,
2296+
)
2297+
)
2298+
response = api_instance.create_docker_image_batch_job_v1_docker_image_batch_jobs_post(
2299+
body=create_docker_image_batch_job_request,
2300+
skip_deserialization=True,
2301+
)
2302+
resp = json.loads(response.response.data)
2303+
return resp
2304+
2305+
def get_docker_image_batch_job(self, batch_job_id: str):
2306+
"""
2307+
For self hosted mode only. Gets information about a batch job given a batch job id.
2308+
"""
2309+
with ApiClient(self.configuration) as api_client:
2310+
api_instance = DefaultApi(api_client)
2311+
path_params = frozendict({"batch_job_id": batch_job_id})
2312+
response = (
2313+
api_instance.get_docker_image_batch_job_v1_docker_image_batch_jobs_batch_job_id_get( # type: ignore
2314+
path_params=path_params,
2315+
skip_deserialization=True,
2316+
)
2317+
)
2318+
resp = json.loads(response.response.data)
2319+
2320+
return resp
2321+
2322+
def update_docker_image_batch_job(self, batch_job_id: str, cancel: bool):
2323+
"""
2324+
For self hosted mode only. Updates a batch job by id.
2325+
Use this if you want to cancel/delete a batch job.
2326+
"""
2327+
with ApiClient(self.configuration) as api_client:
2328+
api_instance = DefaultApi(api_client)
2329+
path_params = frozendict({"batch_job_id": batch_job_id})
2330+
body = UpdateDockerImageBatchJobV1Request(cancel=cancel)
2331+
response = api_instance.update_docker_image_batch_job_v1_docker_image_batch_jobs_batch_job_id_put( # type: ignore # noqa: E501
2332+
body=body,
2333+
path_params=path_params,
2334+
skip_deserialization=True,
2335+
)
2336+
resp = json.loads(response.response.data)
2337+
2338+
return resp
2339+
20772340

20782341
def _zip_directory(zipf: ZipFile, path: str) -> None:
20792342
for root, _, files in os.walk(path):
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import datetime
2+
from typing import Dict, List, Optional
3+
4+
from pydantic import BaseModel
5+
6+
7+
class CreateDockerImageBatchJobBundleResponse(BaseModel):
8+
"""
9+
Response Object for creating a Docker Image Batch Job Bundle
10+
Note: only available for self-hosted mode
11+
"""
12+
13+
docker_image_batch_job_bundle_id: str
14+
"""ID of the Docker Image Batch Job Bundle"""
15+
16+
17+
class DockerImageBatchJobBundleResponse(BaseModel):
18+
"""
19+
Response object for a single Docker Image Batch Job Bundle
20+
Note: only available for self-hosted mode
21+
"""
22+
23+
id: str
24+
"""ID of the Docker Image Batch Job Bundle"""
25+
name: str
26+
"""Name of the Docker Image Batch Job Bundle"""
27+
created_at: datetime.datetime
28+
"""Timestamp of when the Docker Image Batch Job Bundle was created"""
29+
image_repository: str
30+
"""Short repository name of the underlying docker image"""
31+
image_tag: str
32+
"""Tag of the underlying docker image"""
33+
command: List[str]
34+
"""The command to run inside the docker image"""
35+
env: Dict[str, str]
36+
"""Environment variables to be injected into the docker image"""
37+
mount_location: Optional[str]
38+
"""Location of a json-formatted file to mount inside the docker image.
39+
Contents get populated at runtime, and this is the method to change behavior on runtime."""
40+
cpus: Optional[str]
41+
"""Default number of cpus to give to the docker image"""
42+
memory: Optional[str]
43+
"""Default amount of memory to give to the docker image"""
44+
storage: Optional[str]
45+
"""Default amount of disk to give to the docker image"""
46+
gpus: Optional[int]
47+
"""Default number of gpus to give to the docker image"""
48+
gpu_type: Optional[str]
49+
"""Default type of gpu, e.g. nvidia-tesla-t4, nvidia-ampere-a10 to give to the docker image"""
50+
51+
52+
class ListDockerImageBatchJobBundleResponse(BaseModel):
53+
"""
54+
Response object for listing Docker Image Batch Job Bundles.
55+
Note: only available for self-hosted mode
56+
"""
57+
58+
docker_image_batch_job_bundles: List[DockerImageBatchJobBundleResponse]
59+
"""A list of
60+
[Docker Image Batch Job Bundles](./#launch.docker_image_batch_job_bundle.DockerImageBatchJobBundleResponse)."""

0 commit comments

Comments
 (0)