Ansible模塊開發-自定義模塊


Ansible模塊開發-自定義模塊

第一步創建ansible自定義模塊路徑

cd /data/db/playbooks/
mkdir -p library

vim ansible.cfg 增加如下內容:

[defaults]
library = ./library

下面我們開始第一個模塊開發

創建第一個模塊

vim library/info.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2018/11/12 12:00 PM
# @Author  : biglittle
# @Contact : biglittleant@hotmail.com
# @Site    :
# @File    : info.py
# @Software: PyCharm
# @Desc    : python file
# @license : Copyright(C), Your Company

from ansible.module_utils.basic import *

# 實例化一個module,因為不需要參數所以argument_spec初始化參數為空字典。
module = AnsibleModule(
        argument_spec = dict(),
)
output="hello word!"

result = dict(module='myinfo',stdout=output,changed=False,rc=0)

module.exit_json(**result)

ansible -i inventory/devlop linux-node1 -m myinfo
linux-node1 | SUCCESS => {
    "changed": false,
    "module": "myinfo",
    "rc": 0,
    "stdout": "hello word!",
    "stdout_lines": [
        "hello word!"
    ]
}

創建一個帶參數的腳本

vim library/myinfo_args.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2018/11/12 12:00 PM
# @Author  : biglittle
# @Contact : biglittleant@hotmail.com
# @Site    :
# @File    : myinfo_args.py
# @Software: PyCharm
# @Desc    : python file
# @license : Copyright(C), Your Company

from ansible.module_utils.basic import *

module = AnsibleModule(
        argument_spec = dict(
                 msg=dict(required=True),
        ),
)
msg = module.params['msg']

result = dict(module='myinfo_args',stdout=msg,changed=False,rc=0)

module.exit_json(**result)

執行驗證

ansible -i inventory/devlop linux-node1 -m myinfo_args -a "msg='new word'"
linux-node1 | SUCCESS => {
    "changed": false,
    "module": "myinfo_args",
    "rc": 0,
    "stdout": "new word",
    "stdout_lines": [
        "new word"
    ]
}

來個不帶參數的的執行

ansible -i inventory/devlop linux-node1 -m myinfo_args
linux-node1 | FAILED! => {
    "changed": false,
    "msg": "missing required arguments: msg"
}

自己實現一個shell模塊

vim library/myshell.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2020年01月10日16:39:09
# @Author  : biglittle
# @Contact : biglittleant@hotmail.com
# @Site    :
# @File    : myshell.py
# @Software: PyCharm
# @Desc    : python file
# @license : Copyright(C), Your Company
from ansible.module_utils.basic import AnsibleModule
import commands


def main():
    """
    run shell
    """
    changed = False
    module = AnsibleModule(
                argument_spec = dict(
                 cmd = dict(type='str', required=True),
                ),
    )
    cmd = module.params['cmd']

    code,output = commands.getstatusoutput(cmd)
    if code == 0:
        # 按照ansible 的返回格式定義返回內容,stdout為標准輸出,changed代表系統有沒有東西被變更,rc=0代表執行成功
        result = dict(stdout=output,changed=changed,rc=0)
        # 使用ansible規則的module實例下的exit_json返回正常內容
        module.exit_json(**result)
    else:
        # 當調用失敗返回錯誤信息的時候,數據字典只要傳遞msg信息就可了,然后調用module實例的fail_json方法給返回
        result = dict(msg=output,rc=code)
        module.fail_json(**result)


if __name__ == '__main__':

    main()

執行一個正確的命令

ansible -i inventory/devlop linux-node1 -m myshell -a cmd='pwd'
linux-node1 | SUCCESS => {
    "changed": false,
    "rc": 0,
    "stdout": "/home/niu",
    "stdout_lines": [
        "/home/niu"
    ]
}
ansible -i inventory/devlop linux-node1 -m myshell -a cmd='pws'
linux-node1 | FAILED! => {
    "changed": false,
    "msg": "sh: pws: command not found",
    "rc": 32512
}

