apache-airflow-providers-cncf-kubernetes 8.0.1rc1__tar.gz → 8.1.0rc1__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 apache-airflow-providers-cncf-kubernetes might be problematic. Click here for more details.

Files changed (57) hide show
  1. {apache_airflow_providers_cncf_kubernetes-8.0.1rc1 → apache_airflow_providers_cncf_kubernetes-8.1.0rc1}/PKG-INFO +9 -8
  2. {apache_airflow_providers_cncf_kubernetes-8.0.1rc1 → apache_airflow_providers_cncf_kubernetes-8.1.0rc1}/README.rst +4 -4
  3. {apache_airflow_providers_cncf_kubernetes-8.0.1rc1 → apache_airflow_providers_cncf_kubernetes-8.1.0rc1}/airflow/providers/cncf/kubernetes/__init__.py +1 -1
  4. {apache_airflow_providers_cncf_kubernetes-8.0.1rc1 → apache_airflow_providers_cncf_kubernetes-8.1.0rc1}/airflow/providers/cncf/kubernetes/backcompat/backwards_compat_converters.py +1 -0
  5. {apache_airflow_providers_cncf_kubernetes-8.0.1rc1 → apache_airflow_providers_cncf_kubernetes-8.1.0rc1}/airflow/providers/cncf/kubernetes/executors/kubernetes_executor.py +1 -0
  6. {apache_airflow_providers_cncf_kubernetes-8.0.1rc1 → apache_airflow_providers_cncf_kubernetes-8.1.0rc1}/airflow/providers/cncf/kubernetes/get_provider_info.py +6 -2
  7. {apache_airflow_providers_cncf_kubernetes-8.0.1rc1 → apache_airflow_providers_cncf_kubernetes-8.1.0rc1}/airflow/providers/cncf/kubernetes/hooks/kubernetes.py +149 -0
  8. {apache_airflow_providers_cncf_kubernetes-8.0.1rc1 → apache_airflow_providers_cncf_kubernetes-8.1.0rc1}/airflow/providers/cncf/kubernetes/k8s_model.py +1 -0
  9. {apache_airflow_providers_cncf_kubernetes-8.0.1rc1 → apache_airflow_providers_cncf_kubernetes-8.1.0rc1}/airflow/providers/cncf/kubernetes/kube_client.py +1 -0
  10. {apache_airflow_providers_cncf_kubernetes-8.0.1rc1 → apache_airflow_providers_cncf_kubernetes-8.1.0rc1}/airflow/providers/cncf/kubernetes/kubernetes_helper_functions.py +1 -1
  11. {apache_airflow_providers_cncf_kubernetes-8.0.1rc1 → apache_airflow_providers_cncf_kubernetes-8.1.0rc1}/airflow/providers/cncf/kubernetes/operators/custom_object_launcher.py +4 -3
  12. {apache_airflow_providers_cncf_kubernetes-8.0.1rc1 → apache_airflow_providers_cncf_kubernetes-8.1.0rc1}/airflow/providers/cncf/kubernetes/operators/job.py +239 -0
  13. {apache_airflow_providers_cncf_kubernetes-8.0.1rc1 → apache_airflow_providers_cncf_kubernetes-8.1.0rc1}/airflow/providers/cncf/kubernetes/operators/kubernetes_pod.py +1 -0
  14. {apache_airflow_providers_cncf_kubernetes-8.0.1rc1 → apache_airflow_providers_cncf_kubernetes-8.1.0rc1}/airflow/providers/cncf/kubernetes/operators/pod.py +35 -16
  15. {apache_airflow_providers_cncf_kubernetes-8.0.1rc1 → apache_airflow_providers_cncf_kubernetes-8.1.0rc1}/airflow/providers/cncf/kubernetes/operators/resource.py +47 -13
  16. {apache_airflow_providers_cncf_kubernetes-8.0.1rc1 → apache_airflow_providers_cncf_kubernetes-8.1.0rc1}/airflow/providers/cncf/kubernetes/operators/spark_kubernetes.py +27 -3
  17. {apache_airflow_providers_cncf_kubernetes-8.0.1rc1 → apache_airflow_providers_cncf_kubernetes-8.1.0rc1}/airflow/providers/cncf/kubernetes/pod_generator.py +3 -1
  18. {apache_airflow_providers_cncf_kubernetes-8.0.1rc1 → apache_airflow_providers_cncf_kubernetes-8.1.0rc1}/airflow/providers/cncf/kubernetes/pod_generator_deprecated.py +1 -0
  19. {apache_airflow_providers_cncf_kubernetes-8.0.1rc1 → apache_airflow_providers_cncf_kubernetes-8.1.0rc1}/airflow/providers/cncf/kubernetes/pod_launcher_deprecated.py +1 -0
  20. {apache_airflow_providers_cncf_kubernetes-8.0.1rc1 → apache_airflow_providers_cncf_kubernetes-8.1.0rc1}/airflow/providers/cncf/kubernetes/python_kubernetes_script.py +1 -0
  21. {apache_airflow_providers_cncf_kubernetes-8.0.1rc1 → apache_airflow_providers_cncf_kubernetes-8.1.0rc1}/airflow/providers/cncf/kubernetes/secret.py +1 -0
  22. apache_airflow_providers_cncf_kubernetes-8.1.0rc1/airflow/providers/cncf/kubernetes/triggers/job.py +101 -0
  23. {apache_airflow_providers_cncf_kubernetes-8.0.1rc1 → apache_airflow_providers_cncf_kubernetes-8.1.0rc1}/airflow/providers/cncf/kubernetes/triggers/kubernetes_pod.py +1 -0
  24. {apache_airflow_providers_cncf_kubernetes-8.0.1rc1 → apache_airflow_providers_cncf_kubernetes-8.1.0rc1}/airflow/providers/cncf/kubernetes/triggers/pod.py +11 -3
  25. {apache_airflow_providers_cncf_kubernetes-8.0.1rc1 → apache_airflow_providers_cncf_kubernetes-8.1.0rc1}/airflow/providers/cncf/kubernetes/utils/pod_manager.py +2 -1
  26. {apache_airflow_providers_cncf_kubernetes-8.0.1rc1 → apache_airflow_providers_cncf_kubernetes-8.1.0rc1}/airflow/providers/cncf/kubernetes/utils/xcom_sidecar.py +1 -0
  27. {apache_airflow_providers_cncf_kubernetes-8.0.1rc1 → apache_airflow_providers_cncf_kubernetes-8.1.0rc1}/pyproject.toml +5 -4
  28. {apache_airflow_providers_cncf_kubernetes-8.0.1rc1 → apache_airflow_providers_cncf_kubernetes-8.1.0rc1}/airflow/providers/cncf/kubernetes/LICENSE +0 -0
  29. {apache_airflow_providers_cncf_kubernetes-8.0.1rc1 → apache_airflow_providers_cncf_kubernetes-8.1.0rc1}/airflow/providers/cncf/kubernetes/backcompat/__init__.py +0 -0
  30. {apache_airflow_providers_cncf_kubernetes-8.0.1rc1 → apache_airflow_providers_cncf_kubernetes-8.1.0rc1}/airflow/providers/cncf/kubernetes/callbacks.py +0 -0
  31. {apache_airflow_providers_cncf_kubernetes-8.0.1rc1 → apache_airflow_providers_cncf_kubernetes-8.1.0rc1}/airflow/providers/cncf/kubernetes/decorators/__init__.py +0 -0
  32. {apache_airflow_providers_cncf_kubernetes-8.0.1rc1 → apache_airflow_providers_cncf_kubernetes-8.1.0rc1}/airflow/providers/cncf/kubernetes/decorators/kubernetes.py +0 -0
  33. {apache_airflow_providers_cncf_kubernetes-8.0.1rc1 → apache_airflow_providers_cncf_kubernetes-8.1.0rc1}/airflow/providers/cncf/kubernetes/executors/__init__.py +0 -0
  34. {apache_airflow_providers_cncf_kubernetes-8.0.1rc1 → apache_airflow_providers_cncf_kubernetes-8.1.0rc1}/airflow/providers/cncf/kubernetes/executors/kubernetes_executor_types.py +0 -0
  35. {apache_airflow_providers_cncf_kubernetes-8.0.1rc1 → apache_airflow_providers_cncf_kubernetes-8.1.0rc1}/airflow/providers/cncf/kubernetes/executors/kubernetes_executor_utils.py +0 -0
  36. {apache_airflow_providers_cncf_kubernetes-8.0.1rc1 → apache_airflow_providers_cncf_kubernetes-8.1.0rc1}/airflow/providers/cncf/kubernetes/executors/local_kubernetes_executor.py +0 -0
  37. {apache_airflow_providers_cncf_kubernetes-8.0.1rc1 → apache_airflow_providers_cncf_kubernetes-8.1.0rc1}/airflow/providers/cncf/kubernetes/hooks/__init__.py +0 -0
  38. {apache_airflow_providers_cncf_kubernetes-8.0.1rc1 → apache_airflow_providers_cncf_kubernetes-8.1.0rc1}/airflow/providers/cncf/kubernetes/kube_config.py +0 -0
  39. {apache_airflow_providers_cncf_kubernetes-8.0.1rc1 → apache_airflow_providers_cncf_kubernetes-8.1.0rc1}/airflow/providers/cncf/kubernetes/kubernetes_executor_templates/__init__.py +0 -0
  40. {apache_airflow_providers_cncf_kubernetes-8.0.1rc1 → apache_airflow_providers_cncf_kubernetes-8.1.0rc1}/airflow/providers/cncf/kubernetes/kubernetes_executor_templates/basic_template.yaml +0 -0
  41. {apache_airflow_providers_cncf_kubernetes-8.0.1rc1 → apache_airflow_providers_cncf_kubernetes-8.1.0rc1}/airflow/providers/cncf/kubernetes/operators/__init__.py +0 -0
  42. {apache_airflow_providers_cncf_kubernetes-8.0.1rc1 → apache_airflow_providers_cncf_kubernetes-8.1.0rc1}/airflow/providers/cncf/kubernetes/pod_template_file_examples/__init__.py +0 -0
  43. {apache_airflow_providers_cncf_kubernetes-8.0.1rc1 → apache_airflow_providers_cncf_kubernetes-8.1.0rc1}/airflow/providers/cncf/kubernetes/pod_template_file_examples/dags_in_image_template.yaml +0 -0
  44. {apache_airflow_providers_cncf_kubernetes-8.0.1rc1 → apache_airflow_providers_cncf_kubernetes-8.1.0rc1}/airflow/providers/cncf/kubernetes/pod_template_file_examples/dags_in_volume_template.yaml +0 -0
  45. {apache_airflow_providers_cncf_kubernetes-8.0.1rc1 → apache_airflow_providers_cncf_kubernetes-8.1.0rc1}/airflow/providers/cncf/kubernetes/pod_template_file_examples/git_sync_template.yaml +0 -0
  46. {apache_airflow_providers_cncf_kubernetes-8.0.1rc1 → apache_airflow_providers_cncf_kubernetes-8.1.0rc1}/airflow/providers/cncf/kubernetes/python_kubernetes_script.jinja2 +0 -0
  47. {apache_airflow_providers_cncf_kubernetes-8.0.1rc1 → apache_airflow_providers_cncf_kubernetes-8.1.0rc1}/airflow/providers/cncf/kubernetes/resource_convert/__init__.py +0 -0
  48. {apache_airflow_providers_cncf_kubernetes-8.0.1rc1 → apache_airflow_providers_cncf_kubernetes-8.1.0rc1}/airflow/providers/cncf/kubernetes/resource_convert/configmap.py +0 -0
  49. {apache_airflow_providers_cncf_kubernetes-8.0.1rc1 → apache_airflow_providers_cncf_kubernetes-8.1.0rc1}/airflow/providers/cncf/kubernetes/resource_convert/env_variable.py +0 -0
  50. {apache_airflow_providers_cncf_kubernetes-8.0.1rc1 → apache_airflow_providers_cncf_kubernetes-8.1.0rc1}/airflow/providers/cncf/kubernetes/resource_convert/secret.py +0 -0
  51. {apache_airflow_providers_cncf_kubernetes-8.0.1rc1 → apache_airflow_providers_cncf_kubernetes-8.1.0rc1}/airflow/providers/cncf/kubernetes/sensors/__init__.py +0 -0
  52. {apache_airflow_providers_cncf_kubernetes-8.0.1rc1 → apache_airflow_providers_cncf_kubernetes-8.1.0rc1}/airflow/providers/cncf/kubernetes/sensors/spark_kubernetes.py +0 -0
  53. {apache_airflow_providers_cncf_kubernetes-8.0.1rc1 → apache_airflow_providers_cncf_kubernetes-8.1.0rc1}/airflow/providers/cncf/kubernetes/template_rendering.py +0 -0
  54. {apache_airflow_providers_cncf_kubernetes-8.0.1rc1 → apache_airflow_providers_cncf_kubernetes-8.1.0rc1}/airflow/providers/cncf/kubernetes/triggers/__init__.py +0 -0
  55. {apache_airflow_providers_cncf_kubernetes-8.0.1rc1 → apache_airflow_providers_cncf_kubernetes-8.1.0rc1}/airflow/providers/cncf/kubernetes/utils/__init__.py +0 -0
  56. {apache_airflow_providers_cncf_kubernetes-8.0.1rc1 → apache_airflow_providers_cncf_kubernetes-8.1.0rc1}/airflow/providers/cncf/kubernetes/utils/delete_from.py +0 -0
  57. {apache_airflow_providers_cncf_kubernetes-8.0.1rc1 → apache_airflow_providers_cncf_kubernetes-8.1.0rc1}/airflow/providers/cncf/kubernetes/utils/k8s_resource_iterator.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: apache-airflow-providers-cncf-kubernetes
