Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Kubernetes decorator #21077

Closed
wants to merge 95 commits into from
Closed
Show file tree
Hide file tree
Changes from 87 commits
Commits
Show all changes
95 commits
Select commit Hold shift + click to select a range
a1c532e
[16185] Added LocalKubernetesExecutor to breeze supported executors
subkanthi Nov 22, 2021
6cbb506
Merge branch 'master' of github.com:subkanthi/airflow
subkanthi Nov 22, 2021
d16a343
Revert "[16185] Added LocalKubernetesExecutor to breeze supported exe…
subkanthi Nov 22, 2021
a336e17
Merge branch 'apache:main' into master
subkanthi Nov 30, 2021
382eedf
Merge branch 'apache:main' into master
subkanthi Dec 2, 2021
c3030fb
Merge branch 'apache:main' into master
subkanthi Dec 4, 2021
1c3c029
Merge branch 'apache:main' into master
subkanthi Dec 6, 2021
0eb6598
Merge branch 'apache:main' into master
subkanthi Dec 10, 2021
35a344e
Merge branch 'apache:main' into master
subkanthi Dec 12, 2021
8d47486
Merge branch 'apache:main' into master
subkanthi Dec 12, 2021
f450679
Merge branch 'apache:main' into master
subkanthi Dec 14, 2021
67c6f5e
Merge branch 'apache:main' into master
subkanthi Dec 14, 2021
a09d628
Merge branch 'apache:main' into master
subkanthi Dec 14, 2021
1568b72
Merge branch 'apache:main' into master
subkanthi Dec 15, 2021
a89daf1
Merge branch 'apache:main' into master
subkanthi Dec 16, 2021
3c24d50
Merge branch 'apache:main' into master
subkanthi Dec 18, 2021
874b0c2
Merge branch 'apache:main' into master
subkanthi Dec 19, 2021
c07aabf
Merge branch 'apache:main' into master
subkanthi Dec 20, 2021
0f385fc
Merge branch 'apache:main' into master
subkanthi Dec 20, 2021
8bab66c
Merge branch 'apache:main' into master
subkanthi Dec 21, 2021
9f34837
Merge branch 'apache:main' into master
subkanthi Dec 24, 2021
a1dea59
Merge branch 'apache:main' into master
subkanthi Dec 29, 2021
2cbccda
Merge branch 'apache:main' into master
subkanthi Dec 30, 2021
00fbfcb
Merge branch 'apache:main' into master
subkanthi Dec 30, 2021
0c7cc12
Merge branch 'apache:main' into master
subkanthi Dec 31, 2021
3a308dc
Merge branch 'apache:main' into master
subkanthi Dec 31, 2021
c2aa679
Merge branch 'apache:main' into master
subkanthi Jan 4, 2022
a50c41a
Merge branch 'apache:main' into master
subkanthi Jan 5, 2022
2631ca1
Merge branch 'apache:main' into master
subkanthi Jan 6, 2022
8ce7c49
Merge branch 'apache:main' into master
subkanthi Jan 7, 2022
8fb9929
Merge branch 'apache:main' into master
subkanthi Jan 7, 2022
0a9a843
Merge branch 'apache:main' into master
subkanthi Jan 9, 2022
b2a30ba
Merge branch 'apache:main' into master
subkanthi Jan 12, 2022
3e1b58c
Merge branch 'apache:main' into master
subkanthi Jan 15, 2022
41a420c
Merge branch 'apache:main' into master
subkanthi Jan 18, 2022
68c3443
Added logic for kubernetes decorator
subkanthi Jan 18, 2022
d94c4ce
Merge branch 'apache:main' into master
subkanthi Jan 18, 2022
a24a664
Merged from master
subkanthi Jan 18, 2022
402ccaf
Merged from master
subkanthi Jan 18, 2022
01f9319
Merge branch 'apache:main' into master
subkanthi Jan 18, 2022
8faffba
Merge branch 'master' of github.com:subkanthi/airflow into kubernetes…
subkanthi Jan 19, 2022
e778325
Changes related to decorator composition
subkanthi Jan 19, 2022
9ef371f
Added kubernetes executor
subkanthi Jan 20, 2022
cf2376f
Merge branch 'apache:main' into master
subkanthi Jan 22, 2022
8880c75
Merge branch 'apache:main' into master
subkanthi Jan 23, 2022
857700f
Added jinja template for kubernetes decorator, fixed logic of passing…
subkanthi Jan 23, 2022
1e2ae11
Refactoring of Kubernetes decorator
subkanthi Jan 23, 2022
ee61fa9
Merge branch 'apache:main' into master
subkanthi Jan 24, 2022
8822af9
Merge branch 'apache:main' into master
subkanthi Jan 24, 2022
22a314e
Merge branch 'apache:main' into master
subkanthi Jan 24, 2022
33d6fff
Clean up and added test case
subkanthi Jan 24, 2022
7fd13d7
Clean up and added test case
subkanthi Jan 24, 2022
52adfdd
Merge branch 'master' of github.com:subkanthi/airflow into kubernetes…
subkanthi Jan 24, 2022
2f54ba1
Merge branch 'apache:main' into master
subkanthi Jan 24, 2022
f1c89a1
Added test case for kubernetes decorator
subkanthi Jan 24, 2022
f63986d
Rebase from master
subkanthi Jan 24, 2022
05162fd
Merge branch 'apache:main' into master
subkanthi Jan 25, 2022
b335457
Merge branch 'apache:main' into master
subkanthi Jan 27, 2022
7d72855
Merge branch 'apache:main' into master
subkanthi Jan 27, 2022
353012f
Merge branch 'master' of github.com:subkanthi/airflow into kubernetes…
subkanthi Jan 28, 2022
084c712
Removed unused code
subkanthi Jan 28, 2022
031dc2a
Merge branch 'master' of github.com:subkanthi/airflow into kubernetes…
subkanthi Jan 29, 2022
cb114c3
Merge branch 'master' of github.com:subkanthi/airflow into kubernetes…
subkanthi Feb 1, 2022
cd5911c
Fix flake8, lint errors
subkanthi Feb 1, 2022
e5f32b8
Changes to move kubernetes decorator logic out of airflow/decorators
subkanthi Feb 1, 2022
eb8ccf1
Reverted back change in __init__.pyi
subkanthi Feb 6, 2022
875be8a
Added kubernetespodopertor parameter to kubernetes decorator
subkanthi Feb 7, 2022
51845b7
Merge branch 'master' of github.com:subkanthi/airflow into kubernetes…
subkanthi Feb 7, 2022
0fce88e
Merge branch 'master' of github.com:subkanthi/airflow into kubernetes…
subkanthi Feb 10, 2022
aaf1864
Merge branch 'main' into kubernetes_decorator
subkanthi Feb 13, 2022
5e6419b
Merge branch 'main' into kubernetes_decorator
subkanthi Feb 16, 2022
d97ef0c
Removed type definitions in kubernetes decorator
subkanthi Feb 16, 2022
f470507
Merge branch 'main' into kubernetes_decorator
subkanthi Feb 24, 2022
8dd8f4d
Merge branch 'main' into kubernetes_decorator
subkanthi Feb 27, 2022
442e4ce
Cherry pick changes from 21881
subkanthi Mar 1, 2022
49abdd1
Merge branch 'main' into kubernetes_decorator
subkanthi Mar 1, 2022
cf6653b
Update airflow/decorators/__init__.pyi
subkanthi Mar 20, 2022
a1f7ad1
Update airflow/decorators/__init__.pyi
subkanthi Mar 20, 2022
775742a
Update airflow/providers/cncf/kubernetes/decorators/kubernetes.py
subkanthi Mar 20, 2022
83dd407
Update airflow/example_dags/example_kubernetes_decorator.py
subkanthi Mar 20, 2022
cff5197
Merge branch 'main' into kubernetes_decorator
subkanthi Mar 20, 2022
3ca339c
Make @task.kubernetes arguments keyword-only
uranusjr Mar 21, 2022
b4a61da
Merge branch 'main' into kubernetes_decorator
subkanthi Apr 10, 2022
65996b7
Throw exception if image is not passed to kubernetes decorator.
subkanthi Apr 10, 2022
6626060
Add image parameter to kubernetes decorator.
subkanthi Apr 11, 2022
453e32a
Kubernetes decorator -set image parameter as required
subkanthi Apr 11, 2022
ee725a9
Merge branch 'main' into kubernetes_decorator
subkanthi Apr 11, 2022
3b12142
Update airflow/decorators/__init__.pyi
subkanthi Apr 12, 2022
a0d122f
Merge branch 'main' into kubernetes_decorator
subkanthi Apr 13, 2022
821e449
Merge branch 'main' into kubernetes_decorator
subkanthi Apr 27, 2022
890f829
Merge branch 'main' into kubernetes_decorator
subkanthi Jul 5, 2022
f8d54b0
Merge branch 'main' into kubernetes_decorator
subkanthi Jul 5, 2022
47b9062
Merge branch 'main' into kubernetes_decorator
subkanthi Jul 12, 2022
f6edafa
Merge branch 'main' into kubernetes_decorator
subkanthi Jul 12, 2022
00d4f1c
Merge branch 'main' into kubernetes_decorator
subkanthi Jul 12, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 115 additions & 2 deletions airflow/decorators/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -188,8 +188,7 @@ class TaskDecoratorCollection:
Dict will unroll to XCom values with keys as XCom keys. Defaults to False.
:param use_dill: Whether to use dill or pickle for serialization
:param python_command: Python command for executing functions, Default: python3
:param image: Docker image from which to create the container.
If image tag is omitted, "latest" will be used.
:param image: Docker image from which to create the container.(Required)
subkanthi marked this conversation as resolved.
Show resolved Hide resolved
:param api_version: Remote API version. Set to ``auto`` to automatically
detect the server's version.
:param container_name: Name of the container. Optional (templated)
Expand Down Expand Up @@ -245,5 +244,119 @@ class TaskDecoratorCollection:
:param cap_add: Include container capabilities
"""
# [END decorator_signature]
def kubernetes(
self,
uranusjr marked this conversation as resolved.
Show resolved Hide resolved
*,
multiple_outputs: Optional[bool] = None,
namespace: Optional[str] = None,
image: str,
name: Optional[str] = None,
random_name_suffix: bool = True,
cmds: Optional[List[str]] = None,
arguments: Optional[List[str]] = None,
ports: Optional[List[k8s.V1ContainerPort]] = None,
volume_mounts: Optional[List[k8s.V1VolumeMount]] = None,
volumes: Optional[List[k8s.V1Volume]] = None,
env_vars: Optional[List[k8s.V1EnvVar]] = None,
env_from: Optional[List[k8s.V1EnvFromSource]] = None,
secrets: Optional[List[Secret]] = None,
in_cluster: Optional[bool] = None,
cluster_context: Optional[str] = None,
labels: Optional[Dict] = None,
reattach_on_restart: bool = True,
startup_timeout_seconds: int = 120,
get_logs: bool = True,
image_pull_policy: Optional[str] = None,
annotations: Optional[Dict] = None,
resources: Optional[k8s.V1ResourceRequirements] = None,
affinity: Optional[k8s.V1Affinity] = None,
config_file: Optional[str] = None,
node_selectors: Optional[dict] = None,
node_selector: Optional[dict] = None,
image_pull_secrets: Optional[List[k8s.V1LocalObjectReference]] = None,
service_account_name: Optional[str] = None,
is_delete_operator_pod: bool = True,
hostnetwork: bool = False,
tolerations: Optional[List[k8s.V1Toleration]] = None,
security_context: Optional[Dict] = None,
dnspolicy: Optional[str] = None,
schedulername: Optional[str] = None,
full_pod_spec: Optional[k8s.V1Pod] = None,
init_containers: Optional[List[k8s.V1Container]] = None,
log_events_on_failure: bool = False,
do_xcom_push: bool = False,
pod_template_file: Optional[str] = None,
priority_class_name: Optional[str] = None,
pod_runtime_info_envs: Optional[List[PodRuntimeInfoEnv]] = None,
termination_grace_period: Optional[int] = None,
configmaps: Optional[List[str]] = None,
**kwargs,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What can go into kwargs here? It seems unnecessary.

) -> TaskDecorator:
"""Wraps a function to be executed on a k8s pod using KubernetesPodOperator

