Skip to content

Commit

Permalink
feat(bentocloud): deployment v2 api client
Browse files Browse the repository at this point in the history
  • Loading branch information
Haivilo committed Dec 13, 2023
1 parent 863e691 commit 45cd52a
Show file tree
Hide file tree
Showing 12 changed files with 745 additions and 450 deletions.
4 changes: 3 additions & 1 deletion src/bentoml/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@
from . import server # Server API
from . import monitoring # Monitoring API
from . import cloud # Cloud API
from . import deployment # deployment API

# isort: on
else:
Expand Down Expand Up @@ -154,7 +155,7 @@
exceptions = _LazyLoader("bentoml.exceptions", globals(), "bentoml.exceptions")
monitoring = _LazyLoader("bentoml.monitoring", globals(), "bentoml.monitoring")
cloud = _LazyLoader("bentoml.cloud", globals(), "bentoml.cloud")

deployment = _LazyLoader("bentoml.cloud", globals(), "bentoml.deployment")
del _LazyLoader


Expand Down Expand Up @@ -228,4 +229,5 @@
"set_serialization_strategy",
"Strategy",
"Resource",
"deployment",
]
42 changes: 21 additions & 21 deletions src/bentoml/_internal/cloud/bentocloud.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,33 +30,33 @@
from .base import CloudClient
from .config import get_rest_api_client
from .deployment import Deployment
from .schemas import BentoApiSchema
from .schemas import BentoManifestSchema
from .schemas import BentoRunnerResourceSchema
from .schemas import BentoRunnerSchema
from .schemas import BentoUploadStatus
from .schemas import CompleteMultipartUploadSchema
from .schemas import CompletePartSchema
from .schemas import CreateBentoRepositorySchema
from .schemas import CreateBentoSchema
from .schemas import CreateModelRepositorySchema
from .schemas import CreateModelSchema
from .schemas import FinishUploadBentoSchema
from .schemas import FinishUploadModelSchema
from .schemas import LabelItemSchema
from .schemas import ModelManifestSchema
from .schemas import ModelUploadStatus
from .schemas import PreSignMultipartUploadUrlSchema
from .schemas import TransmissionStrategy
from .schemas import UpdateBentoSchema
from .schemas.modelschemas import BentoApiSchema
from .schemas.modelschemas import BentoRunnerResourceSchema
from .schemas.modelschemas import BentoRunnerSchema
from .schemas.schemasv1 import BentoManifestSchema
from .schemas.schemasv1 import BentoUploadStatus
from .schemas.schemasv1 import CompleteMultipartUploadSchema
from .schemas.schemasv1 import CompletePartSchema
from .schemas.schemasv1 import CreateBentoRepositorySchema
from .schemas.schemasv1 import CreateBentoSchema
from .schemas.schemasv1 import CreateModelRepositorySchema
from .schemas.schemasv1 import CreateModelSchema
from .schemas.schemasv1 import FinishUploadBentoSchema
from .schemas.schemasv1 import FinishUploadModelSchema
from .schemas.schemasv1 import LabelItemSchema
from .schemas.schemasv1 import ModelManifestSchema
from .schemas.schemasv1 import ModelUploadStatus
from .schemas.schemasv1 import PreSignMultipartUploadUrlSchema
from .schemas.schemasv1 import TransmissionStrategy
from .schemas.schemasv1 import UpdateBentoSchema

if t.TYPE_CHECKING:
from concurrent.futures import Future

from rich.progress import TaskID

from .schemas import BentoWithRepositoryListSchema
from .schemas import ModelWithRepositoryListSchema
from .schemas.schemasv1 import BentoWithRepositoryListSchema
from .schemas.schemasv1 import ModelWithRepositoryListSchema


class BentoCloudClient(CloudClient):
Expand Down
64 changes: 37 additions & 27 deletions src/bentoml/_internal/cloud/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,32 +8,33 @@

