dagster-k8s 0.25.8__tar.gz → 0.25.10__tar.gz
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.
Potentially problematic release.
This version of dagster-k8s might be problematic. Click here for more details.
- {dagster-k8s-0.25.8/dagster_k8s.egg-info → dagster-k8s-0.25.10}/PKG-INFO +1 -1
- {dagster-k8s-0.25.8 → dagster-k8s-0.25.10}/dagster_k8s/client.py +6 -6
- {dagster-k8s-0.25.8 → dagster-k8s-0.25.10}/dagster_k8s/container_context.py +9 -8
- {dagster-k8s-0.25.8 → dagster-k8s-0.25.10}/dagster_k8s/executor.py +5 -4
- {dagster-k8s-0.25.8 → dagster-k8s-0.25.10}/dagster_k8s/job.py +6 -5
- {dagster-k8s-0.25.8 → dagster-k8s-0.25.10}/dagster_k8s/launcher.py +2 -1
- {dagster-k8s-0.25.8 → dagster-k8s-0.25.10}/dagster_k8s/models.py +5 -4
- {dagster-k8s-0.25.8 → dagster-k8s-0.25.10}/dagster_k8s/ops/k8s_job_op.py +22 -16
- {dagster-k8s-0.25.8 → dagster-k8s-0.25.10}/dagster_k8s/pipes.py +3 -3
- dagster-k8s-0.25.10/dagster_k8s/version.py +1 -0
- {dagster-k8s-0.25.8 → dagster-k8s-0.25.10/dagster_k8s.egg-info}/PKG-INFO +1 -1
- {dagster-k8s-0.25.8 → dagster-k8s-0.25.10}/dagster_k8s.egg-info/requires.txt +1 -1
- {dagster-k8s-0.25.8 → dagster-k8s-0.25.10}/setup.py +4 -5
- dagster-k8s-0.25.8/dagster_k8s/version.py +0 -1
- {dagster-k8s-0.25.8 → dagster-k8s-0.25.10}/LICENSE +0 -0
- {dagster-k8s-0.25.8 → dagster-k8s-0.25.10}/MANIFEST.in +0 -0
- {dagster-k8s-0.25.8 → dagster-k8s-0.25.10}/README.md +0 -0
- {dagster-k8s-0.25.8 → dagster-k8s-0.25.10}/dagster_k8s/__init__.py +0 -0
- {dagster-k8s-0.25.8 → dagster-k8s-0.25.10}/dagster_k8s/kubernetes_version.py +0 -0
- {dagster-k8s-0.25.8 → dagster-k8s-0.25.10}/dagster_k8s/ops/__init__.py +0 -0
- {dagster-k8s-0.25.8 → dagster-k8s-0.25.10}/dagster_k8s/py.typed +0 -0
- {dagster-k8s-0.25.8 → dagster-k8s-0.25.10}/dagster_k8s/test.py +0 -0
- {dagster-k8s-0.25.8 → dagster-k8s-0.25.10}/dagster_k8s/utils.py +0 -0
- {dagster-k8s-0.25.8 → dagster-k8s-0.25.10}/dagster_k8s.egg-info/SOURCES.txt +0 -0
- {dagster-k8s-0.25.8 → dagster-k8s-0.25.10}/dagster_k8s.egg-info/dependency_links.txt +0 -0
- {dagster-k8s-0.25.8 → dagster-k8s-0.25.10}/dagster_k8s.egg-info/not-zip-safe +0 -0
- {dagster-k8s-0.25.8 → dagster-k8s-0.25.10}/dagster_k8s.egg-info/top_level.txt +0 -0
- {dagster-k8s-0.25.8 → dagster-k8s-0.25.10}/setup.cfg +0 -0
|
@@ -2,7 +2,7 @@ import logging
|
|
|
2
2
|
import sys
|
|
3
3
|
import time
|
|
4
4
|
from enum import Enum
|
|
5
|
-
from typing import Any, Callable,
|
|
5
|
+
from typing import Any, Callable, Optional, TypeVar
|
|
6
6
|
|
|
7
7
|
import kubernetes.client
|
|
8
8
|
import kubernetes.client.rest
|
|
@@ -52,7 +52,7 @@ class DagsterK8sAPIRetryLimitExceeded(Exception):
|
|
|
52
52
|
max_retries = check.int_param(kwargs.pop("max_retries"), "max_retries")
|
|
53
53
|
|
|
54
54
|
check.invariant(original_exc_info[0] is not None)
|
|
55
|
-
super(
|
|
55
|
+
super().__init__(
|
|
56
56
|
f"Retry limit of {max_retries} exceeded: " + args[0],
|
|
57
57
|
*args[1:],
|
|
58
58
|
**kwargs,
|
|
@@ -72,7 +72,7 @@ class DagsterK8sUnrecoverableAPIError(Exception):
|
|
|
72
72
|
original_exc_info = check.tuple_param(kwargs.pop("original_exc_info"), "original_exc_info")
|
|
73
73
|
|
|
74
74
|
check.invariant(original_exc_info[0] is not None)
|
|
75
|
-
super(
|
|
75
|
+
super().__init__(args[0], *args[1:], **kwargs)
|
|
76
76
|
|
|
77
77
|
self.k8s_api_exception = check.opt_inst_param(
|
|
78
78
|
k8s_api_exception, "k8s_api_exception", Exception
|
|
@@ -573,7 +573,7 @@ class DagsterKubernetesClient:
|
|
|
573
573
|
wait_timeout: float = DEFAULT_WAIT_TIMEOUT,
|
|
574
574
|
wait_time_between_attempts: float = DEFAULT_WAIT_BETWEEN_ATTEMPTS,
|
|
575
575
|
start_time: Any = None,
|
|
576
|
-
ignore_containers: Optional[
|
|
576
|
+
ignore_containers: Optional[set] = None,
|
|
577
577
|
) -> None:
|
|
578
578
|
"""Wait for a pod to launch and be running, or wait for termination (useful for job pods).
|
|
579
579
|
|
|
@@ -847,7 +847,7 @@ class DagsterKubernetesClient:
|
|
|
847
847
|
self,
|
|
848
848
|
pod_name: str,
|
|
849
849
|
namespace: str,
|
|
850
|
-
) ->
|
|
850
|
+
) -> list[Any]:
|
|
851
851
|
# https://github.com/kubernetes-client/python/blob/master/kubernetes/docs/EventsV1Event.md
|
|
852
852
|
field_selector = f"involvedObject.name={pod_name}"
|
|
853
853
|
return self.core_api.list_namespaced_event(namespace, field_selector=field_selector).items
|
|
@@ -916,7 +916,7 @@ class DagsterKubernetesClient:
|
|
|
916
916
|
) -> str:
|
|
917
917
|
if pod is None:
|
|
918
918
|
pods = self.core_api.list_namespaced_pod(
|
|
919
|
-
namespace=namespace, field_selector="metadata.name
|
|
919
|
+
namespace=namespace, field_selector=f"metadata.name={pod_name}"
|
|
920
920
|
).items
|
|
921
921
|
pod = pods[0] if pods else None
|
|
922
922
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import copy
|
|
2
2
|
import logging
|
|
3
|
-
from
|
|
3
|
+
from collections.abc import Mapping, Sequence
|
|
4
|
+
from typing import TYPE_CHECKING, Any, NamedTuple, Optional, cast
|
|
4
5
|
|
|
5
6
|
import dagster._check as check
|
|
6
7
|
import kubernetes
|
|
@@ -121,7 +122,7 @@ class K8sContainerContext(
|
|
|
121
122
|
server_k8s_config or UserDefinedDagsterK8sConfig.from_dict({}),
|
|
122
123
|
)
|
|
123
124
|
|
|
124
|
-
return super(
|
|
125
|
+
return super().__new__(
|
|
125
126
|
cls,
|
|
126
127
|
run_k8s_config=run_k8s_config,
|
|
127
128
|
server_k8s_config=server_k8s_config,
|
|
@@ -236,7 +237,7 @@ class K8sContainerContext(
|
|
|
236
237
|
return UserDefinedDagsterK8sConfig.from_dict(merged_dict)
|
|
237
238
|
|
|
238
239
|
@staticmethod
|
|
239
|
-
def _deep_merge_k8s_config(onto_dict:
|
|
240
|
+
def _deep_merge_k8s_config(onto_dict: dict[str, Any], from_dict: Mapping[str, Any]):
|
|
240
241
|
for from_key, from_value in from_dict.items():
|
|
241
242
|
if from_key not in onto_dict:
|
|
242
243
|
onto_dict[from_key] = from_value
|
|
@@ -369,8 +370,8 @@ class K8sContainerContext(
|
|
|
369
370
|
def _filter_user_defined_k8s_config_env_vars(
|
|
370
371
|
self,
|
|
371
372
|
user_defined_k8s_config: UserDefinedDagsterK8sConfig,
|
|
372
|
-
only_allow_user_defined_env_vars:
|
|
373
|
-
discarded_env_var_names:
|
|
373
|
+
only_allow_user_defined_env_vars: set[str],
|
|
374
|
+
discarded_env_var_names: set[str],
|
|
374
375
|
) -> UserDefinedDagsterK8sConfig:
|
|
375
376
|
"""Filters out any env vars from the supplied UserDefinedDagsterK8sConfig
|
|
376
377
|
that are not in the supplied set of env var names and adds the names of
|
|
@@ -399,7 +400,7 @@ class K8sContainerContext(
|
|
|
399
400
|
|
|
400
401
|
def _filter_user_defined_env_vars(
|
|
401
402
|
self,
|
|
402
|
-
only_allow_user_defined_env_vars:
|
|
403
|
+
only_allow_user_defined_env_vars: set[str],
|
|
403
404
|
) -> "K8sContainerContext":
|
|
404
405
|
discarded_env_var_names = set()
|
|
405
406
|
|
|
@@ -427,7 +428,7 @@ class K8sContainerContext(
|
|
|
427
428
|
|
|
428
429
|
def _get_used_k8s_config_fields(
|
|
429
430
|
self, user_defined_k8s_config: UserDefinedDagsterK8sConfig
|
|
430
|
-
) -> Mapping[str, Mapping[str,
|
|
431
|
+
) -> Mapping[str, Mapping[str, set[str]]]:
|
|
431
432
|
used_fields = {}
|
|
432
433
|
for key, fields in user_defined_k8s_config.to_dict().items():
|
|
433
434
|
if key == "merge_behavior":
|
|
@@ -527,7 +528,7 @@ class K8sContainerContext(
|
|
|
527
528
|
run_k8s_container_context,
|
|
528
529
|
)
|
|
529
530
|
|
|
530
|
-
processed_context_value = cast(
|
|
531
|
+
processed_context_value = cast(dict, processed_container_context.value)
|
|
531
532
|
|
|
532
533
|
return shared_container_context.merge(
|
|
533
534
|
K8sContainerContext(
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
from
|
|
1
|
+
from collections.abc import Iterator
|
|
2
|
+
from typing import Optional, cast
|
|
2
3
|
|
|
3
4
|
import kubernetes.config
|
|
4
5
|
from dagster import (
|
|
@@ -217,7 +218,7 @@ class K8sStepHandler(StepHandler):
|
|
|
217
218
|
|
|
218
219
|
def _get_step_key(self, step_handler_context: StepHandlerContext) -> str:
|
|
219
220
|
step_keys_to_execute = cast(
|
|
220
|
-
|
|
221
|
+
list[str], step_handler_context.execute_step_args.step_keys_to_execute
|
|
221
222
|
)
|
|
222
223
|
assert len(step_keys_to_execute) == 1, "Launching multiple steps is not currently supported"
|
|
223
224
|
return step_keys_to_execute[0]
|
|
@@ -258,9 +259,9 @@ class K8sStepHandler(StepHandler):
|
|
|
258
259
|
if step_handler_context.execute_step_args.known_state:
|
|
259
260
|
retry_state = step_handler_context.execute_step_args.known_state.get_retry_state()
|
|
260
261
|
if retry_state.get_attempt_count(step_key):
|
|
261
|
-
return "dagster-step-%s-%d" % (name_key, retry_state.get_attempt_count(step_key))
|
|
262
|
+
return "dagster-step-%s-%d" % (name_key, retry_state.get_attempt_count(step_key)) # noqa: UP031
|
|
262
263
|
|
|
263
|
-
return "dagster-step
|
|
264
|
+
return f"dagster-step-{name_key}"
|
|
264
265
|
|
|
265
266
|
def launch_step(self, step_handler_context: StepHandlerContext) -> Iterator[DagsterEvent]:
|
|
266
267
|
step_key = self._get_step_key(step_handler_context)
|
|
@@ -2,8 +2,9 @@ import copy
|
|
|
2
2
|
import json
|
|
3
3
|
import random
|
|
4
4
|
import string
|
|
5
|
+
from collections.abc import Mapping, Sequence
|
|
5
6
|
from enum import Enum
|
|
6
|
-
from typing import Any,
|
|
7
|
+
from typing import Any, NamedTuple, Optional
|
|
7
8
|
|
|
8
9
|
import dagster._check as check
|
|
9
10
|
import kubernetes
|
|
@@ -159,7 +160,7 @@ class UserDefinedDagsterK8sConfig(
|
|
|
159
160
|
if service_metadata:
|
|
160
161
|
service_metadata = k8s_snake_case_dict(kubernetes.client.V1ObjectMeta, service_metadata)
|
|
161
162
|
|
|
162
|
-
return super(
|
|
163
|
+
return super().__new__(
|
|
163
164
|
cls,
|
|
164
165
|
container_config=container_config,
|
|
165
166
|
pod_template_spec_metadata=pod_template_spec_metadata,
|
|
@@ -790,13 +791,13 @@ def construct_dagster_k8s_job(
|
|
|
790
791
|
|
|
791
792
|
check.invariant(
|
|
792
793
|
len(job_name) <= MAX_K8S_NAME_LEN,
|
|
793
|
-
"job_name is %d in length; Kubernetes Jobs cannot be longer than %d characters."
|
|
794
|
+
"job_name is %d in length; Kubernetes Jobs cannot be longer than %d characters." # noqa: UP031
|
|
794
795
|
% (len(job_name), MAX_K8S_NAME_LEN),
|
|
795
796
|
)
|
|
796
797
|
|
|
797
798
|
check.invariant(
|
|
798
799
|
len(pod_name) <= MAX_K8S_NAME_LEN,
|
|
799
|
-
"job_name is %d in length; Kubernetes Pods cannot be longer than %d characters."
|
|
800
|
+
"job_name is %d in length; Kubernetes Pods cannot be longer than %d characters." # noqa: UP031
|
|
800
801
|
% (len(pod_name), MAX_K8S_NAME_LEN),
|
|
801
802
|
)
|
|
802
803
|
|
|
@@ -808,7 +809,7 @@ def construct_dagster_k8s_job(
|
|
|
808
809
|
additional_labels = {k: sanitize_k8s_label(v) for k, v in (labels or {}).items()}
|
|
809
810
|
dagster_labels = merge_dicts(k8s_common_labels, additional_labels)
|
|
810
811
|
|
|
811
|
-
env:
|
|
812
|
+
env: list[Mapping[str, Any]] = []
|
|
812
813
|
if env_vars:
|
|
813
814
|
env.extend(env_vars)
|
|
814
815
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import datetime
|
|
2
2
|
import re
|
|
3
|
-
from
|
|
3
|
+
from collections.abc import Mapping
|
|
4
|
+
from typing import Any, TypeVar
|
|
4
5
|
|
|
5
6
|
import dagster._check as check
|
|
6
7
|
import kubernetes
|
|
@@ -21,7 +22,7 @@ T_KubernetesModel = TypeVar("T_KubernetesModel")
|
|
|
21
22
|
shared_k8s_model_configuration = Configuration()
|
|
22
23
|
|
|
23
24
|
|
|
24
|
-
def _get_k8s_class(classname: str) ->
|
|
25
|
+
def _get_k8s_class(classname: str) -> type[Any]:
|
|
25
26
|
if classname in ApiClient.NATIVE_TYPES_MAPPING:
|
|
26
27
|
return ApiClient.NATIVE_TYPES_MAPPING[classname]
|
|
27
28
|
else:
|
|
@@ -133,7 +134,7 @@ def k8s_snake_case_keys(model_class, model_dict: Mapping[str, Any]) -> Mapping[s
|
|
|
133
134
|
return snake_case_dict
|
|
134
135
|
|
|
135
136
|
|
|
136
|
-
def k8s_snake_case_dict(model_class:
|
|
137
|
+
def k8s_snake_case_dict(model_class: type[Any], model_dict: Mapping[str, Any]) -> Mapping[str, Any]:
|
|
137
138
|
snake_case_dict = k8s_snake_case_keys(model_class, model_dict)
|
|
138
139
|
|
|
139
140
|
final_dict = {}
|
|
@@ -148,7 +149,7 @@ def k8s_snake_case_dict(model_class: Type[Any], model_dict: Mapping[str, Any]) -
|
|
|
148
149
|
# that the keys and values match the expected format. Requires k8s attribute names to be in
|
|
149
150
|
# snake_case.
|
|
150
151
|
def k8s_model_from_dict(
|
|
151
|
-
model_class:
|
|
152
|
+
model_class: type[T_KubernetesModel], model_dict: Mapping[str, Any]
|
|
152
153
|
) -> T_KubernetesModel:
|
|
153
154
|
check.mapping_param(model_dict, "model_dict")
|
|
154
155
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import time
|
|
3
|
-
from typing import Any,
|
|
3
|
+
from typing import Any, Optional
|
|
4
4
|
|
|
5
5
|
import kubernetes.config
|
|
6
6
|
import kubernetes.watch
|
|
@@ -139,28 +139,28 @@ K8S_JOB_OP_CONFIG = merge_dicts(
|
|
|
139
139
|
def execute_k8s_job(
|
|
140
140
|
context: OpExecutionContext,
|
|
141
141
|
image: str,
|
|
142
|
-
command: Optional[
|
|
143
|
-
args: Optional[
|
|
142
|
+
command: Optional[list[str]] = None,
|
|
143
|
+
args: Optional[list[str]] = None,
|
|
144
144
|
namespace: Optional[str] = None,
|
|
145
145
|
image_pull_policy: Optional[str] = None,
|
|
146
|
-
image_pull_secrets: Optional[
|
|
146
|
+
image_pull_secrets: Optional[list[dict[str, str]]] = None,
|
|
147
147
|
service_account_name: Optional[str] = None,
|
|
148
|
-
env_config_maps: Optional[
|
|
149
|
-
env_secrets: Optional[
|
|
150
|
-
env_vars: Optional[
|
|
151
|
-
volume_mounts: Optional[
|
|
152
|
-
volumes: Optional[
|
|
153
|
-
labels: Optional[
|
|
154
|
-
resources: Optional[
|
|
148
|
+
env_config_maps: Optional[list[str]] = None,
|
|
149
|
+
env_secrets: Optional[list[str]] = None,
|
|
150
|
+
env_vars: Optional[list[str]] = None,
|
|
151
|
+
volume_mounts: Optional[list[dict[str, Any]]] = None,
|
|
152
|
+
volumes: Optional[list[dict[str, Any]]] = None,
|
|
153
|
+
labels: Optional[dict[str, str]] = None,
|
|
154
|
+
resources: Optional[dict[str, Any]] = None,
|
|
155
155
|
scheduler_name: Optional[str] = None,
|
|
156
156
|
load_incluster_config: bool = True,
|
|
157
157
|
kubeconfig_file: Optional[str] = None,
|
|
158
158
|
timeout: Optional[int] = None,
|
|
159
|
-
container_config: Optional[
|
|
160
|
-
pod_template_spec_metadata: Optional[
|
|
161
|
-
pod_spec_config: Optional[
|
|
162
|
-
job_metadata: Optional[
|
|
163
|
-
job_spec_config: Optional[
|
|
159
|
+
container_config: Optional[dict[str, Any]] = None,
|
|
160
|
+
pod_template_spec_metadata: Optional[dict[str, Any]] = None,
|
|
161
|
+
pod_spec_config: Optional[dict[str, Any]] = None,
|
|
162
|
+
job_metadata: Optional[dict[str, Any]] = None,
|
|
163
|
+
job_spec_config: Optional[dict[str, Any]] = None,
|
|
164
164
|
k8s_job_name: Optional[str] = None,
|
|
165
165
|
merge_behavior: K8sConfigMergeBehavior = K8sConfigMergeBehavior.DEEP,
|
|
166
166
|
delete_failed_k8s_jobs: Optional[bool] = True,
|
|
@@ -403,6 +403,12 @@ def execute_k8s_job(
|
|
|
403
403
|
print(log_entry) # noqa: T201
|
|
404
404
|
except StopIteration:
|
|
405
405
|
break
|
|
406
|
+
except Exception:
|
|
407
|
+
context.log.warning(
|
|
408
|
+
"Error reading pod logs. Giving up and waiting for the pod to finish",
|
|
409
|
+
exc_info=True,
|
|
410
|
+
)
|
|
411
|
+
break
|
|
406
412
|
else:
|
|
407
413
|
context.log.info("Pod logs are disabled, because restart_policy is not Never")
|
|
408
414
|
|
|
@@ -5,11 +5,11 @@ import re
|
|
|
5
5
|
import string
|
|
6
6
|
import threading
|
|
7
7
|
import time
|
|
8
|
-
from collections.abc import Callable, Generator
|
|
8
|
+
from collections.abc import Callable, Generator, Iterator, Mapping, Sequence
|
|
9
9
|
from contextlib import contextmanager
|
|
10
10
|
from datetime import datetime
|
|
11
11
|
from pathlib import Path
|
|
12
|
-
from typing import Any,
|
|
12
|
+
from typing import Any, Optional, Union
|
|
13
13
|
|
|
14
14
|
import kubernetes
|
|
15
15
|
from dagster import (
|
|
@@ -370,7 +370,7 @@ class PipesK8sClient(PipesClient, TreatAsResourceParam):
|
|
|
370
370
|
env: Optional[Mapping[str, str]] = None,
|
|
371
371
|
base_pod_meta: Optional[Mapping[str, Any]] = None,
|
|
372
372
|
base_pod_spec: Optional[Mapping[str, Any]] = None,
|
|
373
|
-
ignore_containers: Optional[
|
|
373
|
+
ignore_containers: Optional[set] = None,
|
|
374
374
|
enable_multi_container_logs: bool = False,
|
|
375
375
|
) -> PipesClientCompletedInvocation:
|
|
376
376
|
"""Publish a kubernetes pod and wait for it to complete, enriched with the pipes protocol.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.25.10"
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
from pathlib import Path
|
|
2
|
-
from typing import Dict, Tuple
|
|
3
2
|
|
|
4
3
|
from setuptools import find_packages, setup
|
|
5
4
|
|
|
6
5
|
|
|
7
|
-
def get_version() ->
|
|
8
|
-
version:
|
|
9
|
-
kubernetes_version:
|
|
6
|
+
def get_version() -> tuple[str, str]:
|
|
7
|
+
version: dict[str, str] = {}
|
|
8
|
+
kubernetes_version: dict[str, str] = {}
|
|
10
9
|
|
|
11
10
|
with open(Path(__file__).parent / "dagster_k8s/version.py", encoding="utf8") as fp:
|
|
12
11
|
exec(fp.read(), version)
|
|
@@ -43,7 +42,7 @@ setup(
|
|
|
43
42
|
include_package_data=True,
|
|
44
43
|
python_requires=">=3.9,<3.13",
|
|
45
44
|
install_requires=[
|
|
46
|
-
"dagster==1.9.
|
|
45
|
+
"dagster==1.9.10",
|
|
47
46
|
f"kubernetes<{KUBERNETES_VERSION_UPPER_BOUND}",
|
|
48
47
|
# exclude a google-auth release that added an overly restrictive urllib3 pin that confuses dependency resolvers
|
|
49
48
|
"google-auth!=2.23.1",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.25.8"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|