Skip to content

Commit 18ba360

Browse files
feat: Adding label as cli command for cloud deployment (#5467)
* Adding label as cli command for deployment * adding documentation on cli deployment labels
1 parent 3d0d527 commit 18ba360

File tree

4 files changed

+97
-0
lines changed

4 files changed

+97
-0
lines changed

docs/source/scale-with-bentocloud/deployment/configure-deployments.rst

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,38 @@ To list available instance types on your BentoCloud account, run:
8989

9090
Choose the instance type that best fits the performance requirements and resource demands of your application. The instance type should be compatible with the deployment environment and supported by the underlying infrastructure.
9191

92+
Labels
93+
^^^^^^
94+
You can add labels to your Deployment for better organization and management. Labels are key-value pairs that help you categorize and filter your Deployments based on specific attributes.
95+
96+
.. tab-set::
97+
98+
.. tab-item:: BentoML CLI
99+
100+
To add labels via the BentoML CLI, you can use the ``--label`` option:
101+
102+
.. code-block:: bash
103+
104+
bentoml deploy --label key1=value1 --label key2=value2
105+
106+
.. tab-item:: Python API
107+
108+
When using the Python API, labels are specified through the ``labels`` parameter, which accepts a list of dictionaries. Each dictionary in the list represents a single label. Here's an example:
109+
110+
.. code-block:: python
111+
112+
import bentoml
113+
114+
bentoml.deployment.create(
115+
bento="./path_to_your_project",
116+
labels=[
117+
{"key": "key1", "value": "value1"}, # First label
118+
{"key": "key2", "value": "value2"} # Second label
119+
]
120+
)
121+
122+
Once set, you can use these labels to filter and manage your Deployments in the BentoCloud dashboard or via the BentoML CLI.
123+
92124
Environment variables
93125
^^^^^^^^^^^^^^^^^^^^^
94126

src/bentoml/_internal/cloud/deployment.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ class DeploymentConfigParameters:
7272
scaling_max: int | None = None
7373
instance_type: str | None = None
7474
strategy: str | None = None
75+
labels: t.List[dict[str, str]] | None = None
7576
envs: t.List[dict[str, t.Any]] | None = None
7677
secrets: t.List[str] | None = None
7778
extras: dict[str, t.Any] | None = None
@@ -119,6 +120,7 @@ def verify(self, create: bool = True):
119120
("cluster", self.cluster),
120121
("access_authorization", self.access_authorization),
121122
("envs", self.envs if self.envs else None),
123+
("labels", self.labels if self.labels else None),
122124
("secrets", self.secrets),
123125
("dev", self.dev),
124126
]

src/bentoml/deployment.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ def create(
3838
instance_type: str | None = ...,
3939
strategy: str | None = ...,
4040
envs: t.List[EnvItemSchema] | t.List[dict[str, t.Any]] | None = ...,
41+
labels: t.List[LabelItemSchema] | t.List[dict[str, str]] | None = ...,
4142
extras: dict[str, t.Any] | None = ...,
4243
) -> Deployment: ...
4344

@@ -75,6 +76,7 @@ def create(
7576
instance_type: str | None = None,
7677
strategy: str | None = None,
7778
envs: t.List[EnvItemSchema] | t.List[dict[str, t.Any]] | None = None,
79+
labels: t.List[LabelItemSchema] | t.List[dict[str, str]] | None = None,
7880
extras: dict[str, t.Any] | None = None,
7981
config_dict: dict[str, t.Any] | None = None,
8082
config_file: str | None = None,
@@ -103,6 +105,14 @@ def create(
103105
if envs is not None
104106
else None
105107
),
108+
labels=(
109+
[
110+
attr.asdict(item) if isinstance(item, LabelItemSchema) else item
111+
for item in labels
112+
]
113+
if labels is not None
114+
else None
115+
),
106116
extras=extras,
107117
config_dict=config_dict,
108118
config_file=config_file,
@@ -177,6 +187,9 @@ def update(
177187
| t.List[dict[str, t.Any]]
178188
| None
179189
) = None,
190+
labels: (
191+
t.List[LabelItemSchema] | t.List[dict[str, str]] | t.List[dict[str, str]] | None
192+
) = None,
180193
secrets: t.List[str] | None = None,
181194
extras: dict[str, t.Any] | None = None,
182195
config_dict: dict[str, t.Any] | None = None,
@@ -201,6 +214,14 @@ def update(
201214
if envs is not None
202215
else None
203216
),
217+
labels=(
218+
[
219+
attr.asdict(item) if isinstance(item, LabelItemSchema) else item
220+
for item in labels
221+
]
222+
if labels is not None
223+
else None
224+
),
204225
secrets=secrets,
205226
extras=extras,
206227
config_dict=config_dict,

src/bentoml_cli/deployment.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,22 @@ def raise_deployment_config_error(err: BentoMLException, action: str) -> t.NoRet
4949
) from None
5050

