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.
Files changed (108) hide show
  1. dagster_cloud/__init__.py +3 -3
  2. dagster_cloud/agent/__init__.py +4 -4
  3. dagster_cloud/agent/cli/__init__.py +56 -17
  4. dagster_cloud/agent/dagster_cloud_agent.py +360 -172
  5. dagster_cloud/agent/instrumentation/__init__.py +0 -0
  6. dagster_cloud/agent/instrumentation/constants.py +2 -0
  7. dagster_cloud/agent/instrumentation/run_launch.py +23 -0
  8. dagster_cloud/agent/instrumentation/schedule.py +34 -0
  9. dagster_cloud/agent/instrumentation/sensor.py +34 -0
  10. dagster_cloud/anomaly_detection/__init__.py +2 -2
  11. dagster_cloud/anomaly_detection/defs.py +17 -12
  12. dagster_cloud/anomaly_detection/types.py +3 -3
  13. dagster_cloud/api/dagster_cloud_api.py +209 -293
  14. dagster_cloud/auth/constants.py +21 -5
  15. dagster_cloud/batching/__init__.py +1 -0
  16. dagster_cloud/batching/batcher.py +210 -0
  17. dagster_cloud/dagster_insights/__init__.py +12 -6
  18. dagster_cloud/dagster_insights/bigquery/bigquery_utils.py +3 -2
  19. dagster_cloud/dagster_insights/bigquery/dbt_wrapper.py +39 -12
  20. dagster_cloud/dagster_insights/bigquery/insights_bigquery_resource.py +8 -6
  21. dagster_cloud/dagster_insights/insights_utils.py +18 -8
  22. dagster_cloud/dagster_insights/metrics_utils.py +12 -12
  23. dagster_cloud/dagster_insights/snowflake/dagster_snowflake_insights.py +5 -12
  24. dagster_cloud/dagster_insights/snowflake/dbt_wrapper.py +34 -8
  25. dagster_cloud/dagster_insights/snowflake/definitions.py +38 -12
  26. dagster_cloud/dagster_insights/snowflake/insights_snowflake_resource.py +11 -23
  27. dagster_cloud/definitions/__init__.py +0 -0
  28. dagster_cloud/definitions/job_selection.py +36 -0
  29. dagster_cloud/execution/cloud_run_launcher/k8s.py +1 -1
  30. dagster_cloud/execution/cloud_run_launcher/process.py +3 -3
  31. dagster_cloud/execution/monitoring/__init__.py +27 -33
  32. dagster_cloud/execution/utils/process.py +3 -3
  33. dagster_cloud/instance/__init__.py +125 -38
  34. dagster_cloud/instrumentation/__init__.py +32 -0
  35. dagster_cloud/metadata/source_code.py +13 -8
  36. dagster_cloud/metrics/__init__.py +0 -0
  37. dagster_cloud/metrics/tracer.py +59 -0
  38. dagster_cloud/opentelemetry/__init__.py +0 -0
  39. dagster_cloud/opentelemetry/config/__init__.py +73 -0
  40. dagster_cloud/opentelemetry/config/exporter.py +81 -0
  41. dagster_cloud/opentelemetry/config/log_record_processor.py +40 -0
  42. dagster_cloud/opentelemetry/config/logging_handler.py +14 -0
  43. dagster_cloud/opentelemetry/config/meter_provider.py +9 -0
  44. dagster_cloud/opentelemetry/config/metric_reader.py +39 -0
  45. dagster_cloud/opentelemetry/controller.py +319 -0
  46. dagster_cloud/opentelemetry/enum.py +58 -0
  47. dagster_cloud/opentelemetry/factories/__init__.py +1 -0
  48. dagster_cloud/opentelemetry/factories/logs.py +113 -0
  49. dagster_cloud/opentelemetry/factories/metrics.py +121 -0
  50. dagster_cloud/opentelemetry/metrics/__init__.py +0 -0
  51. dagster_cloud/opentelemetry/metrics/meter.py +140 -0
  52. dagster_cloud/opentelemetry/observers/__init__.py +0 -0
  53. dagster_cloud/opentelemetry/observers/dagster_exception_handler.py +40 -0
  54. dagster_cloud/opentelemetry/observers/execution_observer.py +178 -0
  55. dagster_cloud/pex/grpc/__generated__/multi_pex_api_pb2.pyi +175 -0
  56. dagster_cloud/pex/grpc/__init__.py +2 -2
  57. dagster_cloud/pex/grpc/client.py +4 -4
  58. dagster_cloud/pex/grpc/compile.py +2 -2
  59. dagster_cloud/pex/grpc/server/__init__.py +2 -2
  60. dagster_cloud/pex/grpc/server/cli/__init__.py +31 -19
  61. dagster_cloud/pex/grpc/server/manager.py +60 -42
  62. dagster_cloud/pex/grpc/server/registry.py +28 -21
  63. dagster_cloud/pex/grpc/server/server.py +23 -14
  64. dagster_cloud/pex/grpc/types.py +5 -5
  65. dagster_cloud/py.typed +0 -0
  66. dagster_cloud/secrets/__init__.py +1 -1
  67. dagster_cloud/secrets/loader.py +3 -3
  68. dagster_cloud/serverless/__init__.py +1 -1
  69. dagster_cloud/serverless/io_manager.py +36 -53
  70. dagster_cloud/storage/client.py +54 -17
  71. dagster_cloud/storage/compute_logs/__init__.py +3 -1
  72. dagster_cloud/storage/compute_logs/compute_log_manager.py +22 -17
  73. dagster_cloud/storage/defs_state/__init__.py +3 -0
  74. dagster_cloud/storage/defs_state/queries.py +15 -0
  75. dagster_cloud/storage/defs_state/storage.py +113 -0
  76. dagster_cloud/storage/event_logs/__init__.py +3 -1
  77. dagster_cloud/storage/event_logs/queries.py +102 -4
  78. dagster_cloud/storage/event_logs/storage.py +266 -73
  79. dagster_cloud/storage/event_logs/utils.py +88 -7
  80. dagster_cloud/storage/runs/__init__.py +1 -1
  81. dagster_cloud/storage/runs/queries.py +17 -2
  82. dagster_cloud/storage/runs/storage.py +88 -42
  83. dagster_cloud/storage/schedules/__init__.py +1 -1
  84. dagster_cloud/storage/schedules/storage.py +6 -8
  85. dagster_cloud/storage/tags.py +66 -1
  86. dagster_cloud/util/__init__.py +10 -12
  87. dagster_cloud/util/errors.py +49 -64
  88. dagster_cloud/version.py +1 -1
  89. dagster_cloud/workspace/config_schema/__init__.py +55 -13
  90. dagster_cloud/workspace/docker/__init__.py +76 -25
  91. dagster_cloud/workspace/docker/utils.py +1 -1
  92. dagster_cloud/workspace/ecs/__init__.py +1 -1
  93. dagster_cloud/workspace/ecs/client.py +51 -33
  94. dagster_cloud/workspace/ecs/launcher.py +76 -22
  95. dagster_cloud/workspace/ecs/run_launcher.py +3 -3
  96. dagster_cloud/workspace/ecs/utils.py +14 -5
  97. dagster_cloud/workspace/kubernetes/__init__.py +1 -1
  98. dagster_cloud/workspace/kubernetes/launcher.py +61 -29
  99. dagster_cloud/workspace/kubernetes/utils.py +34 -22
  100. dagster_cloud/workspace/user_code_launcher/__init__.py +5 -3
  101. dagster_cloud/workspace/user_code_launcher/process.py +16 -14
  102. dagster_cloud/workspace/user_code_launcher/user_code_launcher.py +552 -172
  103. dagster_cloud/workspace/user_code_launcher/utils.py +105 -1
  104. {dagster_cloud-1.8.2.dist-info → dagster_cloud-1.12.6.dist-info}/METADATA +48 -42
  105. dagster_cloud-1.12.6.dist-info/RECORD +134 -0
  106. {dagster_cloud-1.8.2.dist-info → dagster_cloud-1.12.6.dist-info}/WHEEL +1 -1
  107. dagster_cloud-1.8.2.dist-info/RECORD +0 -100
  108. {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, Collection, Dict, List, Mapping, NamedTuple, Optional, Set, Tuple
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 ..config_schema.kubernetes import SHARED_K8S_CONFIG
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(K8sUserCodeLauncher, self).__init__(**kwargs)
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=self._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: Dict[Tuple[str, str], Set[str]] = defaultdict(set)
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 self._k8s_core_api_client if self._k8s_core_api_client else client.CoreV1Api()
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 client.ApiClient() as api_client:
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
- ).validate_user_k8s_config(
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: %s\n" % e
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: %s\n" % e
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) -> List[K8sHandle]:
585
- namespaces: Set[str] = set()
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: List[K8sHandle] = []
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.reason == "Not found":
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.reason == "Not found":
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 typing import Mapping, Optional
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
- labels = container_context.labels
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 client.V1Service(
90
- metadata=client.V1ObjectMeta(
91
- name=service_name,
92
- labels={
93
- **labels,
94
- **_get_dagster_k8s_labels(
95
- deployment_name, location_name, instance, server_timestamp
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
- spec=client.V1ServiceSpec(
100
- selector={"user-deployment": service_name},
101
- ports=[client.V1ServicePort(name="grpc", protocol="TCP", port=SERVICE_PORT)],
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 = metadata.get_grpc_server_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
- **container_context.labels,
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 ProcessUserCodeLauncher as ProcessUserCodeLauncher
2
- from .user_code_launcher import (
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 typing import Any, Collection, Dict, List, Mapping, NamedTuple, Optional, Set, Tuple, Union
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(ProcessUserCodeEntry, cls).__new__(
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(MultipexUserCodeEntry, cls).__new__(
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: Dict[int, Union[ProcessUserCodeEntry, MultipexUserCodeEntry]] = {}
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: Dict[Tuple[str, str], Set[int]] = defaultdict(set)
107
+ self._active_pids: dict[tuple[str, str], set[int]] = defaultdict(set)
107
108
 
108
- self._active_multipex_pids: Dict[Tuple[str, str], Set[int]] = defaultdict(set)
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(ProcessUserCodeLauncher, self).__init__(**kwargs)
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) -> Dict:
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 = metadata.get_grpc_server_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) -> List[int]:
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]: