dagster-k8s 0.26.9__py3-none-any.whl → 0.26.10__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/pipes.py +90 -9
- dagster_k8s/version.py +1 -1
- {dagster_k8s-0.26.9.dist-info → dagster_k8s-0.26.10.dist-info}/METADATA +2 -2
- {dagster_k8s-0.26.9.dist-info → dagster_k8s-0.26.10.dist-info}/RECORD +7 -7
- {dagster_k8s-0.26.9.dist-info → dagster_k8s-0.26.10.dist-info}/LICENSE +0 -0
- {dagster_k8s-0.26.9.dist-info → dagster_k8s-0.26.10.dist-info}/WHEEL +0 -0
- {dagster_k8s-0.26.9.dist-info → dagster_k8s-0.26.10.dist-info}/top_level.txt +0 -0
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.10"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: dagster-k8s
|
|
3
|
-
Version: 0.26.
|
|
3
|
+
Version: 0.26.10
|
|
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.10
|
|
18
18
|
Requires-Dist: kubernetes <33
|
|
19
19
|
Requires-Dist: google-auth !=2.23.1
|
|
20
20
|
|
|
@@ -6,15 +6,15 @@ 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=9-z_rPHYsAgEXE1QWFkRpI3_u6ifBXzG8OJefFCirtY,34045
|
|
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=ME_83c8BVbSixEHEcpqZ6-kklj3neFq1tYEhdbpNO5c,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.10.dist-info/LICENSE,sha256=TMatHW4_G9ldRdodEAp-l2Xa2WvsdeOh60E3v1R2jis,11349
|
|
17
|
+
dagster_k8s-0.26.10.dist-info/METADATA,sha256=Q-8FhXNsNNOisiqHT1pheoSd_YInfFYq535OkxnK5Hk,735
|
|
18
|
+
dagster_k8s-0.26.10.dist-info/WHEEL,sha256=yQN5g4mg4AybRjkgi-9yy4iQEFibGQmlz78Pik5Or-A,92
|
|
19
|
+
dagster_k8s-0.26.10.dist-info/top_level.txt,sha256=wFPjskoWPlk2hOLugYCaoZhSiZdUcbCA1QZe9I4dals,12
|
|
20
|
+
dagster_k8s-0.26.10.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|