ansible回調插件介紹


簡介

ansible回調插件(callback plugins)允許為事件添加一些額外響應。這里的事件包括了執行任務(task)的結果,例如(ok、failed、unreachable、skipped),以及執行劇本(playbook)的過程(start、hosts_matched、task_start、stats)等等。豐富的事件回調使得回調插件能夠做非常多的事情,不過,大多數時候他們都用來提供各種各樣的輸出,或者將日志傳輸到日志采集器,又或者當遇到特定事件時觸發某些特定的任務。

使用

配置項

回調插件的配置項與其他ansible配置項類似,既可以通過環境變量定義,也可以在ansible.cfg配置文件中定義,優先級順序為:ANSIBLE_CONFIG --> ansible.cfg --> ~/.ansible.cfg --> /etc/ansible/ansible.cfg

內置插件相關的配置項如下:

# 啟用的回調插件
callbacks_enabled=<list>
# 回調插件默認搜尋路徑
callback_plugins=~/.ansible/plugins/callback:/usr/share/ansible/plugins/callback
# 標准輸出回調插件,可以運行多個回調插件,但只可以運行一個標准輸出類型的回調插件
stdout_callback=default

內置插件示例

通過ansible-doc -t callback -l命令,能夠列出所有可用的插件;通過ansible-doc -t callback <plugin name>命令能夠查閱插件的描述與使用方式。

# ansible-doc -t callback -l
...
default                               default Ansible screen output
junit                                 write playbook output to a JUnit file
minimal                               minimal Ansible screen output
oneline                               oneline Ansible screen output
ovirt.ovirt.stdout                    Output the log of ansible
theforeman.foreman.foreman            Sends events to Foreman
tree                                  Save host events to files

# ansible-doc -t callback oneline
> ANSIBLE.BUILTIN.ONELINE    (/usr/local/lib/python3.9/site-packages/ansible/plugins/callback/oneline.py)

        This is the output callback used by the -o/--one-line command line option.

NAME: oneline

TYPE: stdout

VERSION_ADDED_COLLECTION: ansible.builtin

其中,default是ansible-playbook所使用的默認回調插件,我們運行ansible-playbook時看到的大部分輸出都是運行這個插件的結果。

default回調插件示例:

minimal是ansible命令行(ad-hoc)的默認回調插件。修改stdout_callback=minimal后,輸出結果如下:

oneline會將每個任務的輸出限制為一行:

tree則會將執行的結果以json格式保存在指定目錄中,目錄默認為~/.ansible/tree,可通過callback_tree配置項修改。

這個網站很好的展示了所有內置回調插件的用法,包括svg視頻和文本兩種展示方式:Ansible Callback-Plugins (rndmh3ro.github.io)

開發

ansible支持自定義回調插件,如果內置插件中沒有自己想要的功能,那么可以自行開發插件以實現自己想要的功能。

一個回調插件即是一個python文件,其中定義了一系列特別的回調函數,在這些回調函數中編寫自定義的代碼,即可在ansible playbook執行到特定地方時調用這些代碼,從而實現自己想要的功能。

ansible支持的回調函數均定義於ansible/plugins/callback/__init.py文件的CallbackBase類中,其所定義的回調函數非常豐富,卻沒有詳盡的文檔描述它們的作用,如果想要知道每個函數的觸發點,需要自己查詢源代碼,希望這一段空缺以后能夠補上。

經常用到的回調函數如下:

# task開始時執行
def v2_runner_on_start(self, host, task):
# task結束后執行(failed、ok、skipped、unreachable)
def v2_runner_on_failed(self, result, ignore_errors=False):
def v2_runner_on_ok(self, result):
def v2_runner_on_skipped(self, result):
def v2_runner_on_unreachable(self, result):
# playbook開始時執行
def v2_playbook_on_start(self, playbook):
# playbook結束時執行
def v2_playbook_on_stats(self, stats):

在執行playbook時,往往會遇到如下問題:當任務由於各種問題失敗時,我們需要修復問題,然后再重新執行playbook,可是直接重新執行的話需要跑很長一段重復的步驟,而如果直接在失敗的步驟開始的話,又有可能會有變量未定義的錯誤(定義變量的步驟沒有執行)。這個時候,有一種折中的方案是在失敗步驟所在的role重新執行,當playbook腳本邏輯規范得當時,這種方法能夠保證在絕大多數步驟失敗時得到恰當的解決。