from ...exceptions import CloudRESTApiClientError
from ..configuration import BENTOML_VERSION
from .schemas import BentoRepositorySchema
from .schemas import BentoSchema
from .schemas import BentoWithRepositoryListSchema
from .schemas import ClusterFullSchema
from .schemas import ClusterListSchema
from .schemas import CompleteMultipartUploadSchema
from .schemas import CreateBentoRepositorySchema
from .schemas import CreateBentoSchema
from .schemas import CreateDeploymentSchema
from .schemas import CreateModelRepositorySchema
from .schemas import CreateModelSchema
from .schemas import DeploymentListSchema
from .schemas import DeploymentSchema
from .schemas import FinishUploadBentoSchema
from .schemas import FinishUploadModelSchema
from .schemas import ModelRepositorySchema
from .schemas import ModelSchema
from .schemas import ModelWithRepositoryListSchema
from .schemas import OrganizationSchema
from .schemas import PreSignMultipartUploadUrlSchema
from .schemas import UpdateBentoSchema
from .schemas import UpdateDeploymentSchema
from .schemas import UserSchema
from .schemas import schema_from_json
from .schemas import schema_from_object
from .schemas import schema_to_json
from .schemas.schemasv1 import BentoRepositorySchema
from .schemas.schemasv1 import BentoSchema
from .schemas.schemasv1 import BentoWithRepositoryListSchema
from .schemas.schemasv1 import ClusterFullSchema
from .schemas.schemasv1 import ClusterListSchema
from .schemas.schemasv1 import CompleteMultipartUploadSchema
from .schemas.schemasv1 import CreateBentoRepositorySchema
from .schemas.schemasv1 import CreateBentoSchema
from .schemas.schemasv1 import CreateDeploymentSchema as CreateDeploymentSchemaV1
from .schemas.schemasv1 import CreateModelRepositorySchema
from .schemas.schemasv1 import CreateModelSchema
from .schemas.schemasv1 import DeploymentListSchema
from .schemas.schemasv1 import DeploymentSchema
from .schemas.schemasv1 import FinishUploadBentoSchema
from .schemas.schemasv1 import FinishUploadModelSchema
from .schemas.schemasv1 import ModelRepositorySchema
from .schemas.schemasv1 import ModelSchema
from .schemas.schemasv1 import ModelWithRepositoryListSchema
from .schemas.schemasv1 import OrganizationSchema
from .schemas.schemasv1 import PreSignMultipartUploadUrlSchema
from .schemas.schemasv1 import UpdateBentoSchema
from .schemas.schemasv1 import UpdateDeploymentSchema
from .schemas.schemasv1 import UserSchema
from .schemas.schemasv2 import CreateDeploymentSchema as CreateDeploymentSchemaV2
from .schemas.utils import schema_from_json
from .schemas.utils import schema_from_object
from .schemas.utils import schema_to_json

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -432,13 +433,22 @@ def get_deployment_list(
return schema_from_json(resp.text, DeploymentListSchema)

def create_deployment(
self, cluster_name: str, create_schema: CreateDeploymentSchema
self, cluster_name: str, create_schema: CreateDeploymentSchemaV1
) -> DeploymentSchema | None:
url = urljoin(self.endpoint, f"/api/v1/clusters/{cluster_name}/deployments")
resp = self.session.post(url, data=schema_to_json(create_schema))
self._check_resp(resp)
return schema_from_json(resp.text, DeploymentSchema)

def create_deployment_v2(
self, create_schema: CreateDeploymentSchemaV2
) -> DeploymentSchema | None:
url = urljoin(self.endpoint, "/api/v2/deployments")
print(schema_to_json(create_schema))
resp = self.session.post(url, data=schema_to_json(create_schema))
self._check_resp(resp)
return schema_from_json(resp.text, DeploymentSchema)

def get_deployment(
self, cluster_name: str, kube_namespace: str, deployment_name: str
) -> DeploymentSchema | None:
Expand Down
126 changes: 113 additions & 13 deletions src/bentoml/_internal/cloud/deployment.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import typing as t

import attr
import yaml
from deepmerge.merger import Merger

from ...exceptions import BentoMLException
Expand All @@ -13,17 +14,18 @@
from ..utils import first_not_none
from ..utils import resolve_user_filepath
from .config import get_rest_api_client
from .schemas import CreateDeploymentSchema
from .schemas import DeploymentListSchema
from .schemas import DeploymentMode
from .schemas import DeploymentSchema
from .schemas import DeploymentTargetCanaryRule
from .schemas import DeploymentTargetConfig
from .schemas import DeploymentTargetHPAConf
from .schemas import DeploymentTargetRunnerConfig
from .schemas import DeploymentTargetType
from .schemas import FullDeploymentSchema
from .schemas import UpdateDeploymentSchema
from .schemas.modelschemas import DeploymentTargetHPAConf
from .schemas.modelschemas import DeploymentTargetRunnerConfig
from .schemas.schemasv1 import CreateDeploymentSchema as CreateDeploymentSchemaV1
from .schemas.schemasv1 import DeploymentListSchema
from .schemas.schemasv1 import DeploymentMode
from .schemas.schemasv1 import DeploymentSchema
from .schemas.schemasv1 import DeploymentTargetCanaryRule
from .schemas.schemasv1 import DeploymentTargetConfig
from .schemas.schemasv1 import DeploymentTargetType
from .schemas.schemasv1 import FullDeploymentSchema
from .schemas.schemasv1 import UpdateDeploymentSchema
from .schemas.schemasv2 import CreateDeploymentSchema as CreateDeploymentSchemaV2

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -58,7 +60,10 @@ def for_api_server(cls, **kwargs: t.Any) -> DeploymentTargetConfig:
return bentoml_cattr.structure(kwargs, DeploymentTargetConfig)


@attr.define
class Deployment:
schema: t.Optional[DeploymentSchema] = attr.field(default=None)

@classmethod
def _get_default_kube_namespace(
cls,
Expand All @@ -84,7 +89,7 @@ def _get_default_cluster(cls, context: str | None = None) -> str:
@classmethod
def _create_deployment(
cls,
create_deployment_schema: CreateDeploymentSchema,
create_deployment_schema: CreateDeploymentSchemaV1,
context: str | None = None,
cluster_name: str | None = None,
) -> DeploymentSchema:
Expand Down Expand Up @@ -396,7 +401,7 @@ def create(
context=context,
cluster_name=cluster_name,
create_deployment_schema=bentoml_cattr.structure(
dct, CreateDeploymentSchema
dct, CreateDeploymentSchemaV1
),
)

Expand Down Expand Up @@ -560,3 +565,98 @@ def terminate(
if res is None:
raise BentoMLException("Terminate deployment request failed")
return res

@classmethod
def _create_deploymentV2(
cls,
create_deployment_schema: CreateDeploymentSchemaV2,
context: str | None = None,
) -> DeploymentSchema:
cloud_rest_client = get_rest_api_client(context)
res = cloud_rest_client.create_deployment_v2(create_deployment_schema)
if res is None:
raise BentoMLException("Create deployment request failed")
logger.debug("Deployment Schema: %s", create_deployment_schema)
return res

@classmethod
def create_deploymentV2(
cls,
project_path: str | None = None,
bento: Tag | str | None = None,
access_type: str | None = None,
name: str | None = None,
cluster: str | None = None,
scailing_min: int | None = None,
scailing_max: int | None = None,
instance_type: str | None = None,
strategy: str | None = None,
envs: t.List[dict[str, t.Any]] | None = None,
extras: dict[str, t.Any] | None = None,
config_dct: dict[str, t.Any] | None = None,
config_file: str | None = None,
path_context: str | None = None,
context: str | None = None,
) -> Deployment:
if (not bento and not project_path) or (bento and project_path):
raise BentoMLException(
"Create a deployment needs one and only one target - either a project path or a bento"
)
bento_target = ""
if project_path:
from bentoml import bentos

print(f"Building bento: {project_path}")
bento_target = bentos.build_bentofile(build_ctx=project_path).tag
elif bento is not None:
bento_target = bento

from bentoml._internal.configuration.containers import BentoMLContainer

client = BentoMLContainer.bentocloud_client.get()
bento_store = BentoMLContainer.bento_store.get()
bento_target = Tag.from_taglike(bento_target)
bento_obj = bento_store.get(bento_target)
if not bento_obj:
raise ValueError(f"Bento {bento} not found in local store")
client.push_bento(bento=bento_obj)

dct = {"name": name, "bento": str(bento_target)}
if config_dct:
merging_dct = config_dct
pass
elif config_file:
real_path = resolve_user_filepath(config_file, path_context)
try:
with open(real_path, "r") as file:
merging_dct = yaml.safe_load(file)
except FileNotFoundError:
raise ValueError(f"File not found: {real_path}")
except yaml.YAMLError as exc:
logger.error("Error while parsing YAML file: %s", exc)
raise
except Exception as e:
raise ValueError(
f"An error occurred while reading the file: {real_path}\n{e}"
)
else:
if scailing_min is None:
scailing_min = 1
if scailing_max is None:
scailing_max = max(1, scailing_min)
merging_dct = {
"scaling": {"min_replicas": scailing_min, "max_replicas": scailing_max},
"instance_type": instance_type,
"deployment_strategy": strategy,
"envs": envs,
"extras": extras,
"access_type": access_type,
}
if "cluster" not in dct:
cluster = cls._get_default_cluster(context)
dct["cluster"] = cluster
config_merger.merge(dct, merging_dct)
res = cls._create_deploymentV2(
bentoml_cattr.structure(dct, CreateDeploymentSchemaV2), context
)
return Deployment(schema=res)
Empty file.
Loading

0 comments on commit 45cd52a

Please sign in to comment.