Also accepts any argument that KubernetesPodOperator will via ``kwargs``.

:param multiple_outputs: if set, function return value will be
unrolled to multiple XCom values. Dict will unroll to XCom values with keys as XCom keys.
Defaults to False.
:param namespace: the namespace to run within kubernetes.
:param image: Docker image you wish to launch. Defaults to hub.docker.com,
but fully qualified URLS will point to custom repositories. (templated)
:param name: name of the pod in which the task will run, will be used (plus a random
suffix if random_name_suffix is True) to generate a pod id (DNS-1123 subdomain,
containing only [a-z0-9.-]).
:param random_name_suffix: if True, will generate a random suffix.
:param cmds: entrypoint of the container. (templated)
The docker images's entrypoint is used if this is not provided.
:param arguments: arguments of the entrypoint. (templated)
The docker image's CMD is used if this is not provided.
:param ports: ports for launched pod.
:param volume_mounts: volumeMounts for launched pod.
:param volumes: volumes for launched pod. Includes ConfigMaps and PersistentVolumes.
:param env_vars: Environment variables initialized in the container. (templated)
:param secrets: Kubernetes secrets to inject in the container.
They can be exposed as environment vars or files in a volume.
:param in_cluster: run kubernetes client with in_cluster configuration.
:param cluster_context: context that points to kubernetes cluster.
Ignored when in_cluster is True. If None, current-context is used.
:param reattach_on_restart: if the scheduler dies while the pod is running, reattach and monitor
:param labels: labels to apply to the Pod. (templated)
:param startup_timeout_seconds: timeout in seconds to startup the pod.
:param get_logs: get the stdout of the container as logs of the tasks.
:param image_pull_policy: Specify a policy to cache or always pull an image.
:param annotations: non-identifying metadata you can attach to the Pod.
Can be a large range of data, and can include characters
that are not permitted by labels.
:param resources: A dict containing resources requests and limits.
Possible keys are request_memory, request_cpu, limit_memory, limit_cpu,
and limit_gpu, which will be used to generate airflow.kubernetes.pod.Resources.
See also kubernetes.io/docs/concepts/configuration/manage-compute-resources-container
:param affinity: A dict containing a group of affinity scheduling rules.
:param config_file: The path to the Kubernetes config file. (templated)
If not specified, default value is ``~/.kube/config``
:param node_selector: A dict containing a group of scheduling rules.
:param image_pull_secrets: Any image pull secrets to be given to the pod.
If more than one secret is required, provide a
comma separated list: secret_a,secret_b
:param service_account_name: Name of the service account
:param is_delete_operator_pod: What to do when the pod reaches its final
state, or the execution is interrupted. If True (default), delete the
pod; if False, leave the pod.
:param hostnetwork: If True enable host networking on the pod.
:param tolerations: A list of kubernetes tolerations.
:param security_context: security options the pod should run with (PodSecurityContext).
:param dnspolicy: dnspolicy for the pod.
:param schedulername: Specify a schedulername for the pod
:param full_pod_spec: The complete podSpec
:param init_containers: init container for the launched Pod
:param log_events_on_failure: Log the pod's events if a failure occurs
:param do_xcom_push: If True, the content of the file
/airflow/xcom/return.json in the container will also be pushed to an
XCom when the container completes.
:param pod_template_file: path to pod template file (templated)
:param priority_class_name: priority class name for the launched Pod
:param termination_grace_period: Termination grace period if task killed in UI,
defaults to kubernetes default
"""

task: TaskDecoratorCollection
57 changes: 57 additions & 0 deletions airflow/example_dags/example_kubernetes_decorator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
"""
This is an example dag for using the KubernetesPodOperator.
"""

from datetime import datetime

from airflow import DAG
from airflow.decorators import task

with DAG(
dag_id='example_kubernetes_decorator',
schedule_interval=None,
start_date=datetime(2021, 1, 1),
tags=['example'],
subkanthi marked this conversation as resolved.
Show resolved Hide resolved
catchup=False,
) as dag:

@task.kubernetes(image='python:3.8-slim-buster', name='k8s_test', namespace='default')
def execute_in_k8s_pod():
import time

print("Hello from k8s pod")
time.sleep(2)

@task.kubernetes(image='python:3.8-slim-buster')
def print_pattern():
n = 5
for i in range(0, n):
# inner loop to handle number of columns
# values changing acc. to outer loop
for j in range(0, i + 1):
# printing stars
print("* ", end="")

# ending line after each row
print("\r")

execute_in_k8s_pod_instance = execute_in_k8s_pod()
print_pattern_instance = print_pattern()
execute_in_k8s_pod_instance >> print_pattern_instance
17 changes: 17 additions & 0 deletions airflow/providers/cncf/kubernetes/decorators/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
145 changes: 145 additions & 0 deletions airflow/providers/cncf/kubernetes/decorators/kubernetes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.

import inspect
import os
import pickle
import uuid
from tempfile import TemporaryDirectory
from textwrap import dedent
from typing import TYPE_CHECKING, Callable, Optional, Sequence, TypeVar

from kubernetes.client import models as k8s

from airflow.decorators.base import DecoratedOperator, TaskDecorator, task_decorator_factory
from airflow.providers.cncf.kubernetes.operators.kubernetes_pod import KubernetesPodOperator
from airflow.utils.python_virtualenv import remove_task_decorator, write_python_script

if TYPE_CHECKING:
from airflow.utils.context import Context


def _generate_decode_command(env_var, file):
# We don't need `f.close()` as the interpreter is about to exit anyway
return (
f'python -c "import base64, os;'
rf'x = os.environ[\"{env_var}\"];'
rf'f = open(\"{file}\", \"w\"); f.write(x);"'
)


def _read_file_contents(filename):
with open(filename) as script_file:
return script_file.read()


class _KubernetesDecoratedOperator(DecoratedOperator, KubernetesPodOperator):
"""
Wraps a Python callable and executes in a kubernetes pod

