• 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.
    ",
        "module_stdout": "
    Traceback (most recent call last):
      File "/home/niu/.ansible/tmp/ansible-tmp-1578648957.53-161256530271090/AnsiballZ_myshell.py", line 113, in <module>
        _ansiballz_main()
      File "/home/niu/.ansible/tmp/ansible-tmp-1578648957.53-161256530271090/AnsiballZ_myshell.py", line 105, in _ansiballz_main
        invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)
      File "/home/niu/.ansible/tmp/ansible-tmp-1578648957.53-161256530271090/AnsiballZ_myshell.py", line 48, in invoke_module
        imp.load_module('__main__', mod, module, MOD_DESC)
      File "/tmp/ansible_myshell_payload_XylgIF/__main__.py", line 40, in <module>
      File "/tmp/ansible_myshell_payload_XylgIF/__main__.py", line 33, in main
    UnboundLocalError: local variable 'result' referenced before assignment
    ",
        "msg": "MODULE FAILURE
    See 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模块开发-自定义模块

  • 相关阅读:
    关于使用css3属性:transform固定菜单位置,在滑动页面时菜单闪现抖动的问题
    使用iscroll.js插件时,遇到在Android端无法点击a超链的解决办法
    window.external的使用
    SpringMVC的拦截器(Interceptor)和过滤器(Filter)的区别与联系
    chain.doFilter(request,response)含义
    巧用Ajax的beforeSend 提高用户体验
    getRequestDispatcher(path).forward(),,执行完,后面的代码居然还会执行!!!记得加return 啊亲
    @JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)
    ajax修改表单的值后dom没更新的解决办法
    .net core json序列化首字符小写和日期格式处理
  • 原文地址:https://www.cnblogs.com/biglittleant/p/12857484.html
Copyright © 2020-2023  润新知