apache-airflow-providers-cncf-kubernetes 7.0.0rc2__tar.gz → 7.1.0__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.
- {apache-airflow-providers-cncf-kubernetes-7.0.0rc2/apache_airflow_providers_cncf_kubernetes.egg-info → apache-airflow-providers-cncf-kubernetes-7.1.0}/PKG-INFO +37 -7
- {apache-airflow-providers-cncf-kubernetes-7.0.0rc2 → apache-airflow-providers-cncf-kubernetes-7.1.0}/README.rst +33 -3
- {apache-airflow-providers-cncf-kubernetes-7.0.0rc2 → apache-airflow-providers-cncf-kubernetes-7.1.0}/airflow/providers/cncf/kubernetes/__init__.py +1 -1
- {apache-airflow-providers-cncf-kubernetes-7.0.0rc2 → apache-airflow-providers-cncf-kubernetes-7.1.0}/airflow/providers/cncf/kubernetes/backcompat/backwards_compat_converters.py +10 -10
- {apache-airflow-providers-cncf-kubernetes-7.0.0rc2 → apache-airflow-providers-cncf-kubernetes-7.1.0}/airflow/providers/cncf/kubernetes/get_provider_info.py +3 -1
- {apache-airflow-providers-cncf-kubernetes-7.0.0rc2 → apache-airflow-providers-cncf-kubernetes-7.1.0}/airflow/providers/cncf/kubernetes/hooks/kubernetes.py +14 -12
- {apache-airflow-providers-cncf-kubernetes-7.0.0rc2 → apache-airflow-providers-cncf-kubernetes-7.1.0}/airflow/providers/cncf/kubernetes/operators/pod.py +22 -12
- apache-airflow-providers-cncf-kubernetes-7.1.0/airflow/providers/cncf/kubernetes/operators/resource.py +103 -0
- {apache-airflow-providers-cncf-kubernetes-7.0.0rc2 → apache-airflow-providers-cncf-kubernetes-7.1.0}/airflow/providers/cncf/kubernetes/operators/spark_kubernetes.py +1 -1
- {apache-airflow-providers-cncf-kubernetes-7.0.0rc2 → apache-airflow-providers-cncf-kubernetes-7.1.0}/airflow/providers/cncf/kubernetes/python_kubernetes_script.py +2 -2
- {apache-airflow-providers-cncf-kubernetes-7.0.0rc2 → apache-airflow-providers-cncf-kubernetes-7.1.0}/airflow/providers/cncf/kubernetes/sensors/spark_kubernetes.py +1 -1
- {apache-airflow-providers-cncf-kubernetes-7.0.0rc2 → apache-airflow-providers-cncf-kubernetes-7.1.0}/airflow/providers/cncf/kubernetes/triggers/pod.py +1 -1
- apache-airflow-providers-cncf-kubernetes-7.1.0/airflow/providers/cncf/kubernetes/utils/delete_from.py +157 -0
- {apache-airflow-providers-cncf-kubernetes-7.0.0rc2 → apache-airflow-providers-cncf-kubernetes-7.1.0}/airflow/providers/cncf/kubernetes/utils/pod_manager.py +35 -21
- {apache-airflow-providers-cncf-kubernetes-7.0.0rc2 → apache-airflow-providers-cncf-kubernetes-7.1.0}/airflow/providers/cncf/kubernetes/utils/xcom_sidecar.py +2 -2
- {apache-airflow-providers-cncf-kubernetes-7.0.0rc2 → apache-airflow-providers-cncf-kubernetes-7.1.0/apache_airflow_providers_cncf_kubernetes.egg-info}/PKG-INFO +37 -7
- {apache-airflow-providers-cncf-kubernetes-7.0.0rc2 → apache-airflow-providers-cncf-kubernetes-7.1.0}/apache_airflow_providers_cncf_kubernetes.egg-info/SOURCES.txt +2 -0
- {apache-airflow-providers-cncf-kubernetes-7.0.0rc2 → apache-airflow-providers-cncf-kubernetes-7.1.0}/apache_airflow_providers_cncf_kubernetes.egg-info/requires.txt +1 -1
- {apache-airflow-providers-cncf-kubernetes-7.0.0rc2 → apache-airflow-providers-cncf-kubernetes-7.1.0}/pyproject.toml +6 -5
- {apache-airflow-providers-cncf-kubernetes-7.0.0rc2 → apache-airflow-providers-cncf-kubernetes-7.1.0}/setup.cfg +5 -5
- {apache-airflow-providers-cncf-kubernetes-7.0.0rc2 → apache-airflow-providers-cncf-kubernetes-7.1.0}/setup.py +1 -1
- {apache-airflow-providers-cncf-kubernetes-7.0.0rc2 → apache-airflow-providers-cncf-kubernetes-7.1.0}/LICENSE +0 -0
- {apache-airflow-providers-cncf-kubernetes-7.0.0rc2 → apache-airflow-providers-cncf-kubernetes-7.1.0}/MANIFEST.in +0 -0
- {apache-airflow-providers-cncf-kubernetes-7.0.0rc2 → apache-airflow-providers-cncf-kubernetes-7.1.0}/NOTICE +0 -0
- {apache-airflow-providers-cncf-kubernetes-7.0.0rc2 → apache-airflow-providers-cncf-kubernetes-7.1.0}/airflow/providers/cncf/kubernetes/backcompat/__init__.py +0 -0
- {apache-airflow-providers-cncf-kubernetes-7.0.0rc2 → apache-airflow-providers-cncf-kubernetes-7.1.0}/airflow/providers/cncf/kubernetes/decorators/__init__.py +0 -0
- {apache-airflow-providers-cncf-kubernetes-7.0.0rc2 → apache-airflow-providers-cncf-kubernetes-7.1.0}/airflow/providers/cncf/kubernetes/decorators/kubernetes.py +0 -0
- {apache-airflow-providers-cncf-kubernetes-7.0.0rc2 → apache-airflow-providers-cncf-kubernetes-7.1.0}/airflow/providers/cncf/kubernetes/hooks/__init__.py +0 -0
- {apache-airflow-providers-cncf-kubernetes-7.0.0rc2 → apache-airflow-providers-cncf-kubernetes-7.1.0}/airflow/providers/cncf/kubernetes/operators/__init__.py +0 -0
- {apache-airflow-providers-cncf-kubernetes-7.0.0rc2 → apache-airflow-providers-cncf-kubernetes-7.1.0}/airflow/providers/cncf/kubernetes/operators/kubernetes_pod.py +0 -0
- {apache-airflow-providers-cncf-kubernetes-7.0.0rc2 → apache-airflow-providers-cncf-kubernetes-7.1.0}/airflow/providers/cncf/kubernetes/python_kubernetes_script.jinja2 +0 -0
- {apache-airflow-providers-cncf-kubernetes-7.0.0rc2 → apache-airflow-providers-cncf-kubernetes-7.1.0}/airflow/providers/cncf/kubernetes/sensors/__init__.py +0 -0
- {apache-airflow-providers-cncf-kubernetes-7.0.0rc2 → apache-airflow-providers-cncf-kubernetes-7.1.0}/airflow/providers/cncf/kubernetes/triggers/__init__.py +0 -0
- {apache-airflow-providers-cncf-kubernetes-7.0.0rc2 → apache-airflow-providers-cncf-kubernetes-7.1.0}/airflow/providers/cncf/kubernetes/triggers/kubernetes_pod.py +0 -0
- {apache-airflow-providers-cncf-kubernetes-7.0.0rc2 → apache-airflow-providers-cncf-kubernetes-7.1.0}/airflow/providers/cncf/kubernetes/utils/__init__.py +0 -0
- {apache-airflow-providers-cncf-kubernetes-7.0.0rc2 → apache-airflow-providers-cncf-kubernetes-7.1.0}/apache_airflow_providers_cncf_kubernetes.egg-info/dependency_links.txt +0 -0
- {apache-airflow-providers-cncf-kubernetes-7.0.0rc2 → apache-airflow-providers-cncf-kubernetes-7.1.0}/apache_airflow_providers_cncf_kubernetes.egg-info/entry_points.txt +0 -0
- {apache-airflow-providers-cncf-kubernetes-7.0.0rc2 → apache-airflow-providers-cncf-kubernetes-7.1.0}/apache_airflow_providers_cncf_kubernetes.egg-info/not-zip-safe +0 -0
- {apache-airflow-providers-cncf-kubernetes-7.0.0rc2 → apache-airflow-providers-cncf-kubernetes-7.1.0}/apache_airflow_providers_cncf_kubernetes.egg-info/top_level.txt +0 -0
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: apache-airflow-providers-cncf-kubernetes
|
|
3
|
-
Version: 7.0
|
|
3
|
+
Version: 7.1.0
|
|
4
4
|
Summary: Provider for Apache Airflow. Implements apache-airflow-providers-cncf-kubernetes package
|
|
5
5
|
Home-page: https://airflow.apache.org/
|
|
6
6
|
Download-URL: https://archive.apache.org/dist/airflow/providers
|
|
7
7
|
Author: Apache Software Foundation
|
|
8
8
|
Author-email: dev@airflow.apache.org
|
|
9
9
|
License: Apache License 2.0
|
|
10
|
-
Project-URL: Documentation, https://airflow.apache.org/docs/apache-airflow-providers-cncf-kubernetes/7.
|
|
10
|
+
Project-URL: Documentation, https://airflow.apache.org/docs/apache-airflow-providers-cncf-kubernetes/7.1.0/
|
|
11
11
|
Project-URL: Bug Tracker, https://github.com/apache/airflow/issues
|
|
12
12
|
Project-URL: Source Code, https://github.com/apache/airflow
|
|
13
13
|
Project-URL: Slack Chat, https://s.apache.org/airflow-slack
|
|
@@ -21,12 +21,12 @@ Classifier: Intended Audience :: System Administrators
|
|
|
21
21
|
Classifier: Framework :: Apache Airflow
|
|
22
22
|
Classifier: Framework :: Apache Airflow :: Provider
|
|
23
23
|
Classifier: License :: OSI Approved :: Apache Software License
|
|
24
|
-
Classifier: Programming Language :: Python :: 3.7
|
|
25
24
|
Classifier: Programming Language :: Python :: 3.8
|
|
26
25
|
Classifier: Programming Language :: Python :: 3.9
|
|
27
26
|
Classifier: Programming Language :: Python :: 3.10
|
|
27
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
28
28
|
Classifier: Topic :: System :: Monitoring
|
|
29
|
-
Requires-Python: ~=3.
|
|
29
|
+
Requires-Python: ~=3.8
|
|
30
30
|
Description-Content-Type: text/x-rst
|
|
31
31
|
License-File: LICENSE
|
|
32
32
|
License-File: NOTICE
|
|
@@ -52,7 +52,7 @@ License-File: NOTICE
|
|
|
52
52
|
|
|
53
53
|
Package ``apache-airflow-providers-cncf-kubernetes``
|
|
54
54
|
|
|
55
|
-
Release: ``7.0
|
|
55
|
+
Release: ``7.1.0``
|
|
56
56
|
|
|
57
57
|
|
|
58
58
|
`Kubernetes <https://kubernetes.io/>`__
|
|
@@ -65,7 +65,7 @@ This is a provider package for ``cncf.kubernetes`` provider. All classes for thi
|
|
|
65
65
|
are in ``airflow.providers.cncf.kubernetes`` python package.
|
|
66
66
|
|
|
67
67
|
You can find package information and changelog for the provider
|
|
68
|
-
in the `documentation <https://airflow.apache.org/docs/apache-airflow-providers-cncf-kubernetes/7.
|
|
68
|
+
in the `documentation <https://airflow.apache.org/docs/apache-airflow-providers-cncf-kubernetes/7.1.0/>`_.
|
|
69
69
|
|
|
70
70
|
|
|
71
71
|
Installation
|
|
@@ -75,7 +75,7 @@ You can install this package on top of an existing Airflow 2 installation (see `
|
|
|
75
75
|
for the minimum Airflow version supported) via
|
|
76
76
|
``pip install apache-airflow-providers-cncf-kubernetes``
|
|
77
77
|
|
|
78
|
-
The package supports the following python versions: 3.
|
|
78
|
+
The package supports the following python versions: 3.8,3.9,3.10,3.11
|
|
79
79
|
|
|
80
80
|
Requirements
|
|
81
81
|
------------
|
|
@@ -116,7 +116,37 @@ PIP package Version required
|
|
|
116
116
|
Changelog
|
|
117
117
|
---------
|
|
118
118
|
|
|
119
|
+
7.1.0
|
|
120
|
+
.....
|
|
121
|
+
|
|
122
|
+
.. note::
|
|
123
|
+
This release dropped support for Python 3.7
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
Features
|
|
127
|
+
~~~~~~~~
|
|
128
|
+
* ``KubernetesResourceOperator - KubernetesDeleteResourceOperator & KubernetesCreateResourceOperator (#29930)``
|
|
129
|
+
* ``add a return when the event is yielded in a loop to stop the execution (#31985)``
|
|
130
|
+
* ``Add possibility to disable logging the pod template in a case when task fails (#31595)``
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
Bug Fixes
|
|
134
|
+
~~~~~~~~~
|
|
135
|
+
|
|
136
|
+
* ``Remove return statement after yield from triggers class (#31703)``
|
|
137
|
+
* ``Fix Fargate logging for AWS system tests (#31622)``
|
|
119
138
|
|
|
139
|
+
Misc
|
|
140
|
+
~~~~
|
|
141
|
+
|
|
142
|
+
* ``Remove Python 3.7 support (#30963)``
|
|
143
|
+
|
|
144
|
+
.. Below changes are excluded from the changelog. Move them to
|
|
145
|
+
appropriate section above if needed. Do not delete the lines(!):
|
|
146
|
+
* ``Add D400 pydocstyle check (#31742)``
|
|
147
|
+
* ``Add discoverability for triggers in provider.yaml (#31576)``
|
|
148
|
+
* ``Add D400 pydocstyle check - Providers (#31427)``
|
|
149
|
+
* ``Add note about dropping Python 3.7 for providers (#32015)``
|
|
120
150
|
|
|
121
151
|
7.0.0
|
|
122
152
|
.....
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
|
|
20
20
|
Package ``apache-airflow-providers-cncf-kubernetes``
|
|
21
21
|
|
|
22
|
-
Release: ``7.0
|
|
22
|
+
Release: ``7.1.0``
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
`Kubernetes <https://kubernetes.io/>`__
|
|
@@ -32,7 +32,7 @@ This is a provider package for ``cncf.kubernetes`` provider. All classes for thi
|
|
|
32
32
|
are in ``airflow.providers.cncf.kubernetes`` python package.
|
|
33
33
|
|
|
34
34
|
You can find package information and changelog for the provider
|
|
35
|
-
in the `documentation <https://airflow.apache.org/docs/apache-airflow-providers-cncf-kubernetes/7.
|
|
35
|
+
in the `documentation <https://airflow.apache.org/docs/apache-airflow-providers-cncf-kubernetes/7.1.0/>`_.
|
|
36
36
|
|
|
37
37
|
|
|
38
38
|
Installation
|
|
@@ -42,7 +42,7 @@ You can install this package on top of an existing Airflow 2 installation (see `
|
|
|
42
42
|
for the minimum Airflow version supported) via
|
|
43
43
|
``pip install apache-airflow-providers-cncf-kubernetes``
|
|
44
44
|
|
|
45
|
-
The package supports the following python versions: 3.
|
|
45
|
+
The package supports the following python versions: 3.8,3.9,3.10,3.11
|
|
46
46
|
|
|
47
47
|
Requirements
|
|
48
48
|
------------
|
|
@@ -83,7 +83,37 @@ PIP package Version required
|
|
|
83
83
|
Changelog
|
|
84
84
|
---------
|
|
85
85
|
|
|
86
|
+
7.1.0
|
|
87
|
+
.....
|
|
88
|
+
|
|
89
|
+
.. note::
|
|
90
|
+
This release dropped support for Python 3.7
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
Features
|
|
94
|
+
~~~~~~~~
|
|
95
|
+
* ``KubernetesResourceOperator - KubernetesDeleteResourceOperator & KubernetesCreateResourceOperator (#29930)``
|
|
96
|
+
* ``add a return when the event is yielded in a loop to stop the execution (#31985)``
|
|
97
|
+
* ``Add possibility to disable logging the pod template in a case when task fails (#31595)``
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
Bug Fixes
|
|
101
|
+
~~~~~~~~~
|
|
102
|
+
|
|
103
|
+
* ``Remove return statement after yield from triggers class (#31703)``
|
|
104
|
+
* ``Fix Fargate logging for AWS system tests (#31622)``
|
|
86
105
|
|
|
106
|
+
Misc
|
|
107
|
+
~~~~
|
|
108
|
+
|
|
109
|
+
* ``Remove Python 3.7 support (#30963)``
|
|
110
|
+
|
|
111
|
+
.. Below changes are excluded from the changelog. Move them to
|
|
112
|
+
appropriate section above if needed. Do not delete the lines(!):
|
|
113
|
+
* ``Add D400 pydocstyle check (#31742)``
|
|
114
|
+
* ``Add discoverability for triggers in provider.yaml (#31576)``
|
|
115
|
+
* ``Add D400 pydocstyle check - Providers (#31427)``
|
|
116
|
+
* ``Add note about dropping Python 3.7 for providers (#32015)``
|
|
87
117
|
|
|
88
118
|
7.0.0
|
|
89
119
|
.....
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
# KIND, either express or implied. See the License for the
|
|
15
15
|
# specific language governing permissions and limitations
|
|
16
16
|
# under the License.
|
|
17
|
-
"""Executes task in a Kubernetes POD"""
|
|
17
|
+
"""Executes task in a Kubernetes POD."""
|
|
18
18
|
from __future__ import annotations
|
|
19
19
|
|
|
20
20
|
from kubernetes.client import ApiClient, models as k8s
|
|
@@ -43,7 +43,7 @@ def _convert_from_dict(obj, new_class):
|
|
|
43
43
|
|
|
44
44
|
|
|
45
45
|
def convert_volume(volume) -> k8s.V1Volume:
|
|
46
|
-
"""Converts an airflow Volume object into a k8s.V1Volume
|
|
46
|
+
"""Converts an airflow Volume object into a k8s.V1Volume.
|
|
47
47
|
|
|
48
48
|
:param volume:
|
|
49
49
|
"""
|
|
@@ -51,7 +51,7 @@ def convert_volume(volume) -> k8s.V1Volume:
|
|
|
51
51
|
|
|
52
52
|
|
|
53
53
|
def convert_volume_mount(volume_mount) -> k8s.V1VolumeMount:
|
|
54
|
-
"""Converts an airflow VolumeMount object into a k8s.V1VolumeMount
|
|
54
|
+
"""Converts an airflow VolumeMount object into a k8s.V1VolumeMount.
|
|
55
55
|
|
|
56
56
|
:param volume_mount:
|
|
57
57
|
"""
|
|
@@ -59,7 +59,7 @@ def convert_volume_mount(volume_mount) -> k8s.V1VolumeMount:
|
|
|
59
59
|
|
|
60
60
|
|
|
61
61
|
def convert_port(port) -> k8s.V1ContainerPort:
|
|
62
|
-
"""Converts an airflow Port object into a k8s.V1ContainerPort
|
|
62
|
+
"""Converts an airflow Port object into a k8s.V1ContainerPort.
|
|
63
63
|
|
|
64
64
|
:param port:
|
|
65
65
|
"""
|
|
@@ -67,7 +67,7 @@ def convert_port(port) -> k8s.V1ContainerPort:
|
|
|
67
67
|
|
|
68
68
|
|
|
69
69
|
def convert_env_vars(env_vars) -> list[k8s.V1EnvVar]:
|
|
70
|
-
"""Converts a dictionary into a list of env_vars
|
|
70
|
+
"""Converts a dictionary into a list of env_vars.
|
|
71
71
|
|
|
72
72
|
:param env_vars:
|
|
73
73
|
"""
|
|
@@ -83,7 +83,7 @@ def convert_env_vars(env_vars) -> list[k8s.V1EnvVar]:
|
|
|
83
83
|
|
|
84
84
|
|
|
85
85
|
def convert_pod_runtime_info_env(pod_runtime_info_envs) -> k8s.V1EnvVar:
|
|
86
|
-
"""Converts a PodRuntimeInfoEnv into an k8s.V1EnvVar
|
|
86
|
+
"""Converts a PodRuntimeInfoEnv into an k8s.V1EnvVar.
|
|
87
87
|
|
|
88
88
|
:param pod_runtime_info_envs:
|
|
89
89
|
"""
|
|
@@ -91,7 +91,7 @@ def convert_pod_runtime_info_env(pod_runtime_info_envs) -> k8s.V1EnvVar:
|
|
|
91
91
|
|
|
92
92
|
|
|
93
93
|
def convert_image_pull_secrets(image_pull_secrets) -> list[k8s.V1LocalObjectReference]:
|
|
94
|
-
"""Converts a PodRuntimeInfoEnv into an k8s.V1EnvVar
|
|
94
|
+
"""Converts a PodRuntimeInfoEnv into an k8s.V1EnvVar.
|
|
95
95
|
|
|
96
96
|
:param image_pull_secrets:
|
|
97
97
|
"""
|
|
@@ -103,7 +103,7 @@ def convert_image_pull_secrets(image_pull_secrets) -> list[k8s.V1LocalObjectRefe
|
|
|
103
103
|
|
|
104
104
|
|
|
105
105
|
def convert_configmap(configmaps) -> k8s.V1EnvFromSource:
|
|
106
|
-
"""Converts a str into an k8s.V1EnvFromSource
|
|
106
|
+
"""Converts a str into an k8s.V1EnvFromSource.
|
|
107
107
|
|
|
108
108
|
:param configmaps:
|
|
109
109
|
"""
|
|
@@ -111,10 +111,10 @@ def convert_configmap(configmaps) -> k8s.V1EnvFromSource:
|
|
|
111
111
|
|
|
112
112
|
|
|
113
113
|
def convert_affinity(affinity) -> k8s.V1Affinity:
|
|
114
|
-
"""Converts a dict into an k8s.V1Affinity"""
|
|
114
|
+
"""Converts a dict into an k8s.V1Affinity."""
|
|
115
115
|
return _convert_from_dict(affinity, k8s.V1Affinity)
|
|
116
116
|
|
|
117
117
|
|
|
118
118
|
def convert_toleration(toleration) -> k8s.V1Toleration:
|
|
119
|
-
"""Converts a dict into an k8s.V1Toleration"""
|
|
119
|
+
"""Converts a dict into an k8s.V1Toleration."""
|
|
120
120
|
return _convert_from_dict(toleration, k8s.V1Toleration)
|
|
@@ -29,6 +29,7 @@ def get_provider_info():
|
|
|
29
29
|
"description": "`Kubernetes <https://kubernetes.io/>`__\n",
|
|
30
30
|
"suspended": False,
|
|
31
31
|
"versions": [
|
|
32
|
+
"7.1.0",
|
|
32
33
|
"7.0.0",
|
|
33
34
|
"6.1.0",
|
|
34
35
|
"6.0.0",
|
|
@@ -93,6 +94,7 @@ def get_provider_info():
|
|
|
93
94
|
"airflow.providers.cncf.kubernetes.operators.kubernetes_pod",
|
|
94
95
|
"airflow.providers.cncf.kubernetes.operators.pod",
|
|
95
96
|
"airflow.providers.cncf.kubernetes.operators.spark_kubernetes",
|
|
97
|
+
"airflow.providers.cncf.kubernetes.operators.resource",
|
|
96
98
|
],
|
|
97
99
|
}
|
|
98
100
|
],
|
|
@@ -111,7 +113,7 @@ def get_provider_info():
|
|
|
111
113
|
"triggers": [
|
|
112
114
|
{
|
|
113
115
|
"integration-name": "Kubernetes",
|
|
114
|
-
"
|
|
116
|
+
"python-modules": ["airflow.providers.cncf.kubernetes.triggers.pod"],
|
|
115
117
|
}
|
|
116
118
|
],
|
|
117
119
|
"connection-types": [
|
|
@@ -18,6 +18,7 @@ from __future__ import annotations
|
|
|
18
18
|
|
|
19
19
|
import contextlib
|
|
20
20
|
import tempfile
|
|
21
|
+
from functools import cached_property
|
|
21
22
|
from typing import TYPE_CHECKING, Any, Generator
|
|
22
23
|
|
|
23
24
|
from asgiref.sync import sync_to_async
|
|
@@ -27,7 +28,6 @@ from kubernetes.config import ConfigException
|
|
|
27
28
|
from kubernetes_asyncio import client as async_client, config as async_config
|
|
28
29
|
from urllib3.exceptions import HTTPError
|
|
29
30
|
|
|
30
|
-
from airflow.compat.functools import cached_property
|
|
31
31
|
from airflow.exceptions import AirflowException, AirflowNotFoundException
|
|
32
32
|
from airflow.hooks.base import BaseHook
|
|
33
33
|
from airflow.kubernetes.kube_client import _disable_verify_ssl, _enable_tcp_keepalive
|
|
@@ -84,7 +84,7 @@ class KubernetesHook(BaseHook, PodOperatorHookProtocol):
|
|
|
84
84
|
|
|
85
85
|
@staticmethod
|
|
86
86
|
def get_connection_form_widgets() -> dict[str, Any]:
|
|
87
|
-
"""Returns connection widgets to add to connection form"""
|
|
87
|
+
"""Returns connection widgets to add to connection form."""
|
|
88
88
|
from flask_appbuilder.fieldwidgets import BS3TextFieldWidget
|
|
89
89
|
from flask_babel import lazy_gettext
|
|
90
90
|
from wtforms import BooleanField, StringField
|
|
@@ -103,7 +103,7 @@ class KubernetesHook(BaseHook, PodOperatorHookProtocol):
|
|
|
103
103
|
|
|
104
104
|
@staticmethod
|
|
105
105
|
def get_ui_field_behaviour() -> dict[str, Any]:
|
|
106
|
-
"""Returns custom field behaviour"""
|
|
106
|
+
"""Returns custom field behaviour."""
|
|
107
107
|
return {
|
|
108
108
|
"hidden_fields": ["host", "schema", "login", "password", "port", "extra"],
|
|
109
109
|
"relabeling": {},
|
|
@@ -177,7 +177,7 @@ class KubernetesHook(BaseHook, PodOperatorHookProtocol):
|
|
|
177
177
|
return self.conn_extras.get(prefixed_name) or None
|
|
178
178
|
|
|
179
179
|
def get_conn(self) -> client.ApiClient:
|
|
180
|
-
"""Returns kubernetes api session for use with requests"""
|
|
180
|
+
"""Returns kubernetes api session for use with requests."""
|
|
181
181
|
in_cluster = self._coalesce_param(self.in_cluster, self._get_field("in_cluster"))
|
|
182
182
|
cluster_context = self._coalesce_param(self.cluster_context, self._get_field("cluster_context"))
|
|
183
183
|
kubeconfig_path = self._coalesce_param(self.config_file, self._get_field("kube_config_path"))
|
|
@@ -253,7 +253,7 @@ class KubernetesHook(BaseHook, PodOperatorHookProtocol):
|
|
|
253
253
|
|
|
254
254
|
@property
|
|
255
255
|
def is_in_cluster(self) -> bool:
|
|
256
|
-
"""Expose whether the hook is configured with ``load_incluster_config`` or not"""
|
|
256
|
+
"""Expose whether the hook is configured with ``load_incluster_config`` or not."""
|
|
257
257
|
if self._is_in_cluster is not None:
|
|
258
258
|
return self._is_in_cluster
|
|
259
259
|
self.api_client # so we can determine if we are in_cluster or not
|
|
@@ -263,7 +263,7 @@ class KubernetesHook(BaseHook, PodOperatorHookProtocol):
|
|
|
263
263
|
|
|
264
264
|
@cached_property
|
|
265
265
|
def api_client(self) -> client.ApiClient:
|
|
266
|
-
"""Cached Kubernetes API client"""
|
|
266
|
+
"""Cached Kubernetes API client."""
|
|
267
267
|
return self.get_conn()
|
|
268
268
|
|
|
269
269
|
@cached_property
|
|
@@ -278,7 +278,8 @@ class KubernetesHook(BaseHook, PodOperatorHookProtocol):
|
|
|
278
278
|
self, group: str, version: str, plural: str, body: str | dict, namespace: str | None = None
|
|
279
279
|
):
|
|
280
280
|
"""
|
|
281
|
-
Creates custom resource definition object in Kubernetes
|
|
281
|
+
Creates custom resource definition object in Kubernetes.
|
|
282
|
+
|
|
282
283
|
:param group: api group
|
|
283
284
|
:param version: api version
|
|
284
285
|
:param plural: api plural
|
|
@@ -307,7 +308,7 @@ class KubernetesHook(BaseHook, PodOperatorHookProtocol):
|
|
|
307
308
|
self, group: str, version: str, plural: str, name: str, namespace: str | None = None
|
|
308
309
|
):
|
|
309
310
|
"""
|
|
310
|
-
Get custom resource definition object from Kubernetes
|
|
311
|
+
Get custom resource definition object from Kubernetes.
|
|
311
312
|
|
|
312
313
|
:param group: api group
|
|
313
314
|
:param version: api version
|
|
@@ -329,7 +330,7 @@ class KubernetesHook(BaseHook, PodOperatorHookProtocol):
|
|
|
329
330
|
self, group: str, version: str, plural: str, name: str, namespace: str | None = None, **kwargs
|
|
330
331
|
):
|
|
331
332
|
"""
|
|
332
|
-
Delete custom resource definition object from Kubernetes
|
|
333
|
+
Delete custom resource definition object from Kubernetes.
|
|
333
334
|
|
|
334
335
|
:param group: api group
|
|
335
336
|
:param version: api version
|
|
@@ -348,7 +349,7 @@ class KubernetesHook(BaseHook, PodOperatorHookProtocol):
|
|
|
348
349
|
)
|
|
349
350
|
|
|
350
351
|
def get_namespace(self) -> str | None:
|
|
351
|
-
"""Returns the namespace that defined in the connection"""
|
|
352
|
+
"""Returns the namespace that defined in the connection."""
|
|
352
353
|
if self.conn_id:
|
|
353
354
|
return self._get_field("namespace")
|
|
354
355
|
return None
|
|
@@ -412,7 +413,8 @@ class KubernetesHook(BaseHook, PodOperatorHookProtocol):
|
|
|
412
413
|
**kwargs,
|
|
413
414
|
):
|
|
414
415
|
"""
|
|
415
|
-
Retrieves a list of Kind pod which belong default kubernetes namespace
|
|
416
|
+
Retrieves a list of Kind pod which belong default kubernetes namespace.
|
|
417
|
+
|
|
416
418
|
:param label_selector: A selector to restrict the list of returned objects by their labels
|
|
417
419
|
:param namespace: kubernetes namespace
|
|
418
420
|
:param watch: Watch for changes to the described resources and return them as a stream
|
|
@@ -449,7 +451,7 @@ class AsyncKubernetesHook(KubernetesHook):
|
|
|
449
451
|
self._extras: dict | None = None
|
|
450
452
|
|
|
451
453
|
async def _load_config(self):
|
|
452
|
-
"""Returns Kubernetes API session for use with requests"""
|
|
454
|
+
"""Returns Kubernetes API session for use with requests."""
|
|
453
455
|
in_cluster = self._coalesce_param(self.in_cluster, await self._get_field("in_cluster"))
|
|
454
456
|
cluster_context = self._coalesce_param(self.cluster_context, await self._get_field("cluster_context"))
|
|
455
457
|
kubeconfig_path = self._coalesce_param(self.config_file, await self._get_field("kube_config_path"))
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
# KIND, either express or implied. See the License for the
|
|
15
15
|
# specific language governing permissions and limitations
|
|
16
16
|
# under the License.
|
|
17
|
-
"""Executes task in a Kubernetes POD"""
|
|
17
|
+
"""Executes task in a Kubernetes POD."""
|
|
18
18
|
|
|
19
19
|
from __future__ import annotations
|
|
20
20
|
|
|
@@ -25,13 +25,13 @@ import secrets
|
|
|
25
25
|
import string
|
|
26
26
|
from collections.abc import Container
|
|
27
27
|
from contextlib import AbstractContextManager
|
|
28
|
+
from functools import cached_property
|
|
28
29
|
from typing import TYPE_CHECKING, Any, Sequence
|
|
29
30
|
|
|
30
31
|
from kubernetes.client import CoreV1Api, models as k8s
|
|
31
32
|
from slugify import slugify
|
|
32
33
|
from urllib3.exceptions import HTTPError
|
|
33
34
|
|
|
34
|
-
from airflow.compat.functools import cached_property
|
|
35
35
|
from airflow.exceptions import AirflowException, AirflowSkipException
|
|
36
36
|
from airflow.kubernetes import pod_generator
|
|
37
37
|
from airflow.kubernetes.pod_generator import PodGenerator
|
|
@@ -85,7 +85,7 @@ def _rand_str(num):
|
|
|
85
85
|
|
|
86
86
|
|
|
87
87
|
def _add_pod_suffix(*, pod_name, rand_len=8, max_len=253):
|
|
88
|
-
"""Add random string to pod name while staying under max len
|
|
88
|
+
"""Add random string to pod name while staying under max len.
|
|
89
89
|
|
|
90
90
|
TODO: when min airflow version >= 2.5, delete this function and import from kubernetes_helper_functions.
|
|
91
91
|
|
|
@@ -135,7 +135,7 @@ class PodReattachFailure(AirflowException):
|
|
|
135
135
|
|
|
136
136
|
class KubernetesPodOperator(BaseOperator):
|
|
137
137
|
"""
|
|
138
|
-
Execute a task in a Kubernetes Pod
|
|
138
|
+
Execute a task in a Kubernetes Pod.
|
|
139
139
|
|
|
140
140
|
.. seealso::
|
|
141
141
|
For more information on how to use this operator, take a look at the guide:
|
|
@@ -225,6 +225,7 @@ class KubernetesPodOperator(BaseOperator):
|
|
|
225
225
|
container name to use.
|
|
226
226
|
:param deferrable: Run operator in the deferrable mode.
|
|
227
227
|
:param poll_interval: Polling period in seconds to check for the status. Used only in deferrable mode.
|
|
228
|
+
:param log_pod_spec_on_failure: Log the pod's specification if a failure occurs
|
|
228
229
|
"""
|
|
229
230
|
|
|
230
231
|
# This field can be overloaded at the instance level via base_container_name
|
|
@@ -301,6 +302,7 @@ class KubernetesPodOperator(BaseOperator):
|
|
|
301
302
|
base_container_name: str | None = None,
|
|
302
303
|
deferrable: bool = False,
|
|
303
304
|
poll_interval: float = 2,
|
|
305
|
+
log_pod_spec_on_failure: bool = True,
|
|
304
306
|
**kwargs,
|
|
305
307
|
) -> None:
|
|
306
308
|
# TODO: remove in provider 6.0.0 release. This is a mitigate step to advise users to switch to the
|
|
@@ -381,6 +383,7 @@ class KubernetesPodOperator(BaseOperator):
|
|
|
381
383
|
self.deferrable = deferrable
|
|
382
384
|
self.poll_interval = poll_interval
|
|
383
385
|
self.remote_pod: k8s.V1Pod | None = None
|
|
386
|
+
self.log_pod_spec_on_failure = log_pod_spec_on_failure
|
|
384
387
|
self._config_dict: dict | None = None # TODO: remove it when removing convert_config_file_to_dict
|
|
385
388
|
|
|
386
389
|
@cached_property
|
|
@@ -423,7 +426,7 @@ class KubernetesPodOperator(BaseOperator):
|
|
|
423
426
|
@staticmethod
|
|
424
427
|
def _get_ti_pod_labels(context: Context | None = None, include_try_number: bool = True) -> dict[str, str]:
|
|
425
428
|
"""
|
|
426
|
-
Generate labels for the pod to track the pod in case of Operator crash
|
|
429
|
+
Generate labels for the pod to track the pod in case of Operator crash.
|
|
427
430
|
|
|
428
431
|
:param context: task context provided by airflow DAG
|
|
429
432
|
:return: dict
|
|
@@ -515,7 +518,7 @@ class KubernetesPodOperator(BaseOperator):
|
|
|
515
518
|
raise
|
|
516
519
|
|
|
517
520
|
def extract_xcom(self, pod: k8s.V1Pod):
|
|
518
|
-
"""Retrieves xcom value and kills xcom sidecar container"""
|
|
521
|
+
"""Retrieves xcom value and kills xcom sidecar container."""
|
|
519
522
|
result = self.pod_manager.extract_xcom(pod)
|
|
520
523
|
if isinstance(result, str) and result.rstrip() == "__airflow_xcom_result_empty__":
|
|
521
524
|
self.log.info("xcom result file is empty.")
|
|
@@ -525,7 +528,7 @@ class KubernetesPodOperator(BaseOperator):
|
|
|
525
528
|
return json.loads(result)
|
|
526
529
|
|
|
527
530
|
def execute(self, context: Context):
|
|
528
|
-
"""Based on the deferrable parameter runs the pod asynchronously or synchronously"""
|
|
531
|
+
"""Based on the deferrable parameter runs the pod asynchronously or synchronously."""
|
|
529
532
|
if self.deferrable:
|
|
530
533
|
self.execute_async(context)
|
|
531
534
|
else:
|
|
@@ -676,7 +679,6 @@ class KubernetesPodOperator(BaseOperator):
|
|
|
676
679
|
self.process_pod_deletion(remote_pod, reraise=False)
|
|
677
680
|
|
|
678
681
|
error_message = get_container_termination_message(remote_pod, self.base_container_name)
|
|
679
|
-
error_message = "\n" + error_message if error_message else ""
|
|
680
682
|
if self.skip_on_exit_code is not None:
|
|
681
683
|
container_statuses = (
|
|
682
684
|
remote_pod.status.container_statuses if remote_pod and remote_pod.status else None
|
|
@@ -697,14 +699,22 @@ class KubernetesPodOperator(BaseOperator):
|
|
|
697
699
|
f"{self.skip_on_exit_code}. Skipping."
|
|
698
700
|
)
|
|
699
701
|
raise AirflowException(
|
|
700
|
-
|
|
701
|
-
|
|
702
|
+
"\n".join(
|
|
703
|
+
filter(
|
|
704
|
+
None,
|
|
705
|
+
[
|
|
706
|
+
f"Pod {pod and pod.metadata.name} returned a failure.",
|
|
707
|
+
error_message if isinstance(error_message, str) else None,
|
|
708
|
+
f"remote_pod: {remote_pod}" if self.log_pod_spec_on_failure else None,
|
|
709
|
+
],
|
|
710
|
+
)
|
|
711
|
+
)
|
|
702
712
|
)
|
|
703
713
|
else:
|
|
704
714
|
self.process_pod_deletion(remote_pod, reraise=False)
|
|
705
715
|
|
|
706
716
|
def _read_pod_events(self, pod, *, reraise=True):
|
|
707
|
-
"""Will fetch and emit events from pod"""
|
|
717
|
+
"""Will fetch and emit events from pod."""
|
|
708
718
|
with _optionally_suppress(reraise=reraise):
|
|
709
719
|
for event in self.pod_manager.read_pod_events(pod).items:
|
|
710
720
|
self.log.error("Pod Event: %s - %s", event.reason, event.message)
|
|
@@ -735,7 +745,7 @@ class KubernetesPodOperator(BaseOperator):
|
|
|
735
745
|
return None
|
|
736
746
|
|
|
737
747
|
def patch_already_checked(self, pod: k8s.V1Pod, *, reraise=True):
|
|
738
|
-
"""Add an "already checked" annotation to ensure we don't reattach on retries"""
|
|
748
|
+
"""Add an "already checked" annotation to ensure we don't reattach on retries."""
|
|
739
749
|
with _optionally_suppress(reraise=reraise):
|
|
740
750
|
self.client.patch_namespaced_pod(
|
|
741
751
|
name=pod.metadata.name,
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# Licensed to the Apache Software Foundation (ASF) under one
|
|
2
|
+
# or more contributor license agreements. See the NOTICE file
|
|
3
|
+
# distributed with this work for additional information
|
|
4
|
+
# regarding copyright ownership. The ASF licenses this file
|
|
5
|
+
# to you under the Apache License, Version 2.0 (the
|
|
6
|
+
# "License"); you may not use this file except in compliance
|
|
7
|
+
# with the License. You may obtain a copy of the License at
|
|
8
|
+
#
|
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
#
|
|
11
|
+
# Unless required by applicable law or agreed to in writing,
|
|
12
|
+
# software distributed under the License is distributed on an
|
|
13
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
14
|
+
# KIND, either express or implied. See the License for the
|
|
15
|
+
# specific language governing permissions and limitations
|
|
16
|
+
# under the License.
|
|
17
|
+
"""Manage a Kubernetes Resource."""
|
|
18
|
+
|
|
19
|
+
from __future__ import annotations
|
|
20
|
+
|
|
21
|
+
from functools import cached_property
|
|
22
|
+
|
|
23
|
+
import yaml
|
|
24
|
+
from kubernetes.client import ApiClient
|
|
25
|
+
from kubernetes.utils import create_from_yaml
|
|
26
|
+
|
|
27
|
+
from airflow.models import BaseOperator
|
|
28
|
+
from airflow.providers.cncf.kubernetes.hooks.kubernetes import KubernetesHook
|
|
29
|
+
from airflow.providers.cncf.kubernetes.utils.delete_from import delete_from_yaml
|
|
30
|
+
|
|
31
|
+
__all__ = ["KubernetesCreateResourceOperator", "KubernetesDeleteResourceOperator"]
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class KubernetesResourceBaseOperator(BaseOperator):
|
|
35
|
+
"""
|
|
36
|
+
Abstract base class for all Kubernetes Resource operators.
|
|
37
|
+
|
|
38
|
+
:param yaml_conf: string. Contains the kubernetes resources to Create or Delete
|
|
39
|
+
:param namespace: string. Contains the namespace to create all resources inside.
|
|
40
|
+
The namespace must preexist otherwise the resource creation will fail.
|
|
41
|
+
If the API object in the yaml file already contains a namespace definition then
|
|
42
|
+
this parameter has no effect.
|
|
43
|
+
:param kubernetes_conn_id: The :ref:`kubernetes connection id <howto/connection:kubernetes>`
|
|
44
|
+
for the Kubernetes cluster.
|
|
45
|
+
:param in_cluster: run kubernetes client with in_cluster configuration.
|
|
46
|
+
:param cluster_context: context that points to kubernetes cluster.
|
|
47
|
+
Ignored when in_cluster is True. If None, current-context is used.
|
|
48
|
+
:param config_file: The path to the Kubernetes config file. (templated)
|
|
49
|
+
If not specified, default value is ``~/.kube/config``
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
template_fields = ("yaml_conf",)
|
|
53
|
+
template_fields_renderers = {"yaml_conf": "yaml"}
|
|
54
|
+
|
|
55
|
+
def __init__(
|
|
56
|
+
self,
|
|
57
|
+
*,
|
|
58
|
+
yaml_conf: str,
|
|
59
|
+
namespace: str | None = None,
|
|
60
|
+
kubernetes_conn_id: str | None = KubernetesHook.default_conn_name,
|
|
61
|
+
**kwargs,
|
|
62
|
+
) -> None:
|
|
63
|
+
super().__init__(**kwargs)
|
|
64
|
+
self._namespace = namespace
|
|
65
|
+
self.kubernetes_conn_id = kubernetes_conn_id
|
|
66
|
+
self.yaml_conf = yaml_conf
|
|
67
|
+
|
|
68
|
+
@cached_property
|
|
69
|
+
def client(self) -> ApiClient:
|
|
70
|
+
return self.hook.api_client
|
|
71
|
+
|
|
72
|
+
@cached_property
|
|
73
|
+
def hook(self) -> KubernetesHook:
|
|
74
|
+
hook = KubernetesHook(conn_id=self.kubernetes_conn_id)
|
|
75
|
+
return hook
|
|
76
|
+
|
|
77
|
+
def get_namespace(self) -> str:
|
|
78
|
+
if self._namespace:
|
|
79
|
+
return self._namespace
|
|
80
|
+
else:
|
|
81
|
+
return self.hook.get_namespace() or "default"
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
class KubernetesCreateResourceOperator(KubernetesResourceBaseOperator):
|
|
85
|
+
"""Create a resource in a kubernetes."""
|
|
86
|
+
|
|
87
|
+
def execute(self, context) -> None:
|
|
88
|
+
create_from_yaml(
|
|
89
|
+
k8s_client=self.client,
|
|
90
|
+
yaml_objects=yaml.safe_load_all(self.yaml_conf),
|
|
91
|
+
namespace=self.get_namespace(),
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
class KubernetesDeleteResourceOperator(KubernetesResourceBaseOperator):
|
|
96
|
+
"""Delete a resource in a kubernetes."""
|
|
97
|
+
|
|
98
|
+
def execute(self, context) -> None:
|
|
99
|
+
delete_from_yaml(
|
|
100
|
+
k8s_client=self.client,
|
|
101
|
+
yaml_objects=yaml.safe_load_all(self.yaml_conf),
|
|
102
|
+
namespace=self.get_namespace(),
|
|
103
|
+
)
|
|
@@ -30,7 +30,7 @@ if TYPE_CHECKING:
|
|
|
30
30
|
|
|
31
31
|
class SparkKubernetesOperator(BaseOperator):
|
|
32
32
|
"""
|
|
33
|
-
Creates sparkApplication object in kubernetes cluster
|
|
33
|
+
Creates sparkApplication object in kubernetes cluster.
|
|
34
34
|
|
|
35
35
|
.. seealso::
|
|
36
36
|
For more detail about Spark Application Object have a look at the reference:
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
# KIND, either express or implied. See the License for the
|
|
16
16
|
# specific language governing permissions and limitations
|
|
17
17
|
# under the License.
|
|
18
|
-
"""Utilities for using the kubernetes decorator"""
|
|
18
|
+
"""Utilities for using the kubernetes decorator."""
|
|
19
19
|
from __future__ import annotations
|
|
20
20
|
|
|
21
21
|
import os
|
|
@@ -39,7 +39,7 @@ def _balance_parens(after_decorator):
|
|
|
39
39
|
|
|
40
40
|
def remove_task_decorator(python_source: str, task_decorator_name: str) -> str:
|
|
41
41
|
"""
|
|
42
|
-
Removes @task.kubernetes or similar as well as @setup and @teardown
|
|
42
|
+
Removes @task.kubernetes or similar as well as @setup and @teardown.
|
|
43
43
|
|
|
44
44
|
:param python_source: python source code
|
|
45
45
|
:param task_decorator_name: the task decorator name
|
|
@@ -31,7 +31,7 @@ if TYPE_CHECKING:
|
|
|
31
31
|
|
|
32
32
|
class SparkKubernetesSensor(BaseSensorOperator):
|
|
33
33
|
"""
|
|
34
|
-
Checks sparkApplication object in kubernetes cluster
|
|
34
|
+
Checks sparkApplication object in kubernetes cluster.
|
|
35
35
|
|
|
36
36
|
.. seealso::
|
|
37
37
|
For more detail about Spark Application Object have a look at the reference:
|
|
@@ -116,7 +116,7 @@ class KubernetesPodTrigger(BaseTrigger):
|
|
|
116
116
|
)
|
|
117
117
|
|
|
118
118
|
async def run(self) -> AsyncIterator[TriggerEvent]: # type: ignore[override]
|
|
119
|
-
"""Gets current pod status and yields a TriggerEvent"""
|
|
119
|
+
"""Gets current pod status and yields a TriggerEvent."""
|
|
120
120
|
hook = self._get_async_hook()
|
|
121
121
|
self.log.info("Checking pod %r in namespace %r.", self.pod_name, self.pod_namespace)
|
|
122
122
|
while True:
|