zenml-nightly 0.61.0.dev20240711__py3-none-any.whl → 0.61.0.dev20240713__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.
- zenml/VERSION +1 -1
- zenml/cli/stack.py +220 -71
- zenml/constants.py +6 -0
- zenml/enums.py +16 -0
- zenml/integrations/gcp/service_connectors/gcp_service_connector.py +54 -6
- zenml/logging/step_logging.py +34 -35
- zenml/models/__init__.py +2 -0
- zenml/models/v2/core/server_settings.py +0 -20
- zenml/models/v2/misc/stack_deployment.py +20 -0
- zenml/orchestrators/step_launcher.py +1 -0
- zenml/stack_deployments/aws_stack_deployment.py +56 -91
- zenml/stack_deployments/gcp_stack_deployment.py +260 -0
- zenml/stack_deployments/stack_deployment.py +103 -25
- zenml/stack_deployments/utils.py +4 -0
- zenml/zen_server/routers/devices_endpoints.py +4 -1
- zenml/zen_server/routers/server_endpoints.py +29 -2
- zenml/zen_server/routers/stack_deployment_endpoints.py +34 -20
- zenml/zen_stores/migrations/versions/b4fca5241eea_migrate_onboarding_state.py +167 -0
- zenml/zen_stores/rest_zen_store.py +45 -21
- zenml/zen_stores/schemas/server_settings_schemas.py +23 -11
- zenml/zen_stores/sql_zen_store.py +117 -19
- zenml/zen_stores/zen_store_interface.py +6 -5
- {zenml_nightly-0.61.0.dev20240711.dist-info → zenml_nightly-0.61.0.dev20240713.dist-info}/METADATA +1 -1
- {zenml_nightly-0.61.0.dev20240711.dist-info → zenml_nightly-0.61.0.dev20240713.dist-info}/RECORD +27 -25
- {zenml_nightly-0.61.0.dev20240711.dist-info → zenml_nightly-0.61.0.dev20240713.dist-info}/LICENSE +0 -0
- {zenml_nightly-0.61.0.dev20240711.dist-info → zenml_nightly-0.61.0.dev20240713.dist-info}/WHEEL +0 -0
- {zenml_nightly-0.61.0.dev20240711.dist-info → zenml_nightly-0.61.0.dev20240713.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,260 @@
|
|
1
|
+
# Copyright (c) ZenML GmbH 2024. All Rights Reserved.
|
2
|
+
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at:
|
6
|
+
|
7
|
+
# https://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
12
|
+
# or implied. See the License for the specific language governing
|
13
|
+
# permissions and limitations under the License.
|
14
|
+
"""Functionality to deploy a ZenML stack to GCP."""
|
15
|
+
|
16
|
+
from typing import ClassVar, Dict, List
|
17
|
+
|
18
|
+
from zenml.enums import StackDeploymentProvider
|
19
|
+
from zenml.models import StackDeploymentConfig
|
20
|
+
from zenml.stack_deployments.stack_deployment import ZenMLCloudStackDeployment
|
21
|
+
|
22
|
+
GCP_DEPLOYMENT_TYPE = "deployment-manager"
|
23
|
+
|
24
|
+
|
25
|
+
class GCPZenMLCloudStackDeployment(ZenMLCloudStackDeployment):
|
26
|
+
"""GCP ZenML Cloud Stack Deployment."""
|
27
|
+
|
28
|
+
provider: ClassVar[StackDeploymentProvider] = StackDeploymentProvider.GCP
|
29
|
+
deployment: ClassVar[str] = GCP_DEPLOYMENT_TYPE
|
30
|
+
|
31
|
+
@classmethod
|
32
|
+
def description(cls) -> str:
|
33
|
+
"""Return a description of the ZenML Cloud Stack Deployment.
|
34
|
+
|
35
|
+
This will be displayed when the user is prompted to deploy
|
36
|
+
the ZenML stack.
|
37
|
+
|
38
|
+
Returns:
|
39
|
+
A MarkDown description of the ZenML Cloud Stack Deployment.
|
40
|
+
"""
|
41
|
+
return """
|
42
|
+
Provision and register a basic GCP ZenML stack authenticated and connected to
|
43
|
+
all the necessary cloud infrastructure resources required to run pipelines in
|
44
|
+
GCP.
|
45
|
+
"""
|
46
|
+
|
47
|
+
@classmethod
|
48
|
+
def instructions(cls) -> str:
|
49
|
+
"""Return instructions on how to deploy the ZenML stack to the specified cloud provider.
|
50
|
+
|
51
|
+
This will be displayed before the user is prompted to deploy the ZenML
|
52
|
+
stack.
|
53
|
+
|
54
|
+
Returns:
|
55
|
+
MarkDown instructions on how to deploy the ZenML stack to the
|
56
|
+
specified cloud provider.
|
57
|
+
"""
|
58
|
+
return """
|
59
|
+
You will be redirected to a GCP Cloud Shell console in your browser where you'll
|
60
|
+
be asked to log into your GCP project and then create a Deployment Manager
|
61
|
+
deployment to provision the necessary cloud resources for ZenML.
|
62
|
+
|
63
|
+
**NOTE**: The Deployment Manager deployment will create the following new
|
64
|
+
resources in your GCP project. Please ensure you have the necessary permissions
|
65
|
+
and are aware of any potential costs:
|
66
|
+
|
67
|
+
- A GCS bucket registered as a [ZenML artifact store](https://docs.zenml.io/stack-components/artifact-stores/gcp).
|
68
|
+
- A Google Artifact Registry registered as a [ZenML container registry](https://docs.zenml.io/stack-components/container-registries/gcp).
|
69
|
+
- Vertex AI registered as a [ZenML orchestrator](https://docs.zenml.io/stack-components/orchestrators/vertex).
|
70
|
+
- GCP Cloud Build registered as a [ZenML image builder](https://docs.zenml.io/stack-components/image-builders/gcp).
|
71
|
+
- A GCP Service Account with the minimum necessary permissions to access the
|
72
|
+
above resources.
|
73
|
+
- An GCP Service Account access key used to give access to ZenML to connect to
|
74
|
+
the above resources through a [ZenML service connector](https://docs.zenml.io/how-to/auth-management/gcp-service-connector).
|
75
|
+
|
76
|
+
The Deployment Manager deployment will automatically create a GCP Service
|
77
|
+
Account secret key and will share it with ZenML to give it permission to access
|
78
|
+
the resources created by the stack. You can revoke these permissions at any time
|
79
|
+
by deleting the Deployment Manager deployment in the GCP Cloud Console.
|
80
|
+
|
81
|
+
**Estimated costs**
|
82
|
+
|
83
|
+
A small training job would cost around: $0.60
|
84
|
+
|
85
|
+
These are rough estimates and actual costs may vary based on your usage and specific GCP pricing.
|
86
|
+
Some services may be eligible for the GCP Free Tier. Use [the GCP Pricing Calculator](https://cloud.google.com/products/calculator)
|
87
|
+
for a detailed estimate based on your usage.
|
88
|
+
|
89
|
+
⚠️ **The Cloud Shell session will warn you that the ZenML GitHub repository is
|
90
|
+
untrusted. We recommend that you review [the contents of the repository](https://github.com/zenml-io/zenml/tree/main/infra/gcp)
|
91
|
+
and then check the `Trust repo` checkbox to proceed with the deployment,
|
92
|
+
otherwise the Cloud Shell session will not be authenticated to access your
|
93
|
+
GCP projects. You will also get a chance to review the scripts that will be
|
94
|
+
executed in the Cloud Shell session before proceeding.**
|
95
|
+
|
96
|
+
💡 **After the Deployment Manager deployment is complete, you can close the Cloud
|
97
|
+
Shell session and return to the CLI to view details about the associated ZenML
|
98
|
+
stack automatically registered with ZenML.**
|
99
|
+
"""
|
100
|
+
|
101
|
+
@classmethod
|
102
|
+
def post_deploy_instructions(cls) -> str:
|
103
|
+
"""Return instructions on what to do after the deployment is complete.
|
104
|
+
|
105
|
+
This will be displayed after the deployment is complete.
|
106
|
+
|
107
|
+
Returns:
|
108
|
+
MarkDown instructions on what to do after the deployment is
|
109
|
+
complete.
|
110
|
+
"""
|
111
|
+
return """
|
112
|
+
The ZenML stack has been successfully deployed and registered. You can delete
|
113
|
+
the Deployment Manager deployment at any time to revoke ZenML's access to your
|
114
|
+
GCP project and to clean up the resources created by the stack by using
|
115
|
+
[the GCP Cloud Console](https://console.cloud.google.com/dm/deployments).
|
116
|
+
"""
|
117
|
+
|
118
|
+
@classmethod
|
119
|
+
def integrations(cls) -> List[str]:
|
120
|
+
"""Return the ZenML integrations required for the stack.
|
121
|
+
|
122
|
+
Returns:
|
123
|
+
The list of ZenML integrations that need to be installed for the
|
124
|
+
stack to be usable.
|
125
|
+
"""
|
126
|
+
return [
|
127
|
+
"gcp",
|
128
|
+
]
|
129
|
+
|
130
|
+
@classmethod
|
131
|
+
def permissions(cls) -> Dict[str, List[str]]:
|
132
|
+
"""Return the permissions granted to ZenML to access the cloud resources.
|
133
|
+
|
134
|
+
Returns:
|
135
|
+
The permissions granted to ZenML to access the cloud resources, as
|
136
|
+
a dictionary grouping permissions by resource.
|
137
|
+
"""
|
138
|
+
return {
|
139
|
+
"GCS Bucket": [
|
140
|
+
"roles/storage.objectUser",
|
141
|
+
],
|
142
|
+
"GCP Artifact Registry": [
|
143
|
+
"roles/artifactregistry.createOnPushWriter",
|
144
|
+
],
|
145
|
+
"Vertex AI (Client)": [
|
146
|
+
"roles/aiplatform.user",
|
147
|
+
],
|
148
|
+
"Vertex AI (Jobs)": [
|
149
|
+
"roles/aiplatform.serviceAgent",
|
150
|
+
],
|
151
|
+
"Cloud Build (Client)": [
|
152
|
+
"roles/cloudbuild.builds.editor",
|
153
|
+
],
|
154
|
+
}
|
155
|
+
|
156
|
+
@classmethod
|
157
|
+
def locations(cls) -> Dict[str, str]:
|
158
|
+
"""Return the locations where the ZenML stack can be deployed.
|
159
|
+
|
160
|
+
Returns:
|
161
|
+
The regions where the ZenML stack can be deployed as a map of region
|
162
|
+
names to region descriptions.
|
163
|
+
"""
|
164
|
+
# Return a list of all possible GCP regions
|
165
|
+
|
166
|
+
# Based on the AWS regions listed at
|
167
|
+
# https://cloud.google.com/about/locations
|
168
|
+
return {
|
169
|
+
"Africa (Johannesburg)": "africa-south1",
|
170
|
+
"Asia Pacific (Taiwan)": "asia-east1",
|
171
|
+
"Asia Pacific (Hong Kong)": "asia-east2",
|
172
|
+
"Asia Pacific (Tokyo)": "asia-northeast1",
|
173
|
+
"Asia Pacific (Osaka)": "asia-northeast2",
|
174
|
+
"Asia Pacific (Seoul)": "asia-northeast3",
|
175
|
+
"Asia Pacific (Mumbai)": "asia-south1",
|
176
|
+
"Asia Pacific (Delhi)": "asia-south2",
|
177
|
+
"Asia Pacific (Singapore)": "asia-southeast1",
|
178
|
+
"Asia Pacific (Jakarta)": "asia-southeast2",
|
179
|
+
"Australia (Sydney)": "australia-southeast1",
|
180
|
+
"Australia (Melbourne)": "australia-southeast2",
|
181
|
+
"Europe (Belgium)": "europe-west1",
|
182
|
+
"Europe (London)": "europe-west2",
|
183
|
+
"Europe (Frankfurt)": "europe-west3",
|
184
|
+
"Europe (Netherlands)": "europe-west4",
|
185
|
+
"Europe (Zurich)": "europe-west6",
|
186
|
+
"Europe (Milan)": "europe-west8",
|
187
|
+
"Europe (Paris)": "europe-west9",
|
188
|
+
"Europe (Berlin)": "europe-west10",
|
189
|
+
"Europe (Turin)": "europe-west12",
|
190
|
+
"Europe (Warsaw)": "europe-central2",
|
191
|
+
"Europe (Finland)": "europe-north1",
|
192
|
+
"Europe (Madrid)": "europe-southwest1",
|
193
|
+
"Middle East (Doha)": "me-central1",
|
194
|
+
"Middle East (Dubai)": "me-central2",
|
195
|
+
"Middle East (Tel Aviv)": "me-west1",
|
196
|
+
"North America (Montreal)": "northamerica-northeast1",
|
197
|
+
"North America (Toronto)": "northamerica-northeast2",
|
198
|
+
"South America (Sao Paulo)": "southamerica-east1",
|
199
|
+
"South America (Santiago)": "southamerica-west1",
|
200
|
+
"US Central (Iowa)": "us-central1",
|
201
|
+
"US East (South Carolina)": "us-east1",
|
202
|
+
"US East (Northern Virginia)": "us-east4",
|
203
|
+
"US East (Columbus)": "us-east5",
|
204
|
+
"US South (Dallas)": "us-south1",
|
205
|
+
"US West (Oregon)": "us-west1",
|
206
|
+
"US West (Los Angeles)": "us-west2",
|
207
|
+
"US West (Salt Lake City)": "us-west3",
|
208
|
+
"US West (Las Vegas)": "us-west4",
|
209
|
+
}
|
210
|
+
|
211
|
+
def get_deployment_config(
|
212
|
+
self,
|
213
|
+
) -> StackDeploymentConfig:
|
214
|
+
"""Return the configuration to deploy the ZenML stack to the specified cloud provider.
|
215
|
+
|
216
|
+
The configuration should include:
|
217
|
+
|
218
|
+
* a cloud provider console URL where the user will be redirected to
|
219
|
+
deploy the ZenML stack. The URL should include as many pre-filled
|
220
|
+
URL query parameters as possible.
|
221
|
+
* a textual description of the URL
|
222
|
+
* some deployment providers may require additional configuration
|
223
|
+
parameters to be passed to the cloud provider in addition to the
|
224
|
+
deployment URL query parameters. Where that is the case, this method
|
225
|
+
should also return a string that the user can copy and paste into the
|
226
|
+
cloud provider console to deploy the ZenML stack (e.g. a set of
|
227
|
+
environment variables, or YAML configuration snippet etc.).
|
228
|
+
|
229
|
+
Returns:
|
230
|
+
The configuration to deploy the ZenML stack to the specified cloud
|
231
|
+
provider.
|
232
|
+
"""
|
233
|
+
params = dict(
|
234
|
+
cloudshell_git_repo="https://github.com/zenml-io/zenml",
|
235
|
+
cloudshell_workspace="infra/gcp",
|
236
|
+
cloudshell_open_in_editor="gcp-gar-gcs-vertex.jinja,gcp-gar-gcs-vertex-deploy.sh",
|
237
|
+
cloudshell_tutorial="gcp-gar-gcs-vertex.md",
|
238
|
+
ephemeral="true",
|
239
|
+
# TODO: remove this before the branch is merged
|
240
|
+
cloudshell_git_branch="feature/prd-482-gcp-stack-deployment",
|
241
|
+
)
|
242
|
+
# Encode the parameters as URL query parameters
|
243
|
+
query_params = "&".join([f"{k}={v}" for k, v in params.items()])
|
244
|
+
url = (
|
245
|
+
f"https://shell.cloud.google.com/cloudshell/editor?{query_params}"
|
246
|
+
)
|
247
|
+
|
248
|
+
config = f"""
|
249
|
+
### BEGIN CONFIGURATION ###
|
250
|
+
ZENML_STACK_NAME={self.stack_name}
|
251
|
+
ZENML_STACK_REGION={self.location or "europe-west3"}
|
252
|
+
ZENML_SERVER_URL={self.zenml_server_url}
|
253
|
+
ZENML_SERVER_API_TOKEN={self.zenml_server_api_token}
|
254
|
+
### END CONFIGURATION ###
|
255
|
+
"""
|
256
|
+
return StackDeploymentConfig(
|
257
|
+
deployment_url=url,
|
258
|
+
deployment_url_text="GCP Cloud Shell Console",
|
259
|
+
configuration=config,
|
260
|
+
)
|
@@ -15,13 +15,16 @@
|
|
15
15
|
|
16
16
|
import datetime
|
17
17
|
from abc import abstractmethod
|
18
|
-
from typing import ClassVar, Dict, List, Optional
|
18
|
+
from typing import ClassVar, Dict, List, Optional
|
19
19
|
|
20
20
|
from pydantic import BaseModel
|
21
21
|
|
22
|
-
from zenml.
|
22
|
+
from zenml.client import Client
|
23
|
+
from zenml.enums import StackComponentType, StackDeploymentProvider
|
23
24
|
from zenml.models import (
|
24
25
|
DeployedStack,
|
26
|
+
StackDeploymentConfig,
|
27
|
+
StackDeploymentInfo,
|
25
28
|
)
|
26
29
|
|
27
30
|
|
@@ -29,7 +32,10 @@ class ZenMLCloudStackDeployment(BaseModel):
|
|
29
32
|
"""ZenML Cloud Stack CLI Deployment base class."""
|
30
33
|
|
31
34
|
provider: ClassVar[StackDeploymentProvider]
|
35
|
+
deployment: ClassVar[str]
|
32
36
|
stack_name: str
|
37
|
+
zenml_server_url: str
|
38
|
+
zenml_server_api_token: str
|
33
39
|
location: Optional[str] = None
|
34
40
|
|
35
41
|
@classmethod
|
@@ -69,6 +75,16 @@ class ZenMLCloudStackDeployment(BaseModel):
|
|
69
75
|
complete.
|
70
76
|
"""
|
71
77
|
|
78
|
+
@classmethod
|
79
|
+
@abstractmethod
|
80
|
+
def integrations(cls) -> List[str]:
|
81
|
+
"""Return the ZenML integrations required for the stack.
|
82
|
+
|
83
|
+
Returns:
|
84
|
+
The list of ZenML integrations that need to be installed for the
|
85
|
+
stack to be usable.
|
86
|
+
"""
|
87
|
+
|
72
88
|
@classmethod
|
73
89
|
@abstractmethod
|
74
90
|
def permissions(cls) -> Dict[str, List[str]]:
|
@@ -89,42 +105,104 @@ class ZenMLCloudStackDeployment(BaseModel):
|
|
89
105
|
names to region descriptions.
|
90
106
|
"""
|
91
107
|
|
92
|
-
@
|
93
|
-
def
|
94
|
-
|
95
|
-
zenml_server_url: str,
|
96
|
-
zenml_server_api_token: str,
|
97
|
-
) -> Tuple[str, str]:
|
98
|
-
"""Return the URL to deploy the ZenML stack to the specified cloud provider.
|
108
|
+
@classmethod
|
109
|
+
def get_deployment_info(cls) -> StackDeploymentInfo:
|
110
|
+
"""Return information about the ZenML Cloud Stack Deployment.
|
99
111
|
|
100
|
-
|
101
|
-
|
102
|
-
|
112
|
+
Returns:
|
113
|
+
Information about the ZenML Cloud Stack Deployment.
|
114
|
+
"""
|
115
|
+
return StackDeploymentInfo(
|
116
|
+
provider=cls.provider,
|
117
|
+
description=cls.description(),
|
118
|
+
instructions=cls.instructions(),
|
119
|
+
post_deploy_instructions=cls.post_deploy_instructions(),
|
120
|
+
integrations=cls.integrations(),
|
121
|
+
permissions=cls.permissions(),
|
122
|
+
locations=cls.locations(),
|
123
|
+
)
|
103
124
|
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
125
|
+
@abstractmethod
|
126
|
+
def get_deployment_config(
|
127
|
+
self,
|
128
|
+
) -> StackDeploymentConfig:
|
129
|
+
"""Return the configuration to deploy the ZenML stack to the specified cloud provider.
|
130
|
+
|
131
|
+
The configuration should include:
|
132
|
+
|
133
|
+
* a cloud provider console URL where the user will be redirected to
|
134
|
+
deploy the ZenML stack. The URL should include as many pre-filled
|
135
|
+
URL query parameters as possible.
|
136
|
+
* a textual description of the URL
|
137
|
+
* some deployment providers may require additional configuration
|
138
|
+
parameters to be passed to the cloud provider in addition to the
|
139
|
+
deployment URL query parameters. Where that is the case, this method
|
140
|
+
should also return a string that the user can copy and paste into the
|
141
|
+
cloud provider console to deploy the ZenML stack (e.g. a set of
|
142
|
+
environment variables, or YAML configuration snippet etc.).
|
108
143
|
|
109
144
|
Returns:
|
110
|
-
The
|
111
|
-
|
145
|
+
The configuration to deploy the ZenML stack to the specified cloud
|
146
|
+
provider.
|
112
147
|
"""
|
113
148
|
|
114
|
-
@abstractmethod
|
115
149
|
def get_stack(
|
116
|
-
self,
|
117
|
-
date_start: Optional[datetime.datetime] = None,
|
150
|
+
self, date_start: Optional[datetime.datetime] = None
|
118
151
|
) -> Optional[DeployedStack]:
|
119
152
|
"""Return the ZenML stack that was deployed and registered.
|
120
153
|
|
121
154
|
This method is called to retrieve a ZenML stack matching the deployment
|
122
|
-
provider
|
155
|
+
provider.
|
123
156
|
|
124
157
|
Args:
|
125
|
-
date_start: The
|
158
|
+
date_start: The date when the deployment started.
|
126
159
|
|
127
160
|
Returns:
|
128
|
-
The ZenML stack that was deployed and registered or None if
|
129
|
-
stack was not found.
|
161
|
+
The ZenML stack that was deployed and registered or None if a
|
162
|
+
matching stack was not found.
|
130
163
|
"""
|
164
|
+
client = Client()
|
165
|
+
|
166
|
+
# It's difficult to find a stack that matches the CloudFormation
|
167
|
+
# deployment 100% because the user can change the stack name before they
|
168
|
+
# deploy the stack in GCP.
|
169
|
+
#
|
170
|
+
# We try to find a full GCP stack that matches the deployment provider
|
171
|
+
# that was registered after this deployment was created.
|
172
|
+
|
173
|
+
# Get all stacks created after the start date
|
174
|
+
stacks = client.list_stacks(
|
175
|
+
created=f"gt:{str(date_start.replace(microsecond=0))}"
|
176
|
+
if date_start
|
177
|
+
else None,
|
178
|
+
sort_by="desc:created",
|
179
|
+
size=50,
|
180
|
+
)
|
181
|
+
|
182
|
+
if not stacks.items:
|
183
|
+
return None
|
184
|
+
|
185
|
+
# Find a stack that best matches the deployment provider
|
186
|
+
for stack in stacks.items:
|
187
|
+
if not stack.labels:
|
188
|
+
continue
|
189
|
+
|
190
|
+
if stack.labels.get("zenml:provider") != self.provider.value:
|
191
|
+
continue
|
192
|
+
|
193
|
+
if stack.labels.get("zenml:deployment") != self.deployment:
|
194
|
+
continue
|
195
|
+
|
196
|
+
artifact_store = stack.components[
|
197
|
+
StackComponentType.ARTIFACT_STORE
|
198
|
+
][0]
|
199
|
+
|
200
|
+
if not artifact_store.connector:
|
201
|
+
continue
|
202
|
+
|
203
|
+
return DeployedStack(
|
204
|
+
stack=stack,
|
205
|
+
service_connector=artifact_store.connector,
|
206
|
+
)
|
207
|
+
|
208
|
+
return None
|
zenml/stack_deployments/utils.py
CHANGED
@@ -19,10 +19,14 @@ from zenml.enums import StackDeploymentProvider
|
|
19
19
|
from zenml.stack_deployments.aws_stack_deployment import (
|
20
20
|
AWSZenMLCloudStackDeployment,
|
21
21
|
)
|
22
|
+
from zenml.stack_deployments.gcp_stack_deployment import (
|
23
|
+
GCPZenMLCloudStackDeployment,
|
24
|
+
)
|
22
25
|
from zenml.stack_deployments.stack_deployment import ZenMLCloudStackDeployment
|
23
26
|
|
24
27
|
STACK_DEPLOYMENT_PROVIDERS = {
|
25
28
|
StackDeploymentProvider.AWS: AWSZenMLCloudStackDeployment,
|
29
|
+
StackDeploymentProvider.GCP: GCPZenMLCloudStackDeployment,
|
26
30
|
}
|
27
31
|
|
28
32
|
|
@@ -27,7 +27,7 @@ from zenml.constants import (
|
|
27
27
|
DEVICES,
|
28
28
|
VERSION_1,
|
29
29
|
)
|
30
|
-
from zenml.enums import OAuthDeviceStatus
|
30
|
+
from zenml.enums import OAuthDeviceStatus, OnboardingStep
|
31
31
|
from zenml.models import (
|
32
32
|
OAuthDeviceFilter,
|
33
33
|
OAuthDeviceInternalUpdate,
|
@@ -270,6 +270,9 @@ def verify_authorized_device(
|
|
270
270
|
update=update,
|
271
271
|
)
|
272
272
|
|
273
|
+
store.update_onboarding_state(
|
274
|
+
completed_steps={OnboardingStep.DEVICE_VERIFIED}
|
275
|
+
)
|
273
276
|
return device_model
|
274
277
|
|
275
278
|
|
@@ -13,12 +13,19 @@
|
|
13
13
|
# permissions and limitations under the License.
|
14
14
|
"""Endpoint definitions for authentication (login)."""
|
15
15
|
|
16
|
-
from typing import Optional
|
16
|
+
from typing import List, Optional
|
17
17
|
|
18
18
|
from fastapi import APIRouter, Security
|
19
19
|
|
20
20
|
import zenml
|
21
|
-
from zenml.constants import
|
21
|
+
from zenml.constants import (
|
22
|
+
ACTIVATE,
|
23
|
+
API,
|
24
|
+
INFO,
|
25
|
+
ONBOARDING_STATE,
|
26
|
+
SERVER_SETTINGS,
|
27
|
+
VERSION_1,
|
28
|
+
)
|
22
29
|
from zenml.enums import AuthScheme
|
23
30
|
from zenml.exceptions import IllegalOperationError
|
24
31
|
from zenml.models import (
|
@@ -64,6 +71,26 @@ def server_info() -> ServerModel:
|
|
64
71
|
return zen_store().get_store_info()
|
65
72
|
|
66
73
|
|
74
|
+
@router.get(
|
75
|
+
ONBOARDING_STATE,
|
76
|
+
responses={
|
77
|
+
401: error_response,
|
78
|
+
404: error_response,
|
79
|
+
422: error_response,
|
80
|
+
},
|
81
|
+
)
|
82
|
+
@handle_exceptions
|
83
|
+
def get_onboarding_state(
|
84
|
+
_: AuthContext = Security(authorize),
|
85
|
+
) -> List[str]:
|
86
|
+
"""Get the onboarding state of the server.
|
87
|
+
|
88
|
+
Returns:
|
89
|
+
The onboarding state of the server.
|
90
|
+
"""
|
91
|
+
return zen_store().get_onboarding_state()
|
92
|
+
|
93
|
+
|
67
94
|
# We don't have any concrete value that tells us whether a server is a cloud
|
68
95
|
# tenant, so we use `external_server_id` as the best proxy option.
|
69
96
|
# For cloud tenants, we don't add these endpoints as the server settings don't
|
@@ -14,13 +14,25 @@
|
|
14
14
|
"""Endpoint definitions for stack deployments."""
|
15
15
|
|
16
16
|
import datetime
|
17
|
-
from typing import Optional
|
17
|
+
from typing import Optional
|
18
18
|
|
19
19
|
from fastapi import APIRouter, Request, Security
|
20
20
|
|
21
|
-
from zenml.constants import
|
21
|
+
from zenml.constants import (
|
22
|
+
API,
|
23
|
+
CONFIG,
|
24
|
+
INFO,
|
25
|
+
STACK,
|
26
|
+
STACK_DEPLOYMENT,
|
27
|
+
STACK_DEPLOYMENT_API_TOKEN_EXPIRATION,
|
28
|
+
VERSION_1,
|
29
|
+
)
|
22
30
|
from zenml.enums import StackDeploymentProvider
|
23
|
-
from zenml.models import
|
31
|
+
from zenml.models import (
|
32
|
+
DeployedStack,
|
33
|
+
StackDeploymentConfig,
|
34
|
+
StackDeploymentInfo,
|
35
|
+
)
|
24
36
|
from zenml.stack_deployments.utils import get_stack_deployment_class
|
25
37
|
from zenml.zen_server.auth import AuthContext, authorize
|
26
38
|
from zenml.zen_server.exceptions import error_response
|
@@ -54,27 +66,20 @@ def get_stack_deployment_info(
|
|
54
66
|
Information about the stack deployment provider.
|
55
67
|
"""
|
56
68
|
stack_deployment_class = get_stack_deployment_class(provider)
|
57
|
-
return
|
58
|
-
provider=provider,
|
59
|
-
description=stack_deployment_class.description(),
|
60
|
-
instructions=stack_deployment_class.instructions(),
|
61
|
-
post_deploy_instructions=stack_deployment_class.post_deploy_instructions(),
|
62
|
-
permissions=stack_deployment_class.permissions(),
|
63
|
-
locations=stack_deployment_class.locations(),
|
64
|
-
)
|
69
|
+
return stack_deployment_class.get_deployment_info()
|
65
70
|
|
66
71
|
|
67
72
|
@router.get(
|
68
|
-
|
73
|
+
CONFIG,
|
69
74
|
)
|
70
75
|
@handle_exceptions
|
71
|
-
def
|
76
|
+
def get_stack_deployment_config(
|
72
77
|
request: Request,
|
73
78
|
provider: StackDeploymentProvider,
|
74
79
|
stack_name: str,
|
75
80
|
location: Optional[str] = None,
|
76
81
|
auth_context: AuthContext = Security(authorize),
|
77
|
-
) ->
|
82
|
+
) -> StackDeploymentConfig:
|
78
83
|
"""Return the URL to deploy the ZenML stack to the specified cloud provider.
|
79
84
|
|
80
85
|
Args:
|
@@ -85,8 +90,8 @@ def get_stack_deployment_url(
|
|
85
90
|
auth_context: The authentication context.
|
86
91
|
|
87
92
|
Returns:
|
88
|
-
The URL
|
89
|
-
|
93
|
+
The cloud provider console URL where the stack will be deployed and
|
94
|
+
the configuration for the stack deployment.
|
90
95
|
"""
|
91
96
|
verify_permission(
|
92
97
|
resource_type=ResourceType.SERVICE_CONNECTOR, action=Action.CREATE
|
@@ -107,12 +112,17 @@ def get_stack_deployment_url(
|
|
107
112
|
assert token is not None
|
108
113
|
|
109
114
|
# A new API token is generated for the stack deployment
|
110
|
-
expires = datetime.datetime.utcnow() + datetime.timedelta(
|
115
|
+
expires = datetime.datetime.utcnow() + datetime.timedelta(
|
116
|
+
minutes=STACK_DEPLOYMENT_API_TOKEN_EXPIRATION
|
117
|
+
)
|
111
118
|
api_token = token.encode(expires=expires)
|
112
119
|
|
113
120
|
return stack_deployment_class(
|
114
|
-
stack_name=stack_name,
|
115
|
-
|
121
|
+
stack_name=stack_name,
|
122
|
+
location=location,
|
123
|
+
zenml_server_url=str(url),
|
124
|
+
zenml_server_api_token=api_token,
|
125
|
+
).get_deployment_config()
|
116
126
|
|
117
127
|
|
118
128
|
@router.get(
|
@@ -140,5 +150,9 @@ def get_deployed_stack(
|
|
140
150
|
"""
|
141
151
|
stack_deployment_class = get_stack_deployment_class(provider)
|
142
152
|
return stack_deployment_class(
|
143
|
-
stack_name=stack_name,
|
153
|
+
stack_name=stack_name,
|
154
|
+
location=location,
|
155
|
+
# These fields are not needed for this operation
|
156
|
+
zenml_server_url="",
|
157
|
+
zenml_server_api_token="",
|
144
158
|
).get_stack(date_start=date_start)
|