5151

52+
def convert_label_to_dict(label: tuple[str] | None) -> list[dict[str, str]] | None:
53+
if label is None:
54+
return None
55+
collected_labels: list[dict[str, str]] = []
56+
if label:
57+
for item in label:
58+
if "=" in item:
59+
name, value = item.split("=", 1)
60+
else:
61+
raise CLIException(
62+
f"Invalid label format '{item}'. Expected format is key=value."
63+
)
64+
collected_labels.append({"key": name, "value": value})
65+
return collected_labels
66+
67+
5268
def convert_env_to_dict(env: tuple[str] | None) -> list[dict[str, str]] | None:
5369
if env is None:
5470
return None
@@ -110,6 +126,12 @@ def convert_env_to_dict(env: tuple[str] | None) -> list[dict[str, str]] | None:
110126
),
111127
help="Deployment strategy",
112128
)
129+
@click.option(
130+
"--label",
131+
type=click.STRING,
132+
help="List of labels pass by --label key=value --label ...",
133+
multiple=True,
134+
)
113135
@click.option(
114136
"--env",
115137
type=click.STRING,
@@ -158,6 +180,7 @@ def deploy_command(
158180
scaling_max: int | None,
159181
instance_type: str | None,
160182
strategy: str | None,
183+
label: tuple[str] | None,
161184
env: tuple[str] | None,
162185
secret: tuple[str] | None,
163186
config_file: str | t.TextIO | None,
@@ -180,6 +203,7 @@ def deploy_command(
180203
instance_type=instance_type,
181204
strategy=strategy,
182205
env=env,
206+
label=label,
183207
secret=secret,
184208
config_file=config_file,
185209
config_dict=config_dict,
@@ -361,6 +385,12 @@ def deployment_command():
361385
),
362386
help="Deployment strategy",
363387
)
388+
@click.option(
389+
"--label",
390+
type=click.STRING,
391+
help="List of labels pass by --label key=value --label ...",
392+
multiple=True,
393+
)
364394
@click.option(
365395
"--env",
366396
type=click.STRING,
@@ -397,6 +427,7 @@ def update( # type: ignore
397427
scaling_max: int | None,
398428
instance_type: str | None,
399429
strategy: str | None,
430+
label: tuple[str] | None,
400431
env: tuple[str] | None,
401432
secret: tuple[str] | None,
402433
config_file: t.TextIO | None,
@@ -422,6 +453,7 @@ def update( # type: ignore
422453
instance_type=instance_type,
423454
strategy=strategy,
424455
envs=convert_env_to_dict(env),
456+
labels=convert_label_to_dict(label),
425457
secrets=list(secret) if secret else None,
426458
config_file=config_file,
427459
config_dict=cfg_dict,
@@ -482,6 +514,12 @@ def update( # type: ignore
482514
),
483515
help="Deployment strategy",
484516
)
517+
@click.option(
518+
"--label",
519+
type=click.STRING,
520+
help="List of labels pass by --label key=value --label ...",
521+
multiple=True,
522+
)
485523
@click.option(
486524
"--env",
487525
type=click.STRING,
@@ -518,6 +556,7 @@ def apply( # type: ignore
518556
scaling_max: int | None,
519557
instance_type: str | None,
520558
strategy: str | None,
559+
label: tuple[str] | None,
521560
env: tuple[str] | None,
522561
secret: tuple[str] | None,
523562
config_file: str | t.TextIO | None,
@@ -541,6 +580,7 @@ def apply( # type: ignore
541580
scaling_min=scaling_min,
542581
instance_type=instance_type,
543582
strategy=strategy,
583+
labels=convert_label_to_dict(label),
544584
envs=convert_env_to_dict(env),
545585
secrets=list(secret) if secret else None,
546586
config_file=config_file,
@@ -853,6 +893,7 @@ def create_deployment(
853893
scaling_max: int | None = None,
854894
instance_type: str | None = None,
855895
strategy: str | None = None,
896+
label: tuple[str] | None = None,
856897
env: tuple[str] | None = None,
857898
secret: tuple[str] | None = None,
858899
config_file: str | t.TextIO | None = None,
@@ -875,6 +916,7 @@ def create_deployment(
875916
scaling_min=scaling_min,
876917
instance_type=instance_type,
877918
strategy=strategy,
919+
labels=convert_label_to_dict(label),
878920
envs=convert_env_to_dict(env),
879921
secrets=list(secret) if secret else None,
880922
config_file=config_file,

0 commit comments

Comments
 (0)