dagster-k8s 0.26.9__tar.gz → 0.26.11rc0__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.

Files changed (28) hide show
  1. {dagster-k8s-0.26.9/dagster_k8s.egg-info → dagster-k8s-0.26.11rc0}/PKG-INFO +1 -1
  2. {dagster-k8s-0.26.9 → dagster-k8s-0.26.11rc0}/dagster_k8s/container_context.py +1 -1
  3. {dagster-k8s-0.26.9 → dagster-k8s-0.26.11rc0}/dagster_k8s/executor.py +4 -4
  4. {dagster-k8s-0.26.9 → dagster-k8s-0.26.11rc0}/dagster_k8s/pipes.py +90 -9
  5. dagster-k8s-0.26.11rc0/dagster_k8s/version.py +1 -0
  6. {dagster-k8s-0.26.9 → dagster-k8s-0.26.11rc0/dagster_k8s.egg-info}/PKG-INFO +1 -1
  7. {dagster-k8s-0.26.9 → dagster-k8s-0.26.11rc0}/dagster_k8s.egg-info/requires.txt +1 -1
  8. {dagster-k8s-0.26.9 → dagster-k8s-0.26.11rc0}/setup.py +1 -1
  9. dagster-k8s-0.26.9/dagster_k8s/version.py +0 -1
  10. {dagster-k8s-0.26.9 → dagster-k8s-0.26.11rc0}/LICENSE +0 -0
  11. {dagster-k8s-0.26.9 → dagster-k8s-0.26.11rc0}/MANIFEST.in +0 -0
  12. {dagster-k8s-0.26.9 → dagster-k8s-0.26.11rc0}/README.md +0 -0
  13. {dagster-k8s-0.26.9 → dagster-k8s-0.26.11rc0}/dagster_k8s/__init__.py +0 -0
  14. {dagster-k8s-0.26.9 → dagster-k8s-0.26.11rc0}/dagster_k8s/client.py +0 -0
  15. {dagster-k8s-0.26.9 → dagster-k8s-0.26.11rc0}/dagster_k8s/job.py +0 -0
  16. {dagster-k8s-0.26.9 → dagster-k8s-0.26.11rc0}/dagster_k8s/kubernetes_version.py +0 -0
  17. {dagster-k8s-0.26.9 → dagster-k8s-0.26.11rc0}/dagster_k8s/launcher.py +0 -0
  18. {dagster-k8s-0.26.9 → dagster-k8s-0.26.11rc0}/dagster_k8s/models.py +0 -0
  19. {dagster-k8s-0.26.9 → dagster-k8s-0.26.11rc0}/dagster_k8s/ops/__init__.py +0 -0
  20. {dagster-k8s-0.26.9 → dagster-k8s-0.26.11rc0}/dagster_k8s/ops/k8s_job_op.py +0 -0
  21. {dagster-k8s-0.26.9 → dagster-k8s-0.26.11rc0}/dagster_k8s/py.typed +0 -0
  22. {dagster-k8s-0.26.9 → dagster-k8s-0.26.11rc0}/dagster_k8s/test.py +0 -0
  23. {dagster-k8s-0.26.9 → dagster-k8s-0.26.11rc0}/dagster_k8s/utils.py +0 -0
  24. {dagster-k8s-0.26.9 → dagster-k8s-0.26.11rc0}/dagster_k8s.egg-info/SOURCES.txt +0 -0
  25. {dagster-k8s-0.26.9 → dagster-k8s-0.26.11rc0}/dagster_k8s.egg-info/dependency_links.txt +0 -0
  26. {dagster-k8s-0.26.9 → dagster-k8s-0.26.11rc0}/dagster_k8s.egg-info/not-zip-safe +0 -0
  27. {dagster-k8s-0.26.9 → dagster-k8s-0.26.11rc0}/dagster_k8s.egg-info/top_level.txt +0 -0
  28. {dagster-k8s-0.26.9 → dagster-k8s-0.26.11rc0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dagster-k8s
3
- Version: 0.26.9
3
+ Version: 0.26.11rc0
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
@@ -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(
@@ -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)
@@ -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
- for line in core_api.read_namespaced_pod_log(
93
- pod_name,
94
- namespace,
95
- follow=True,
96
- _preload_content=False, # avoid JSON processing
97
- ).stream():
98
- log_chunk = line.decode("utf-8")
99
- for log_line in log_chunk.split("\n"):
100
- extract_message_or_forward_to_stdout(handler, log_line)
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,
@@ -0,0 +1 @@
1
+ __version__ = "0.26.11rc0"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dagster-k8s
3
- Version: 0.26.9
3
+ Version: 0.26.11rc0
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
@@ -1,3 +1,3 @@
1
- dagster==1.10.9
1
+ dagster==1.10.11rc0
2
2
  kubernetes<33
3
3
  google-auth!=2.23.1
@@ -42,7 +42,7 @@ setup(
42
42
  include_package_data=True,
43
43
  python_requires=">=3.9,<3.13",
44
44
  install_requires=[
45
- "dagster==1.10.9",
45
+ "dagster==1.10.11rc0",
46
46
  f"kubernetes<{KUBERNETES_VERSION_UPPER_BOUND}",
47
47
  # exclude a google-auth release that added an overly restrictive urllib3 pin that confuses dependency resolvers
48
48
  "google-auth!=2.23.1",
@@ -1 +0,0 @@
1
- __version__ = "0.26.9"
File without changes
File without changes
File without changes