Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
15 changes: 15 additions & 0 deletions airflow/api_connexion/openapi/v1.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3833,6 +3833,21 @@ components:
type: string
description: The plugin source
nullable: true
ti_deps:
type: array
items:
type: string
description: The plugin task instance dependencies
listeners:
type: array
items:
type: string
description: The plugin listeners
timetables:
type: array
items:
type: string
description: The plugin timetables

PluginCollection:
type: object
Expand Down
3 changes: 3 additions & 0 deletions airflow/api_connexion/schemas/plugin_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ class PluginSchema(Schema):
global_operator_extra_links = fields.List(fields.String())
operator_extra_links = fields.List(fields.String())
source = fields.String()
ti_deps = fields.List(fields.String())
listeners = fields.List(fields.String())
timetables = fields.List(fields.String())


class PluginCollection(NamedTuple):
Expand Down
4 changes: 3 additions & 1 deletion airflow/plugins_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,14 +78,16 @@
"hooks",
"executors",
"macros",
"admin_views",
"flask_blueprints",
"menu_links",
"appbuilder_views",
"appbuilder_menu_items",
"global_operator_extra_links",
"operator_extra_links",
"source",
"ti_deps",
"timetables",
"source",
"listeners",
}

Expand Down
6 changes: 6 additions & 0 deletions airflow/www/static/js/types/api-generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1597,6 +1597,12 @@ export interface components {
operator_extra_links?: (string | null)[];
/** @description The plugin source */
source?: string | null;
/** @description The plugin task instance dependencies */
ti_deps?: string[];
/** @description The plugin listeners */
listeners?: string[];
/** @description The plugin timetables */
timetables?: string[];
};
/**
* @description A collection of plugin.
Expand Down
15 changes: 2 additions & 13 deletions airflow/www/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@
from airflow.models.operator import needs_expansion
from airflow.models.serialized_dag import SerializedDagModel
from airflow.models.taskinstance import TaskInstance, TaskInstanceNote
from airflow.plugins_manager import PLUGINS_ATTRIBUTES_TO_DUMP
from airflow.providers_manager import ProvidersManager
from airflow.security import permissions
from airflow.ti_deps.dep_context import DepContext
Expand Down Expand Up @@ -4521,19 +4522,7 @@ class PluginView(AirflowBaseView):
permissions.ACTION_CAN_ACCESS_MENU,
]

plugins_attributes_to_dump = [
"hooks",
"executors",
"macros",
"admin_views",
"flask_blueprints",
"menu_links",
"appbuilder_views",
"appbuilder_menu_items",
"global_operator_extra_links",
"operator_extra_links",
"source",
]
plugins_attributes_to_dump = PLUGINS_ATTRIBUTES_TO_DUMP

@expose("/plugin")
@auth.has_access_website()
Expand Down
37 changes: 37 additions & 0 deletions tests/api_connexion/endpoints/test_plugin_endpoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
# under the License.
from __future__ import annotations

import inspect

import pytest
from flask import Blueprint
from flask_appbuilder import BaseView
Expand All @@ -24,6 +26,8 @@
from airflow.models.baseoperator import BaseOperatorLink
from airflow.plugins_manager import AirflowPlugin
from airflow.security import permissions
from airflow.ti_deps.deps.base_ti_dep import BaseTIDep
from airflow.timetables.base import Timetable
from airflow.utils.module_loading import qualname
from tests.test_utils.api_connexion_utils import assert_401, create_user, delete_user
from tests.test_utils.config import conf_vars
Expand Down Expand Up @@ -60,6 +64,30 @@ class MockView(BaseView):
}


class CustomTIDep(BaseTIDep):
pass


ti_dep = CustomTIDep()


class CustomTimetable(Timetable):
def infer_manual_data_interval(self, *, run_after):
pass

def next_dagrun_info(
self,
*,
last_automated_data_interval,
restriction,
):
pass


class MyCustomListener:
pass


class MockPlugin(AirflowPlugin):
name = "mock_plugin"
flask_blueprints = [bp]
Expand All @@ -69,6 +97,9 @@ class MockPlugin(AirflowPlugin):
operator_extra_links = [MockOperatorLink()]
hooks = [PluginHook]
macros = [plugin_macro]
ti_deps = [ti_dep]
timetables = [CustomTimetable]
listeners = [pytest, MyCustomListener()] # using pytest here because we need a module(just for test)


@pytest.fixture(scope="module")
Expand Down Expand Up @@ -120,6 +151,12 @@ def test_get_plugins_return_200(self):
"operator_extra_links": [f"<{qualname(MockOperatorLink().__class__)} object>"],
"source": None,
"name": "test_plugin",
"timetables": [qualname(CustomTimetable)],
"ti_deps": [str(ti_dep)],
"listeners": [
d.__name__ if inspect.ismodule(d) else qualname(d)
for d in [pytest, MyCustomListener()]
],
}
],
"total_entries": 1,
Expand Down
9 changes: 9 additions & 0 deletions tests/api_connexion/schemas/test_plugin_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@ def test_serialize(self):
"operator_extra_links": [str(MockOperatorLink())],
"source": None,
"name": "test_plugin",
"ti_deps": [],
"listeners": [],
"timetables": [],
}


Expand All @@ -112,6 +115,9 @@ def test_serialize(self):
"operator_extra_links": [str(MockOperatorLink())],
"source": None,
"name": "test_plugin",
"ti_deps": [],
"listeners": [],
"timetables": [],
},
{
"appbuilder_menu_items": [appbuilder_menu_items],
Expand All @@ -124,6 +130,9 @@ def test_serialize(self):
"operator_extra_links": [str(MockOperatorLink())],
"source": None,
"name": "test_plugin_2",
"ti_deps": [],
"listeners": [],
"timetables": [],
},
],
"total_entries": 2,
Expand Down
2 changes: 2 additions & 0 deletions tests/cli/commands/test_plugins_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,9 @@ def test_should_display_one_plugins(self):
assert info == [
{
"name": "test_plugin",
"admin_views": [],
"macros": ["tests.plugins.test_plugin.plugin_macro"],
"menu_links": [],
"executors": ["tests.plugins.test_plugin.PluginExecutor"],
"flask_blueprints": [
"<flask.blueprints.Blueprint: name='test_plugin' import_name='tests.plugins.test_plugin'>"
Expand Down