每次人力尋找失敗步驟所在的role耗時耗力,這種事情可以交給回調插件進行。如下自定義插件用來在任務失敗時保存最后運行的role,以便於重新執行playbook時指定開始的任務。其中,當每個task開始時會保存當前運行的role以及此role的第一個task;當task失敗時則會將role的第一個task保存在/tmp/ansible_failed_role文件中。

# ~/.ansible/plugins/callback/lastrole.py
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type

DOCUMENTATION = '''
    name: lastrole
    type: stdout
    short_description: store last role when playbook failed.
    version_added: historical
    description:
        - store last role to /tmp/ansible_failed_role when playbook failed.
'''

from ansible.plugins.callback import CallbackBase
from ansible import constants as C

class CallbackModule(CallbackBase):
    CALLBACK_VERSION = 2.0
    CALLBACK_TYPE = 'aggregate'
    CALLBACK_NAME = 'lastrole'

    def __init__(self):
        self.task = None
        self.role = None
        self.role_first_task = None
        super(CallbackModule, self).__init__()

    def v2_playbook_on_task_start(self, task, is_conditional):
        self.task = task.get_name()
        if task._role:
            if task._role._role_name != self.role:
                self.role_first_task = self.task
            self.role = task._role._role_name

    def v2_runner_on_failed(self, result, ignore_errors=False):
        if ignore_errors==True:
            return
        with open('/tmp/ansible_failed_role','w') as f:
            f.write('%s\n'%(self.role_first_task))

將此文件保存在~/.ansible/plugins/callback/(或任一callback_plugins配置項中的搜尋路徑)目錄下,隨后在callbacks_enabled配置項中追加lastrole插件,即可在playbook運行時調用該插件。

執行playbook失敗后查看/tmp/ansible_failed_role文件。

# cat /tmp/ansible_failed_role
pre_deploy : get external ip

再次執行playbook時從此task開始。

ansible-playbook -i inventory/hosts.ini playbooks/setup.yml --start-at-task='pre_deploy : get external ip'

一般來說,在項目中都是由程序執行playbook,這時也可自行編寫邏輯,將ansible_failed_role寫入到數據庫中,在執行playbook時判斷並傳入該參數,更為自動化。

附錄

回調函數的調試

ansible通過TaskQueueManager的send_callback方法調用回調函數,在playbook的運行過程中有各種地方都調用了這個方法。如果想要快速地了解知道ansible playbook在運行中到底在何時調用了什么回調函數,可以通過在代碼中添加debug信息的方式得知。

# ansible/executor/task_queue_manager.py
...
class TaskQueueManager:
    ...
    def send_callback(self, method_name, *args, **kwargs):
        # 添加debug信息
        print(f'* send_callback, method_name: {method_name} args: {args} kwargs: {kwargs}')
        ...

調試能夠精確地得出各個回調函數的運行順序,下圖展示了主要回調函數的運行過程。

除此之外,有一個特別的回調函數為def v2_on_any(self, *args, **kwargs):,ansible調用任何回調函數之后,都會調用一次該函數,一般用於調試。

目前所有的回調函數:

def v2_on_any(self, *args, **kwargs):
def v2_runner_on_failed(self, result, ignore_errors=False):
def v2_runner_on_ok(self, result):
def v2_runner_on_skipped(self, result):
def v2_runner_on_unreachable(self, result):
def v2_runner_on_async_poll(self, result):
def v2_runner_on_async_ok(self, result):
def v2_runner_on_async_failed(self, result):
def v2_playbook_on_start(self, playbook):
def v2_playbook_on_notify(self, handler, host):
def v2_playbook_on_no_hosts_matched(self):
def v2_playbook_on_no_hosts_remaining(self):
def v2_playbook_on_task_start(self, task, is_conditional):
def v2_playbook_on_cleanup_task_start(self, task):
def v2_playbook_on_handler_task_start(self, task):
def v2_playbook_on_vars_prompt(self, varname, private=True, prompt=None, encrypt=None, confirm=False, salt_size=None, salt=None, default=None, unsafe=None):
def v2_playbook_on_import_for_host(self, result, imported_file):
def v2_playbook_on_not_import_for_host(self, result, missing_file):
def v2_playbook_on_play_start(self, play):
def v2_playbook_on_stats(self, stats):
def v2_on_file_diff(self, result):
def v2_playbook_on_include(self, included_file):
def v2_runner_item_on_ok(self, result):
def v2_runner_item_on_failed(self, result):
def v2_runner_item_on_skipped(self, result):
def v2_runner_retry(self, result):
def v2_runner_on_start(self, host, task):

參考文檔

Callback plugins — Ansible Documentation


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM