模块自定义开发
ansible的模块非常多,官方/社区提供的模块数量非常多,大多数都可以满足需求,但有时候需要满足公司业务的一些特殊需求,则需要自己对模块的开发。
ansible module的原理
根据ansible 搜索路径找到inventory 以及对应的模块路径 加载模块文件 ansible 将模块加载到内存中,并同步生成对应的临时py文件(python脚本), 并将文件传到目标服务器(基于ssh),期间会打开3次ssh 链接,分别是传脚本-传文件-赋权限 执行并返回结果 删除临时py文件根据以上步骤,可以发现几个问题
module 文件是被传送到 远端主机 执行的。 module是 文件 , 而非脚本,所以可以使用任何语言编写,哪怕最终是个编译后的二进制文件也可以。 模块的返回值必须是 json dumps的字符串 。调试
module 是远端主机执行的,所以调试会比较麻烦,一般有2个方法进行调试
保留传过去的python 脚本以及文件:# 设置环境变量,让传过去的文件不会自动被清理,这样就可以在远端进行调试 ANSIBLE_KEEP_REMOTE_FILES=1本地调试
# 下载官方的本地调试脚本 wget https://raw.githubusercontent.com/ansible/ansible/devel/hacking/test-module.py # 执行脚本 python test-module.py -m mymod {"changed": true, "end": "2020-01-01 23:00:00.125895", "stdout": "", "cmd": ["/bin/sleep", "3"], "rc": 0, "start": "2020-01-01 23:10:00.125895", "stderr": "", "delta": "0:00:03.077342", "invocation": {"module_args": {"creates": null, "executable": null, "_uses_shell": false, "strip_empty_ends": true, "_raw_params": "/bin/sleep 3", "removes": null, "argv": null, "warn": true, "chdir": null, "stdin_add_newline": true, "stdin": null}}}
模块开发
需要修改ansible.cfg的配置文件,将library 里面的路径改成自己定义的模块路径
以下是一个简单的检查文件md5的demo:
#!/usr/bin/env python # -*- codingutf-8-*- from ansible.module_utils.basic import * import hashlib import os.path # 初始化一个module实例,需要传入文件的m5d 以及 路径,用于对比文件是否经过修改。 module = AnsibleModule( argument_spec = dict( path=dict(type='str', required=True), checksum=dict(type='str', required=True), ), ) # 获取参数变量 path = module.params['path'] checksum = module.params['checksum'] if os.path.isfile(path): fp = open(path,'rb') contents = fp.read() fp.close() md5sum = hashlib.md5(contents).hexdigest() if md5sum == checksum: result = dict(stdout = "file checksum is ok", changed = False, rc = 0) module.exit_json(**result) else: result = dict(msg = 'file checksum is wrong',rc = 1) module.fail_json(**result) else: result = dict(msg='file not exists',rc = 1) module.fail_json(**result)
其他语言编写module
args_file=$1 [ ! -f "$args_file" ] && echo -n '{"failed": true, "msg": "missing required arguments: file"}' && exit 1 args_result=$(cat $args_file | gawk -F'file=' '{print $2}' | gawk -F' ' '{print $1}') [ ! -n "$args_result" ] && echo -n "{\"failed\": true, \"msg\": \"file () is absent, cannot continue\", \"file\": \"$args_result\"}" && exit 1 touch $args_result && echo -n "{\"changed\": true, \"rc\": $?,\"file\": \"$args_result\"}" || echo -n "{\"failed\": true, \"rc\": $?, \"file\": \"$args_result\"}" exit $?
参数是通过 文件形式 进行传递的,而不是通过参数形式进行传输的,所以参数的解析需要注意,且返回值必须是json格式的字符串,满足这2项后,用其他语言都可以进行模块的开发。
个人公众号, 分享一些日常开发,运维工作中的日常以及一些学习感悟,欢迎大家互相学习,交流
声明:本文来自网络,不代表【好得很程序员自学网】立场,转载请注明出处:http://www.haodehen.cn/did125845