zenml-nightly 0.68.0.dev20241027__py3-none-any.whl → 0.68.1.dev20241101__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.
- README.md +17 -11
- RELEASE_NOTES.md +9 -0
- zenml/VERSION +1 -1
- zenml/__init__.py +1 -1
- zenml/analytics/context.py +16 -1
- zenml/analytics/utils.py +18 -7
- zenml/artifacts/utils.py +40 -216
- zenml/cli/__init__.py +63 -90
- zenml/cli/base.py +3 -3
- zenml/cli/login.py +951 -0
- zenml/cli/server.py +462 -353
- zenml/cli/service_accounts.py +4 -4
- zenml/cli/stack.py +77 -2
- zenml/cli/stack_components.py +5 -16
- zenml/cli/user_management.py +0 -12
- zenml/cli/utils.py +24 -77
- zenml/client.py +46 -14
- zenml/config/compiler.py +1 -0
- zenml/config/global_config.py +9 -0
- zenml/config/pipeline_configurations.py +2 -1
- zenml/config/pipeline_run_configuration.py +2 -1
- zenml/constants.py +3 -9
- zenml/enums.py +1 -1
- zenml/exceptions.py +11 -0
- zenml/integrations/github/code_repositories/github_code_repository.py +1 -1
- zenml/login/__init__.py +16 -0
- zenml/login/credentials.py +346 -0
- zenml/login/credentials_store.py +603 -0
- zenml/login/pro/__init__.py +16 -0
- zenml/login/pro/client.py +496 -0
- zenml/login/pro/constants.py +34 -0
- zenml/login/pro/models.py +25 -0
- zenml/login/pro/organization/__init__.py +14 -0
- zenml/login/pro/organization/client.py +79 -0
- zenml/login/pro/organization/models.py +32 -0
- zenml/login/pro/tenant/__init__.py +14 -0
- zenml/login/pro/tenant/client.py +92 -0
- zenml/login/pro/tenant/models.py +174 -0
- zenml/login/pro/utils.py +121 -0
- zenml/{cli → login}/web_login.py +64 -28
- zenml/materializers/base_materializer.py +43 -9
- zenml/materializers/built_in_materializer.py +1 -1
- zenml/metadata/metadata_types.py +49 -0
- zenml/model/model.py +0 -38
- zenml/models/__init__.py +3 -0
- zenml/models/v2/base/base.py +12 -8
- zenml/models/v2/base/filter.py +9 -0
- zenml/models/v2/core/artifact_version.py +49 -10
- zenml/models/v2/core/component.py +54 -19
- zenml/models/v2/core/flavor.py +13 -13
- zenml/models/v2/core/model.py +3 -1
- zenml/models/v2/core/model_version.py +3 -5
- zenml/models/v2/core/model_version_artifact.py +3 -1
- zenml/models/v2/core/model_version_pipeline_run.py +3 -1
- zenml/models/v2/core/pipeline.py +3 -1
- zenml/models/v2/core/pipeline_run.py +23 -1
- zenml/models/v2/core/run_template.py +3 -1
- zenml/models/v2/core/stack.py +7 -3
- zenml/models/v2/core/step_run.py +43 -2
- zenml/models/v2/misc/auth_models.py +11 -2
- zenml/models/v2/misc/server_models.py +2 -0
- zenml/orchestrators/base_orchestrator.py +8 -4
- zenml/orchestrators/step_launcher.py +1 -0
- zenml/orchestrators/step_run_utils.py +10 -2
- zenml/orchestrators/step_runner.py +67 -55
- zenml/orchestrators/utils.py +45 -22
- zenml/pipelines/pipeline_decorator.py +5 -0
- zenml/pipelines/pipeline_definition.py +206 -160
- zenml/pipelines/run_utils.py +11 -10
- zenml/services/local/local_daemon_entrypoint.py +4 -4
- zenml/services/service.py +2 -2
- zenml/stack/stack.py +2 -6
- zenml/stack/stack_component.py +2 -7
- zenml/stack/utils.py +26 -14
- zenml/steps/base_step.py +8 -2
- zenml/steps/step_context.py +0 -3
- zenml/steps/step_invocation.py +14 -5
- zenml/steps/utils.py +1 -0
- zenml/utils/materializer_utils.py +1 -1
- zenml/utils/requirements_utils.py +71 -0
- zenml/utils/singleton.py +15 -3
- zenml/utils/source_utils.py +39 -2
- zenml/utils/visualization_utils.py +1 -1
- zenml/zen_server/auth.py +44 -39
- zenml/zen_server/deploy/__init__.py +7 -7
- zenml/zen_server/deploy/base_provider.py +46 -73
- zenml/zen_server/deploy/{local → daemon}/__init__.py +3 -3
- zenml/zen_server/deploy/{local/local_provider.py → daemon/daemon_provider.py} +44 -63
- zenml/zen_server/deploy/{local/local_zen_server.py → daemon/daemon_zen_server.py} +50 -22
- zenml/zen_server/deploy/deployer.py +90 -171
- zenml/zen_server/deploy/deployment.py +20 -12
- zenml/zen_server/deploy/docker/docker_provider.py +9 -28
- zenml/zen_server/deploy/docker/docker_zen_server.py +19 -3
- zenml/zen_server/deploy/helm/Chart.yaml +1 -1
- zenml/zen_server/deploy/helm/README.md +2 -2
- zenml/zen_server/exceptions.py +11 -0
- zenml/zen_server/jwt.py +9 -9
- zenml/zen_server/routers/auth_endpoints.py +30 -8
- zenml/zen_server/routers/stack_components_endpoints.py +1 -1
- zenml/zen_server/routers/workspaces_endpoints.py +1 -1
- zenml/zen_server/template_execution/runner_entrypoint_configuration.py +7 -4
- zenml/zen_server/template_execution/utils.py +6 -61
- zenml/zen_server/utils.py +64 -36
- zenml/zen_stores/base_zen_store.py +4 -49
- zenml/zen_stores/migrations/versions/0.68.1_release.py +23 -0
- zenml/zen_stores/migrations/versions/c22561cbb3a9_add_artifact_unique_constraints.py +86 -0
- zenml/zen_stores/rest_zen_store.py +325 -147
- zenml/zen_stores/schemas/api_key_schemas.py +9 -4
- zenml/zen_stores/schemas/artifact_schemas.py +21 -2
- zenml/zen_stores/schemas/artifact_visualization_schemas.py +1 -1
- zenml/zen_stores/schemas/component_schemas.py +49 -6
- zenml/zen_stores/schemas/device_schemas.py +9 -4
- zenml/zen_stores/schemas/flavor_schemas.py +1 -1
- zenml/zen_stores/schemas/model_schemas.py +1 -1
- zenml/zen_stores/schemas/service_schemas.py +1 -1
- zenml/zen_stores/schemas/step_run_schemas.py +1 -1
- zenml/zen_stores/schemas/trigger_schemas.py +1 -1
- zenml/zen_stores/sql_zen_store.py +393 -140
- zenml/zen_stores/template_utils.py +3 -1
- {zenml_nightly-0.68.0.dev20241027.dist-info → zenml_nightly-0.68.1.dev20241101.dist-info}/METADATA +18 -12
- {zenml_nightly-0.68.0.dev20241027.dist-info → zenml_nightly-0.68.1.dev20241101.dist-info}/RECORD +124 -107
- zenml/api.py +0 -60
- {zenml_nightly-0.68.0.dev20241027.dist-info → zenml_nightly-0.68.1.dev20241101.dist-info}/LICENSE +0 -0
- {zenml_nightly-0.68.0.dev20241027.dist-info → zenml_nightly-0.68.1.dev20241101.dist-info}/WHEEL +0 -0
- {zenml_nightly-0.68.0.dev20241027.dist-info → zenml_nightly-0.68.1.dev20241101.dist-info}/entry_points.txt +0 -0
@@ -11,7 +11,7 @@
|
|
11
11
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
12
12
|
# or implied. See the License for the specific language governing
|
13
13
|
# permissions and limitations under the License.
|
14
|
-
"""Local ZenML server deployment service implementation."""
|
14
|
+
"""Local daemon ZenML server deployment service implementation."""
|
15
15
|
|
16
16
|
import ipaddress
|
17
17
|
import os
|
@@ -24,14 +24,18 @@ from zenml.config.global_config import GlobalConfiguration
|
|
24
24
|
from zenml.config.store_config import StoreConfiguration
|
25
25
|
from zenml.constants import (
|
26
26
|
DEFAULT_LOCAL_SERVICE_IP_ADDRESS,
|
27
|
+
ENV_ZENML_ANALYTICS_OPT_IN,
|
27
28
|
ENV_ZENML_CONFIG_PATH,
|
28
29
|
ENV_ZENML_DISABLE_DATABASE_MIGRATION,
|
29
30
|
ENV_ZENML_LOCAL_STORES_PATH,
|
31
|
+
ENV_ZENML_SERVER,
|
32
|
+
ENV_ZENML_SERVER_AUTH_SCHEME,
|
30
33
|
ENV_ZENML_SERVER_AUTO_ACTIVATE,
|
31
34
|
ENV_ZENML_SERVER_DEPLOYMENT_TYPE,
|
35
|
+
ENV_ZENML_USER_ID,
|
32
36
|
ZEN_SERVER_ENTRYPOINT,
|
33
37
|
)
|
34
|
-
from zenml.enums import StoreType
|
38
|
+
from zenml.enums import AuthScheme, StoreType
|
35
39
|
from zenml.logger import get_logger
|
36
40
|
from zenml.models import ServerDeploymentType
|
37
41
|
from zenml.services import (
|
@@ -41,16 +45,16 @@ from zenml.services import (
|
|
41
45
|
ServiceType,
|
42
46
|
)
|
43
47
|
from zenml.utils.io_utils import get_global_config_directory
|
44
|
-
from zenml.zen_server.deploy.deployment import
|
48
|
+
from zenml.zen_server.deploy.deployment import LocalServerDeploymentConfig
|
45
49
|
|
46
50
|
logger = get_logger(__name__)
|
47
51
|
|
48
52
|
ZEN_SERVER_HEALTHCHECK_URL_PATH = "health"
|
49
|
-
|
53
|
+
DAEMON_ZENML_SERVER_DEFAULT_TIMEOUT = 30
|
50
54
|
|
51
55
|
|
52
|
-
class LocalServerDeploymentConfig
|
53
|
-
"""
|
56
|
+
class DaemonServerDeploymentConfig(LocalServerDeploymentConfig):
|
57
|
+
"""Daemon server deployment configuration.
|
54
58
|
|
55
59
|
Attributes:
|
56
60
|
port: The TCP port number where the server is accepting connections.
|
@@ -67,21 +71,30 @@ class LocalServerDeploymentConfig(ServerDeploymentConfig):
|
|
67
71
|
blocking: bool = False
|
68
72
|
store: Optional[StoreConfiguration] = None
|
69
73
|
|
74
|
+
@property
|
75
|
+
def url(self) -> Optional[str]:
|
76
|
+
"""Get the configured server URL.
|
77
|
+
|
78
|
+
Returns:
|
79
|
+
The configured server URL.
|
80
|
+
"""
|
81
|
+
return f"http://{self.ip_address}:{self.port}"
|
82
|
+
|
70
83
|
model_config = ConfigDict(extra="forbid")
|
71
84
|
|
72
85
|
|
73
|
-
class
|
74
|
-
"""Local Zen server configuration.
|
86
|
+
class DaemonZenServerConfig(LocalDaemonServiceConfig):
|
87
|
+
"""Local daemon Zen server configuration.
|
75
88
|
|
76
89
|
Attributes:
|
77
90
|
server: The deployment configuration.
|
78
91
|
"""
|
79
92
|
|
80
|
-
server:
|
93
|
+
server: DaemonServerDeploymentConfig
|
81
94
|
|
82
95
|
|
83
|
-
class
|
84
|
-
"""Service daemon that can be used to start a local ZenML
|
96
|
+
class DaemonZenServer(LocalDaemonService):
|
97
|
+
"""Service daemon that can be used to start a local daemon ZenML server.
|
85
98
|
|
86
99
|
Attributes:
|
87
100
|
config: service configuration
|
@@ -89,26 +102,26 @@ class LocalZenServer(LocalDaemonService):
|
|
89
102
|
"""
|
90
103
|
|
91
104
|
SERVICE_TYPE = ServiceType(
|
92
|
-
name="
|
105
|
+
name="daemon_zenml_server",
|
93
106
|
type="zen_server",
|
94
|
-
flavor="
|
95
|
-
description="
|
107
|
+
flavor="daemon",
|
108
|
+
description="local daemon ZenML server deployment",
|
96
109
|
)
|
97
110
|
|
98
|
-
config:
|
111
|
+
config: DaemonZenServerConfig
|
99
112
|
endpoint: LocalDaemonServiceEndpoint
|
100
113
|
|
101
114
|
@classmethod
|
102
115
|
def config_path(cls) -> str:
|
103
|
-
"""Path to the directory where the local ZenML server files are located.
|
116
|
+
"""Path to the directory where the local daemon ZenML server files are located.
|
104
117
|
|
105
118
|
Returns:
|
106
|
-
Path to the local ZenML server runtime directory.
|
119
|
+
Path to the local daemon ZenML server runtime directory.
|
107
120
|
"""
|
108
121
|
return os.path.join(
|
109
122
|
get_global_config_directory(),
|
110
123
|
"zen_server",
|
111
|
-
"
|
124
|
+
"daemon",
|
112
125
|
)
|
113
126
|
|
114
127
|
@property
|
@@ -121,18 +134,18 @@ class LocalZenServer(LocalDaemonService):
|
|
121
134
|
return os.path.join(self.config_path(), ".zenconfig")
|
122
135
|
|
123
136
|
@classmethod
|
124
|
-
def get_service(cls) -> Optional["
|
125
|
-
"""Load and return the local ZenML server service, if present.
|
137
|
+
def get_service(cls) -> Optional["DaemonZenServer"]:
|
138
|
+
"""Load and return the local daemon ZenML server service, if present.
|
126
139
|
|
127
140
|
Returns:
|
128
|
-
The local ZenML server service or None, if the local server
|
141
|
+
The local daemon ZenML server service or None, if the local server
|
129
142
|
deployment is not found.
|
130
143
|
"""
|
131
144
|
config_filename = os.path.join(cls.config_path(), "service.json")
|
132
145
|
try:
|
133
146
|
with open(config_filename, "r") as f:
|
134
147
|
return cast(
|
135
|
-
"
|
148
|
+
"DaemonZenServer", DaemonZenServer.from_json(f.read())
|
136
149
|
)
|
137
150
|
except FileNotFoundError:
|
138
151
|
return None
|
@@ -147,8 +160,15 @@ class LocalZenServer(LocalDaemonService):
|
|
147
160
|
The command to start the daemon and the environment variables to
|
148
161
|
set for the command.
|
149
162
|
"""
|
163
|
+
gc = GlobalConfiguration()
|
164
|
+
|
150
165
|
cmd, env = super()._get_daemon_cmd()
|
166
|
+
env[ENV_ZENML_SERVER] = "true"
|
151
167
|
env[ENV_ZENML_CONFIG_PATH] = self._global_config_path
|
168
|
+
env[ENV_ZENML_ANALYTICS_OPT_IN] = str(gc.analytics_opt_in)
|
169
|
+
env[ENV_ZENML_USER_ID] = str(gc.user_id)
|
170
|
+
# Disable authentication for the local server
|
171
|
+
env[ENV_ZENML_SERVER_AUTH_SCHEME] = AuthScheme.NO_AUTH.value
|
152
172
|
env[ENV_ZENML_SERVER_DEPLOYMENT_TYPE] = ServerDeploymentType.LOCAL
|
153
173
|
# Set the local stores path to the same path used by the client. This
|
154
174
|
# ensures that the server's default store configuration is initialized
|
@@ -176,6 +196,8 @@ class LocalZenServer(LocalDaemonService):
|
|
176
196
|
if not self.config.blocking:
|
177
197
|
super().start(timeout)
|
178
198
|
else:
|
199
|
+
gc = GlobalConfiguration()
|
200
|
+
|
179
201
|
# In the blocking mode, we need to temporarily set the environment
|
180
202
|
# variables for the running process to make it look like the server
|
181
203
|
# is running in a separate environment (i.e. using a different
|
@@ -185,21 +207,27 @@ class LocalZenServer(LocalDaemonService):
|
|
185
207
|
GlobalConfiguration._reset_instance()
|
186
208
|
Client._reset_instance()
|
187
209
|
original_config_path = os.environ.get(ENV_ZENML_CONFIG_PATH)
|
210
|
+
os.environ[ENV_ZENML_SERVER] = "true"
|
188
211
|
os.environ[ENV_ZENML_CONFIG_PATH] = self._global_config_path
|
212
|
+
os.environ[ENV_ZENML_ANALYTICS_OPT_IN] = str(gc.analytics_opt_in)
|
213
|
+
os.environ[ENV_ZENML_USER_ID] = str(gc.user_id)
|
189
214
|
# Set the local stores path to the same path used by the client.
|
190
215
|
# This ensures that the server's default store configuration is
|
191
216
|
# initialized to point at the same local SQLite database as the
|
192
217
|
# client.
|
193
218
|
os.environ[ENV_ZENML_LOCAL_STORES_PATH] = local_stores_path
|
219
|
+
os.environ[ENV_ZENML_SERVER_AUTH_SCHEME] = AuthScheme.NO_AUTH.value
|
194
220
|
try:
|
195
221
|
self.run()
|
196
222
|
finally:
|
197
223
|
# Restore the original client environment variables
|
224
|
+
del os.environ[ENV_ZENML_SERVER]
|
198
225
|
if original_config_path:
|
199
226
|
os.environ[ENV_ZENML_CONFIG_PATH] = original_config_path
|
200
227
|
else:
|
201
228
|
del os.environ[ENV_ZENML_CONFIG_PATH]
|
202
229
|
del os.environ[ENV_ZENML_LOCAL_STORES_PATH]
|
230
|
+
del os.environ[ENV_ZENML_SERVER_AUTH_SCHEME]
|
203
231
|
GlobalConfiguration._reset_instance()
|
204
232
|
Client._reset_instance()
|
205
233
|
|
@@ -13,7 +13,7 @@
|
|
13
13
|
# permissions and limitations under the License.
|
14
14
|
"""ZenML server deployer singleton implementation."""
|
15
15
|
|
16
|
-
from typing import ClassVar, Dict, Generator,
|
16
|
+
from typing import ClassVar, Dict, Generator, Optional, Type
|
17
17
|
|
18
18
|
from zenml.config.global_config import GlobalConfiguration
|
19
19
|
from zenml.enums import ServerProviderType, StoreType
|
@@ -21,22 +21,22 @@ from zenml.logger import get_logger
|
|
21
21
|
from zenml.utils.singleton import SingletonMetaClass
|
22
22
|
from zenml.zen_server.deploy.base_provider import BaseServerProvider
|
23
23
|
from zenml.zen_server.deploy.deployment import (
|
24
|
-
|
25
|
-
|
24
|
+
LocalServerDeployment,
|
25
|
+
LocalServerDeploymentConfig,
|
26
26
|
)
|
27
27
|
from zenml.zen_server.deploy.exceptions import (
|
28
28
|
ServerDeploymentError,
|
29
|
-
ServerDeploymentExistsError,
|
30
29
|
ServerDeploymentNotFoundError,
|
31
30
|
ServerProviderNotFoundError,
|
32
31
|
)
|
32
|
+
from zenml.zen_stores.base_zen_store import BaseZenStore
|
33
33
|
from zenml.zen_stores.rest_zen_store import RestZenStoreConfiguration
|
34
34
|
|
35
35
|
logger = get_logger(__name__)
|
36
36
|
|
37
37
|
|
38
|
-
class
|
39
|
-
"""
|
38
|
+
class LocalServerDeployer(metaclass=SingletonMetaClass):
|
39
|
+
"""Local server deployer singleton.
|
40
40
|
|
41
41
|
This class is responsible for managing the various server provider
|
42
42
|
implementations and for directing server deployment lifecycle requests to
|
@@ -85,126 +85,133 @@ class ServerDeployer(metaclass=SingletonMetaClass):
|
|
85
85
|
)
|
86
86
|
return cls._providers[provider_type]
|
87
87
|
|
88
|
+
def initialize_local_database(self) -> None:
|
89
|
+
"""Initialize the local ZenML database."""
|
90
|
+
default_store_cfg = GlobalConfiguration().get_default_store()
|
91
|
+
BaseZenStore.create_store(default_store_cfg)
|
92
|
+
|
88
93
|
def deploy_server(
|
89
94
|
self,
|
90
|
-
config:
|
95
|
+
config: LocalServerDeploymentConfig,
|
91
96
|
timeout: Optional[int] = None,
|
92
|
-
|
93
|
-
|
97
|
+
restart: bool = False,
|
98
|
+
) -> LocalServerDeployment:
|
99
|
+
"""Deploy the local ZenML server or update the existing deployment.
|
94
100
|
|
95
101
|
Args:
|
96
102
|
config: The server deployment configuration.
|
97
103
|
timeout: The timeout in seconds to wait until the deployment is
|
98
104
|
successful. If not supplied, the default timeout value specified
|
99
105
|
by the provider is used.
|
106
|
+
restart: If True, the existing server deployment will be torn down
|
107
|
+
and a new server will be deployed.
|
100
108
|
|
101
109
|
Returns:
|
102
|
-
The server deployment.
|
110
|
+
The local server deployment.
|
103
111
|
"""
|
104
|
-
#
|
105
|
-
#
|
106
|
-
|
107
|
-
gc = GlobalConfiguration()
|
108
|
-
|
109
|
-
_ = gc.zen_store
|
112
|
+
# Ensure that the local database is always initialized before any local
|
113
|
+
# server is deployed or updated.
|
114
|
+
self.initialize_local_database()
|
110
115
|
|
111
116
|
try:
|
112
|
-
self.get_server(
|
117
|
+
self.get_server()
|
113
118
|
except ServerDeploymentNotFoundError:
|
114
119
|
pass
|
115
120
|
else:
|
116
|
-
return self.update_server(
|
121
|
+
return self.update_server(
|
122
|
+
config=config, timeout=timeout, restart=restart
|
123
|
+
)
|
117
124
|
|
118
125
|
provider_name = config.provider.value
|
119
126
|
provider = self.get_provider(config.provider)
|
120
127
|
|
121
|
-
logger.info(
|
122
|
-
f"Deploying a {provider_name} ZenML server with name "
|
123
|
-
f"'{config.name}'."
|
124
|
-
)
|
128
|
+
logger.info(f"Deploying a local {provider_name} ZenML server.")
|
125
129
|
return provider.deploy_server(config, timeout=timeout)
|
126
130
|
|
127
131
|
def update_server(
|
128
132
|
self,
|
129
|
-
config:
|
133
|
+
config: LocalServerDeploymentConfig,
|
130
134
|
timeout: Optional[int] = None,
|
131
|
-
|
132
|
-
|
135
|
+
restart: bool = False,
|
136
|
+
) -> LocalServerDeployment:
|
137
|
+
"""Update an existing local ZenML server deployment.
|
133
138
|
|
134
139
|
Args:
|
135
140
|
config: The new server deployment configuration.
|
136
141
|
timeout: The timeout in seconds to wait until the deployment is
|
137
142
|
successful. If not supplied, a default timeout value of 30
|
138
143
|
seconds is used.
|
144
|
+
restart: If True, the existing server deployment will be torn down
|
145
|
+
and a new server will be deployed.
|
139
146
|
|
140
147
|
Returns:
|
141
148
|
The updated server deployment.
|
142
|
-
|
143
|
-
Raises:
|
144
|
-
ServerDeploymentExistsError: If an existing deployment with the same
|
145
|
-
name but a different provider type is found.
|
146
149
|
"""
|
147
150
|
# this will also raise ServerDeploymentNotFoundError if the server
|
148
151
|
# does not exist
|
149
|
-
existing_server = self.get_server(
|
152
|
+
existing_server = self.get_server()
|
150
153
|
|
151
154
|
provider = self.get_provider(config.provider)
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
155
|
+
if existing_server.config.provider != config.provider or restart:
|
156
|
+
existing_provider = self.get_provider(
|
157
|
+
existing_server.config.provider
|
158
|
+
)
|
159
|
+
|
160
|
+
# Tear down the existing server deployment
|
161
|
+
existing_provider.remove_server(
|
162
|
+
existing_server.config, timeout=timeout
|
160
163
|
)
|
161
164
|
|
165
|
+
# Deploy a new server with the new provider
|
166
|
+
return provider.deploy_server(config, timeout=timeout)
|
167
|
+
|
162
168
|
return provider.update_server(config, timeout=timeout)
|
163
169
|
|
164
170
|
def remove_server(
|
165
171
|
self,
|
166
|
-
server_name: str,
|
167
172
|
timeout: Optional[int] = None,
|
168
173
|
) -> None:
|
169
|
-
"""Tears down and removes all resources and files associated with
|
174
|
+
"""Tears down and removes all resources and files associated with the local ZenML server deployment.
|
170
175
|
|
171
176
|
Args:
|
172
|
-
server_name: The server deployment name.
|
173
177
|
timeout: The timeout in seconds to wait until the deployment is
|
174
178
|
successfully torn down. If not supplied, a provider specific
|
175
179
|
default timeout value is used.
|
176
180
|
"""
|
177
181
|
# this will also raise ServerDeploymentNotFoundError if the server
|
178
182
|
# does not exist
|
179
|
-
|
183
|
+
try:
|
184
|
+
server = self.get_server()
|
185
|
+
except ServerDeploymentNotFoundError:
|
186
|
+
return
|
180
187
|
|
181
188
|
provider_name = server.config.provider.value
|
182
189
|
provider = self.get_provider(server.config.provider)
|
183
190
|
|
184
|
-
if self.is_connected_to_server(
|
191
|
+
if self.is_connected_to_server():
|
185
192
|
try:
|
186
|
-
self.disconnect_from_server(
|
193
|
+
self.disconnect_from_server()
|
187
194
|
except Exception as e:
|
188
|
-
logger.warning(
|
195
|
+
logger.warning(
|
196
|
+
f"Failed to disconnect from the local server: {e}"
|
197
|
+
)
|
189
198
|
|
190
|
-
logger.info(
|
191
|
-
f"Tearing down the '{server_name}' {provider_name} ZenML server."
|
192
|
-
)
|
199
|
+
logger.info(f"Tearing down the local {provider_name} ZenML server.")
|
193
200
|
provider.remove_server(server.config, timeout=timeout)
|
194
201
|
|
195
|
-
def is_connected_to_server(self
|
196
|
-
"""Check if the ZenML client is currently connected to
|
197
|
-
|
198
|
-
Args:
|
199
|
-
server_name: The server deployment name.
|
202
|
+
def is_connected_to_server(self) -> bool:
|
203
|
+
"""Check if the ZenML client is currently connected to the local ZenML server.
|
200
204
|
|
201
205
|
Returns:
|
202
|
-
True if the ZenML client is connected to the ZenML server, False
|
206
|
+
True if the ZenML client is connected to the local ZenML server, False
|
203
207
|
otherwise.
|
204
208
|
"""
|
205
209
|
# this will also raise ServerDeploymentNotFoundError if the server
|
206
210
|
# does not exist
|
207
|
-
|
211
|
+
try:
|
212
|
+
server = self.get_server()
|
213
|
+
except ServerDeploymentNotFoundError:
|
214
|
+
return False
|
208
215
|
|
209
216
|
gc = GlobalConfiguration()
|
210
217
|
return (
|
@@ -215,188 +222,101 @@ class ServerDeployer(metaclass=SingletonMetaClass):
|
|
215
222
|
|
216
223
|
def connect_to_server(
|
217
224
|
self,
|
218
|
-
server_name: str,
|
219
|
-
username: str,
|
220
|
-
password: str,
|
221
|
-
verify_ssl: Union[bool, str] = True,
|
222
225
|
) -> None:
|
223
|
-
"""Connect to
|
224
|
-
|
225
|
-
Args:
|
226
|
-
server_name: The server deployment name.
|
227
|
-
username: The username to use to connect to the server.
|
228
|
-
password: The password to use to connect to the server.
|
229
|
-
verify_ssl: Either a boolean, in which case it controls whether we
|
230
|
-
verify the server's TLS certificate, or a string, in which case
|
231
|
-
it must be a path to a CA bundle to use or the CA bundle value
|
232
|
-
itself.
|
226
|
+
"""Connect to the local ZenML server instance.
|
233
227
|
|
234
228
|
Raises:
|
235
|
-
ServerDeploymentError: If the ZenML server is not running or
|
229
|
+
ServerDeploymentError: If the local ZenML server is not running or
|
236
230
|
is unreachable.
|
237
231
|
"""
|
238
232
|
# this will also raise ServerDeploymentNotFoundError if the server
|
239
233
|
# does not exist
|
240
|
-
server = self.get_server(
|
234
|
+
server = self.get_server()
|
241
235
|
provider_name = server.config.provider.value
|
242
236
|
|
243
237
|
gc = GlobalConfiguration()
|
244
238
|
if not server.status or not server.status.url:
|
245
239
|
raise ServerDeploymentError(
|
246
|
-
f"The {provider_name}
|
247
|
-
|
240
|
+
f"The local {provider_name} ZenML server is not currently "
|
241
|
+
"running or is unreachable."
|
248
242
|
)
|
249
243
|
|
250
244
|
store_config = RestZenStoreConfiguration(
|
251
245
|
url=server.status.url,
|
252
|
-
username=username,
|
253
|
-
password=password,
|
254
|
-
verify_ssl=verify_ssl,
|
255
246
|
)
|
256
247
|
|
257
248
|
if gc.store_configuration == store_config:
|
258
249
|
logger.info(
|
259
|
-
|
250
|
+
"Your client is already connected to the local "
|
260
251
|
f"{provider_name} ZenML server."
|
261
252
|
)
|
262
253
|
return
|
263
254
|
|
264
255
|
logger.info(
|
265
|
-
f"Connecting
|
266
|
-
f"
|
256
|
+
f"Connecting to the local {provider_name} ZenML server "
|
257
|
+
f"({store_config.url})."
|
267
258
|
)
|
268
259
|
|
269
260
|
gc.set_store(store_config)
|
270
261
|
|
271
262
|
logger.info(
|
272
|
-
f"Connected
|
273
|
-
f"
|
263
|
+
f"Connected to the local {provider_name} ZenML server "
|
264
|
+
f"({store_config.url})."
|
274
265
|
)
|
275
266
|
|
276
267
|
def disconnect_from_server(
|
277
268
|
self,
|
278
|
-
server_name: Optional[str] = None,
|
279
269
|
) -> None:
|
280
|
-
"""Disconnect from
|
281
|
-
|
282
|
-
Args:
|
283
|
-
server_name: The server deployment name. If supplied, the deployer
|
284
|
-
will check if the ZenML client is indeed connected to the server
|
285
|
-
and disconnect only if that is the case. Otherwise the deployer
|
286
|
-
will disconnect from any ZenML server.
|
287
|
-
"""
|
270
|
+
"""Disconnect from the ZenML server instance."""
|
288
271
|
gc = GlobalConfiguration()
|
289
272
|
store_cfg = gc.store_configuration
|
290
273
|
|
291
274
|
if store_cfg.type != StoreType.REST:
|
292
|
-
logger.info("ZenML is not currently connected to a ZenML server.")
|
293
|
-
return
|
294
|
-
|
295
|
-
if server_name:
|
296
|
-
# this will also raise ServerDeploymentNotFoundError if the server
|
297
|
-
# does not exist
|
298
|
-
server = self.get_server(server_name)
|
299
|
-
provider_name = server.config.provider.value
|
300
|
-
|
301
|
-
if not self.is_connected_to_server(server_name):
|
302
|
-
logger.info(
|
303
|
-
f"ZenML is not currently connected to the '{server_name}' "
|
304
|
-
f"{provider_name} ZenML server."
|
305
|
-
)
|
306
|
-
return
|
307
|
-
|
308
|
-
logger.info(
|
309
|
-
f"Disconnecting ZenML from the '{server_name}' "
|
310
|
-
f"{provider_name} ZenML server ({store_cfg.url})."
|
311
|
-
)
|
312
|
-
else:
|
313
275
|
logger.info(
|
314
|
-
|
276
|
+
"Your client is not currently connected to a ZenML server."
|
315
277
|
)
|
278
|
+
return
|
279
|
+
|
280
|
+
logger.info(
|
281
|
+
f"Disconnecting from the local ({store_cfg.url}) ZenML server."
|
282
|
+
)
|
316
283
|
|
317
284
|
gc.set_default_store()
|
318
285
|
|
319
|
-
logger.info("Disconnected
|
286
|
+
logger.info("Disconnected from the local ZenML server.")
|
320
287
|
|
321
288
|
def get_server(
|
322
289
|
self,
|
323
|
-
|
324
|
-
|
325
|
-
"""Get a server deployment.
|
326
|
-
|
327
|
-
Args:
|
328
|
-
server_name: The server deployment name.
|
290
|
+
) -> LocalServerDeployment:
|
291
|
+
"""Get the local server deployment.
|
329
292
|
|
330
293
|
Returns:
|
331
|
-
The
|
294
|
+
The local server deployment.
|
332
295
|
|
333
296
|
Raises:
|
334
|
-
ServerDeploymentNotFoundError: If no server deployment
|
335
|
-
|
297
|
+
ServerDeploymentNotFoundError: If no local server deployment is
|
298
|
+
found.
|
336
299
|
"""
|
337
300
|
for provider in self._providers.values():
|
338
301
|
try:
|
339
302
|
return provider.get_server(
|
340
|
-
|
341
|
-
name=server_name, provider=provider.TYPE
|
342
|
-
)
|
303
|
+
LocalServerDeploymentConfig(provider=provider.TYPE)
|
343
304
|
)
|
344
305
|
except ServerDeploymentNotFoundError:
|
345
306
|
pass
|
346
307
|
|
347
308
|
raise ServerDeploymentNotFoundError(
|
348
|
-
|
309
|
+
"No local server deployment was found."
|
349
310
|
)
|
350
311
|
|
351
|
-
def list_servers(
|
352
|
-
self,
|
353
|
-
server_name: Optional[str] = None,
|
354
|
-
provider_type: Optional[ServerProviderType] = None,
|
355
|
-
) -> List[ServerDeployment]:
|
356
|
-
"""List all server deployments.
|
357
|
-
|
358
|
-
Args:
|
359
|
-
server_name: The server deployment name to filter by.
|
360
|
-
provider_type: The server provider type to filter by.
|
361
|
-
|
362
|
-
Returns:
|
363
|
-
The list of server deployments.
|
364
|
-
"""
|
365
|
-
providers: List[BaseServerProvider] = []
|
366
|
-
if provider_type:
|
367
|
-
providers = [self.get_provider(provider_type)]
|
368
|
-
else:
|
369
|
-
providers = list(self._providers.values())
|
370
|
-
|
371
|
-
servers: List[ServerDeployment] = []
|
372
|
-
for provider in providers:
|
373
|
-
if server_name:
|
374
|
-
try:
|
375
|
-
servers.append(
|
376
|
-
provider.get_server(
|
377
|
-
ServerDeploymentConfig(
|
378
|
-
name=server_name,
|
379
|
-
provider=provider.TYPE,
|
380
|
-
)
|
381
|
-
)
|
382
|
-
)
|
383
|
-
except ServerDeploymentNotFoundError:
|
384
|
-
pass
|
385
|
-
else:
|
386
|
-
servers.extend(provider.list_servers())
|
387
|
-
|
388
|
-
return servers
|
389
|
-
|
390
312
|
def get_server_logs(
|
391
313
|
self,
|
392
|
-
server_name: str,
|
393
314
|
follow: bool = False,
|
394
315
|
tail: Optional[int] = None,
|
395
316
|
) -> Generator[str, bool, None]:
|
396
|
-
"""Retrieve the logs
|
317
|
+
"""Retrieve the logs for the local ZenML server.
|
397
318
|
|
398
319
|
Args:
|
399
|
-
server_name: The server deployment name.
|
400
320
|
follow: if True, the logs will be streamed as they are written
|
401
321
|
tail: only retrieve the last NUM lines of log output.
|
402
322
|
|
@@ -405,14 +325,13 @@ class ServerDeployer(metaclass=SingletonMetaClass):
|
|
405
325
|
"""
|
406
326
|
# this will also raise ServerDeploymentNotFoundError if the server
|
407
327
|
# does not exist
|
408
|
-
server = self.get_server(
|
328
|
+
server = self.get_server()
|
409
329
|
|
410
330
|
provider_name = server.config.provider.value
|
411
331
|
provider = self.get_provider(server.config.provider)
|
412
332
|
|
413
333
|
logger.info(
|
414
|
-
f"Fetching logs from the
|
415
|
-
f"server..."
|
334
|
+
f"Fetching logs from the local {provider_name} ZenML " f"server..."
|
416
335
|
)
|
417
336
|
return provider.get_server_logs(
|
418
337
|
server.config, follow=follow, tail=tail
|