dagster-cloud 1.8.2__py3-none-any.whl → 1.12.6__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.
- dagster_cloud/__init__.py +3 -3
- dagster_cloud/agent/__init__.py +4 -4
- dagster_cloud/agent/cli/__init__.py +56 -17
- dagster_cloud/agent/dagster_cloud_agent.py +360 -172
- dagster_cloud/agent/instrumentation/__init__.py +0 -0
- dagster_cloud/agent/instrumentation/constants.py +2 -0
- dagster_cloud/agent/instrumentation/run_launch.py +23 -0
- dagster_cloud/agent/instrumentation/schedule.py +34 -0
- dagster_cloud/agent/instrumentation/sensor.py +34 -0
- dagster_cloud/anomaly_detection/__init__.py +2 -2
- dagster_cloud/anomaly_detection/defs.py +17 -12
- dagster_cloud/anomaly_detection/types.py +3 -3
- dagster_cloud/api/dagster_cloud_api.py +209 -293
- dagster_cloud/auth/constants.py +21 -5
- dagster_cloud/batching/__init__.py +1 -0
- dagster_cloud/batching/batcher.py +210 -0
- dagster_cloud/dagster_insights/__init__.py +12 -6
- dagster_cloud/dagster_insights/bigquery/bigquery_utils.py +3 -2
- dagster_cloud/dagster_insights/bigquery/dbt_wrapper.py +39 -12
- dagster_cloud/dagster_insights/bigquery/insights_bigquery_resource.py +8 -6
- dagster_cloud/dagster_insights/insights_utils.py +18 -8
- dagster_cloud/dagster_insights/metrics_utils.py +12 -12
- dagster_cloud/dagster_insights/snowflake/dagster_snowflake_insights.py +5 -12
- dagster_cloud/dagster_insights/snowflake/dbt_wrapper.py +34 -8
- dagster_cloud/dagster_insights/snowflake/definitions.py +38 -12
- dagster_cloud/dagster_insights/snowflake/insights_snowflake_resource.py +11 -23
- dagster_cloud/definitions/__init__.py +0 -0
- dagster_cloud/definitions/job_selection.py +36 -0
- dagster_cloud/execution/cloud_run_launcher/k8s.py +1 -1
- dagster_cloud/execution/cloud_run_launcher/process.py +3 -3
- dagster_cloud/execution/monitoring/__init__.py +27 -33
- dagster_cloud/execution/utils/process.py +3 -3
- dagster_cloud/instance/__init__.py +125 -38
- dagster_cloud/instrumentation/__init__.py +32 -0
- dagster_cloud/metadata/source_code.py +13 -8
- dagster_cloud/metrics/__init__.py +0 -0
- dagster_cloud/metrics/tracer.py +59 -0
- dagster_cloud/opentelemetry/__init__.py +0 -0
- dagster_cloud/opentelemetry/config/__init__.py +73 -0
- dagster_cloud/opentelemetry/config/exporter.py +81 -0
- dagster_cloud/opentelemetry/config/log_record_processor.py +40 -0
- dagster_cloud/opentelemetry/config/logging_handler.py +14 -0
- dagster_cloud/opentelemetry/config/meter_provider.py +9 -0
- dagster_cloud/opentelemetry/config/metric_reader.py +39 -0
- dagster_cloud/opentelemetry/controller.py +319 -0
- dagster_cloud/opentelemetry/enum.py +58 -0
- dagster_cloud/opentelemetry/factories/__init__.py +1 -0
- dagster_cloud/opentelemetry/factories/logs.py +113 -0
- dagster_cloud/opentelemetry/factories/metrics.py +121 -0
- dagster_cloud/opentelemetry/metrics/__init__.py +0 -0
- dagster_cloud/opentelemetry/metrics/meter.py +140 -0
- dagster_cloud/opentelemetry/observers/__init__.py +0 -0
- dagster_cloud/opentelemetry/observers/dagster_exception_handler.py +40 -0
- dagster_cloud/opentelemetry/observers/execution_observer.py +178 -0
- dagster_cloud/pex/grpc/__generated__/multi_pex_api_pb2.pyi +175 -0
- dagster_cloud/pex/grpc/__init__.py +2 -2
- dagster_cloud/pex/grpc/client.py +4 -4
- dagster_cloud/pex/grpc/compile.py +2 -2
- dagster_cloud/pex/grpc/server/__init__.py +2 -2
- dagster_cloud/pex/grpc/server/cli/__init__.py +31 -19
- dagster_cloud/pex/grpc/server/manager.py +60 -42
- dagster_cloud/pex/grpc/server/registry.py +28 -21
- dagster_cloud/pex/grpc/server/server.py +23 -14
- dagster_cloud/pex/grpc/types.py +5 -5
- dagster_cloud/py.typed +0 -0
- dagster_cloud/secrets/__init__.py +1 -1
- dagster_cloud/secrets/loader.py +3 -3
- dagster_cloud/serverless/__init__.py +1 -1
- dagster_cloud/serverless/io_manager.py +36 -53
- dagster_cloud/storage/client.py +54 -17
- dagster_cloud/storage/compute_logs/__init__.py +3 -1
- dagster_cloud/storage/compute_logs/compute_log_manager.py +22 -17
- dagster_cloud/storage/defs_state/__init__.py +3 -0
- dagster_cloud/storage/defs_state/queries.py +15 -0
- dagster_cloud/storage/defs_state/storage.py +113 -0
- dagster_cloud/storage/event_logs/__init__.py +3 -1
- dagster_cloud/storage/event_logs/queries.py +102 -4
- dagster_cloud/storage/event_logs/storage.py +266 -73
- dagster_cloud/storage/event_logs/utils.py +88 -7
- dagster_cloud/storage/runs/__init__.py +1 -1
- dagster_cloud/storage/runs/queries.py +17 -2
- dagster_cloud/storage/runs/storage.py +88 -42
- dagster_cloud/storage/schedules/__init__.py +1 -1
- dagster_cloud/storage/schedules/storage.py +6 -8
- dagster_cloud/storage/tags.py +66 -1
- dagster_cloud/util/__init__.py +10 -12
- dagster_cloud/util/errors.py +49 -64
- dagster_cloud/version.py +1 -1
- dagster_cloud/workspace/config_schema/__init__.py +55 -13
- dagster_cloud/workspace/docker/__init__.py +76 -25
- dagster_cloud/workspace/docker/utils.py +1 -1
- dagster_cloud/workspace/ecs/__init__.py +1 -1
- dagster_cloud/workspace/ecs/client.py +51 -33
- dagster_cloud/workspace/ecs/launcher.py +76 -22
- dagster_cloud/workspace/ecs/run_launcher.py +3 -3
- dagster_cloud/workspace/ecs/utils.py +14 -5
- dagster_cloud/workspace/kubernetes/__init__.py +1 -1
- dagster_cloud/workspace/kubernetes/launcher.py +61 -29
- dagster_cloud/workspace/kubernetes/utils.py +34 -22
- dagster_cloud/workspace/user_code_launcher/__init__.py +5 -3
- dagster_cloud/workspace/user_code_launcher/process.py +16 -14
- dagster_cloud/workspace/user_code_launcher/user_code_launcher.py +552 -172
- dagster_cloud/workspace/user_code_launcher/utils.py +105 -1
- {dagster_cloud-1.8.2.dist-info → dagster_cloud-1.12.6.dist-info}/METADATA +48 -42
- dagster_cloud-1.12.6.dist-info/RECORD +134 -0
- {dagster_cloud-1.8.2.dist-info → dagster_cloud-1.12.6.dist-info}/WHEEL +1 -1
- dagster_cloud-1.8.2.dist-info/RECORD +0 -100
- {dagster_cloud-1.8.2.dist-info → dagster_cloud-1.12.6.dist-info}/top_level.txt +0 -0
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
from collections import defaultdict
|
|
3
|
+
from collections.abc import Collection, Mapping
|
|
3
4
|
from contextlib import contextmanager
|
|
4
5
|
from pathlib import Path
|
|
5
|
-
from typing import Any,
|
|
6
|
+
from typing import Any, NamedTuple, Optional
|
|
6
7
|
|
|
7
8
|
import kubernetes
|
|
8
9
|
import kubernetes.client as client
|
|
@@ -21,6 +22,7 @@ from dagster._serdes import ConfigurableClass
|
|
|
21
22
|
from dagster._serdes.config_class import ConfigurableClassData
|
|
22
23
|
from dagster._utils.merger import merge_dicts
|
|
23
24
|
from dagster_cloud_cli.core.workspace import CodeLocationDeployData
|
|
25
|
+
from dagster_k8s.client import PatchedApiClient
|
|
24
26
|
from dagster_k8s.container_context import K8sContainerContext
|
|
25
27
|
from dagster_k8s.job import UserDefinedDagsterK8sConfig
|
|
26
28
|
from dagster_k8s.models import k8s_snake_case_dict
|
|
@@ -31,17 +33,7 @@ from dagster_cloud.api.dagster_cloud_api import UserCodeDeploymentType
|
|
|
31
33
|
from dagster_cloud.constants import RESERVED_ENV_VAR_NAMES
|
|
32
34
|
from dagster_cloud.execution.cloud_run_launcher.k8s import CloudK8sRunLauncher
|
|
33
35
|
from dagster_cloud.execution.monitoring import CloudContainerResourceLimits
|
|
34
|
-
|
|
35
|
-
from ..user_code_launcher import (
|
|
36
|
-
DEFAULT_SERVER_PROCESS_STARTUP_TIMEOUT,
|
|
37
|
-
SHARED_USER_CODE_LAUNCHER_CONFIG,
|
|
38
|
-
DagsterCloudGrpcServer,
|
|
39
|
-
DagsterCloudUserCodeLauncher,
|
|
40
|
-
ServerEndpoint,
|
|
41
|
-
UserCodeLauncherEntry,
|
|
42
|
-
)
|
|
43
|
-
from ..user_code_launcher.utils import deterministic_label_for_location
|
|
44
|
-
from .utils import (
|
|
36
|
+
from dagster_cloud.workspace.kubernetes.utils import (
|
|
45
37
|
SERVICE_PORT,
|
|
46
38
|
construct_code_location_deployment,
|
|
47
39
|
construct_code_location_service,
|
|
@@ -49,11 +41,20 @@ from .utils import (
|
|
|
49
41
|
unique_k8s_resource_name,
|
|
50
42
|
wait_for_deployment_complete,
|
|
51
43
|
)
|
|
44
|
+
from dagster_cloud.workspace.user_code_launcher import (
|
|
45
|
+
DEFAULT_SERVER_PROCESS_STARTUP_TIMEOUT,
|
|
46
|
+
SHARED_USER_CODE_LAUNCHER_CONFIG,
|
|
47
|
+
DagsterCloudGrpcServer,
|
|
48
|
+
DagsterCloudUserCodeLauncher,
|
|
49
|
+
ServerEndpoint,
|
|
50
|
+
UserCodeLauncherEntry,
|
|
51
|
+
)
|
|
52
|
+
from dagster_cloud.workspace.user_code_launcher.utils import deterministic_label_for_location
|
|
52
53
|
|
|
53
54
|
DEFAULT_DEPLOYMENT_STARTUP_TIMEOUT = 300
|
|
54
55
|
DEFAULT_IMAGE_PULL_GRACE_PERIOD = 30
|
|
55
56
|
|
|
56
|
-
from
|
|
57
|
+
from dagster_cloud.workspace.config_schema.kubernetes import SHARED_K8S_CONFIG
|
|
57
58
|
|
|
58
59
|
|
|
59
60
|
class K8sHandle(NamedTuple):
|
|
@@ -94,6 +95,7 @@ class K8sUserCodeLauncher(DagsterCloudUserCodeLauncher[K8sHandle], ConfigurableC
|
|
|
94
95
|
security_context=None,
|
|
95
96
|
only_allow_user_defined_k8s_config_fields=None,
|
|
96
97
|
only_allow_user_defined_env_vars=None,
|
|
98
|
+
fail_pod_on_run_failure=None,
|
|
97
99
|
**kwargs,
|
|
98
100
|
):
|
|
99
101
|
self._inst_data = inst_data
|
|
@@ -176,7 +178,7 @@ class K8sUserCodeLauncher(DagsterCloudUserCodeLauncher[K8sHandle], ConfigurableC
|
|
|
176
178
|
self._only_allow_user_defined_k8s_config_fields = only_allow_user_defined_k8s_config_fields
|
|
177
179
|
self._only_allow_user_defined_env_vars = only_allow_user_defined_env_vars
|
|
178
180
|
|
|
179
|
-
super(
|
|
181
|
+
super().__init__(**kwargs)
|
|
180
182
|
|
|
181
183
|
self._launcher = CloudK8sRunLauncher(
|
|
182
184
|
dagster_home=self._dagster_home,
|
|
@@ -189,22 +191,32 @@ class K8sUserCodeLauncher(DagsterCloudUserCodeLauncher[K8sHandle], ConfigurableC
|
|
|
189
191
|
env_config_maps=self._env_config_maps,
|
|
190
192
|
env_secrets=self._env_secrets,
|
|
191
193
|
env_vars=self._env_vars,
|
|
192
|
-
job_namespace=self._namespace,
|
|
194
|
+
job_namespace=self._namespace, # pyright: ignore[reportArgumentType]
|
|
193
195
|
volume_mounts=self._volume_mounts,
|
|
194
196
|
volumes=self._volumes,
|
|
195
197
|
labels=self._labels,
|
|
196
198
|
resources=self._resources,
|
|
197
199
|
scheduler_name=self._scheduler_name,
|
|
198
200
|
run_k8s_config=self._run_k8s_config,
|
|
201
|
+
fail_pod_on_run_failure=fail_pod_on_run_failure,
|
|
199
202
|
kubeconfig_file=kubeconfig_file,
|
|
200
203
|
load_incluster_config=not kubeconfig_file,
|
|
201
204
|
security_context=self._security_context,
|
|
202
|
-
only_allow_user_defined_k8s_config_fields
|
|
205
|
+
# leave out the code server specific fields from only_allow_user_defined_k8s_config_fields
|
|
206
|
+
only_allow_user_defined_k8s_config_fields=(
|
|
207
|
+
{
|
|
208
|
+
key: val
|
|
209
|
+
for key, val in only_allow_user_defined_k8s_config_fields.items()
|
|
210
|
+
if key not in {"service_metadata", "deployment_metadata"}
|
|
211
|
+
}
|
|
212
|
+
if only_allow_user_defined_k8s_config_fields
|
|
213
|
+
else only_allow_user_defined_k8s_config_fields
|
|
214
|
+
),
|
|
203
215
|
only_allow_user_defined_env_vars=self._only_allow_user_defined_env_vars,
|
|
204
216
|
)
|
|
205
217
|
|
|
206
218
|
# mutable set of observed namespaces to assist with cleanup
|
|
207
|
-
self._used_namespaces:
|
|
219
|
+
self._used_namespaces: dict[tuple[str, str], set[str]] = defaultdict(set)
|
|
208
220
|
|
|
209
221
|
@property
|
|
210
222
|
def requires_images(self):
|
|
@@ -272,12 +284,22 @@ class K8sUserCodeLauncher(DagsterCloudUserCodeLauncher[K8sHandle], ConfigurableC
|
|
|
272
284
|
is_required=False,
|
|
273
285
|
description="Raw Kubernetes configuration for launched runs.",
|
|
274
286
|
),
|
|
287
|
+
"fail_pod_on_run_failure": Field(
|
|
288
|
+
bool,
|
|
289
|
+
is_required=False,
|
|
290
|
+
description=(
|
|
291
|
+
"Whether the launched Kubernetes Jobs and Pods should fail if the Dagster"
|
|
292
|
+
" run fails"
|
|
293
|
+
),
|
|
294
|
+
),
|
|
275
295
|
"server_k8s_config": Field(
|
|
276
296
|
Shape(
|
|
277
297
|
{
|
|
278
298
|
"container_config": Permissive(),
|
|
279
299
|
"pod_spec_config": Permissive(),
|
|
280
300
|
"pod_template_spec_metadata": Permissive(),
|
|
301
|
+
"deployment_metadata": Permissive(),
|
|
302
|
+
"service_metadata": Permissive(),
|
|
281
303
|
}
|
|
282
304
|
),
|
|
283
305
|
is_required=False,
|
|
@@ -301,6 +323,12 @@ class K8sUserCodeLauncher(DagsterCloudUserCodeLauncher[K8sHandle], ConfigurableC
|
|
|
301
323
|
"job_spec_config": Field(
|
|
302
324
|
Map(key_type=str, inner_type=bool), is_required=False
|
|
303
325
|
),
|
|
326
|
+
"deployment_metadata": Field(
|
|
327
|
+
Map(key_type=str, inner_type=bool), is_required=False
|
|
328
|
+
),
|
|
329
|
+
"service_metadata": Field(
|
|
330
|
+
Map(key_type=str, inner_type=bool), is_required=False
|
|
331
|
+
),
|
|
304
332
|
"namespace": Field(bool, is_required=False),
|
|
305
333
|
}
|
|
306
334
|
),
|
|
@@ -341,7 +369,11 @@ class K8sUserCodeLauncher(DagsterCloudUserCodeLauncher[K8sHandle], ConfigurableC
|
|
|
341
369
|
)
|
|
342
370
|
|
|
343
371
|
def _get_core_api_client(self):
|
|
344
|
-
return
|
|
372
|
+
return (
|
|
373
|
+
self._k8s_core_api_client
|
|
374
|
+
if self._k8s_core_api_client
|
|
375
|
+
else client.CoreV1Api(api_client=PatchedApiClient())
|
|
376
|
+
)
|
|
345
377
|
|
|
346
378
|
@contextmanager
|
|
347
379
|
def _get_apps_api_instance(self):
|
|
@@ -349,13 +381,13 @@ class K8sUserCodeLauncher(DagsterCloudUserCodeLauncher[K8sHandle], ConfigurableC
|
|
|
349
381
|
yield self._k8s_apps_api_client
|
|
350
382
|
return
|
|
351
383
|
|
|
352
|
-
with
|
|
384
|
+
with PatchedApiClient() as api_client:
|
|
353
385
|
yield client.AppsV1Api(api_client)
|
|
354
386
|
|
|
355
387
|
def _resolve_container_context(self, metadata: CodeLocationDeployData) -> K8sContainerContext:
|
|
356
388
|
user_defined_container_context = K8sContainerContext.create_from_config(
|
|
357
389
|
metadata.container_context
|
|
358
|
-
).
|
|
390
|
+
).validate_user_k8s_config_for_code_server(
|
|
359
391
|
self._only_allow_user_defined_k8s_config_fields, self._only_allow_user_defined_env_vars
|
|
360
392
|
)
|
|
361
393
|
return K8sContainerContext(
|
|
@@ -423,7 +455,7 @@ class K8sUserCodeLauncher(DagsterCloudUserCodeLauncher[K8sHandle], ConfigurableC
|
|
|
423
455
|
try:
|
|
424
456
|
with self._get_apps_api_instance() as api_instance:
|
|
425
457
|
deployment_reponse = api_instance.create_namespaced_deployment(
|
|
426
|
-
container_context.namespace,
|
|
458
|
+
namespace=container_context.namespace,
|
|
427
459
|
body=construct_code_location_deployment(
|
|
428
460
|
self._instance,
|
|
429
461
|
deployment_name,
|
|
@@ -440,7 +472,7 @@ class K8sUserCodeLauncher(DagsterCloudUserCodeLauncher[K8sHandle], ConfigurableC
|
|
|
440
472
|
)
|
|
441
473
|
except ApiException as e:
|
|
442
474
|
self._logger.error(
|
|
443
|
-
"Exception when calling AppsV1Api->create_namespaced_deployment:
|
|
475
|
+
f"Exception when calling AppsV1Api->create_namespaced_deployment: {e}\n"
|
|
444
476
|
)
|
|
445
477
|
raise e
|
|
446
478
|
|
|
@@ -465,7 +497,7 @@ class K8sUserCodeLauncher(DagsterCloudUserCodeLauncher[K8sHandle], ConfigurableC
|
|
|
465
497
|
)
|
|
466
498
|
except ApiException as e:
|
|
467
499
|
self._logger.error(
|
|
468
|
-
"Exception when calling AppsV1Api->create_namespaced_service:
|
|
500
|
+
f"Exception when calling AppsV1Api->create_namespaced_service: {e}\n"
|
|
469
501
|
)
|
|
470
502
|
raise e
|
|
471
503
|
|
|
@@ -570,7 +602,7 @@ class K8sUserCodeLauncher(DagsterCloudUserCodeLauncher[K8sHandle], ConfigurableC
|
|
|
570
602
|
for deployment in deployments:
|
|
571
603
|
handles.append(
|
|
572
604
|
K8sHandle(
|
|
573
|
-
namespace=namespace,
|
|
605
|
+
namespace=namespace, # pyright: ignore[reportArgumentType]
|
|
574
606
|
name=deployment.metadata.name,
|
|
575
607
|
labels=deployment.metadata.labels,
|
|
576
608
|
creation_timestamp=deployment.metadata.creation_timestamp.timestamp()
|
|
@@ -581,14 +613,14 @@ class K8sUserCodeLauncher(DagsterCloudUserCodeLauncher[K8sHandle], ConfigurableC
|
|
|
581
613
|
|
|
582
614
|
return handles
|
|
583
615
|
|
|
584
|
-
def _list_server_handles(self) ->
|
|
585
|
-
namespaces:
|
|
616
|
+
def _list_server_handles(self) -> list[K8sHandle]:
|
|
617
|
+
namespaces: set[str] = set()
|
|
586
618
|
if self._namespace:
|
|
587
619
|
namespaces.add(self._namespace)
|
|
588
620
|
for namespace_items in self._used_namespaces.values():
|
|
589
621
|
for namespace in namespace_items:
|
|
590
622
|
namespaces.add(namespace)
|
|
591
|
-
handles:
|
|
623
|
+
handles: list[K8sHandle] = []
|
|
592
624
|
with self._get_apps_api_instance() as api_instance:
|
|
593
625
|
for namespace in namespaces:
|
|
594
626
|
deployments = api_instance.list_namespaced_deployment(
|
|
@@ -623,7 +655,7 @@ class K8sUserCodeLauncher(DagsterCloudUserCodeLauncher[K8sHandle], ConfigurableC
|
|
|
623
655
|
server_handle.name, server_handle.namespace
|
|
624
656
|
)
|
|
625
657
|
except ApiException as e:
|
|
626
|
-
if e.
|
|
658
|
+
if e.status == 404:
|
|
627
659
|
self._logger.exception(
|
|
628
660
|
f"Tried to delete service {server_handle.name} but it was not found"
|
|
629
661
|
)
|
|
@@ -636,7 +668,7 @@ class K8sUserCodeLauncher(DagsterCloudUserCodeLauncher[K8sHandle], ConfigurableC
|
|
|
636
668
|
server_handle.name, server_handle.namespace
|
|
637
669
|
)
|
|
638
670
|
except ApiException as e:
|
|
639
|
-
if e.
|
|
671
|
+
if e.status == 404:
|
|
640
672
|
self._logger.exception(
|
|
641
673
|
f"Tried to delete deployment {server_handle.name} but it was not found"
|
|
642
674
|
)
|
|
@@ -2,7 +2,8 @@ import asyncio
|
|
|
2
2
|
import copy
|
|
3
3
|
import re
|
|
4
4
|
import time
|
|
5
|
-
from
|
|
5
|
+
from collections.abc import Mapping
|
|
6
|
+
from typing import Optional
|
|
6
7
|
|
|
7
8
|
import kubernetes
|
|
8
9
|
from dagster_k8s.client import DagsterKubernetesClient
|
|
@@ -10,9 +11,9 @@ from dagster_k8s.models import k8s_model_from_dict
|
|
|
10
11
|
from kubernetes import client
|
|
11
12
|
|
|
12
13
|
from dagster_cloud.instance import DagsterCloudAgentInstance
|
|
13
|
-
|
|
14
|
-
from ..user_code_launcher.utils import (
|
|
14
|
+
from dagster_cloud.workspace.user_code_launcher.utils import (
|
|
15
15
|
deterministic_label_for_location,
|
|
16
|
+
get_grpc_server_env,
|
|
16
17
|
get_human_readable_label,
|
|
17
18
|
unique_resource_name,
|
|
18
19
|
)
|
|
@@ -84,22 +85,30 @@ def construct_code_location_service(
|
|
|
84
85
|
instance,
|
|
85
86
|
server_timestamp: float,
|
|
86
87
|
):
|
|
87
|
-
|
|
88
|
+
user_defined_k8s_config = container_context.server_k8s_config
|
|
89
|
+
user_defined_service_metadata = copy.deepcopy(dict(user_defined_k8s_config.service_metadata))
|
|
90
|
+
user_defined_service_labels = user_defined_service_metadata.pop("labels", {})
|
|
88
91
|
|
|
89
|
-
return
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
92
|
+
return k8s_model_from_dict(
|
|
93
|
+
client.V1Service,
|
|
94
|
+
{
|
|
95
|
+
"api_version": "v1",
|
|
96
|
+
"kind": "Service",
|
|
97
|
+
"metadata": {
|
|
98
|
+
**user_defined_service_metadata,
|
|
99
|
+
"name": service_name,
|
|
100
|
+
"labels": {
|
|
101
|
+
**user_defined_service_labels,
|
|
102
|
+
**_get_dagster_k8s_labels(
|
|
103
|
+
deployment_name, location_name, instance, server_timestamp
|
|
104
|
+
),
|
|
105
|
+
},
|
|
97
106
|
},
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
107
|
+
"spec": {
|
|
108
|
+
"selector": {"user-deployment": service_name},
|
|
109
|
+
"ports": [{"name": "grpc", "protocol": "TCP", "port": SERVICE_PORT}],
|
|
110
|
+
},
|
|
111
|
+
},
|
|
103
112
|
)
|
|
104
113
|
|
|
105
114
|
|
|
@@ -113,12 +122,15 @@ def construct_code_location_deployment(
|
|
|
113
122
|
args,
|
|
114
123
|
server_timestamp: float,
|
|
115
124
|
):
|
|
116
|
-
env =
|
|
117
|
-
SERVICE_PORT, location_name, instance.ref_for_deployment(deployment_name)
|
|
125
|
+
env = get_grpc_server_env(
|
|
126
|
+
metadata, SERVICE_PORT, location_name, instance.ref_for_deployment(deployment_name)
|
|
118
127
|
)
|
|
119
128
|
|
|
120
129
|
user_defined_config = container_context.server_k8s_config
|
|
121
130
|
|
|
131
|
+
user_defined_deployment_metadata = copy.deepcopy(dict(user_defined_config.deployment_metadata))
|
|
132
|
+
user_defined_deployment_labels = user_defined_deployment_metadata.pop("labels", {})
|
|
133
|
+
|
|
122
134
|
container_config = copy.deepcopy(user_defined_config.container_config)
|
|
123
135
|
|
|
124
136
|
user_defined_env_vars = container_config.pop("env", [])
|
|
@@ -148,9 +160,10 @@ def construct_code_location_deployment(
|
|
|
148
160
|
|
|
149
161
|
deployment_dict = {
|
|
150
162
|
"metadata": {
|
|
163
|
+
**user_defined_deployment_metadata,
|
|
151
164
|
"name": k8s_deployment_name,
|
|
152
165
|
"labels": {
|
|
153
|
-
**
|
|
166
|
+
**user_defined_deployment_labels,
|
|
154
167
|
**_get_dagster_k8s_labels(
|
|
155
168
|
deployment_name, location_name, instance, server_timestamp
|
|
156
169
|
),
|
|
@@ -162,12 +175,11 @@ def construct_code_location_deployment(
|
|
|
162
175
|
"metadata": {
|
|
163
176
|
**pod_template_spec_metadata,
|
|
164
177
|
"labels": {
|
|
165
|
-
"user-deployment": k8s_deployment_name,
|
|
166
|
-
**container_context.labels,
|
|
167
178
|
**user_defined_pod_template_labels,
|
|
168
179
|
**_get_dagster_k8s_labels(
|
|
169
180
|
deployment_name, location_name, instance, server_timestamp
|
|
170
181
|
),
|
|
182
|
+
"user-deployment": k8s_deployment_name,
|
|
171
183
|
},
|
|
172
184
|
},
|
|
173
185
|
"spec": pod_spec_config,
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
from .process import
|
|
2
|
-
|
|
1
|
+
from dagster_cloud.workspace.user_code_launcher.process import (
|
|
2
|
+
ProcessUserCodeLauncher as ProcessUserCodeLauncher,
|
|
3
|
+
)
|
|
4
|
+
from dagster_cloud.workspace.user_code_launcher.user_code_launcher import (
|
|
3
5
|
DEFAULT_SERVER_PROCESS_STARTUP_TIMEOUT as DEFAULT_SERVER_PROCESS_STARTUP_TIMEOUT,
|
|
4
6
|
DEFAULT_SERVER_TTL_SECONDS as DEFAULT_SERVER_TTL_SECONDS,
|
|
5
7
|
SHARED_USER_CODE_LAUNCHER_CONFIG as SHARED_USER_CODE_LAUNCHER_CONFIG,
|
|
@@ -8,7 +10,7 @@ from .user_code_launcher import (
|
|
|
8
10
|
ServerEndpoint as ServerEndpoint,
|
|
9
11
|
UserCodeLauncherEntry as UserCodeLauncherEntry,
|
|
10
12
|
)
|
|
11
|
-
from .utils import (
|
|
13
|
+
from dagster_cloud.workspace.user_code_launcher.utils import (
|
|
12
14
|
deterministic_label_for_location as deterministic_label_for_location,
|
|
13
15
|
get_human_readable_label as get_human_readable_label,
|
|
14
16
|
unique_resource_name as unique_resource_name,
|
|
@@ -4,9 +4,9 @@ import subprocess
|
|
|
4
4
|
import sys
|
|
5
5
|
import threading
|
|
6
6
|
from collections import defaultdict
|
|
7
|
-
from
|
|
7
|
+
from collections.abc import Collection, Mapping
|
|
8
|
+
from typing import Any, NamedTuple, Optional, Union
|
|
8
9
|
|
|
9
|
-
import dagster._seven as seven
|
|
10
10
|
from dagster import (
|
|
11
11
|
BoolSource,
|
|
12
12
|
Field,
|
|
@@ -16,17 +16,17 @@ from dagster import (
|
|
|
16
16
|
from dagster._core.errors import DagsterUserCodeUnreachableError
|
|
17
17
|
from dagster._grpc.client import DagsterGrpcClient, client_heartbeat_thread
|
|
18
18
|
from dagster._serdes import ConfigurableClass, ConfigurableClassData
|
|
19
|
-
from dagster._serdes.ipc import open_ipc_subprocess
|
|
20
19
|
from dagster._utils import find_free_port, safe_tempfile_path_unmanaged
|
|
21
20
|
from dagster._utils.merger import merge_dicts
|
|
21
|
+
from dagster_shared import seven
|
|
22
|
+
from dagster_shared.ipc import open_ipc_subprocess
|
|
22
23
|
from typing_extensions import Self
|
|
23
24
|
|
|
24
25
|
from dagster_cloud.api.dagster_cloud_api import UserCodeDeploymentType
|
|
25
26
|
from dagster_cloud.execution.cloud_run_launcher.process import CloudProcessRunLauncher
|
|
26
27
|
from dagster_cloud.execution.monitoring import CloudContainerResourceLimits
|
|
27
28
|
from dagster_cloud.pex.grpc import MultiPexGrpcClient
|
|
28
|
-
|
|
29
|
-
from .user_code_launcher import (
|
|
29
|
+
from dagster_cloud.workspace.user_code_launcher.user_code_launcher import (
|
|
30
30
|
DEFAULT_SERVER_PROCESS_STARTUP_TIMEOUT,
|
|
31
31
|
SHARED_USER_CODE_LAUNCHER_CONFIG,
|
|
32
32
|
DagsterCloudGrpcServer,
|
|
@@ -34,6 +34,7 @@ from .user_code_launcher import (
|
|
|
34
34
|
ServerEndpoint,
|
|
35
35
|
UserCodeLauncherEntry,
|
|
36
36
|
)
|
|
37
|
+
from dagster_cloud.workspace.user_code_launcher.utils import get_grpc_server_env
|
|
37
38
|
|
|
38
39
|
CLEANUP_ZOMBIE_PROCESSES_INTERVAL = 5
|
|
39
40
|
|
|
@@ -56,7 +57,7 @@ class ProcessUserCodeEntry(
|
|
|
56
57
|
heartbeat_shutdown_event: threading.Event,
|
|
57
58
|
heartbeat_thread: threading.Thread,
|
|
58
59
|
):
|
|
59
|
-
return super(
|
|
60
|
+
return super().__new__(
|
|
60
61
|
cls,
|
|
61
62
|
check.inst_param(grpc_server_process, "grpc_server_process", subprocess.Popen),
|
|
62
63
|
check.inst_param(grpc_client, "grpc_client", DagsterGrpcClient),
|
|
@@ -79,7 +80,7 @@ class MultipexUserCodeEntry(
|
|
|
79
80
|
grpc_server_process: subprocess.Popen,
|
|
80
81
|
grpc_client: MultiPexGrpcClient,
|
|
81
82
|
):
|
|
82
|
-
return super(
|
|
83
|
+
return super().__new__(
|
|
83
84
|
cls,
|
|
84
85
|
check.inst_param(grpc_server_process, "grpc_server_process", subprocess.Popen),
|
|
85
86
|
check.inst_param(grpc_client, "grpc_client", MultiPexGrpcClient),
|
|
@@ -98,14 +99,14 @@ class ProcessUserCodeLauncher(DagsterCloudUserCodeLauncher, ConfigurableClass):
|
|
|
98
99
|
|
|
99
100
|
# map from pid to server being spun up
|
|
100
101
|
# (including old servers in the process of being shut down)
|
|
101
|
-
self._process_entries:
|
|
102
|
+
self._process_entries: dict[int, Union[ProcessUserCodeEntry, MultipexUserCodeEntry]] = {}
|
|
102
103
|
|
|
103
104
|
# map from locationname to the pid(s) for that location-metadata combination.
|
|
104
105
|
# Generally there should be only one pid per location unless an exception was raised partway
|
|
105
106
|
# through an update
|
|
106
|
-
self._active_pids:
|
|
107
|
+
self._active_pids: dict[tuple[str, str], set[int]] = defaultdict(set)
|
|
107
108
|
|
|
108
|
-
self._active_multipex_pids:
|
|
109
|
+
self._active_multipex_pids: dict[tuple[str, str], set[int]] = defaultdict(set)
|
|
109
110
|
|
|
110
111
|
self._heartbeat_ttl = 60
|
|
111
112
|
self._wait_for_processes = wait_for_processes
|
|
@@ -115,7 +116,7 @@ class ProcessUserCodeLauncher(DagsterCloudUserCodeLauncher, ConfigurableClass):
|
|
|
115
116
|
|
|
116
117
|
self._run_launcher: Optional[CloudProcessRunLauncher] = None
|
|
117
118
|
|
|
118
|
-
super(
|
|
119
|
+
super().__init__(**kwargs)
|
|
119
120
|
|
|
120
121
|
@property
|
|
121
122
|
def requires_images(self) -> bool:
|
|
@@ -174,7 +175,7 @@ class ProcessUserCodeLauncher(DagsterCloudUserCodeLauncher, ConfigurableClass):
|
|
|
174
175
|
return self._inst_data
|
|
175
176
|
|
|
176
177
|
@classmethod
|
|
177
|
-
def config_type(cls) ->
|
|
178
|
+
def config_type(cls) -> dict:
|
|
178
179
|
return merge_dicts(
|
|
179
180
|
{
|
|
180
181
|
"server_process_startup_timeout": Field(
|
|
@@ -266,7 +267,8 @@ class ProcessUserCodeLauncher(DagsterCloudUserCodeLauncher, ConfigurableClass):
|
|
|
266
267
|
str(self._heartbeat_ttl),
|
|
267
268
|
]
|
|
268
269
|
|
|
269
|
-
additional_env =
|
|
270
|
+
additional_env = get_grpc_server_env(
|
|
271
|
+
metadata,
|
|
270
272
|
port=port,
|
|
271
273
|
location_name=location_name,
|
|
272
274
|
instance_ref=self._instance.ref_for_deployment(deployment_name),
|
|
@@ -384,7 +386,7 @@ class ProcessUserCodeLauncher(DagsterCloudUserCodeLauncher, ConfigurableClass):
|
|
|
384
386
|
|
|
385
387
|
return self._run_launcher
|
|
386
388
|
|
|
387
|
-
def _list_server_handles(self) ->
|
|
389
|
+
def _list_server_handles(self) -> list[int]:
|
|
388
390
|
return list(self._process_entries.keys())
|
|
389
391
|
|
|
390
392
|
def get_agent_id_for_server(self, handle: int) -> Optional[str]:
|