qwak-sdk 0.5.62__py3-none-any.whl → 0.5.64__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of qwak-sdk might be problematic. Click here for more details.
- qwak_sdk/__init__.py +1 -1
- qwak_sdk/commands/models/build/ui.py +5 -0
- qwak_sdk/commands/models/deployments/deploy/_logic/deploy_config.py +1 -1
- qwak_sdk/commands/models/deployments/deploy/_logic/deployment_message_helpers.py +1 -8
- qwak_sdk/commands/models/deployments/deploy/_logic/deployment_size_mapper.py +41 -3
- qwak_sdk/commands/models/deployments/deploy/_logic/local_deployment.py +193 -0
- qwak_sdk/commands/models/deployments/deploy/batch/_logic/deploy_executor.py +0 -1
- qwak_sdk/commands/models/deployments/deploy/batch/ui.py +1 -1
- qwak_sdk/commands/models/deployments/deploy/realtime/_logic/deploy_executor.py +0 -1
- qwak_sdk/commands/models/deployments/deploy/realtime/_logic/serving_strategy_mapper.py +0 -35
- qwak_sdk/commands/models/deployments/deploy/realtime/ui.py +25 -5
- qwak_sdk/commands/models/deployments/deploy/streaming/_logic/deploy_executor.py +0 -1
- qwak_sdk/commands/models/deployments/undeploy/_logic/request_undeploy.py +0 -27
- qwak_sdk/commands/models/runtime/runtime_commands_group.py +0 -2
- {qwak_sdk-0.5.62.dist-info → qwak_sdk-0.5.64.dist-info}/METADATA +5 -3
- {qwak_sdk-0.5.62.dist-info → qwak_sdk-0.5.64.dist-info}/RECORD +18 -26
- qwak_sdk/commands/models/_logic/__init__.py +0 -0
- qwak_sdk/commands/models/_logic/variations.py +0 -55
- qwak_sdk/commands/models/deployments/deploy/_logic/variations.py +0 -81
- qwak_sdk/commands/models/deployments/undeploy/_logic/variations.py +0 -74
- qwak_sdk/commands/models/runtime/traffic_update/__init__.py +0 -0
- qwak_sdk/commands/models/runtime/traffic_update/_logic/__init__.py +0 -0
- qwak_sdk/commands/models/runtime/traffic_update/_logic/execute_runtime_update_traffic.py +0 -54
- qwak_sdk/commands/models/runtime/traffic_update/_logic/variations.py +0 -84
- qwak_sdk/commands/models/runtime/traffic_update/ui.py +0 -37
- {qwak_sdk-0.5.62.dist-info → qwak_sdk-0.5.64.dist-info}/WHEEL +0 -0
- {qwak_sdk-0.5.62.dist-info → qwak_sdk-0.5.64.dist-info}/entry_points.txt +0 -0
qwak_sdk/__init__.py
CHANGED
|
@@ -110,6 +110,11 @@ from qwak_sdk.inner.tools.config_handler import config_handler
|
|
|
110
110
|
type=str,
|
|
111
111
|
help="[REMOTE BUILD] Custom IAM Role ARN.",
|
|
112
112
|
)
|
|
113
|
+
@click.option(
|
|
114
|
+
"--service-account-key-secret-name",
|
|
115
|
+
type=str,
|
|
116
|
+
help="Custom service account for Gcp.",
|
|
117
|
+
)
|
|
113
118
|
@click.option(
|
|
114
119
|
"--cache/--no-cache",
|
|
115
120
|
default=None,
|
|
@@ -246,7 +246,7 @@ class DeployConfig(YamlConfigMixin, QwakConfigBase):
|
|
|
246
246
|
@dataclass
|
|
247
247
|
class AdvancedOptions:
|
|
248
248
|
iam_role_arn: str = field(default=None)
|
|
249
|
-
purchase_option: str = field(default=
|
|
249
|
+
purchase_option: str = field(default="")
|
|
250
250
|
service_account_key_secret_name: str = field(default=None)
|
|
251
251
|
|
|
252
252
|
model_id: str = field(default="")
|
|
@@ -11,7 +11,6 @@ from _qwak_proto.qwak.deployment.deployment_pb2 import (
|
|
|
11
11
|
ServingStrategy,
|
|
12
12
|
)
|
|
13
13
|
from qwak.clients.administration.eco_system.client import EcosystemClient
|
|
14
|
-
from qwak.clients.deployment.client import DeploymentManagementClient
|
|
15
14
|
from qwak.clients.instance_template.client import InstanceTemplateManagementClient
|
|
16
15
|
from qwak.exceptions import QwakException
|
|
17
16
|
|
|
@@ -40,12 +39,11 @@ UNKNOWN_SERVING_STRATEGY = (
|
|
|
40
39
|
def get_env_to_deployment_message(
|
|
41
40
|
deploy_config: DeployConfig,
|
|
42
41
|
kube_deployment_type: KubeDeploymentType,
|
|
43
|
-
deployment_client: DeploymentManagementClient,
|
|
44
42
|
ecosystem_client: EcosystemClient,
|
|
45
43
|
instance_template_client: InstanceTemplateManagementClient,
|
|
46
44
|
) -> Dict[str, EnvironmentDeploymentMessage]:
|
|
47
45
|
deployment_size = deployment_size_from_deploy_config(
|
|
48
|
-
deploy_config, instance_template_client
|
|
46
|
+
deploy_config, instance_template_client, ecosystem_client
|
|
49
47
|
)
|
|
50
48
|
advanced_deployment_options = get_advanced_deployment_options_from_deploy_config(
|
|
51
49
|
deploy_config, kube_deployment_type
|
|
@@ -60,13 +58,8 @@ def get_env_to_deployment_message(
|
|
|
60
58
|
)
|
|
61
59
|
|
|
62
60
|
if kube_deployment_type == KubeDeploymentType.ONLINE:
|
|
63
|
-
model_traffic = deployment_client.get_model_traffic_config(
|
|
64
|
-
deploy_config.model_id
|
|
65
|
-
)
|
|
66
|
-
|
|
67
61
|
env_to_serving_strategy = create_realtime_serving_strategy_from_deploy_config(
|
|
68
62
|
deploy_config,
|
|
69
|
-
model_traffic,
|
|
70
63
|
environment_name_to_config,
|
|
71
64
|
)
|
|
72
65
|
environment_variables = dictify_params(deploy_config.realtime.env_vars)
|
|
@@ -7,8 +7,11 @@ from _qwak_proto.qwak.user_application.common.v0.resources_pb2 import (
|
|
|
7
7
|
GpuResources,
|
|
8
8
|
PodComputeResourceTemplateSpec,
|
|
9
9
|
)
|
|
10
|
+
from qwak.clients.administration.eco_system.client import EcosystemClient
|
|
10
11
|
from qwak.clients.instance_template.client import InstanceTemplateManagementClient
|
|
12
|
+
from qwak.exceptions import QwakException
|
|
11
13
|
from qwak.inner.instance_template.verify_template_id import verify_template_id
|
|
14
|
+
from qwak.inner.provider import Provider
|
|
12
15
|
|
|
13
16
|
from qwak_sdk.commands.models.deployments.deploy._logic.deploy_config import (
|
|
14
17
|
DeployConfig,
|
|
@@ -18,14 +21,37 @@ from qwak_sdk.commands.models.deployments.deploy._logic.deploy_config import (
|
|
|
18
21
|
def deployment_size_from_deploy_config(
|
|
19
22
|
deploy_config: DeployConfig,
|
|
20
23
|
instance_template_client: InstanceTemplateManagementClient,
|
|
24
|
+
ecosystem_client: EcosystemClient,
|
|
21
25
|
) -> DeploymentSize:
|
|
22
26
|
if deploy_config.resources.instance_size:
|
|
23
27
|
deploy_config.resources.instance_size = (
|
|
24
28
|
deploy_config.resources.instance_size.lower()
|
|
25
29
|
)
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
30
|
+
account_details = ecosystem_client.get_account_details()
|
|
31
|
+
if deploy_config.environments:
|
|
32
|
+
environments_config = list(
|
|
33
|
+
ecosystem_client.get_environments_names_to_details(
|
|
34
|
+
deploy_config.environments
|
|
35
|
+
).values()
|
|
36
|
+
)
|
|
37
|
+
else:
|
|
38
|
+
environments_config = [
|
|
39
|
+
account_details.environment_by_id[
|
|
40
|
+
account_details.default_environment_id
|
|
41
|
+
]
|
|
42
|
+
]
|
|
43
|
+
for environment_config in environments_config:
|
|
44
|
+
provider = __get_provider(environment_config)
|
|
45
|
+
try:
|
|
46
|
+
verify_template_id(
|
|
47
|
+
deploy_config.resources.instance_size,
|
|
48
|
+
instance_template_client,
|
|
49
|
+
provider=provider,
|
|
50
|
+
)
|
|
51
|
+
except QwakException as e:
|
|
52
|
+
raise QwakException(
|
|
53
|
+
f"Error with template {deploy_config.resources.instance_size} for environment {environment_config.name}: {e.message}"
|
|
54
|
+
)
|
|
29
55
|
|
|
30
56
|
return DeploymentSize(
|
|
31
57
|
number_of_pods=deploy_config.resources.pods,
|
|
@@ -56,3 +82,15 @@ def deployment_size_from_deploy_config(
|
|
|
56
82
|
)
|
|
57
83
|
),
|
|
58
84
|
)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def __get_provider(environment_config):
|
|
88
|
+
provider = None
|
|
89
|
+
cloud_type = environment_config.configuration.cloud_configuration.WhichOneof(
|
|
90
|
+
"configuration"
|
|
91
|
+
)
|
|
92
|
+
if cloud_type == "aws_cloud_configuration":
|
|
93
|
+
provider = Provider.AWS
|
|
94
|
+
elif cloud_type == "gcp_cloud_configuration":
|
|
95
|
+
provider = Provider.GCP
|
|
96
|
+
return provider
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import base64
|
|
2
|
+
|
|
3
|
+
from _qwak_proto.qwak.ecosystem.v0.ecosystem_runtime_service_pb2 import (
|
|
4
|
+
GetCloudCredentialsParameters,
|
|
5
|
+
GetCloudCredentialsRequest,
|
|
6
|
+
PermissionSet,
|
|
7
|
+
PullModelsContainerRegistry,
|
|
8
|
+
)
|
|
9
|
+
from google.protobuf.duration_pb2 import Duration
|
|
10
|
+
from qwak.clients.administration.eco_system.client import EcosystemClient
|
|
11
|
+
from qwak.clients.build_orchestrator import BuildOrchestratorClient
|
|
12
|
+
from qwak.exceptions import QwakException
|
|
13
|
+
from rich.console import Console
|
|
14
|
+
from rich.layout import Layout
|
|
15
|
+
from rich.panel import Panel
|
|
16
|
+
from rich.progress import Progress
|
|
17
|
+
|
|
18
|
+
from qwak_sdk.commands.models.deployments.deploy._logic.deploy_config import (
|
|
19
|
+
DeployConfig,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
tasks = {}
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def local_deploy(config: DeployConfig):
|
|
26
|
+
try:
|
|
27
|
+
import docker
|
|
28
|
+
except ImportError:
|
|
29
|
+
raise QwakException(
|
|
30
|
+
"Error: 'docker' package is required to for local model deployment."
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
console = Console()
|
|
34
|
+
console.print(Panel(f"Deploying model {config.model_id} locally", style="green"))
|
|
35
|
+
|
|
36
|
+
client = docker.from_env()
|
|
37
|
+
build_image = _get_build_image(config)
|
|
38
|
+
|
|
39
|
+
if not client.images.list(name=build_image):
|
|
40
|
+
console.print(
|
|
41
|
+
"Pulling serving image from Qwak's remote repository. Might take a few minutes...",
|
|
42
|
+
style="yellow",
|
|
43
|
+
)
|
|
44
|
+
_docker_login(client)
|
|
45
|
+
_image_pull(client, build_image)
|
|
46
|
+
|
|
47
|
+
try:
|
|
48
|
+
container = start_local_qwak_container(build_image, client, config)
|
|
49
|
+
container.reload()
|
|
50
|
+
host_port = container.ports.get("5000/tcp")[0]["HostPort"]
|
|
51
|
+
|
|
52
|
+
layout = example_usage_layout(host_port)
|
|
53
|
+
console.print(layout)
|
|
54
|
+
|
|
55
|
+
for line in container.logs(stream=True):
|
|
56
|
+
console.print(str(line.strip().decode()), style="blue")
|
|
57
|
+
|
|
58
|
+
except KeyboardInterrupt:
|
|
59
|
+
console.print(Panel("Stopping container...", style="red"))
|
|
60
|
+
container.stop()
|
|
61
|
+
container.remove()
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def example_usage_layout(host_port: str):
|
|
65
|
+
layout = Layout(size=6)
|
|
66
|
+
layout.split_row(
|
|
67
|
+
Layout(name="left"),
|
|
68
|
+
Layout(name="right"),
|
|
69
|
+
)
|
|
70
|
+
layout["left"].update(
|
|
71
|
+
Panel(
|
|
72
|
+
f"[bold]cURL usage:[bold]\n\n"
|
|
73
|
+
f"curl --location\n"
|
|
74
|
+
f"--request POST http://localhost:{host_port}/predict\n"
|
|
75
|
+
f"--header 'Content-Type: application/json'\n"
|
|
76
|
+
f"--data '...'",
|
|
77
|
+
style="green",
|
|
78
|
+
)
|
|
79
|
+
)
|
|
80
|
+
layout["right"].update(
|
|
81
|
+
Panel(
|
|
82
|
+
f"[bold]Python client usage:[bold]\n\n"
|
|
83
|
+
f"from qwak_inference import RealtimeClient\n\nfeature_vector=[...]\n"
|
|
84
|
+
f"client = RealTimeClient(model_api='http://localhost:{host_port}/predict')\n"
|
|
85
|
+
f"client.predict(feature_vector)",
|
|
86
|
+
style="green",
|
|
87
|
+
)
|
|
88
|
+
)
|
|
89
|
+
return layout
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def start_local_qwak_container(build_image: str, docker_client, config: DeployConfig):
|
|
93
|
+
return docker_client.containers.run(
|
|
94
|
+
build_image,
|
|
95
|
+
command=["bentoml", "serve-gunicorn", "./"],
|
|
96
|
+
entrypoint="./docker-entrypoint.sh",
|
|
97
|
+
environment=[
|
|
98
|
+
"BENTOML_GUNICORN_WORKERS=2",
|
|
99
|
+
"QWAK_DEBUG_MODE=True",
|
|
100
|
+
f"QWAK_MODEL_ID={config.model_id}",
|
|
101
|
+
"BENTOML_DO_NOT_TRACK=True",
|
|
102
|
+
"PYTHONPATH=/qwak/model_dir:/qwak/model_dir/main:$PYTHONPATH",
|
|
103
|
+
f"QWAK_BUILD_ID={config.build_id}",
|
|
104
|
+
"BUNDLE_PATH=/home/bentoml/bundle",
|
|
105
|
+
"BENTOML_HOME=/home/bentoml/",
|
|
106
|
+
],
|
|
107
|
+
stream=True,
|
|
108
|
+
detach=True,
|
|
109
|
+
publish_all_ports=True,
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def _get_build_image(config: DeployConfig):
|
|
114
|
+
return (
|
|
115
|
+
BuildOrchestratorClient().get_build(config.build_id).build.build_destined_image
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def _show_progress(line, progress):
|
|
120
|
+
if line["status"] == "Downloading":
|
|
121
|
+
idx = f'[red][Download {line["id"]}]'
|
|
122
|
+
elif line["status"] == "Extracting":
|
|
123
|
+
idx = f'[green][Extract {line["id"]}]'
|
|
124
|
+
else:
|
|
125
|
+
# skip other statuses
|
|
126
|
+
return
|
|
127
|
+
|
|
128
|
+
if idx not in tasks.keys():
|
|
129
|
+
tasks[idx] = progress.add_task(f"{idx}", total=line["progressDetail"]["total"])
|
|
130
|
+
else:
|
|
131
|
+
progress.update(tasks[idx], completed=line["progressDetail"]["current"])
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def _image_pull(docker_client, image_name: str):
|
|
135
|
+
with Progress() as progress:
|
|
136
|
+
resp = docker_client.api.pull(image_name, stream=True, decode=True)
|
|
137
|
+
for line in resp:
|
|
138
|
+
_show_progress(line, progress)
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
def _docker_login(docker_client):
|
|
142
|
+
try:
|
|
143
|
+
import boto3
|
|
144
|
+
except ImportError:
|
|
145
|
+
raise QwakException(
|
|
146
|
+
"Error: The 'boto3' package is necessary for local model deployment. Install it directly or by running"
|
|
147
|
+
" 'pip install qwak[local-deployment]'"
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
# TODO: block if not an AWS based container registry
|
|
151
|
+
credentials = _get_aws_credentials()
|
|
152
|
+
|
|
153
|
+
aws_credentials = credentials.cloud_credentials.aws_temporary_credentials
|
|
154
|
+
ecr_client = boto3.Session(
|
|
155
|
+
aws_access_key_id=aws_credentials.access_key_id,
|
|
156
|
+
aws_secret_access_key=aws_credentials.secret_access_key,
|
|
157
|
+
aws_session_token=aws_credentials.session_token,
|
|
158
|
+
region_name=aws_credentials.region,
|
|
159
|
+
).client("ecr")
|
|
160
|
+
|
|
161
|
+
ecr_credentials = ecr_client.get_authorization_token()["authorizationData"][0]
|
|
162
|
+
|
|
163
|
+
try:
|
|
164
|
+
docker_client.login(
|
|
165
|
+
username="AWS",
|
|
166
|
+
registry=ecr_credentials["proxyEndpoint"],
|
|
167
|
+
password=base64.b64decode(ecr_credentials["authorizationToken"])
|
|
168
|
+
.replace(b"AWS:", b"")
|
|
169
|
+
.decode("utf-8"),
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
except Exception as e:
|
|
173
|
+
raise QwakException(f"Failed to login to Qwak's container registry: {e}")
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
def _get_aws_credentials():
|
|
177
|
+
try:
|
|
178
|
+
eco_client = EcosystemClient()
|
|
179
|
+
credentials = eco_client.get_cloud_credentials(
|
|
180
|
+
request=GetCloudCredentialsRequest(
|
|
181
|
+
parameters=GetCloudCredentialsParameters(
|
|
182
|
+
duration=Duration(seconds=60 * 60, nanos=0), # 6 hours
|
|
183
|
+
permission_set=PermissionSet(
|
|
184
|
+
pull_models_container_registry=PullModelsContainerRegistry()
|
|
185
|
+
),
|
|
186
|
+
)
|
|
187
|
+
)
|
|
188
|
+
)
|
|
189
|
+
return credentials
|
|
190
|
+
except Exception as e:
|
|
191
|
+
raise QwakException(
|
|
192
|
+
f"Failed to get credentials to pull image from Qwak's container registry: {e}."
|
|
193
|
+
)
|
|
@@ -7,24 +7,14 @@ from _qwak_proto.qwak.deployment.deployment_pb2 import (
|
|
|
7
7
|
RealTimeConfig,
|
|
8
8
|
ServingStrategy,
|
|
9
9
|
TrafficConfig,
|
|
10
|
-
Variation,
|
|
11
|
-
)
|
|
12
|
-
from _qwak_proto.qwak.deployment.deployment_service_pb2 import (
|
|
13
|
-
GetDeploymentStatusResponse,
|
|
14
10
|
)
|
|
15
11
|
from _qwak_proto.qwak.ecosystem.v0.ecosystem_pb2 import UserContextEnvironmentDetails
|
|
16
12
|
from qwak.exceptions import QwakException
|
|
17
13
|
|
|
18
14
|
from qwak_sdk.commands.audience._logic.config.v1.audience_config import AudienceConfig
|
|
19
|
-
from qwak_sdk.commands.models._logic.variations import (
|
|
20
|
-
create_variation_from_variation_config,
|
|
21
|
-
)
|
|
22
15
|
from qwak_sdk.commands.models.deployments.deploy._logic.deploy_config import (
|
|
23
16
|
DeployConfig,
|
|
24
17
|
)
|
|
25
|
-
from qwak_sdk.commands.models.deployments.deploy._logic.variations import (
|
|
26
|
-
get_variations_for_deploy,
|
|
27
|
-
)
|
|
28
18
|
|
|
29
19
|
|
|
30
20
|
def create_realtime_serving_strategy(
|
|
@@ -32,7 +22,6 @@ def create_realtime_serving_strategy(
|
|
|
32
22
|
audiences: List[AudienceConfig],
|
|
33
23
|
fallback_variation: str,
|
|
34
24
|
variation_name: str,
|
|
35
|
-
variations: List[Variation],
|
|
36
25
|
variation_protected_state: bool = False,
|
|
37
26
|
) -> ServingStrategy:
|
|
38
27
|
return ServingStrategy(
|
|
@@ -41,7 +30,6 @@ def create_realtime_serving_strategy(
|
|
|
41
30
|
auto_scaling_config=auto_scaling,
|
|
42
31
|
traffic_config=TrafficConfig(
|
|
43
32
|
selected_variation_name=variation_name,
|
|
44
|
-
variations=variations,
|
|
45
33
|
audience_routes_entries=[
|
|
46
34
|
audience.to_audience_route_entry(index)
|
|
47
35
|
for index, audience in enumerate(audiences)
|
|
@@ -56,7 +44,6 @@ def create_realtime_serving_strategy(
|
|
|
56
44
|
|
|
57
45
|
def create_realtime_serving_strategy_from_deploy_config(
|
|
58
46
|
deploy_config: DeployConfig,
|
|
59
|
-
model_traffic: GetDeploymentStatusResponse,
|
|
60
47
|
environment_name_to_config: Dict[str, UserContextEnvironmentDetails],
|
|
61
48
|
) -> Dict[str, ServingStrategy]:
|
|
62
49
|
serving_strategies = {}
|
|
@@ -70,34 +57,12 @@ def create_realtime_serving_strategy_from_deploy_config(
|
|
|
70
57
|
else None
|
|
71
58
|
)
|
|
72
59
|
for env_name, env_config in environment_name_to_config.items():
|
|
73
|
-
env_variations_response = model_traffic.environment_to_model_traffic.get(
|
|
74
|
-
env_config.id
|
|
75
|
-
)
|
|
76
|
-
existing_variation = (
|
|
77
|
-
env_variations_response.variations if env_variations_response else []
|
|
78
|
-
)
|
|
79
60
|
try:
|
|
80
|
-
variations = []
|
|
81
|
-
if not deploy_config.realtime.audiences:
|
|
82
|
-
variations = get_variations_for_deploy(
|
|
83
|
-
variation_name=variation_name,
|
|
84
|
-
existing_variations=existing_variation,
|
|
85
|
-
requested_variations=list(
|
|
86
|
-
map(
|
|
87
|
-
create_variation_from_variation_config,
|
|
88
|
-
deploy_config.realtime.variations,
|
|
89
|
-
)
|
|
90
|
-
),
|
|
91
|
-
environment_name=env_name,
|
|
92
|
-
variation_protected_state=variation_protected_state,
|
|
93
|
-
)
|
|
94
|
-
|
|
95
61
|
serving_strategies[env_config.id] = create_realtime_serving_strategy(
|
|
96
62
|
auto_scaling,
|
|
97
63
|
deploy_config.realtime.audiences,
|
|
98
64
|
fallback_variation,
|
|
99
65
|
variation_name,
|
|
100
|
-
variations,
|
|
101
66
|
variation_protected_state,
|
|
102
67
|
)
|
|
103
68
|
|
|
@@ -14,6 +14,9 @@ from qwak_sdk.commands.models.deployments.deploy._logic.deploy_config import (
|
|
|
14
14
|
from qwak_sdk.commands.models.deployments.deploy._logic.deployment_response_handler import (
|
|
15
15
|
client_deployment,
|
|
16
16
|
)
|
|
17
|
+
from qwak_sdk.commands.models.deployments.deploy._logic.local_deployment import (
|
|
18
|
+
local_deploy,
|
|
19
|
+
)
|
|
17
20
|
from qwak_sdk.commands.models.deployments.deploy.realtime._logic.deploy_executor import (
|
|
18
21
|
RealtimeDeployExecutor,
|
|
19
22
|
)
|
|
@@ -87,7 +90,7 @@ logger = get_qwak_logger()
|
|
|
87
90
|
@click.option(
|
|
88
91
|
"--service-account-key-secret-name",
|
|
89
92
|
type=str,
|
|
90
|
-
help="Custom service
|
|
93
|
+
help="Custom service account for Gcp.",
|
|
91
94
|
)
|
|
92
95
|
@click.option(
|
|
93
96
|
"--max-batch-size",
|
|
@@ -113,6 +116,12 @@ logger = get_qwak_logger()
|
|
|
113
116
|
default=False,
|
|
114
117
|
help="Waiting for deployments to be ready",
|
|
115
118
|
)
|
|
119
|
+
@click.option(
|
|
120
|
+
"--local",
|
|
121
|
+
is_flag=True,
|
|
122
|
+
default=False,
|
|
123
|
+
help="Deploy the model container locally, for development purposes only",
|
|
124
|
+
)
|
|
116
125
|
@click.option(
|
|
117
126
|
"-v",
|
|
118
127
|
"--verbose",
|
|
@@ -170,13 +179,20 @@ logger = get_qwak_logger()
|
|
|
170
179
|
help="Whether the deployment variation is protected. Default is false",
|
|
171
180
|
)
|
|
172
181
|
def realtime(
|
|
173
|
-
verbose: bool,
|
|
182
|
+
verbose: bool,
|
|
183
|
+
from_file: Optional[str],
|
|
184
|
+
out_conf: bool,
|
|
185
|
+
sync: bool,
|
|
186
|
+
local: bool,
|
|
187
|
+
**kwargs,
|
|
174
188
|
):
|
|
175
189
|
set_qwak_logger_stdout_verbosity_level(verbose + 1)
|
|
176
|
-
deploy_realtime(from_file, out_conf, sync, **kwargs)
|
|
190
|
+
deploy_realtime(from_file, out_conf, sync, local, **kwargs)
|
|
177
191
|
|
|
178
192
|
|
|
179
|
-
def deploy_realtime(
|
|
193
|
+
def deploy_realtime(
|
|
194
|
+
from_file: Optional[str], out_conf: bool, sync: bool, local: bool, **kwargs
|
|
195
|
+
):
|
|
180
196
|
config: DeployConfig = config_handler(
|
|
181
197
|
config=DeployConfig,
|
|
182
198
|
from_file=from_file,
|
|
@@ -184,6 +200,10 @@ def deploy_realtime(from_file: Optional[str], out_conf: bool, sync: bool, **kwar
|
|
|
184
200
|
sections=("realtime", "autoscaling"),
|
|
185
201
|
**kwargs,
|
|
186
202
|
)
|
|
187
|
-
|
|
203
|
+
|
|
204
|
+
if local:
|
|
205
|
+
local_deploy(config)
|
|
206
|
+
|
|
207
|
+
elif not out_conf:
|
|
188
208
|
deploy_executor = RealtimeDeployExecutor(config)
|
|
189
209
|
client_deployment(deploy=deploy_executor, sync=sync)
|
|
@@ -8,7 +8,6 @@ from _qwak_proto.qwak.deployment.deployment_pb2 import (
|
|
|
8
8
|
EnvironmentUndeploymentMessage,
|
|
9
9
|
ModelDeploymentStatus,
|
|
10
10
|
TrafficConfig,
|
|
11
|
-
Variation,
|
|
12
11
|
)
|
|
13
12
|
from _qwak_proto.qwak.ecosystem.v0.ecosystem_pb2 import EnvironmentDetails
|
|
14
13
|
from qwak.clients.administration.eco_system.client import EcosystemClient
|
|
@@ -16,15 +15,9 @@ from qwak.clients.deployment.client import DeploymentManagementClient
|
|
|
16
15
|
from qwak.exceptions import QwakException
|
|
17
16
|
from qwak.tools.logger.logger import get_qwak_logger
|
|
18
17
|
|
|
19
|
-
from qwak_sdk.commands.models._logic.variations import (
|
|
20
|
-
create_variation_from_variation_config,
|
|
21
|
-
)
|
|
22
18
|
from qwak_sdk.commands.models.deployments.deploy._logic.deploy_config import (
|
|
23
19
|
DeployConfig,
|
|
24
20
|
)
|
|
25
|
-
from qwak_sdk.commands.models.deployments.undeploy._logic.variations import (
|
|
26
|
-
validate_variations_for_undeploy,
|
|
27
|
-
)
|
|
28
21
|
from qwak_sdk.tools.utils import qwak_spinner
|
|
29
22
|
|
|
30
23
|
NO_DEPLOYED_VARIATIONS_ERROR_MSG = (
|
|
@@ -45,12 +38,10 @@ def get_deployed_variation_name(existing_variations_names: Set[str]) -> str:
|
|
|
45
38
|
|
|
46
39
|
def get_environment_undeploy_message(
|
|
47
40
|
audiences: List[AudienceRoutesEntry],
|
|
48
|
-
env_name: str,
|
|
49
41
|
existing_variations_names: Set[str],
|
|
50
42
|
fallback_variation: str,
|
|
51
43
|
model_id: str,
|
|
52
44
|
model_uuid: str,
|
|
53
|
-
requested_variations: List[Variation],
|
|
54
45
|
variation_name: str,
|
|
55
46
|
):
|
|
56
47
|
if not variation_name and len(existing_variations_names) == 1:
|
|
@@ -58,20 +49,12 @@ def get_environment_undeploy_message(
|
|
|
58
49
|
existing_variations_names=existing_variations_names
|
|
59
50
|
)
|
|
60
51
|
|
|
61
|
-
if not audiences:
|
|
62
|
-
validate_variations_for_undeploy(
|
|
63
|
-
variation_name,
|
|
64
|
-
existing_variations_names,
|
|
65
|
-
requested_variations,
|
|
66
|
-
env_name,
|
|
67
|
-
)
|
|
68
52
|
return EnvironmentUndeploymentMessage(
|
|
69
53
|
model_id=model_id,
|
|
70
54
|
model_uuid=model_uuid,
|
|
71
55
|
hosting_service_type=DeploymentHostingServiceType.KUBE_DEPLOYMENT,
|
|
72
56
|
traffic_config=TrafficConfig(
|
|
73
57
|
selected_variation_name=variation_name,
|
|
74
|
-
variations=requested_variations,
|
|
75
58
|
audience_routes_entries=audiences,
|
|
76
59
|
fallback_variation=fallback_variation,
|
|
77
60
|
),
|
|
@@ -84,7 +67,6 @@ def get_env_to_undeploy_message(
|
|
|
84
67
|
env_id_to_deployment_details: Dict[str, EnvironmentDeploymentDetailsMessage],
|
|
85
68
|
env_name_to_env_details: Dict[str, EnvironmentDetails],
|
|
86
69
|
model_id: str,
|
|
87
|
-
requested_variations: List[Variation],
|
|
88
70
|
variation_name: str,
|
|
89
71
|
fallback_variation: str,
|
|
90
72
|
) -> Dict[str, EnvironmentUndeploymentMessage]:
|
|
@@ -111,12 +93,10 @@ def get_env_to_undeploy_message(
|
|
|
111
93
|
env_details.id
|
|
112
94
|
] = get_environment_undeploy_message(
|
|
113
95
|
audiences,
|
|
114
|
-
env_name,
|
|
115
96
|
existing_variations_names,
|
|
116
97
|
fallback_variation,
|
|
117
98
|
model_id,
|
|
118
99
|
model_uuid,
|
|
119
|
-
requested_variations,
|
|
120
100
|
variation_name,
|
|
121
101
|
)
|
|
122
102
|
except QwakException as e:
|
|
@@ -138,12 +118,6 @@ def undeploy(
|
|
|
138
118
|
audience.to_audience_route_entry(index)
|
|
139
119
|
for index, audience in enumerate(config.realtime.audiences)
|
|
140
120
|
]
|
|
141
|
-
requested_variations = list(
|
|
142
|
-
map(
|
|
143
|
-
create_variation_from_variation_config,
|
|
144
|
-
config.realtime.variations if config.realtime else [],
|
|
145
|
-
)
|
|
146
|
-
)
|
|
147
121
|
|
|
148
122
|
if not model_uuid:
|
|
149
123
|
raise QwakException("missing argument model uuid")
|
|
@@ -164,7 +138,6 @@ def undeploy(
|
|
|
164
138
|
env_id_to_deployment_details,
|
|
165
139
|
env_name_to_env_details,
|
|
166
140
|
model_id,
|
|
167
|
-
requested_variations,
|
|
168
141
|
config.realtime.variation_name,
|
|
169
142
|
config.realtime.fallback_variation,
|
|
170
143
|
)
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import click
|
|
2
2
|
|
|
3
3
|
from qwak_sdk.commands.models.runtime.logs.ui import runtime_logs
|
|
4
|
-
from qwak_sdk.commands.models.runtime.traffic_update.ui import runtime_traffic_update
|
|
5
4
|
from qwak_sdk.commands.models.runtime.update.ui import runtime_update
|
|
6
5
|
|
|
7
6
|
|
|
@@ -15,5 +14,4 @@ def runtime_commands_group():
|
|
|
15
14
|
|
|
16
15
|
|
|
17
16
|
runtime_commands_group.add_command(runtime_logs)
|
|
18
|
-
runtime_commands_group.add_command(runtime_traffic_update)
|
|
19
17
|
runtime_commands_group.add_command(runtime_update)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: qwak-sdk
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.64
|
|
4
4
|
Summary: Qwak SDK and CLI for qwak models
|
|
5
5
|
License: Apache-2.0
|
|
6
6
|
Keywords: mlops,ml,deployment,serving,model
|
|
@@ -19,7 +19,8 @@ Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
|
19
19
|
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
20
20
|
Provides-Extra: batch
|
|
21
21
|
Provides-Extra: feedback
|
|
22
|
-
|
|
22
|
+
Provides-Extra: local-deployment
|
|
23
|
+
Requires-Dist: boto3 (>=1.24.116,<2.0.0) ; extra == "batch" or extra == "feedback" or extra == "local-deployment"
|
|
23
24
|
Requires-Dist: cookiecutter
|
|
24
25
|
Requires-Dist: croniter (==1.4.1)
|
|
25
26
|
Requires-Dist: gitpython (>=2.1.0)
|
|
@@ -28,8 +29,9 @@ Requires-Dist: pandas (<1.4) ; (python_full_version >= "3.7.1" and python_versio
|
|
|
28
29
|
Requires-Dist: pandas (>=1.4.3,<2.0.0) ; (python_version >= "3.8" and python_version < "3.10") and (extra == "batch" or extra == "feedback")
|
|
29
30
|
Requires-Dist: pyarrow (>=6.0.0,<11.0.0) ; extra == "batch"
|
|
30
31
|
Requires-Dist: python-json-logger (>=2.0.2)
|
|
31
|
-
Requires-Dist: qwak-core (==0.3.
|
|
32
|
+
Requires-Dist: qwak-core (==0.3.163)
|
|
32
33
|
Requires-Dist: qwak-inference (>=0.1,<0.2)
|
|
34
|
+
Requires-Dist: rich (>=13.0.0)
|
|
33
35
|
Requires-Dist: tabulate (>=0.8.0)
|
|
34
36
|
Requires-Dist: yaspin (>=2.0.0)
|
|
35
37
|
Project-URL: Home page, https://www.qwak.com/
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
qwak_sdk/__init__.py,sha256=
|
|
1
|
+
qwak_sdk/__init__.py,sha256=lNU63Fap7GcBaP4WD3Kn5M3EOnMoAoKbJPYJRjJuWHA,135
|
|
2
2
|
qwak_sdk/cli.py,sha256=FIK1dUNxR57ypb-CeD7fKSJnPJ02lrjR9G4aj2qMLPU,2458
|
|
3
3
|
qwak_sdk/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
4
|
qwak_sdk/commands/_logic/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -99,8 +99,6 @@ qwak_sdk/commands/feature_store/resume/ui.py,sha256=nI87xvA30qNQVJnT67lYJgwKGBtv
|
|
|
99
99
|
qwak_sdk/commands/feature_store/trigger/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
100
100
|
qwak_sdk/commands/feature_store/trigger/ui.py,sha256=1VJBqzxMwUWcytmZL0ymf9QlYa7oX6RDLmKsLmYVW_4,1015
|
|
101
101
|
qwak_sdk/commands/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
102
|
-
qwak_sdk/commands/models/_logic/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
103
|
-
qwak_sdk/commands/models/_logic/variations.py,sha256=fpe6kM8HWP7zkRl0AhZa6Ffg_LE6uiSSow0Wf5HAJxA,2050
|
|
104
102
|
qwak_sdk/commands/models/build/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
105
103
|
qwak_sdk/commands/models/build/_logic/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
106
104
|
qwak_sdk/commands/models/build/_logic/build_steps.py,sha256=Iqc3XDWhJ4LSlUiqfwP2Y9aUDpqab3WWVq-xXt-Uvo0,1533
|
|
@@ -123,7 +121,7 @@ qwak_sdk/commands/models/build/_logic/util/__init__.py,sha256=47DEQpj8HBSa-_TImW
|
|
|
123
121
|
qwak_sdk/commands/models/build/_logic/util/protobuf_factory.py,sha256=ar_oY38w_x0sxgVF7EBs5h7gchNsDntvtKK5sSYxb24,1686
|
|
124
122
|
qwak_sdk/commands/models/build/_logic/util/step_decorator.py,sha256=HLZyCGdqe3Ir7SaPWp1YNRHJpjXG-e-bbAvnOFysAVM,1913
|
|
125
123
|
qwak_sdk/commands/models/build/_logic/util/text.py,sha256=tH-v19Mt8l90sMVxku5XRtrderT0qdRqJ-jLijqannA,188
|
|
126
|
-
qwak_sdk/commands/models/build/ui.py,sha256=
|
|
124
|
+
qwak_sdk/commands/models/build/ui.py,sha256=MX4OpBHh3X83JXc0FFsx4PP_4IZVVGe2bBS1Z5VK36o,8967
|
|
127
125
|
qwak_sdk/commands/models/builds/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
128
126
|
qwak_sdk/commands/models/builds/builds_commands_group.py,sha256=0nSfTY8TracXG61rFboQWUTXJisHO6dgtJKeijy6ru8,491
|
|
129
127
|
qwak_sdk/commands/models/builds/cancel/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -145,34 +143,33 @@ qwak_sdk/commands/models/deployments/deploy/__init__.py,sha256=47DEQpj8HBSa-_TIm
|
|
|
145
143
|
qwak_sdk/commands/models/deployments/deploy/_logic/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
146
144
|
qwak_sdk/commands/models/deployments/deploy/_logic/advance_deployment_options_handler.py,sha256=gCo3WuP-IDuA5Sg7WbFmp1hYT5qyXyf6pUD3tZGyZXs,1251
|
|
147
145
|
qwak_sdk/commands/models/deployments/deploy/_logic/base_deploy_executor.py,sha256=HYKUG5s4ZrpFwoxJYn3EuTYU71lmM0cFOOjbHqd9ajY,2706
|
|
148
|
-
qwak_sdk/commands/models/deployments/deploy/_logic/deploy_config.py,sha256=
|
|
146
|
+
qwak_sdk/commands/models/deployments/deploy/_logic/deploy_config.py,sha256=4kcjUeUqkuGf9Zab2t6Z05Spp8VgJszRpe1rjeTZ64w,8956
|
|
149
147
|
qwak_sdk/commands/models/deployments/deploy/_logic/deployment.py,sha256=zBTjeeEVtTnTwUMwUfGTI3Ip9AgqKDvHAZ6_Wi22XVo,13221
|
|
150
|
-
qwak_sdk/commands/models/deployments/deploy/_logic/deployment_message_helpers.py,sha256=
|
|
148
|
+
qwak_sdk/commands/models/deployments/deploy/_logic/deployment_message_helpers.py,sha256=wkRiQWlnQr6tjWb4wfN00Lb4Dy98QydE-Zd4j9-3zDw,4608
|
|
151
149
|
qwak_sdk/commands/models/deployments/deploy/_logic/deployment_response_handler.py,sha256=cHa2iF_2A8e1wx2a4UZuTjQ5IHgPvua1xziFJwzP_6s,5837
|
|
152
|
-
qwak_sdk/commands/models/deployments/deploy/_logic/deployment_size_mapper.py,sha256=
|
|
150
|
+
qwak_sdk/commands/models/deployments/deploy/_logic/deployment_size_mapper.py,sha256=sfECrq-6Emt-qY6K3J-hf8-PYw8TP4EgpjynTPstDUE,3655
|
|
153
151
|
qwak_sdk/commands/models/deployments/deploy/_logic/get_latest_successful_build.py,sha256=fsahuSvgGzVjkZGaTH9YyNSOtRWBHYlyAU3wTriyCgI,978
|
|
154
|
-
qwak_sdk/commands/models/deployments/deploy/_logic/
|
|
152
|
+
qwak_sdk/commands/models/deployments/deploy/_logic/local_deployment.py,sha256=n42Hc-FnA3ODKok-_Nmnbjj1aPGW2P-DJ2dGDSZpSrE,6270
|
|
155
153
|
qwak_sdk/commands/models/deployments/deploy/batch/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
156
154
|
qwak_sdk/commands/models/deployments/deploy/batch/_logic/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
157
155
|
qwak_sdk/commands/models/deployments/deploy/batch/_logic/advanced_deployment_mapper.py,sha256=bwvPIoKCNaJmaNsPYL_dhK04FCRZvlj_jkwhCZM-eks,599
|
|
158
|
-
qwak_sdk/commands/models/deployments/deploy/batch/_logic/deploy_executor.py,sha256=
|
|
159
|
-
qwak_sdk/commands/models/deployments/deploy/batch/ui.py,sha256=
|
|
156
|
+
qwak_sdk/commands/models/deployments/deploy/batch/_logic/deploy_executor.py,sha256=7ND4JlV0xT8v_0kEHBseS9dHtpuCs_8D1CC2L_nVJDc,914
|
|
157
|
+
qwak_sdk/commands/models/deployments/deploy/batch/ui.py,sha256=Sek4sZ-XiFAJ7-bCakMX1BlOB7zrOLYHF1QyRo6LETw,3542
|
|
160
158
|
qwak_sdk/commands/models/deployments/deploy/deploy_commands_group.py,sha256=LnfdnfeSTCO90SrJfgXf21xiVRry6Y2sfj_JfdBQu_U,500
|
|
161
159
|
qwak_sdk/commands/models/deployments/deploy/realtime/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
162
160
|
qwak_sdk/commands/models/deployments/deploy/realtime/_logic/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
163
161
|
qwak_sdk/commands/models/deployments/deploy/realtime/_logic/advanced_deployment_mapper.py,sha256=LDJR2XzSG3QkHaAY4cSeDOb6e1-Aw-p5ZbRiLy2BXsU,1006
|
|
164
|
-
qwak_sdk/commands/models/deployments/deploy/realtime/_logic/deploy_executor.py,sha256=
|
|
165
|
-
qwak_sdk/commands/models/deployments/deploy/realtime/_logic/serving_strategy_mapper.py,sha256=
|
|
166
|
-
qwak_sdk/commands/models/deployments/deploy/realtime/ui.py,sha256=
|
|
162
|
+
qwak_sdk/commands/models/deployments/deploy/realtime/_logic/deploy_executor.py,sha256=XuuwuOBS2FtT0mEhngwo1z6teKT3GyHvWvXAJXMZG9s,918
|
|
163
|
+
qwak_sdk/commands/models/deployments/deploy/realtime/_logic/serving_strategy_mapper.py,sha256=297a6ncG-lS7kscZRy88Fg11qn3_vgB6rTYeq7kXH24,2580
|
|
164
|
+
qwak_sdk/commands/models/deployments/deploy/realtime/ui.py,sha256=hiVte3GkLZp3Iio6TsOs6B1RmkGmsslCXyABGZPiT5A,5509
|
|
167
165
|
qwak_sdk/commands/models/deployments/deploy/streaming/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
168
166
|
qwak_sdk/commands/models/deployments/deploy/streaming/_logic/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
169
|
-
qwak_sdk/commands/models/deployments/deploy/streaming/_logic/deploy_executor.py,sha256=
|
|
167
|
+
qwak_sdk/commands/models/deployments/deploy/streaming/_logic/deploy_executor.py,sha256=tfYZ3Qdk4yFBelkASYamn60JKWZRlFeFEfdXrMs8N9A,916
|
|
170
168
|
qwak_sdk/commands/models/deployments/deploy/streaming/_logic/serving_strategy_mapper.py,sha256=97m93afiwmrNL9EQ3tE4JmrBYfcBnKZB9ipcvzrIWDk,1500
|
|
171
169
|
qwak_sdk/commands/models/deployments/deploy/streaming/ui.py,sha256=9tPMnVnLNX3lYyBd4BAh-YThDFz99oyvrCRd_tDZufU,5796
|
|
172
170
|
qwak_sdk/commands/models/deployments/undeploy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
173
171
|
qwak_sdk/commands/models/deployments/undeploy/_logic/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
174
|
-
qwak_sdk/commands/models/deployments/undeploy/_logic/request_undeploy.py,sha256=
|
|
175
|
-
qwak_sdk/commands/models/deployments/undeploy/_logic/variations.py,sha256=qo4qUB78voUhtM1YIuTz1OSBaLRS3xw97bwxgqRuLgI,3036
|
|
172
|
+
qwak_sdk/commands/models/deployments/undeploy/_logic/request_undeploy.py,sha256=s9YneVS_RgBMTGODAxLxK5qqgQ9bdGsO91xoNS76CdY,8623
|
|
176
173
|
qwak_sdk/commands/models/deployments/undeploy/ui.py,sha256=1XYBouPgbJWOJCNR1UU1UOVnQS10iKsUqeNkvIBhHY8,2008
|
|
177
174
|
qwak_sdk/commands/models/describe/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
178
175
|
qwak_sdk/commands/models/describe/_logic.py,sha256=LN1r3zrXLHf83U5ate7ED7VdoZuWUqcHwLZPMMZXRfs,5589
|
|
@@ -252,12 +249,7 @@ qwak_sdk/commands/models/models_command_group.py,sha256=xrI_XwHUaahnH0P2iNkUps34
|
|
|
252
249
|
qwak_sdk/commands/models/runtime/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
253
250
|
qwak_sdk/commands/models/runtime/logs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
254
251
|
qwak_sdk/commands/models/runtime/logs/ui.py,sha256=2wxk4eqwKqSr83Wsn-4wHRvug3hQLmHeoyJ4zBAsW4U,1577
|
|
255
|
-
qwak_sdk/commands/models/runtime/runtime_commands_group.py,sha256=
|
|
256
|
-
qwak_sdk/commands/models/runtime/traffic_update/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
257
|
-
qwak_sdk/commands/models/runtime/traffic_update/_logic/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
258
|
-
qwak_sdk/commands/models/runtime/traffic_update/_logic/execute_runtime_update_traffic.py,sha256=el3MlANMcmbfxNCVTeqfT6x9DB_F4Ns6O-M2Am9F_uI,1811
|
|
259
|
-
qwak_sdk/commands/models/runtime/traffic_update/_logic/variations.py,sha256=UhVjyW4jeS7558ItpgffvBa7b8Pl2Jbb7SIEL0kgukU,3160
|
|
260
|
-
qwak_sdk/commands/models/runtime/traffic_update/ui.py,sha256=gCuPpRNYtB98Glr5FExj5nLfe8iwKF7xLAUzxqJ4tb8,1212
|
|
252
|
+
qwak_sdk/commands/models/runtime/runtime_commands_group.py,sha256=nuyPkGSbJ7RD6HNif6ygfR4yPXtPiDEEJ7UaVn04Wm8,421
|
|
261
253
|
qwak_sdk/commands/models/runtime/update/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
262
254
|
qwak_sdk/commands/models/runtime/update/_logic.py,sha256=vXgx16OTwx-8iucop-fU5o-BTWo5Iqiv-8aZjyeZ3Yg,393
|
|
263
255
|
qwak_sdk/commands/models/runtime/update/ui.py,sha256=24GX7V05zK0HwLdNIBMaf1zJ9CC2BcrWjQsgXAJviy8,622
|
|
@@ -326,7 +318,7 @@ qwak_sdk/tools/colors.py,sha256=7pui_GGjC4uZKYFsIyXaJjYsjLxJVHb4OrfTgr93hqo,287
|
|
|
326
318
|
qwak_sdk/tools/files.py,sha256=AyKJTOy7NhvP3SrqwIw_lxYNCOy1CvLgMmSJpWZ0OKM,2257
|
|
327
319
|
qwak_sdk/tools/log_handling.py,sha256=Aa1EmxUPCX8YWiZRutUvnqPv6K_z1zoGMwIWsEv24mM,6327
|
|
328
320
|
qwak_sdk/tools/utils.py,sha256=SHmU4r_m2ABZyFYMC03P17GvltPbYbmB39hvalIZEtI,1168
|
|
329
|
-
qwak_sdk-0.5.
|
|
330
|
-
qwak_sdk-0.5.
|
|
331
|
-
qwak_sdk-0.5.
|
|
332
|
-
qwak_sdk-0.5.
|
|
321
|
+
qwak_sdk-0.5.64.dist-info/entry_points.txt,sha256=vSl0ELYDyj640oMM57u0AjBP87wtLYxCcGOendhEx80,47
|
|
322
|
+
qwak_sdk-0.5.64.dist-info/WHEEL,sha256=vVCvjcmxuUltf8cYhJ0sJMRDLr1XsPuxEId8YDzbyCY,88
|
|
323
|
+
qwak_sdk-0.5.64.dist-info/METADATA,sha256=9eccdkFDg9jVxb-G3KZOWYoUwQtBJKKEp-bRBOjiSVE,1984
|
|
324
|
+
qwak_sdk-0.5.64.dist-info/RECORD,,
|
|
File without changes
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from typing import List
|
|
4
|
-
|
|
5
|
-
from _qwak_proto.qwak.deployment.deployment_pb2 import TrafficSpec, Variation
|
|
6
|
-
from qwak.exceptions import QwakException
|
|
7
|
-
|
|
8
|
-
from qwak_sdk.commands.models.deployments.deploy._logic.deploy_config import (
|
|
9
|
-
DeployConfig,
|
|
10
|
-
)
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
def validate_percentages(variations: List[Variation]):
|
|
14
|
-
for variation in variations:
|
|
15
|
-
if not (0 <= variation.traffic.percentage <= 100):
|
|
16
|
-
raise QwakException(
|
|
17
|
-
f"The variation '{variation.name}' contains invalid value '{variation.traffic.percentage}'. "
|
|
18
|
-
f"Value must be between 0 and 100."
|
|
19
|
-
)
|
|
20
|
-
|
|
21
|
-
non_shadow_variations = list(filter(lambda v: not v.traffic.is_shadow, variations))
|
|
22
|
-
non_shadow_variations_percentage_sum = sum(
|
|
23
|
-
map(lambda v: v.traffic.percentage, non_shadow_variations)
|
|
24
|
-
)
|
|
25
|
-
if non_shadow_variations and non_shadow_variations_percentage_sum != 100:
|
|
26
|
-
raise QwakException(
|
|
27
|
-
"The variations do not sum to 100 percent. Please go over the variations config file."
|
|
28
|
-
)
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
def validate_shadow_variation(variations: List[Variation]):
|
|
32
|
-
shadow_variations = list(filter(lambda v: v.traffic.is_shadow, variations))
|
|
33
|
-
if len(shadow_variations) > 1:
|
|
34
|
-
shadow_variations_names = list(map(lambda v: v.name, shadow_variations))
|
|
35
|
-
raise QwakException(
|
|
36
|
-
f"The variations contain more than one shadow variation {shadow_variations_names}. "
|
|
37
|
-
f"Please go over the variations config file."
|
|
38
|
-
)
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
def create_variation_from_variation_config(
|
|
42
|
-
variation_def: DeployConfig.Realtime.VariationConfig,
|
|
43
|
-
) -> Variation:
|
|
44
|
-
try:
|
|
45
|
-
return Variation(
|
|
46
|
-
name=variation_def.name,
|
|
47
|
-
traffic=TrafficSpec(
|
|
48
|
-
percentage=variation_def.traffic.percentage,
|
|
49
|
-
is_shadow=variation_def.traffic.shadow,
|
|
50
|
-
),
|
|
51
|
-
)
|
|
52
|
-
except Exception:
|
|
53
|
-
raise QwakException(
|
|
54
|
-
f"Could not parse variation {variation_def}. Please check you variation configuration file."
|
|
55
|
-
)
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from typing import List
|
|
4
|
-
|
|
5
|
-
from _qwak_proto.qwak.deployment.deployment_pb2 import TrafficSpec, Variation
|
|
6
|
-
from qwak.exceptions import QwakException
|
|
7
|
-
|
|
8
|
-
from qwak_sdk.commands.models._logic.variations import (
|
|
9
|
-
validate_percentages,
|
|
10
|
-
validate_shadow_variation,
|
|
11
|
-
)
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
def get_variations_for_deploy(
|
|
15
|
-
variation_name: str,
|
|
16
|
-
existing_variations: List[Variation],
|
|
17
|
-
requested_variations: List[Variation],
|
|
18
|
-
environment_name: str,
|
|
19
|
-
variation_protected_state: bool,
|
|
20
|
-
):
|
|
21
|
-
if not existing_variations:
|
|
22
|
-
existing_variations: List[Variation] = [
|
|
23
|
-
Variation(
|
|
24
|
-
name=variation_name,
|
|
25
|
-
traffic=TrafficSpec(
|
|
26
|
-
percentage=100,
|
|
27
|
-
is_shadow=False,
|
|
28
|
-
),
|
|
29
|
-
protected=variation_protected_state,
|
|
30
|
-
)
|
|
31
|
-
]
|
|
32
|
-
requested_variations_names = set(
|
|
33
|
-
map(lambda variation: variation.name, requested_variations)
|
|
34
|
-
)
|
|
35
|
-
existing_variations_names = set(
|
|
36
|
-
map(lambda variation: variation.name, existing_variations)
|
|
37
|
-
)
|
|
38
|
-
if requested_variations_names:
|
|
39
|
-
if variation_name not in requested_variations_names:
|
|
40
|
-
raise QwakException(
|
|
41
|
-
f"Selected deployment to variation '{variation_name}' in {environment_name}, but provided the "
|
|
42
|
-
f"following variations {list(requested_variations_names)}. "
|
|
43
|
-
f"Please modify the variation name, or adjust the requested variations definitions"
|
|
44
|
-
)
|
|
45
|
-
elif variation_name not in existing_variations_names:
|
|
46
|
-
raise QwakException(
|
|
47
|
-
f"Selected deployment to existing variation '{variation_name}' in {environment_name}, but it is not one of "
|
|
48
|
-
f"the existing variations {list(existing_variations_names)}. "
|
|
49
|
-
f"Please modify the variation name, or supply the requested variations definitions with"
|
|
50
|
-
f" the necessary changes"
|
|
51
|
-
)
|
|
52
|
-
else:
|
|
53
|
-
# We are deploying to an existing variations without any change
|
|
54
|
-
return existing_variations
|
|
55
|
-
|
|
56
|
-
ignored_variations = existing_variations_names.difference(
|
|
57
|
-
requested_variations_names
|
|
58
|
-
)
|
|
59
|
-
if ignored_variations:
|
|
60
|
-
raise QwakException(
|
|
61
|
-
f"The given variation configuration does not contain the configuration for the following "
|
|
62
|
-
f"variations {list(ignored_variations)} in {environment_name}. You must include all the existing "
|
|
63
|
-
f"variations configuration when passing the configuration"
|
|
64
|
-
)
|
|
65
|
-
|
|
66
|
-
unexpected_variations = requested_variations_names.difference(
|
|
67
|
-
existing_variations_names
|
|
68
|
-
)
|
|
69
|
-
if variation_name in unexpected_variations:
|
|
70
|
-
unexpected_variations.remove(variation_name)
|
|
71
|
-
if unexpected_variations:
|
|
72
|
-
raise QwakException(
|
|
73
|
-
f"The given variation configuration contains the configuration for the following "
|
|
74
|
-
f"variations {list(unexpected_variations)} in {environment_name} which are not expected. When deploying, "
|
|
75
|
-
f"the variations configuration must contain all the existing variations, and an optional new variation."
|
|
76
|
-
)
|
|
77
|
-
|
|
78
|
-
validate_percentages(requested_variations)
|
|
79
|
-
validate_shadow_variation(requested_variations)
|
|
80
|
-
|
|
81
|
-
return requested_variations
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from typing import List, Set
|
|
4
|
-
|
|
5
|
-
from _qwak_proto.qwak.deployment.deployment_pb2 import Variation
|
|
6
|
-
from qwak.exceptions import QwakException
|
|
7
|
-
|
|
8
|
-
from qwak_sdk.commands.models.deployments.deploy._logic.variations import (
|
|
9
|
-
validate_percentages,
|
|
10
|
-
validate_shadow_variation,
|
|
11
|
-
)
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
def validate_variations_for_undeploy(
|
|
15
|
-
variation_name: str,
|
|
16
|
-
existing_variations_names: Set[str],
|
|
17
|
-
requested_variations: List[Variation],
|
|
18
|
-
environment_name: str,
|
|
19
|
-
):
|
|
20
|
-
if variation_name not in existing_variations_names:
|
|
21
|
-
if not variation_name:
|
|
22
|
-
raise QwakException(
|
|
23
|
-
f"No selected variation. You must specify a variation since there is more than one deployed in "
|
|
24
|
-
f"{environment_name}. Currently {list(existing_variations_names)} are deployed"
|
|
25
|
-
)
|
|
26
|
-
raise QwakException(
|
|
27
|
-
f"The selected variation {variation_name} is not deployed in {environment_name}. "
|
|
28
|
-
f"Only {list(existing_variations_names)} are deployed"
|
|
29
|
-
)
|
|
30
|
-
|
|
31
|
-
requested_variations_names = set(
|
|
32
|
-
map(lambda variation: variation.name, requested_variations)
|
|
33
|
-
)
|
|
34
|
-
if variation_name in requested_variations_names:
|
|
35
|
-
raise QwakException(
|
|
36
|
-
f"Selected undeploy to variation '{variation_name}', but it is part of "
|
|
37
|
-
f"the requested variations {list(requested_variations_names)}. "
|
|
38
|
-
f"Please modify the variation name, or supply the requested variations definitions with"
|
|
39
|
-
f" the necessary changes"
|
|
40
|
-
)
|
|
41
|
-
if variation_name not in existing_variations_names:
|
|
42
|
-
raise QwakException(
|
|
43
|
-
f"Selected undeploy to variation {variation_name} but it is not one of "
|
|
44
|
-
f"the existing variations {list(existing_variations_names)}. "
|
|
45
|
-
f"Please modify the variation name."
|
|
46
|
-
)
|
|
47
|
-
|
|
48
|
-
ignored_variations = existing_variations_names.difference(
|
|
49
|
-
requested_variations_names
|
|
50
|
-
)
|
|
51
|
-
if variation_name in ignored_variations:
|
|
52
|
-
ignored_variations.remove(variation_name)
|
|
53
|
-
|
|
54
|
-
if len(existing_variations_names) != 2 and ignored_variations:
|
|
55
|
-
raise QwakException(
|
|
56
|
-
f"The given variation configuration does not contain the configuration for the following "
|
|
57
|
-
f"variations {list(ignored_variations)}. You must include all the variations that will exist after "
|
|
58
|
-
f"undeploy in the configuration"
|
|
59
|
-
)
|
|
60
|
-
|
|
61
|
-
unexpected_variations = requested_variations_names.difference(
|
|
62
|
-
existing_variations_names
|
|
63
|
-
)
|
|
64
|
-
|
|
65
|
-
if unexpected_variations:
|
|
66
|
-
raise QwakException(
|
|
67
|
-
f"The given variation configuration contains the configuration for the following "
|
|
68
|
-
f"variations {list(unexpected_variations)} which are not expected. When undeploying, the variations "
|
|
69
|
-
f"configuration must contain all expected remaining variations (from the existing ones)."
|
|
70
|
-
)
|
|
71
|
-
|
|
72
|
-
if requested_variations:
|
|
73
|
-
validate_percentages(requested_variations)
|
|
74
|
-
validate_shadow_variation(requested_variations)
|
|
File without changes
|
|
File without changes
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
from typing import Tuple
|
|
2
|
-
|
|
3
|
-
from qwak.clients.administration.eco_system.client import EcosystemClient
|
|
4
|
-
from qwak.clients.deployment.client import DeploymentManagementClient
|
|
5
|
-
from qwak.tools.logger.logger import get_qwak_logger
|
|
6
|
-
|
|
7
|
-
from qwak_sdk.commands.models._logic.variations import (
|
|
8
|
-
create_variation_from_variation_config,
|
|
9
|
-
)
|
|
10
|
-
from qwak_sdk.commands.models.deployments.deploy._logic.deploy_config import (
|
|
11
|
-
DeployConfig,
|
|
12
|
-
)
|
|
13
|
-
from qwak_sdk.commands.models.runtime.traffic_update._logic.variations import (
|
|
14
|
-
validate_requested_variations_against_existing_in_apply,
|
|
15
|
-
)
|
|
16
|
-
from qwak_sdk.inner.tools.config_handler import config_handler
|
|
17
|
-
|
|
18
|
-
logger = get_qwak_logger()
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
def execute_runtime_traffic_update(
|
|
22
|
-
model_id: str, from_file: str, environment_name: Tuple[str]
|
|
23
|
-
):
|
|
24
|
-
deployment_client = DeploymentManagementClient()
|
|
25
|
-
ecosystem_client = EcosystemClient()
|
|
26
|
-
config: DeployConfig = config_handler(
|
|
27
|
-
config=DeployConfig,
|
|
28
|
-
from_file=from_file,
|
|
29
|
-
out_conf=False,
|
|
30
|
-
sections=("realtime",),
|
|
31
|
-
model_id=model_id,
|
|
32
|
-
)
|
|
33
|
-
requested_variations = list(
|
|
34
|
-
map(
|
|
35
|
-
create_variation_from_variation_config,
|
|
36
|
-
config.realtime.variations,
|
|
37
|
-
)
|
|
38
|
-
)
|
|
39
|
-
environment_names_to_details = ecosystem_client.get_environments_names_to_details(
|
|
40
|
-
environment_name if environment_name else config.realtime.environments
|
|
41
|
-
)
|
|
42
|
-
validate_requested_variations_against_existing_in_apply(
|
|
43
|
-
model_id,
|
|
44
|
-
requested_variations,
|
|
45
|
-
environment_names_to_details,
|
|
46
|
-
deployment_client,
|
|
47
|
-
)
|
|
48
|
-
environment_ids = [env.id for env in environment_names_to_details.values()]
|
|
49
|
-
|
|
50
|
-
deployment_client.apply_model_traffic_config(
|
|
51
|
-
model_id=model_id,
|
|
52
|
-
requested_variations=requested_variations,
|
|
53
|
-
environment_ids=environment_ids,
|
|
54
|
-
)
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
from typing import Dict, List, Optional
|
|
2
|
-
|
|
3
|
-
from _qwak_proto.qwak.deployment.deployment_pb2 import (
|
|
4
|
-
EnvironmentTrafficMessage,
|
|
5
|
-
Variation,
|
|
6
|
-
)
|
|
7
|
-
from _qwak_proto.qwak.ecosystem.v0.ecosystem_pb2 import EnvironmentDetails
|
|
8
|
-
from qwak.clients.deployment.client import DeploymentManagementClient
|
|
9
|
-
from qwak.exceptions import QwakException
|
|
10
|
-
|
|
11
|
-
from qwak_sdk.commands.models._logic.variations import (
|
|
12
|
-
validate_percentages,
|
|
13
|
-
validate_shadow_variation,
|
|
14
|
-
)
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
def validate_requested_variations_against_existing_in_apply(
|
|
18
|
-
model_id: str,
|
|
19
|
-
requested_variations: List[Variation],
|
|
20
|
-
environment_names_to_details: Dict[str, EnvironmentDetails],
|
|
21
|
-
deployment_client: DeploymentManagementClient,
|
|
22
|
-
):
|
|
23
|
-
model_traffic = deployment_client.get_model_traffic_config(model_id)
|
|
24
|
-
environments_traffic = dict(model_traffic.environment_to_model_traffic)
|
|
25
|
-
errors = []
|
|
26
|
-
for env_name, env_details in environment_names_to_details.items():
|
|
27
|
-
error = validate_requested_variation_in_envs_for_apply(
|
|
28
|
-
env_details, environments_traffic, requested_variations
|
|
29
|
-
)
|
|
30
|
-
if error:
|
|
31
|
-
errors.append(error)
|
|
32
|
-
if errors:
|
|
33
|
-
raise QwakException("\n".join(errors))
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
def validate_requested_variation_in_envs_for_apply(
|
|
37
|
-
env_details: EnvironmentDetails,
|
|
38
|
-
environments_traffic: Dict[str, EnvironmentTrafficMessage],
|
|
39
|
-
requested_variations: List[Variation],
|
|
40
|
-
) -> Optional[str]:
|
|
41
|
-
environment_traffic = environments_traffic.get(env_details.id)
|
|
42
|
-
existing_variations = environment_traffic.variations if environment_traffic else []
|
|
43
|
-
try:
|
|
44
|
-
validate_variation_for_apply(
|
|
45
|
-
existing_variations=existing_variations,
|
|
46
|
-
requested_variations=requested_variations,
|
|
47
|
-
)
|
|
48
|
-
except QwakException as e:
|
|
49
|
-
return e.message
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
def validate_variation_for_apply(
|
|
53
|
-
existing_variations: List[Variation],
|
|
54
|
-
requested_variations: List[Variation],
|
|
55
|
-
):
|
|
56
|
-
requested_variations_names = set(
|
|
57
|
-
map(lambda variation: variation.name, requested_variations)
|
|
58
|
-
)
|
|
59
|
-
existing_variations_names = set(
|
|
60
|
-
map(lambda variation: variation.name, existing_variations)
|
|
61
|
-
)
|
|
62
|
-
ignored_variations = existing_variations_names.difference(
|
|
63
|
-
requested_variations_names
|
|
64
|
-
)
|
|
65
|
-
if ignored_variations:
|
|
66
|
-
raise QwakException(
|
|
67
|
-
f"The given variation configuration does not contain the configuration for the following "
|
|
68
|
-
f"variations {list(ignored_variations)}. You must include all the existing variations when updating the "
|
|
69
|
-
f"model traffic {list(existing_variations_names)}"
|
|
70
|
-
)
|
|
71
|
-
|
|
72
|
-
unexpected_variations = requested_variations_names.difference(
|
|
73
|
-
existing_variations_names
|
|
74
|
-
)
|
|
75
|
-
|
|
76
|
-
if unexpected_variations:
|
|
77
|
-
raise QwakException(
|
|
78
|
-
f"The given variation configuration contains the configuration for the following "
|
|
79
|
-
f"variations {list(unexpected_variations)} which are not expected. You must include only the existing "
|
|
80
|
-
f"variations when updating the model traffic {list(existing_variations_names)}"
|
|
81
|
-
)
|
|
82
|
-
|
|
83
|
-
validate_percentages(requested_variations)
|
|
84
|
-
validate_shadow_variation(requested_variations)
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
from typing import Tuple
|
|
2
|
-
|
|
3
|
-
import click
|
|
4
|
-
from qwak.exceptions import QwakException
|
|
5
|
-
from qwak.tools.logger.logger import get_qwak_logger
|
|
6
|
-
|
|
7
|
-
from qwak_sdk.commands.models.runtime.traffic_update._logic.execute_runtime_update_traffic import (
|
|
8
|
-
execute_runtime_traffic_update,
|
|
9
|
-
)
|
|
10
|
-
from qwak_sdk.inner.tools.cli_tools import QwakCommand
|
|
11
|
-
|
|
12
|
-
logger = get_qwak_logger()
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
@click.command("traffic_update", cls=QwakCommand)
|
|
16
|
-
@click.option("-m", "--model-id", required=True, help="Model named ID")
|
|
17
|
-
@click.option(
|
|
18
|
-
"--environment-name",
|
|
19
|
-
required=False,
|
|
20
|
-
type=str,
|
|
21
|
-
help="Environments to deploy on (if not specified uses your default environment)",
|
|
22
|
-
multiple=True,
|
|
23
|
-
)
|
|
24
|
-
@click.option(
|
|
25
|
-
"--from-file",
|
|
26
|
-
required=True,
|
|
27
|
-
help="The variations config file path",
|
|
28
|
-
type=click.Path(exists=True, resolve_path=True, dir_okay=False),
|
|
29
|
-
)
|
|
30
|
-
def runtime_traffic_update(
|
|
31
|
-
model_id: str, from_file: str, environment_name: Tuple[str], **kwargs
|
|
32
|
-
):
|
|
33
|
-
try:
|
|
34
|
-
execute_runtime_traffic_update(model_id, from_file, environment_name)
|
|
35
|
-
logger.info(f"Successfully updated traffic for models {model_id}")
|
|
36
|
-
except Exception as e:
|
|
37
|
-
raise QwakException(f'Failed to apply traffic configurations. Error is "{e}"')
|
|
File without changes
|
|
File without changes
|