# 插件
> 貢獻者:[@ImPerat0R\_](https://github.com/tssujt)
Airflow 內置了一個簡單的插件管理器,可以通過簡單地刪除`$AIRFLOW_HOME/plugins`文件夾中的文件,將外部功能集成到其核心。
`plugins`文件夾中的 python 模塊將被導入,**鉤子**,**操作符**,**傳感器**,**宏**,**執行器**和 Web**視圖**將集成到 Airflow 的主要集合中,并可供使用。
## 做什么的?
Airflow 提供了一個用于處理數據的通用工具箱。不同的組織有不同的堆棧和不同的需求。 使用 Airflow 插件可以讓公司定制他們的 Airflow 安裝以反映他們的生態系統。
插件可以簡便地用作編寫,共享和激活新功能集。
當然還需要一組更復雜的應用程序來與不同風格的數據和元數據進行交互。
例子:
* 一組用于解析 Hive 日志和公開 Hive 元數據(CPU/IO/階段/傾斜/...)的工具
* 異常檢測框架,允許人們收集指標,設置閾值和警報
* 審計工具,幫助了解誰訪問了什么
* 配置驅動的 SLA 監控工具,允許您設置受監控的表以及應該在何時著陸,提醒人員并公開停機的可視化
* ...
## 為什么要建立在 Airflow 之上?
Airflow 有許多組件可以在構建應用程序時重用:
* 可用于呈現視圖的 Web 服務器
* 用于存儲模型的元數據數據庫
* 訪問您的數據庫,以及如何連接到它們
* 應用程序可以將工作負載推送到的一組 Workers
* 部署了 Airflow,您可以專注于后面的工作
* 基本的圖表功能,底層庫和抽象
## 接口
要創建插件,您需要派生`airflow.plugins_manager.AirflowPlugin`類并引用要插入 Airflow 的對象。以下是類似您需要派生的類:
```py
class AirflowPlugin(object):
# The name of your plugin (str)
name = None
# A list of class(es) derived from BaseOperator
operators = []
# A list of class(es) derived from BaseSensorOperator
sensors = []
# A list of class(es) derived from BaseHook
hooks = []
# A list of class(es) derived from BaseExecutor
executors = []
# A list of references to inject into the macros namespace
macros = []
# A list of objects created from a class derived
# from flask_admin.BaseView
admin_views = []
# A list of Blueprint object created from flask.Blueprint. For use with the flask_admin based GUI
flask_blueprints = []
# A list of menu links (flask_admin.base.MenuLink). For use with the flask_admin based GUI
menu_links = []
# A list of dictionaries containing FlaskAppBuilder BaseView object and some metadata. See example below
appbuilder_views = []
# A list of dictionaries containing FlaskAppBuilder BaseView object and some metadata. See example below
appbuilder_menu_items = []
```
## 示例
下面的代碼定義了一個插件,它在 Airflow 中注入一組虛擬對象定義。
```py
# This is the class you derive to create a plugin
from airflow.plugins_manager import AirflowPlugin
from flask import Blueprint
from flask_admin import BaseView, expose
from flask_admin.base import MenuLink
# Importing base classes that we need to derive
from airflow.hooks.base_hook import BaseHook
from airflow.models import BaseOperator
from airflow.sensors.base_sensor_operator import BaseSensorOperator
from airflow.executors.base_executor import BaseExecutor
# Will show up under airflow.hooks.test_plugin.PluginHook
class PluginHook(BaseHook):
pass
# Will show up under airflow.operators.test_plugin.PluginOperator
class PluginOperator(BaseOperator):
pass
# Will show up under airflow.sensors.test_plugin.PluginSensorOperator
class PluginSensorOperator(BaseSensorOperator):
pass
# Will show up under airflow.executors.test_plugin.PluginExecutor
class PluginExecutor(BaseExecutor):
pass
# Will show up under airflow.macros.test_plugin.plugin_macro
def plugin_macro():
pass
# Creating a flask admin BaseView
class TestView(BaseView):
@expose('/')
def test(self):
# in this example, put your test_plugin/test.html template at airflow/plugins/templates/test_plugin/test.html
return self.render("test_plugin/test.html", content="Hello galaxy!")
v = TestView(category="Test Plugin", name="Test View")
# Creating a flask blueprint to integrate the templates and static folder
bp = Blueprint(
"test_plugin", __name__,
template_folder='templates', # registers airflow/plugins/templates as a Jinja template folder
static_folder='static',
static_url_path='/static/test_plugin')
ml = MenuLink(
category='Test Plugin',
name='Test Menu Link',
url='https://airflow.incubator.apache.org/')
# Creating a flask appbuilder BaseView
class TestAppBuilderBaseView(AppBuilderBaseView):
@expose("/")
def test(self):
return self.render("test_plugin/test.html", content="Hello galaxy!")
v_appbuilder_view = TestAppBuilderBaseView()
v_appbuilder_package = {"name": "Test View",
"category": "Test Plugin",
"view": v_appbuilder_view}
# Creating a flask appbuilder Menu Item
appbuilder_mitem = {"name": "Google",
"category": "Search",
"category_icon": "fa-th",
"href": "https://www.google.com"}
# Defining the plugin class
class AirflowTestPlugin(AirflowPlugin):
name = "test_plugin"
operators = [PluginOperator]
sensors = [PluginSensorOperator]
hooks = [PluginHook]
executors = [PluginExecutor]
macros = [plugin_macro]
admin_views = [v]
flask_blueprints = [bp]
menu_links = [ml]
appbuilder_views = [v_appbuilder_package]
appbuilder_menu_items = [appbuilder_mitem]
```
## 注意基于角色的視圖
Airflow 1.10 使用 FlaskAppBuilder 引入了基于角色的視圖。您可以通過設置 rbac = True 來配置使用的 UI。為了支持兩個版本的 UI 的插件視圖和鏈接以保持向后兼容性,請將字段 appbuilder_views 和 appbuilder_menu_items 添加到 AirflowTestPlugin 類中。