3
- Version: 8.0.1rc1
3
+ Version: 8.1.0rc1
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>
@@ -19,17 +19,18 @@ Classifier: Programming Language :: Python :: 3.8
19
19
  Classifier: Programming Language :: Python :: 3.9
20
20
  Classifier: Programming Language :: Python :: 3.10
21
21
  Classifier: Programming Language :: Python :: 3.11
22
+ Classifier: Programming Language :: Python :: 3.12
22
23
  Classifier: Topic :: System :: Monitoring
23
24
  Requires-Dist: aiofiles>=23.2.0
24
- Requires-Dist: apache-airflow>=2.6.0.dev0
25
+ Requires-Dist: apache-airflow>=2.6.0rc0
25
26
  Requires-Dist: asgiref>=3.5.2
26
27
  Requires-Dist: cryptography>=2.0.0
27
28
  Requires-Dist: google-re2>=1.0
28
29
  Requires-Dist: kubernetes>=28.1.0,<=29.0.0
29
30
  Requires-Dist: kubernetes_asyncio>=28.1.0,<=29.0.0
30
31
  Project-URL: Bug Tracker, https://github.com/apache/airflow/issues
31
- Project-URL: Changelog, https://airflow.apache.org/docs/apache-airflow-providers-cncf-kubernetes/8.0.1/changelog.html
32
- Project-URL: Documentation, https://airflow.apache.org/docs/apache-airflow-providers-cncf-kubernetes/8.0.1
32
+ Project-URL: Changelog, https://airflow.apache.org/docs/apache-airflow-providers-cncf-kubernetes/8.1.0/changelog.html
33
+ Project-URL: Documentation, https://airflow.apache.org/docs/apache-airflow-providers-cncf-kubernetes/8.1.0
33
34
  Project-URL: Slack Chat, https://s.apache.org/airflow-slack
