apache-airflow-providers-cncf-kubernetes 9.0.0rc1__py3-none-any.whl → 9.0.1__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.
@@ -29,7 +29,7 @@ from airflow import __version__ as airflow_version
29
29
 
30
30
  __all__ = ["__version__"]
31
31
 
32
- __version__ = "9.0.0"
32
+ __version__ = "9.0.1"
33
33
 
34
34
  if packaging.version.parse(packaging.version.parse(airflow_version).base_version) < packaging.version.parse(
35
35
  "2.8.0"
@@ -36,7 +36,7 @@ from queue import Empty, Queue
36
36
  from typing import TYPE_CHECKING, Any, Sequence
37
37
 
38
38
  from kubernetes.dynamic import DynamicClient
39
- from sqlalchemy import select, update
39
+ from sqlalchemy import or_, select, update
40
40
 
41
41
  from airflow.cli.cli_config import (
42
42
  ARG_DAG_ID,
@@ -52,6 +52,7 @@ from airflow.cli.cli_config import (
52
52
  )
53
53
  from airflow.configuration import conf
54
54
  from airflow.executors.base_executor import BaseExecutor
55
+ from airflow.executors.executor_constants import KUBERNETES_EXECUTOR
55
56
  from airflow.providers.cncf.kubernetes.executors.kubernetes_executor_types import (
56
57
  ADOPTED,
57
58
  POD_EXECUTOR_DONE_KEY,
@@ -229,13 +230,30 @@ class KubernetesExecutor(BaseExecutor):
229
230
  assert self.kube_client
230
231
  from airflow.models.taskinstance import TaskInstance
231
232
 
233
+ hybrid_executor_enabled = hasattr(TaskInstance, "executor")
234
+ default_executor = None
235
+ if hybrid_executor_enabled:
236
+ from airflow.executors.executor_loader import ExecutorLoader
237
+
238
+ default_executor = str(ExecutorLoader.get_default_executor_name())
239
+
232
240
  with Stats.timer("kubernetes_executor.clear_not_launched_queued_tasks.duration"):
233
241
  self.log.debug("Clearing tasks that have not been launched")
234
242
  query = select(TaskInstance).where(
235
- TaskInstance.state == TaskInstanceState.QUEUED, TaskInstance.queued_by_job_id == self.job_id
243
+ TaskInstance.state == TaskInstanceState.QUEUED,
244
+ TaskInstance.queued_by_job_id == self.job_id,
236
245
  )
237
246
  if self.kubernetes_queue:
238
247
  query = query.where(TaskInstance.queue == self.kubernetes_queue)
248
+ elif hybrid_executor_enabled and KUBERNETES_EXECUTOR == default_executor:
249
+ query = query.where(
250
+ or_(
251
+ TaskInstance.executor == KUBERNETES_EXECUTOR,
252
+ TaskInstance.executor.is_(None),
253
+ ),
254
+ )
255
+ elif hybrid_executor_enabled:
256
+ query = query.where(TaskInstance.executor == KUBERNETES_EXECUTOR)
239
257
  queued_tis: list[TaskInstance] = session.scalars(query).all()
240
258
  self.log.info("Found %s queued task instances", len(queued_tis))
241
259
 
@@ -482,6 +500,7 @@ class KubernetesExecutor(BaseExecutor):
482
500
  self.running.remove(key)
483
501
  except KeyError:
484
502
  self.log.debug("TI key not in running, not adding to event_buffer: %s", key)
503
+ return
485
504
 
486
505
  # If we don't have a TI state, look it up from the db. event_buffer expects the TI state
487
506
  if state is None:
@@ -273,16 +273,6 @@ class KubernetesJobWatcher(multiprocessing.Process, LoggingMixin):
273
273
  (pod_name, namespace, TaskInstanceState.FAILED, annotations, resource_version)
274
274
  )
275
275
  elif status == "Succeeded":
276
- # We get multiple events once the pod hits a terminal state, and we only want to
277
- # send it along to the scheduler once.
278
- # If our event type is DELETED, or the pod has a deletion timestamp, we've already
279
- # seen the initial Succeeded event and sent it along to the scheduler.
280
- if event["type"] == "DELETED" or pod.metadata.deletion_timestamp:
281
- self.log.info(
282
- "Skipping event for Succeeded pod %s - event for this pod already sent to executor",
283
- pod_name,
284
- )
285
- return
286
276
  self.log.info("Event: %s Succeeded, annotations: %s", pod_name, annotations_string)
287
277
  self.watcher_queue.put((pod_name, namespace, None, annotations, resource_version))
288
278
  elif status == "Running":
@@ -28,8 +28,9 @@ def get_provider_info():
28
28
  "name": "Kubernetes",
29
29
  "description": "`Kubernetes <https://kubernetes.io/>`__\n",
30
30
  "state": "ready",
31
- "source-date-epoch": 1726860352,
31
+ "source-date-epoch": 1730012271,
32
32
  "versions": [
33
+ "9.0.1",
33
34
  "9.0.0",
34
35
  "8.4.2",
35
36
  "8.4.1",
@@ -101,8 +102,8 @@ def get_provider_info():
101
102
  "apache-airflow>=2.8.0",
102
103
  "asgiref>=3.5.2",
103
104
  "cryptography>=41.0.0",
104
- "kubernetes>=29.0.0,<=30.1.0",
105
- "kubernetes_asyncio>=29.0.0,<=30.1.0",
105
+ "kubernetes>=29.0.0,<=31.0.0",
106
+ "kubernetes_asyncio>=29.0.0,<=31.0.0",
106
107
  "google-re2>=1.0",
107
108
  ],
108
109
  "integrations": [
@@ -31,7 +31,7 @@ from collections.abc import Container
31
31
  from contextlib import AbstractContextManager
32
32
  from enum import Enum
33
33
  from functools import cached_property
34
- from typing import TYPE_CHECKING, Any, Callable, Iterable, Sequence
34
+ from typing import TYPE_CHECKING, Any, Callable, Iterable, Literal, Sequence
35
35
 
36
36
  import kubernetes
37
37
  import tenacity
@@ -91,7 +91,6 @@ from airflow.version import version as airflow_version
91
91
  if TYPE_CHECKING:
92
92
  import jinja2
93
93
  from pendulum import DateTime
94
- from typing_extensions import Literal
95
94
 
96
95
  from airflow.providers.cncf.kubernetes.secret import Secret
97
96
  from airflow.utils.context import Context
@@ -171,7 +170,7 @@ class KubernetesPodOperator(BaseOperator):
171
170
  :param affinity: affinity scheduling rules for the launched pod.
172
171
  :param config_file: The path to the Kubernetes config file. (templated)
173
172
  If not specified, default value is ``~/.kube/config``
174
- :param node_selector: A dict containing a group of scheduling rules.
173
+ :param node_selector: A dict containing a group of scheduling rules. (templated)
175
174
  :param image_pull_secrets: Any image pull secrets to be given to the pod.
176
175
  If more than one secret is required, provide a
177
176
  comma separated list: secret_a,secret_b
@@ -259,6 +258,8 @@ class KubernetesPodOperator(BaseOperator):
259
258
  "volume_mounts",
260
259
  "cluster_context",
261
260
  "env_from",
261
+ "node_selector",
262
+ "kubernetes_conn_id",
262
263
  )
263
264
  template_fields_renderers = {"env_vars": "py"}
264
265
 
@@ -285,7 +286,8 @@ class KubernetesPodOperator(BaseOperator):
285
286
  startup_timeout_seconds: int = 120,
286
287
  startup_check_interval_seconds: int = 5,
287
288
  get_logs: bool = True,
288
- container_logs: Iterable[str] | str | Literal[True] = BASE_CONTAINER_NAME,
289
+ base_container_name: str | None = None,
290
+ container_logs: Iterable[str] | str | Literal[True] | None = None,
289
291
  image_pull_policy: str | None = None,
290
292
  annotations: dict | None = None,
291
293
  container_resources: k8s.V1ResourceRequirements | None = None,
@@ -315,7 +317,6 @@ class KubernetesPodOperator(BaseOperator):
315
317
  termination_grace_period: int | None = None,
316
318
  configmaps: list[str] | None = None,
317
319
  skip_on_exit_code: int | Container[int] | None = None,
318
- base_container_name: str | None = None,
319
320
  deferrable: bool = conf.getboolean("operators", "default_deferrable", fallback=False),
320
321
  poll_interval: float = 2,
321
322
  log_pod_spec_on_failure: bool = True,
@@ -357,9 +358,10 @@ class KubernetesPodOperator(BaseOperator):
357
358
  self.cluster_context = cluster_context
358
359
  self.reattach_on_restart = reattach_on_restart
359
360
  self.get_logs = get_logs
360
- self.container_logs = container_logs
361
- if self.container_logs == KubernetesPodOperator.BASE_CONTAINER_NAME:
362
- self.container_logs = base_container_name or self.BASE_CONTAINER_NAME
361
+ # Fallback to the class variable BASE_CONTAINER_NAME here instead of via default argument value
362
+ # in the init method signature, to be compatible with subclasses overloading the class variable value.
363
+ self.base_container_name = base_container_name or self.BASE_CONTAINER_NAME
364
+ self.container_logs = container_logs or self.base_container_name
363
365
  self.image_pull_policy = image_pull_policy
364
366
  self.node_selector = node_selector or {}
365
367
  self.annotations = annotations or {}
@@ -398,7 +400,6 @@ class KubernetesPodOperator(BaseOperator):
398
400
  if skip_on_exit_code is not None
399
401
  else []
400
402
  )
401
- self.base_container_name = base_container_name or self.BASE_CONTAINER_NAME
402
403
  self.deferrable = deferrable
403
404
  self.poll_interval = poll_interval
404
405
  self.remote_pod: k8s.V1Pod | None = None
@@ -785,7 +786,7 @@ class KubernetesPodOperator(BaseOperator):
785
786
 
786
787
  pod_log_status = self.pod_manager.fetch_container_logs(
787
788
  pod=self.pod,
788
- container_name=self.BASE_CONTAINER_NAME,
789
+ container_name=self.base_container_name,
789
790
  follow=follow,
790
791
  since_time=last_log_time,
791
792
  )
@@ -69,7 +69,7 @@ class SparkKubernetesOperator(KubernetesPodOperator):
69
69
  :param kubernetes_conn_id: the connection to Kubernetes cluster
70
70
  """
71
71
 
72
- template_fields = ["application_file", "namespace", "template_spec"]
72
+ template_fields = ["application_file", "namespace", "template_spec", "kubernetes_conn_id"]
73
73
  template_fields_renderers = {"template_spec": "py"}
74
74
  template_ext = ("yaml", "yml", "json")
75
75
  ui_color = "#f4a460"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: apache-airflow-providers-cncf-kubernetes
3
- Version: 9.0.0rc1
3
+ Version: 9.0.1
4
4
  Summary: Provider package apache-airflow-providers-cncf-kubernetes for Apache Airflow
5
5
  Keywords: airflow-provider,cncf.kubernetes,airflow,integration
6
6
  Author-email: Apache Software Foundation <dev@airflow.apache.org>
@@ -21,15 +21,15 @@ Classifier: Programming Language :: Python :: 3.11
21
21
  Classifier: Programming Language :: Python :: 3.12
22
22
  Classifier: Topic :: System :: Monitoring
23
23
  Requires-Dist: aiofiles>=23.2.0
24
- Requires-Dist: apache-airflow>=2.8.0rc0
24
+ Requires-Dist: apache-airflow>=2.8.0
25
25
  Requires-Dist: asgiref>=3.5.2
26
26
  Requires-Dist: cryptography>=41.0.0
27
27
  Requires-Dist: google-re2>=1.0
28
- Requires-Dist: kubernetes>=29.0.0,<=30.1.0
29
- Requires-Dist: kubernetes_asyncio>=29.0.0,<=30.1.0
28
+ Requires-Dist: kubernetes>=29.0.0,<=31.0.0
29
+ Requires-Dist: kubernetes_asyncio>=29.0.0,<=31.0.0
30
30
  Project-URL: Bug Tracker, https://github.com/apache/airflow/issues
31
- Project-URL: Changelog, https://airflow.apache.org/docs/apache-airflow-providers-cncf-kubernetes/9.0.0/changelog.html
32
- Project-URL: Documentation, https://airflow.apache.org/docs/apache-airflow-providers-cncf-kubernetes/9.0.0
31
+ Project-URL: Changelog, https://airflow.apache.org/docs/apache-airflow-providers-cncf-kubernetes/9.0.1/changelog.html
32
+ Project-URL: Documentation, https://airflow.apache.org/docs/apache-airflow-providers-cncf-kubernetes/9.0.1
33
33
  Project-URL: Slack Chat, https://s.apache.org/airflow-slack
34
34
  Project-URL: Source Code, https://github.com/apache/airflow
35
35
  Project-URL: Twitter, https://twitter.com/ApacheAirflow
@@ -79,7 +79,7 @@ Project-URL: YouTube, https://www.youtube.com/channel/UCSXwxpWZQ7XZ1WL3wqevChA/
79
79
 
80
80
  Package ``apache-airflow-providers-cncf-kubernetes``
81
81
 
82
- Release: ``9.0.0.rc1``
82
+ Release: ``9.0.1``
83
83
 
84
84
 
85
85
  `Kubernetes <https://kubernetes.io/>`__
@@ -92,7 +92,7 @@ This is a provider package for ``cncf.kubernetes`` provider. All classes for thi
92
92
  are in ``airflow.providers.cncf.kubernetes`` python package.
93
93
 
94
94
  You can find package information and changelog for the provider
95
- in the `documentation <https://airflow.apache.org/docs/apache-airflow-providers-cncf-kubernetes/9.0.0/>`_.
95
+ in the `documentation <https://airflow.apache.org/docs/apache-airflow-providers-cncf-kubernetes/9.0.1/>`_.
96
96
 
97
97
  Installation
98
98
  ------------
@@ -113,10 +113,10 @@ PIP package Version required
113
113
  ``apache-airflow`` ``>=2.8.0``
114
114
  ``asgiref`` ``>=3.5.2``
115
115
  ``cryptography`` ``>=41.0.0``
116
- ``kubernetes`` ``>=29.0.0,<=30.1.0``
117
- ``kubernetes_asyncio`` ``>=29.0.0,<=30.1.0``
116
+ ``kubernetes`` ``>=29.0.0,<=31.0.0``
117
+ ``kubernetes_asyncio`` ``>=29.0.0,<=31.0.0``
118
118
  ``google-re2`` ``>=1.0``
119
119
  ====================== =====================
120
120
 
121
121
  The changelog for the provider package can be found in the
122
- `changelog <https://airflow.apache.org/docs/apache-airflow-providers-cncf-kubernetes/9.0.0/changelog.html>`_.
122
+ `changelog <https://airflow.apache.org/docs/apache-airflow-providers-cncf-kubernetes/9.0.1/changelog.html>`_.
@@ -1,7 +1,7 @@
1
1
  airflow/providers/cncf/kubernetes/LICENSE,sha256=FFb4jd2AXnOOf7XLP04pQW6jbdhG49TxlGY6fFpCV1Y,13609
2
- airflow/providers/cncf/kubernetes/__init__.py,sha256=VYEaCJTXEsqDXEr1WY7moklTkLqQgKhR1cWglnIlZGY,1502
2
+ airflow/providers/cncf/kubernetes/__init__.py,sha256=p5-ifXMiybbsAM0J0xLXPmubE5pHXdZmpYD5CriC2Ek,1502
3
3
  airflow/providers/cncf/kubernetes/callbacks.py,sha256=SK_gKvGWuU-nxHfsqsYMlNQ8HZbHfpvyItOqieel2lc,4162
4
- airflow/providers/cncf/kubernetes/get_provider_info.py,sha256=dEbAwIRN2-XVVKuy25fpL3jQ7UN1U2VZMDc2hgIGbiE,17965
4
+ airflow/providers/cncf/kubernetes/get_provider_info.py,sha256=B0FUhOfC6Xkj7ynRLYH2CJCEHMVNRQMStARc89kfEC4,17986
5
5
  airflow/providers/cncf/kubernetes/k8s_model.py,sha256=xmdFhX29DjegoZ-cq8-KDL9soVYXf4OpU6fAGr3cPTU,2101
6
6
  airflow/providers/cncf/kubernetes/kube_client.py,sha256=yflZxLousXA9d7t67KrEy55qzb1cUhEyy6yCPkEem28,5329
7
7
  airflow/providers/cncf/kubernetes/kube_config.py,sha256=FAmhZZ_Z2JtoVzL6wENSjcwrlwAenHttTX_Ild9aEms,5225
@@ -20,9 +20,9 @@ airflow/providers/cncf/kubernetes/cli/kubernetes_command.py,sha256=W49hsWZ3XWUJg
20
20
  airflow/providers/cncf/kubernetes/decorators/__init__.py,sha256=mlJxuZLkd5x-iq2SBwD3mvRQpt3YR7wjz_nceyF1IaI,787
21
21
  airflow/providers/cncf/kubernetes/decorators/kubernetes.py,sha256=qfU_MDOhBsHc2leu1RW3YE5steDFOnWxcVswhjC6GXU,5785
22
22
  airflow/providers/cncf/kubernetes/executors/__init__.py,sha256=mlJxuZLkd5x-iq2SBwD3mvRQpt3YR7wjz_nceyF1IaI,787
23
- airflow/providers/cncf/kubernetes/executors/kubernetes_executor.py,sha256=leOd9r6YMkiIyGhqHfVVJXxQvkJ9UdgXppVDb94oegU,33166
23
+ airflow/providers/cncf/kubernetes/executors/kubernetes_executor.py,sha256=tco4nuKFjKmVA_pIsjli-NlB9DA31cq_845hD54N6mM,34006
24
24
  airflow/providers/cncf/kubernetes/executors/kubernetes_executor_types.py,sha256=9rRhfRuujGtSE73Ax0kC12whZCgWF2m6j5w9G9e0F_I,1673
25
- airflow/providers/cncf/kubernetes/executors/kubernetes_executor_utils.py,sha256=aGGtM7QE2cjdq3dRXh7k7c45ipnVfkjFy4SP35clJpc,23963
25
+ airflow/providers/cncf/kubernetes/executors/kubernetes_executor_utils.py,sha256=f2FHTyQyfFR1jjQmZV9bfX7U4Vxk5h61KPJO0yMcGbM,23356
26
26
  airflow/providers/cncf/kubernetes/executors/local_kubernetes_executor.py,sha256=tlUMdInlQjw5pJTxtyQ1lBzq8HCVttNLvZsCtNtb1Io,10844
27
27
  airflow/providers/cncf/kubernetes/hooks/__init__.py,sha256=9hdXHABrVpkbpjZgUft39kOFL2xSGeG4GEua0Hmelus,785
28
28
  airflow/providers/cncf/kubernetes/hooks/kubernetes.py,sha256=WSWQZrAzyrjN9y5TCS796X1L7oB-Sq_2BUzhT9xAE2k,33632
@@ -32,9 +32,9 @@ airflow/providers/cncf/kubernetes/operators/__init__.py,sha256=mlJxuZLkd5x-iq2SB
32
32
  airflow/providers/cncf/kubernetes/operators/custom_object_launcher.py,sha256=ZEXw_PqGItO47AEgGKqAqwFHFo-gb9-7jgEMRJgOfNU,15311
33
33
  airflow/providers/cncf/kubernetes/operators/job.py,sha256=RyPuT0yP7-tRrrS7uqDUBGI_xA9_YEg-JLUDJ5QcTA8,23809
34
34
  airflow/providers/cncf/kubernetes/operators/kubernetes_pod.py,sha256=EFwHEdEqq4I18BeV9hgp_GFxrLI78ihZAccbyGLSjtY,1269
35
- airflow/providers/cncf/kubernetes/operators/pod.py,sha256=leGZOcEnqACp6AK5ZUt1jzP17pzGEHk6qW9wgYqwpNc,54693
35
+ airflow/providers/cncf/kubernetes/operators/pod.py,sha256=MAHaLxy5ScgbY0LO5i3ejH3MHqYyXG3a9harRg-8guE,54803
36
36
  airflow/providers/cncf/kubernetes/operators/resource.py,sha256=ccbZQKB1B5N4Y-ruItacB5Q105Tc0uNSoEmUAaSCrGQ,7570
37
- airflow/providers/cncf/kubernetes/operators/spark_kubernetes.py,sha256=tnRxHZSQTuqFQP0YFPMjuiatklkr45W3N9RPDXhf_-o,13646
37
+ airflow/providers/cncf/kubernetes/operators/spark_kubernetes.py,sha256=oi1JUCoRo7AzAOYhKgbCB60Hmg_slRdj3FsQKWQRhcI,13668
38
38
  airflow/providers/cncf/kubernetes/pod_template_file_examples/__init__.py,sha256=9hdXHABrVpkbpjZgUft39kOFL2xSGeG4GEua0Hmelus,785
39
39
  airflow/providers/cncf/kubernetes/pod_template_file_examples/dags_in_image_template.yaml,sha256=7JdppZ-XDBpv2Bnde2SthhcME8w3b8xQdPAK1fJGW60,2256
40
40
  airflow/providers/cncf/kubernetes/pod_template_file_examples/dags_in_volume_template.yaml,sha256=-Pk_EwKpyWRYZKOnumUxVrDeAfFJ0nr3WZ7JNnvppzg,2442
@@ -54,7 +54,7 @@ airflow/providers/cncf/kubernetes/utils/delete_from.py,sha256=poObZSoEJwQyaYWilE
54
54
  airflow/providers/cncf/kubernetes/utils/k8s_resource_iterator.py,sha256=-Pgc5i2WEDl7ZBvtJZ4eWDqqlSj8WdULqwUyOWmsRp8,1928
55
55
  airflow/providers/cncf/kubernetes/utils/pod_manager.py,sha256=eITiFHU8lsCy3UwRUm-3uOQ3J1BgkshaXd1FJOJ3Q4A,34298
56
56
  airflow/providers/cncf/kubernetes/utils/xcom_sidecar.py,sha256=k6bdmVJ21OrAwGmWwledRrAmaty9ZrmbuM-IbaI4mqo,2519
57
- apache_airflow_providers_cncf_kubernetes-9.0.0rc1.dist-info/entry_points.txt,sha256=ByD3QJJyP9CfmTYtpNI1953akD38RUDgpGXLaq9vpOw,111
58
- apache_airflow_providers_cncf_kubernetes-9.0.0rc1.dist-info/WHEEL,sha256=EZbGkh7Ie4PoZfRQ8I0ZuP9VklN_TvcZ6DSE5Uar4z4,81
59
- apache_airflow_providers_cncf_kubernetes-9.0.0rc1.dist-info/METADATA,sha256=u4HfGJAdX7Q-DaBDqFyt54JzRaf9e9A3PvZMT6TtAtY,5216
60
- apache_airflow_providers_cncf_kubernetes-9.0.0rc1.dist-info/RECORD,,
57
+ apache_airflow_providers_cncf_kubernetes-9.0.1.dist-info/entry_points.txt,sha256=ByD3QJJyP9CfmTYtpNI1953akD38RUDgpGXLaq9vpOw,111
58
+ apache_airflow_providers_cncf_kubernetes-9.0.1.dist-info/WHEEL,sha256=EZbGkh7Ie4PoZfRQ8I0ZuP9VklN_TvcZ6DSE5Uar4z4,81
59
+ apache_airflow_providers_cncf_kubernetes-9.0.1.dist-info/METADATA,sha256=TcqzgCgCkgrxxFlTSpaaOjhIiN747VjmE1fVa4hlTQY,5206
60
+ apache_airflow_providers_cncf_kubernetes-9.0.1.dist-info/RECORD,,