dagster-k8s 0.26.9__py3-none-any.whl → 0.26.11__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.
Potentially problematic release.
This version of dagster-k8s might be problematic. Click here for more details.
- dagster_k8s/container_context.py +1 -1
- dagster_k8s/executor.py +4 -4
- dagster_k8s/pipes.py +90 -9
- dagster_k8s/version.py +1 -1
- {dagster_k8s-0.26.9.dist-info → dagster_k8s-0.26.11.dist-info}/METADATA +2 -2
- {dagster_k8s-0.26.9.dist-info → dagster_k8s-0.26.11.dist-info}/RECORD +9 -9
- {dagster_k8s-0.26.9.dist-info → dagster_k8s-0.26.11.dist-info}/LICENSE +0 -0
- {dagster_k8s-0.26.9.dist-info → dagster_k8s-0.26.11.dist-info}/WHEEL +0 -0
- {dagster_k8s-0.26.9.dist-info → dagster_k8s-0.26.11.dist-info}/top_level.txt +0 -0
dagster_k8s/container_context.py
CHANGED
|
@@ -528,7 +528,7 @@ class K8sContainerContext(
|
|
|
528
528
|
run_k8s_container_context,
|
|
529
529
|
)
|
|
530
530
|
|
|
531
|
-
processed_context_value = cast(dict, processed_container_context.value)
|
|
531
|
+
processed_context_value = cast("dict", processed_container_context.value)
|
|
532
532
|
|
|
533
533
|
return shared_container_context.merge(
|
|
534
534
|
K8sContainerContext(
|
dagster_k8s/executor.py
CHANGED
|
@@ -154,12 +154,12 @@ def k8s_job_executor(init_context: InitExecutorContext) -> Executor:
|
|
|
154
154
|
)
|
|
155
155
|
|
|
156
156
|
if "load_incluster_config" in exc_cfg:
|
|
157
|
-
load_incluster_config = cast(bool, exc_cfg["load_incluster_config"])
|
|
157
|
+
load_incluster_config = cast("bool", exc_cfg["load_incluster_config"])
|
|
158
158
|
else:
|
|
159
159
|
load_incluster_config = run_launcher.load_incluster_config if run_launcher else True
|
|
160
160
|
|
|
161
161
|
if "kubeconfig_file" in exc_cfg:
|
|
162
|
-
kubeconfig_file = cast(Optional[str], exc_cfg["kubeconfig_file"])
|
|
162
|
+
kubeconfig_file = cast("Optional[str]", exc_cfg["kubeconfig_file"])
|
|
163
163
|
else:
|
|
164
164
|
kubeconfig_file = run_launcher.kubeconfig_file if run_launcher else None
|
|
165
165
|
|
|
@@ -218,7 +218,7 @@ class K8sStepHandler(StepHandler):
|
|
|
218
218
|
|
|
219
219
|
def _get_step_key(self, step_handler_context: StepHandlerContext) -> str:
|
|
220
220
|
step_keys_to_execute = cast(
|
|
221
|
-
list[str], step_handler_context.execute_step_args.step_keys_to_execute
|
|
221
|
+
"list[str]", step_handler_context.execute_step_args.step_keys_to_execute
|
|
222
222
|
)
|
|
223
223
|
assert len(step_keys_to_execute) == 1, "Launching multiple steps is not currently supported"
|
|
224
224
|
return step_keys_to_execute[0]
|
|
@@ -230,7 +230,7 @@ class K8sStepHandler(StepHandler):
|
|
|
230
230
|
|
|
231
231
|
context = K8sContainerContext.create_for_run(
|
|
232
232
|
step_handler_context.dagster_run,
|
|
233
|
-
cast(K8sRunLauncher, step_handler_context.instance.run_launcher),
|
|
233
|
+
cast("K8sRunLauncher", step_handler_context.instance.run_launcher),
|
|
234
234
|
include_run_tags=False, # For now don't include job-level dagster-k8s/config tags in step pods
|
|
235
235
|
)
|
|
236
236
|
context = context.merge(self._executor_container_context)
|
dagster_k8s/pipes.py
CHANGED
|
@@ -34,6 +34,7 @@ from dagster._core.pipes.utils import (
|
|
|
34
34
|
extract_message_or_forward_to_stdout,
|
|
35
35
|
open_pipes_session,
|
|
36
36
|
)
|
|
37
|
+
from dagster._time import parse_time_string
|
|
37
38
|
from dagster_pipes import (
|
|
38
39
|
DAGSTER_PIPES_CONTEXT_ENV_VAR,
|
|
39
40
|
DAGSTER_PIPES_MESSAGES_ENV_VAR,
|
|
@@ -41,6 +42,7 @@ from dagster_pipes import (
|
|
|
41
42
|
PipesExtras,
|
|
42
43
|
encode_env_var,
|
|
43
44
|
)
|
|
45
|
+
from urllib3.exceptions import ReadTimeoutError
|
|
44
46
|
|
|
45
47
|
from dagster_k8s.client import (
|
|
46
48
|
DEFAULT_WAIT_BETWEEN_ATTEMPTS,
|
|
@@ -65,6 +67,11 @@ DEFAULT_CONTAINER_NAME = "dagster-pipes-execution"
|
|
|
65
67
|
_NAMESPACE_SECRET_PATH = Path("/var/run/secrets/kubernetes.io/serviceaccount/namespace")
|
|
66
68
|
_DEV_NULL_MESSAGE_WRITER = encode_env_var({"path": "/dev/null"})
|
|
67
69
|
|
|
70
|
+
DEFAULT_CONSUME_POD_LOGS_RETRIES = 5
|
|
71
|
+
|
|
72
|
+
# By default, timeout and reconnect to the log stream every hour.
|
|
73
|
+
DEFAULT_DAGSTER_PIPES_K8S_CONSUME_POD_LOGS_REQUEST_TIMEOUT = 3600
|
|
74
|
+
|
|
68
75
|
|
|
69
76
|
class PipesK8sPodLogsMessageReader(PipesMessageReader):
|
|
70
77
|
"""Message reader that reads messages from kubernetes pod logs."""
|
|
@@ -80,24 +87,97 @@ class PipesK8sPodLogsMessageReader(PipesMessageReader):
|
|
|
80
87
|
finally:
|
|
81
88
|
self._handler = None
|
|
82
89
|
|
|
90
|
+
def _get_consume_logs_request_timeout(self) -> Optional[int]:
|
|
91
|
+
request_timeout_env_var = os.getenv("DAGSTER_PIPES_K8S_CONSUME_POD_LOGS_REQUEST_TIMEOUT")
|
|
92
|
+
if request_timeout_env_var:
|
|
93
|
+
return int(request_timeout_env_var)
|
|
94
|
+
|
|
95
|
+
return DEFAULT_DAGSTER_PIPES_K8S_CONSUME_POD_LOGS_REQUEST_TIMEOUT
|
|
96
|
+
|
|
83
97
|
def consume_pod_logs(
|
|
84
98
|
self,
|
|
99
|
+
context: Union[OpExecutionContext, AssetExecutionContext],
|
|
85
100
|
core_api: kubernetes.client.CoreV1Api,
|
|
86
101
|
pod_name: str,
|
|
87
102
|
namespace: str,
|
|
88
103
|
):
|
|
104
|
+
last_seen_timestamp = None
|
|
105
|
+
catching_up_after_retry = False
|
|
106
|
+
|
|
107
|
+
request_timeout = self._get_consume_logs_request_timeout()
|
|
108
|
+
|
|
109
|
+
retries_remaining = int(
|
|
110
|
+
os.getenv(
|
|
111
|
+
"DAGSTER_PIPES_K8S_CONSUME_POD_LOGS_RETRIES", str(DEFAULT_CONSUME_POD_LOGS_RETRIES)
|
|
112
|
+
)
|
|
113
|
+
)
|
|
114
|
+
|
|
89
115
|
handler = check.not_none(
|
|
90
116
|
self._handler, "can only consume logs within scope of context manager"
|
|
91
117
|
)
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
118
|
+
|
|
119
|
+
while True:
|
|
120
|
+
# On retry, re-connect to the log stream for new messages since the last seen timestamp
|
|
121
|
+
# (with a buffer to ensure none are missed). The messages are deduplicated by timestamp below.
|
|
122
|
+
if last_seen_timestamp:
|
|
123
|
+
since_seconds = int(
|
|
124
|
+
max(time.time() - parse_time_string(last_seen_timestamp).timestamp(), 0)
|
|
125
|
+
+ int(os.getenv("DAGSTER_PIPES_K8S_CONSUME_POD_LOGS_BUFFER_SECONDS", "300"))
|
|
126
|
+
)
|
|
127
|
+
else:
|
|
128
|
+
since_seconds = None
|
|
129
|
+
|
|
130
|
+
try:
|
|
131
|
+
for log_item in _process_log_stream(
|
|
132
|
+
core_api.read_namespaced_pod_log(
|
|
133
|
+
pod_name,
|
|
134
|
+
namespace,
|
|
135
|
+
follow=True,
|
|
136
|
+
timestamps=True,
|
|
137
|
+
since_seconds=since_seconds,
|
|
138
|
+
_preload_content=False, # avoid JSON processing
|
|
139
|
+
_request_timeout=request_timeout,
|
|
140
|
+
)
|
|
141
|
+
):
|
|
142
|
+
timestamp = log_item.timestamp
|
|
143
|
+
message = log_item.log
|
|
144
|
+
|
|
145
|
+
if (
|
|
146
|
+
catching_up_after_retry
|
|
147
|
+
and timestamp
|
|
148
|
+
and last_seen_timestamp
|
|
149
|
+
and timestamp <= last_seen_timestamp
|
|
150
|
+
):
|
|
151
|
+
# This is a log that we've already seen before from before we retried
|
|
152
|
+
continue
|
|
153
|
+
else:
|
|
154
|
+
catching_up_after_retry = False
|
|
155
|
+
extract_message_or_forward_to_stdout(handler, message)
|
|
156
|
+
if timestamp:
|
|
157
|
+
last_seen_timestamp = (
|
|
158
|
+
max(last_seen_timestamp, timestamp)
|
|
159
|
+
if last_seen_timestamp
|
|
160
|
+
else timestamp
|
|
161
|
+
)
|
|
162
|
+
return
|
|
163
|
+
except Exception as e:
|
|
164
|
+
# Expected read timeouts can occur for long-running pods if a request timeout is set
|
|
165
|
+
expected_read_timeout = isinstance(e, ReadTimeoutError) and request_timeout
|
|
166
|
+
|
|
167
|
+
if expected_read_timeout:
|
|
168
|
+
# Expected so doesn't need to be logged to event log, but write to stdout
|
|
169
|
+
# for visibility
|
|
170
|
+
logging.getLogger("dagster").info("Re-connecting to pod logs stream")
|
|
171
|
+
else:
|
|
172
|
+
if retries_remaining == 0:
|
|
173
|
+
raise
|
|
174
|
+
retries_remaining -= 1
|
|
175
|
+
context.log.warning(
|
|
176
|
+
f"Error consuming pod logs. {retries_remaining} retr{('y' if retries_remaining == 1 else 'ies')} remaining",
|
|
177
|
+
exc_info=True,
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
catching_up_after_retry = True
|
|
101
181
|
|
|
102
182
|
@contextmanager
|
|
103
183
|
def async_consume_pod_logs(
|
|
@@ -504,6 +584,7 @@ class PipesK8sClient(PipesClient, TreatAsResourceParam):
|
|
|
504
584
|
return
|
|
505
585
|
else:
|
|
506
586
|
self.message_reader.consume_pod_logs(
|
|
587
|
+
context=context,
|
|
507
588
|
core_api=client.core_api,
|
|
508
589
|
namespace=namespace,
|
|
509
590
|
pod_name=pod_name,
|
dagster_k8s/version.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "0.26.
|
|
1
|
+
__version__ = "0.26.11"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: dagster-k8s
|
|
3
|
-
Version: 0.26.
|
|
3
|
+
Version: 0.26.11
|
|
4
4
|
Summary: A Dagster integration for k8s
|
|
5
5
|
Home-page: https://github.com/dagster-io/dagster/tree/master/python_modules/libraries/dagster-k8s
|
|
6
6
|
Author: Dagster Labs
|
|
@@ -14,7 +14,7 @@ Classifier: License :: OSI Approved :: Apache Software License
|
|
|
14
14
|
Classifier: Operating System :: OS Independent
|
|
15
15
|
Requires-Python: >=3.9,<3.13
|
|
16
16
|
License-File: LICENSE
|
|
17
|
-
Requires-Dist: dagster ==1.10.
|
|
17
|
+
Requires-Dist: dagster ==1.10.11
|
|
18
18
|
Requires-Dist: kubernetes <33
|
|
19
19
|
Requires-Dist: google-auth !=2.23.1
|
|
20
20
|
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
dagster_k8s/__init__.py,sha256=1Vi9HXEW9fatVuNzWTr6Oq-JEHmyDrVkonZuELsQ1C0,751
|
|
2
2
|
dagster_k8s/client.py,sha256=jkTy4uAbFU8KkbpPDMUScNo8mNDZ6q9upe48R6fexQo,39933
|
|
3
|
-
dagster_k8s/container_context.py,sha256=
|
|
4
|
-
dagster_k8s/executor.py,sha256=
|
|
3
|
+
dagster_k8s/container_context.py,sha256=399bdqmV3Ce6lNbfuxnhdyJSCy9keRRPJfVjDGn2U4I,22642
|
|
4
|
+
dagster_k8s/executor.py,sha256=yOvA5KuGi9O5C3KGz6IP8HVPwt2CSD9NU7ITcWxe53M,14872
|
|
5
5
|
dagster_k8s/job.py,sha256=v7RXYLZHzy2sTC7HYdz_INqbLWyZxUz9QIMwORArjJg,43065
|
|
6
6
|
dagster_k8s/kubernetes_version.py,sha256=T7MDA5pOOVE_woRUkKWxtiRj4RCLAVfjSn6ZXUr6sAA,38
|
|
7
7
|
dagster_k8s/launcher.py,sha256=8dPYFkB6W6GS5q7Ab9Mf4Oqyu3riX-HBLYyf7TKV7HQ,16669
|
|
8
8
|
dagster_k8s/models.py,sha256=REKzAY103pZw0pQFqvHaM6lL02hgbi0rxmm71qds4W8,6338
|
|
9
|
-
dagster_k8s/pipes.py,sha256=
|
|
9
|
+
dagster_k8s/pipes.py,sha256=KmCANVZIj6LkJ7b0jtCmQ043bI6CvjUQbZMe9xufs1c,34047
|
|
10
10
|
dagster_k8s/py.typed,sha256=la67KBlbjXN-_-DfGNcdOcjYumVpKG_Tkw-8n5dnGB4,8
|
|
11
11
|
dagster_k8s/test.py,sha256=cNtcbzxytiZtd01wY5ip7KPi01y0BUQuQhohoIfAFUM,684
|
|
12
12
|
dagster_k8s/utils.py,sha256=c1bHqh5f1p5RZ0JCT6WEbPPjDvbgUp3pl4nYZRaaI4s,786
|
|
13
|
-
dagster_k8s/version.py,sha256=
|
|
13
|
+
dagster_k8s/version.py,sha256=KbFltDKZs6Fz9BEm-IuAjy0mNlt5Il5YMdB41Jptyqg,24
|
|
14
14
|
dagster_k8s/ops/__init__.py,sha256=ur-9GrE_DRfnsFCpYan03qOY9cWbjagC8KHZFZuiCmc,113
|
|
15
15
|
dagster_k8s/ops/k8s_job_op.py,sha256=CQHtTowGGLAHH5EUGNfqZxDT1MYMqslAJ9u11SzCf-I,22036
|
|
16
|
-
dagster_k8s-0.26.
|
|
17
|
-
dagster_k8s-0.26.
|
|
18
|
-
dagster_k8s-0.26.
|
|
19
|
-
dagster_k8s-0.26.
|
|
20
|
-
dagster_k8s-0.26.
|
|
16
|
+
dagster_k8s-0.26.11.dist-info/LICENSE,sha256=TMatHW4_G9ldRdodEAp-l2Xa2WvsdeOh60E3v1R2jis,11349
|
|
17
|
+
dagster_k8s-0.26.11.dist-info/METADATA,sha256=xL3uaTmTh4ealcIS1WCdLu0l6kHUOHeO0BA-KfEZgnE,735
|
|
18
|
+
dagster_k8s-0.26.11.dist-info/WHEEL,sha256=yQN5g4mg4AybRjkgi-9yy4iQEFibGQmlz78Pik5Or-A,92
|
|
19
|
+
dagster_k8s-0.26.11.dist-info/top_level.txt,sha256=wFPjskoWPlk2hOLugYCaoZhSiZdUcbCA1QZe9I4dals,12
|
|
20
|
+
dagster_k8s-0.26.11.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|