34
35
  Project-URL: Source Code, https://github.com/apache/airflow
35
36
  Project-URL: Twitter, https://twitter.com/ApacheAirflow
@@ -79,7 +80,7 @@ Project-URL: YouTube, https://www.youtube.com/channel/UCSXwxpWZQ7XZ1WL3wqevChA/
79
80
 
80
81
  Package ``apache-airflow-providers-cncf-kubernetes``
81
82
 
82
- Release: ``8.0.1.rc1``
83
+ Release: ``8.1.0.rc1``
83
84
 
84
85
 
85
86
  `Kubernetes <https://kubernetes.io/>`__
@@ -92,7 +93,7 @@ This is a provider package for ``cncf.kubernetes`` provider. All classes for thi
92
93
  are in ``airflow.providers.cncf.kubernetes`` python package.
93
94
 
94
95
  You can find package information and changelog for the provider
95
- in the `documentation <https://airflow.apache.org/docs/apache-airflow-providers-cncf-kubernetes/8.0.1/>`_.
96
+ in the `documentation <https://airflow.apache.org/docs/apache-airflow-providers-cncf-kubernetes/8.1.0/>`_.
96
97
 
97
98
  Installation
98
99
  ------------
@@ -101,7 +102,7 @@ You can install this package on top of an existing Airflow 2 installation (see `
101
102
  for the minimum Airflow version supported) via
102
103
  ``pip install apache-airflow-providers-cncf-kubernetes``
103
104
 
104
- The package supports the following python versions: 3.8,3.9,3.10,3.11
105
+ The package supports the following python versions: 3.8,3.9,3.10,3.11,3.12
105
106
 
106
107
  Requirements
107
108
  ------------
@@ -119,4 +120,4 @@ PIP package Version required
119
120
  ====================== =====================
120
121
 
121
122
  The changelog for the provider package can be found in the
122
- `changelog <https://airflow.apache.org/docs/apache-airflow-providers-cncf-kubernetes/8.0.1/changelog.html>`_.
123
+ `changelog <https://airflow.apache.org/docs/apache-airflow-providers-cncf-kubernetes/8.1.0/changelog.html>`_.
@@ -42,7 +42,7 @@
42
42
 
43
43
  Package ``apache-airflow-providers-cncf-kubernetes``
44
44
 
45
- Release: ``8.0.1.rc1``
45
+ Release: ``8.1.0.rc1``
46
46
 
47
47
 
48
48
  `Kubernetes <https://kubernetes.io/>`__
@@ -55,7 +55,7 @@ This is a provider package for ``cncf.kubernetes`` provider. All classes for thi
55
55
  are in ``airflow.providers.cncf.kubernetes`` python package.
56
56
 
57
57
  You can find package information and changelog for the provider
58
- in the `documentation <https://airflow.apache.org/docs/apache-airflow-providers-cncf-kubernetes/8.0.1/>`_.
58
+ in the `documentation <https://airflow.apache.org/docs/apache-airflow-providers-cncf-kubernetes/8.1.0/>`_.
59
59
 
60
60
  Installation
61
61
  ------------
@@ -64,7 +64,7 @@ You can install this package on top of an existing Airflow 2 installation (see `
64
64
  for the minimum Airflow version supported) via
65
65
  ``pip install apache-airflow-providers-cncf-kubernetes``
66
66
 
67
- The package supports the following python versions: 3.8,3.9,3.10,3.11
67
+ The package supports the following python versions: 3.8,3.9,3.10,3.11,3.12
68
68
 
69
69
  Requirements
70
70
  ------------
@@ -82,4 +82,4 @@ PIP package Version required
82
82
  ====================== =====================
83
83
 
84
84
  The changelog for the provider package can be found in the
85
- `changelog <https://airflow.apache.org/docs/apache-airflow-providers-cncf-kubernetes/8.0.1/changelog.html>`_.
85
+ `changelog <https://airflow.apache.org/docs/apache-airflow-providers-cncf-kubernetes/8.1.0/changelog.html>`_.
@@ -27,7 +27,7 @@ import packaging.version
27
27
 
28
28
  __all__ = ["__version__"]
29
29
 
30
- __version__ = "8.0.1"
30
+ __version__ = "8.1.0"
31
31
 
32
32
  try:
33
33
  from airflow import __version__ as airflow_version
@@ -15,6 +15,7 @@
15
15
  # specific language governing permissions and limitations
16
16
  # under the License.
17
17
  """Executes task in a Kubernetes POD."""
18
+
18
19
  from __future__ import annotations
19
20
 
20
21
  from kubernetes.client import ApiClient, models as k8s
@@ -21,6 +21,7 @@ KubernetesExecutor.
21
21
  For more information on how the KubernetesExecutor works, take a look at the guide:
22
22
  :doc:`/kubernetes_executor`
23
23
  """
24
+
24
25
  from __future__ import annotations
25
26
 
26
27
  import contextlib
@@ -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": 1709555165,
31
+ "source-date-epoch": 1712665231,
32
32
  "versions": [
33
+ "8.1.0",
33
34
  "8.0.1",
34
35
  "8.0.0",
35
36
  "7.14.0",
@@ -135,7 +136,10 @@ def get_provider_info():
135
136
  "triggers": [
136
137
  {
137
138
  "integration-name": "Kubernetes",
138
- "python-modules": ["airflow.providers.cncf.kubernetes.triggers.pod"],
139
+ "python-modules": [
140
+ "airflow.providers.cncf.kubernetes.triggers.pod",
141
+ "airflow.providers.cncf.kubernetes.triggers.job",
142
+ ],
139
143
  }
140
144
  ],
141
145
  "connection-types": [
@@ -16,10 +16,12 @@
16
16
  # under the License.
17
17
  from __future__ import annotations
18
18
 
19
+ import asyncio
19
20
  import contextlib
20
21
  import json
21
22
  import tempfile
22
23
  from functools import cached_property
24
+ from time import sleep
23
25
  from typing import TYPE_CHECKING, Any, Generator
24
26
 
25
27
  import aiofiles
@@ -37,10 +39,18 @@ from airflow.providers.cncf.kubernetes.utils.pod_manager import PodOperatorHookP
37
39
  from airflow.utils import yaml
38
40
 
39
41
  if TYPE_CHECKING:
42
+ from kubernetes.client import V1JobList
40
43
  from kubernetes.client.models import V1Deployment, V1Job, V1Pod
41
44
 
42
45
  LOADING_KUBE_CONFIG_FILE_RESOURCE = "Loading Kubernetes configuration file kube_config from {}..."
43
46
 
47
+ JOB_FINAL_STATUS_CONDITION_TYPES = {
48
+ "Complete",
49
+ "Failed",
50
+ }
51
+
52
+ JOB_STATUS_CONDITION_TYPES = JOB_FINAL_STATUS_CONDITION_TYPES | {"Suspended"}
53
+
44
54
 
45
55
  def _load_body_to_dict(body: str) -> dict:
46
56
  try:
@@ -502,6 +512,114 @@ class KubernetesHook(BaseHook, PodOperatorHookProtocol):
502
512
  raise e
503
513
  return resp
504
514
 
515
+ def get_job(self, job_name: str, namespace: str) -> V1Job:
516
+ """Get Job of specified name and namespace.
517
+
518
+ :param job_name: Name of Job to fetch.
519
+ :param namespace: Namespace of the Job.
520
+ :return: Job object
521
+ """
522
+ return self.batch_v1_client.read_namespaced_job(name=job_name, namespace=namespace, pretty=True)
523
+
524
+ def get_job_status(self, job_name: str, namespace: str) -> V1Job:
525
+ """Get job with status of specified name and namespace.
526
+
527
+ :param job_name: Name of Job to fetch.
528
+ :param namespace: Namespace of the Job.
529
+ :return: Job object
530
+ """
531
+ return self.batch_v1_client.read_namespaced_job_status(
532
+ name=job_name, namespace=namespace, pretty=True
533
+ )
534
+
535
+ def wait_until_job_complete(self, job_name: str, namespace: str, job_poll_interval: float = 10) -> V1Job:
536
+ """Block job of specified name and namespace until it is complete or failed.
537
+
538
+ :param job_name: Name of Job to fetch.
539
+ :param namespace: Namespace of the Job.
540
+ :param job_poll_interval: Interval in seconds between polling the job status
541
+ :return: Job object
542
+ """
543
+ while True:
544
+ self.log.info("Requesting status for the job '%s' ", job_name)
545
+ job: V1Job = self.get_job_status(job_name=job_name, namespace=namespace)
546
+ if self.is_job_complete(job=job):
547
+ return job
548
+ self.log.info("The job '%s' is incomplete. Sleeping for %i sec.", job_name, job_poll_interval)
549
+ sleep(job_poll_interval)
550
+
551
+ def list_jobs_all_namespaces(self) -> V1JobList:
552
+ """Get list of Jobs from all namespaces.
553
+
554
+ :return: V1JobList object
555
+ """
556
+ return self.batch_v1_client.list_job_for_all_namespaces(pretty=True)
557
+
558
+ def list_jobs_from_namespace(self, namespace: str) -> V1JobList:
559
+ """Get list of Jobs from dedicated namespace.
560
+
561
+ :param namespace: Namespace of the Job.
562
+ :return: V1JobList object
563
+ """
564
+ return self.batch_v1_client.list_namespaced_job(namespace=namespace, pretty=True)
565
+
566
+ def is_job_complete(self, job: V1Job) -> bool:
567
+ """Check whether the given job is complete (with success or fail).
568
+
569
+ :return: Boolean indicating that the given job is complete.
570
+ """
571
+ if status := job.status:
572
+ if conditions := status.conditions:
573
+ if final_condition_types := list(
574
+ c for c in conditions if c.type in JOB_FINAL_STATUS_CONDITION_TYPES and c.status
575
+ ):
576
+ s = "s" if len(final_condition_types) > 1 else ""
577
+ self.log.info(
578
+ "The job '%s' state%s: %s",
579
+ job.metadata.name,
580
+ s,
581
+ ", ".join(f"{c.type} at {c.last_transition_time}" for c in final_condition_types),
582
+ )
583
+ return True
584
+ return False
585
+
586
+ @staticmethod
587
+ def is_job_failed(job: V1Job) -> str | bool:
588
+ """Check whether the given job is failed.
589
+
590
+ :return: Error message if the job is failed, and False otherwise.
591
+ """
592
+ if status := job.status:
593
+ conditions = status.conditions or []
594
+ if fail_condition := next((c for c in conditions if c.type == "Failed" and c.status), None):
595
+ return fail_condition.reason
596
+ return False
597
+
598
+ @staticmethod
599
+ def is_job_successful(job: V1Job) -> str | bool:
600
+ """Check whether the given job is completed successfully..
601
+
602
+ :return: Error message if the job is failed, and False otherwise.
603
+ """
604
+ if status := job.status:
605
+ conditions = status.conditions or []
606
+ return bool(next((c for c in conditions if c.type == "Complete" and c.status), None))
607
+ return False
608
+
609
+ def patch_namespaced_job(self, job_name: str, namespace: str, body: object) -> V1Job:
610
+ """
611
+ Update the specified Job.
612
+
613
+ :param job_name: name of the Job
614
+ :param namespace: the namespace to run within kubernetes
615
+ :param body: json object with parameters for update
616
+ """
617
+ return self.batch_v1_client.patch_namespaced_job(
618
+ name=job_name,
619
+ namespace=namespace,
620
+ body=body,
621
+ )
622
+
505
623
 
506
624
  def _get_bool(val) -> bool | None:
507
625
  """Convert val to bool if can be done with certainty; if we cannot infer intention we return None."""
@@ -667,3 +785,34 @@ class AsyncKubernetesHook(KubernetesHook):
667
785
  except HTTPError:
668
786
  self.log.exception("There was an error reading the kubernetes API.")
669
787
  raise
788
+
789
+ async def get_job_status(self, name: str, namespace: str) -> V1Job:
790
+ """
791
+ Get job's status object.
792
+
793
+ :param name: Name of the pod.
794
+ :param namespace: Name of the pod's namespace.
795
+ """
796
+ async with self.get_conn() as connection:
797
+ v1_api = async_client.BatchV1Api(connection)
798
+ job: V1Job = await v1_api.read_namespaced_job_status(
799
+ name=name,
800
+ namespace=namespace,
801
+ )
802
+ return job
803
+
804
+ async def wait_until_job_complete(self, name: str, namespace: str, poll_interval: float = 10) -> V1Job:
805
+ """Block job of specified name and namespace until it is complete or failed.
806
+
807
+ :param name: Name of Job to fetch.
808
+ :param namespace: Namespace of the Job.
809
+ :param poll_interval: Interval in seconds between polling the job status
810
+ :return: Job object
811
+ """
812
+ while True:
813
+ self.log.info("Requesting status for the job '%s' ", name)
814
+ job: V1Job = await self.get_job_status(name=name, namespace=namespace)
815
+ if self.is_job_complete(job=job):
816
+ return job
817
+ self.log.info("The job '%s' is incomplete. Sleeping for %i sec.", name, poll_interval)
818
+ await asyncio.sleep(poll_interval)
@@ -15,6 +15,7 @@
15
15
  # specific language governing permissions and limitations
16
16
  # under the License.
17
17
  """Classes for interacting with Kubernetes API."""
18
+
18
19
  from __future__ import annotations
19
20
 
20
21
  from abc import ABC, abstractmethod
@@ -15,6 +15,7 @@
15
15
  # specific language governing permissions and limitations
16
16
  # under the License.
17
17
  """Client for kubernetes communication."""
18
+
18
19
  from __future__ import annotations
19
20
 
20
21
  import logging
@@ -104,7 +104,7 @@ def create_unique_id(
104
104
  name += task_id
105
105
  base_name = slugify(name, lowercase=True)[:max_length].strip(".-")
106
106
  if unique:
107
- return add_pod_suffix(pod_name=base_name, rand_len=8, max_len=max_length)
107
+ return add_unique_suffix(name=base_name, rand_len=8, max_len=max_length)
108
108
  else:
109
109
  return base_name
110
110
 
@@ -15,6 +15,7 @@
15
15
  # specific language governing permissions and limitations
16
16
  # under the License.
17
17
  """Launches Custom object."""
18
+
18
19
  from __future__ import annotations
19
20
 
20
21
  import time
@@ -59,9 +60,9 @@ class SparkJobSpec:
59
60
  if self.spec.get("dynamicAllocation", {}).get("enabled"):
60
61
  if not all(
61
62
  [
62
- self.spec["dynamicAllocation"]["initialExecutors"],
63
- self.spec["dynamicAllocation"]["minExecutors"],
64
- self.spec["dynamicAllocation"]["maxExecutors"],
63
+ self.spec["dynamicAllocation"].get("initialExecutors"),
64
+ self.spec["dynamicAllocation"].get("minExecutors"),
65
+ self.spec["dynamicAllocation"].get("maxExecutors"),
65
66
  ]
66
67
  ):
67
68
  raise AirflowException("Make sure initial/min/max value for dynamic allocation is passed")