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.
Files changed (27) hide show
  1. zenml/VERSION +1 -1
  2. zenml/cli/stack.py +220 -71
  3. zenml/constants.py +6 -0
  4. zenml/enums.py +16 -0
  5. zenml/integrations/gcp/service_connectors/gcp_service_connector.py +54 -6
  6. zenml/logging/step_logging.py +34 -35
  7. zenml/models/__init__.py +2 -0
  8. zenml/models/v2/core/server_settings.py +0 -20
  9. zenml/models/v2/misc/stack_deployment.py +20 -0
  10. zenml/orchestrators/step_launcher.py +1 -0
  11. zenml/stack_deployments/aws_stack_deployment.py +56 -91
  12. zenml/stack_deployments/gcp_stack_deployment.py +260 -0
  13. zenml/stack_deployments/stack_deployment.py +103 -25
  14. zenml/stack_deployments/utils.py +4 -0
  15. zenml/zen_server/routers/devices_endpoints.py +4 -1
  16. zenml/zen_server/routers/server_endpoints.py +29 -2
  17. zenml/zen_server/routers/stack_deployment_endpoints.py +34 -20
  18. zenml/zen_stores/migrations/versions/b4fca5241eea_migrate_onboarding_state.py +167 -0
  19. zenml/zen_stores/rest_zen_store.py +45 -21
  20. zenml/zen_stores/schemas/server_settings_schemas.py +23 -11
  21. zenml/zen_stores/sql_zen_store.py +117 -19
  22. zenml/zen_stores/zen_store_interface.py +6 -5
  23. {zenml_nightly-0.61.0.dev20240711.dist-info → zenml_nightly-0.61.0.dev20240713.dist-info}/METADATA +1 -1
  24. {zenml_nightly-0.61.0.dev20240711.dist-info → zenml_nightly-0.61.0.dev20240713.dist-info}/RECORD +27 -25
  25. {zenml_nightly-0.61.0.dev20240711.dist-info → zenml_nightly-0.61.0.dev20240713.dist-info}/LICENSE +0 -0
  26. {zenml_nightly-0.61.0.dev20240711.dist-info → zenml_nightly-0.61.0.dev20240713.dist-info}/WHEEL +0 -0
  27. {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, Tuple
18
+ from typing import ClassVar, Dict, List, Optional
19
19
 
20
20
  from pydantic import BaseModel
21
21
 
22
- from zenml.enums import StackDeploymentProvider
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
- @abstractmethod
93
- def deploy_url(
94
- self,
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
- The URL should point to a cloud provider console where the user can
101
- deploy the ZenML stack and should include as many pre-filled parameters
102
- as possible.
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
- Args:
105
- zenml_server_url: The URL of the ZenML server.
106
- zenml_server_api_token: The API token to authenticate with the ZenML
107
- server.
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 URL to deploy the ZenML stack to the specified cloud provider
111
- and a text description of the URL.
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 and stack name.
155
+ provider.
123
156
 
124
157
  Args:
125
- date_start: The start date of the deployment.
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 the
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
@@ -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 ACTIVATE, API, INFO, SERVER_SETTINGS, VERSION_1
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, Tuple
17
+ from typing import Optional
18
18
 
19
19
  from fastapi import APIRouter, Request, Security
20
20
 
21
- from zenml.constants import API, INFO, STACK, STACK_DEPLOYMENT, URL, VERSION_1
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 DeployedStack, StackDeploymentInfo
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 StackDeploymentInfo(
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
- URL,
73
+ CONFIG,
69
74
  )
70
75
  @handle_exceptions
71
- def get_stack_deployment_url(
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
- ) -> Tuple[str, str]:
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 to deploy the ZenML stack to the specified cloud provider
89
- and a text description of the URL.
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(minutes=60)
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, location=location
115
- ).deploy_url(zenml_server_url=str(url), zenml_server_api_token=api_token)
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, location=location
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)