:param python_callable: A reference to an object that is callable
:param op_kwargs: a dictionary of keyword arguments that will get unpacked
in your function (templated)
:param op_args: a list of positional arguments that will get unpacked when
calling your callable (templated)
:param multiple_outputs: if set, function return value will be
unrolled to multiple XCom values. Dict will unroll to xcom values with keys as keys.
Defaults to False.
"""

template_fields: Sequence[str] = ('op_args', 'op_kwargs')

# since we won't mutate the arguments, we should just do the shallow copy
# there are some cases we can't deepcopy the objects (e.g protobuf).
shallow_copy_attrs: Sequence[str] = ('python_callable',)

def __init__(
self,
**kwargs,
) -> None:
subkanthi marked this conversation as resolved.
Show resolved Hide resolved
self.pickling_library = pickle

# Set defaults for name and namespace.
if 'name' not in kwargs:
kwargs['name'] = f'k8s_airflow_pod_{uuid.uuid4().hex}'

if 'namespace' not in kwargs:
kwargs['namespace'] = 'default'
Comment on lines +76 to +81
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit, it’s easier to use setdefault for these


super().__init__(**kwargs)

def execute(self, context: 'Context'):

with TemporaryDirectory(prefix='venv') as tmp_dir:
script_filename = os.path.join(tmp_dir, 'script.py')
py_source = self._get_python_source()

jinja_context = dict(
op_args=self.op_args,
op_kwargs=self.op_kwargs,
pickling_library=self.pickling_library.__name__,
python_callable=self.python_callable.__name__,
python_callable_source=py_source,
string_args_global=False,
)
write_python_script(
jinja_context=jinja_context,
filename=script_filename,
template_file='python_kubernetes_script.jinja2',
)

self.env_vars.append(
k8s.V1EnvVar(name="__PYTHON_SCRIPT", value=_read_file_contents(script_filename))
)

self.cmds.append("bash")
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thoughts here, The user can still pass cmds and arguments, 2 options, either we limit the user not to pass command and arguments or check here if its passed and not append.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’d say let’s not allow passing the command for now, and loosen the restriction if anyone asks for it.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I am reading this correctly, we are setting the KubernetesPod's cmd to bash then some args to the remaining pieces. I believe this hit us, we had docker images with ENTRYPOINTS and I believe the cmd directive here will override those entirely. So by forcing a bash here we are killing any ENTRYPOINTS. We frequently have dumb init -- ones, or poetry run ones, to make sure we are running our commands safely, and in an isolated manner.

Did I understand this correctly?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nevermind, append :)


self.arguments.append("-cx")
self.arguments.append(
f'{_generate_decode_command("__PYTHON_SCRIPT", "/tmp/script.py")} && python /tmp/script.py'
)

return super().execute(context)

def _get_python_source(self):
raw_source = inspect.getsource(self.python_callable)
res = dedent(raw_source)
res = remove_task_decorator(res, "@task.kubernetes")
return res


T = TypeVar("T", bound=Callable)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused?



def kubernetes_task(
python_callable: Optional[Callable] = None, multiple_outputs: Optional[bool] = None, **kwargs
) -> TaskDecorator:
"""
Kubernetes operator decorator. Wraps a function to be executed in K8s using KubernetesPodOperator.
Also accepts any argument that DockerOperator will via ``kwargs``. Can be reused in a single DAG.

:param python_callable: Function to decorate
:param multiple_outputs: if set, function return value will be
unrolled to multiple XCom values. Dict will unroll to xcom values with keys as XCom keys.
Defaults to False.
"""
return task_decorator_factory(
python_callable=python_callable,
multiple_outputs=multiple_outputs,
decorated_operator_class=_KubernetesDecoratedOperator,
**kwargs,
)
4 changes: 4 additions & 0 deletions airflow/providers/cncf/kubernetes/provider.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,7 @@ hook-class-names: # deprecated - to be removed after providers add dependency o
connection-types:
- hook-class-name: airflow.providers.cncf.kubernetes.hooks.kubernetes.KubernetesHook
connection-type: kubernetes

task-decorators:
- class-name: airflow.providers.cncf.kubernetes.decorators.kubernetes.kubernetes_task
name: kubernetes
Loading