如果不定義: result = dict(msg=output,rc=code) ansible 會有一個默認的返回,輸出類似下面的情況。

ansible -i inventory/devlop linux-node1 -m myshell -a cmd='pws'
linux-node1 | FAILED! => {
    "changed": false,
    "module_stderr": "Shared connection to linux-node1 closed.\r\n",
    "module_stdout": "\r\nTraceback (most recent call last):\r\n  File \"/home/niu/.ansible/tmp/ansible-tmp-1578648957.53-161256530271090/AnsiballZ_myshell.py\", line 113, in <module>\r\n    _ansiballz_main()\r\n  File \"/home/niu/.ansible/tmp/ansible-tmp-1578648957.53-161256530271090/AnsiballZ_myshell.py\", line 105, in _ansiballz_main\r\n    invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)\r\n  File \"/home/niu/.ansible/tmp/ansible-tmp-1578648957.53-161256530271090/AnsiballZ_myshell.py\", line 48, in invoke_module\r\n    imp.load_module('__main__', mod, module, MOD_DESC)\r\n  File \"/tmp/ansible_myshell_payload_XylgIF/__main__.py\", line 40, in <module>\r\n  File \"/tmp/ansible_myshell_payload_XylgIF/__main__.py\", line 33, in main\r\nUnboundLocalError: local variable 'result' referenced before assignment\r\n",
    "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error",
    "rc": 1
}

參數解釋

argument_spec 支持的參數

例子:

module = AnsibleModule(
    argument_spec = dict{
        name = dict(type='str', required=True),
        cwd = dict(type='str', required=False),
        shell = dict(type='bool', default=True),
    }
)

官方的ping模塊分析

模塊路徑:https://github.com/ansible/ansible/blob/devel/lib/ansible/modules/system/ping.py

from ansible.module_utils.basic import AnsibleModule


def main():
    # 實例化了一個類
    module = AnsibleModule(
        argument_spec=dict(
            data=dict(type='str', default='pong'),
        ),
        supports_check_mode=True
    )
    # 判斷參數是否為crash,如果是就拋出異常
    if module.params['data'] == 'crash':
        raise Exception("boom")
    # 正常情況下,定義個字典。ping=data,data默認是pong
    result = dict(
        ping=module.params['data'],
    )
    # 返回結果
    module.exit_json(**result)


if __name__ == '__main__':
    main()
ansible -i inventory/devlop  linux-node1 -m ping
linux-node1 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}

ansible -i inventory/devlop  linux-node1 -m ping -a "data=abcd"
linux-node1 | SUCCESS => {
    "changed": false,
    "ping": "abcd"
}

ansible模塊中的輸出定制

changed: 平時我們使用別人的模塊,會發現changed字段,有的時候是true,有的時候是false,其實changed並不代表什么,ansible里面一致認為的是對系統進行了更改的changed為true,未更改的為false,其實只是一個記錄的值而已,要改變chnged的值,返回的字典里面只要changed=Fasle就好了result = dict(changed=False,stdout=ouput)

ansible模塊中的退出狀態處理

  • 正常退出:module.exit_jons

  • 錯誤退出:module.fail_json

錯誤退出比較不一樣的是,你要傳遞的參數是msg: result = dict(msg=output,rc=code)

報錯匯總

ERROR! this task 'myinfo_args' has extra params, which is only allowed in the following modules: shell, win_shell, include_vars, add_host, raw, include_role, meta, set_fact, include, import_tasks, script, import_role, include_tasks, group_by, command, win_command

命令執行錯了 ansible -i inventory/devlop linux-node1 -m myinfo_args -a 'new word'

正確的命令:ansible -i inventory/devlop linux-node1 -m myinfo_args -a "msg='new word'"

參考文檔

Ansible模塊開發-自定義模塊


免責聲明!

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



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