我试着写一个Ansible模块。我的模块有问题。当我从剧本中运行它时,我得到以下不可读的输出:
$ ansible-playbook lacp.yml
PLAY [xxxxxxxx] ****************************************************************
TASK [Test that my module works] ***********************************************
fatal: [xxxxxxxx]: FAILED! => {"changed": false, "failed": true, "module_stderr": "couldn't set locale correctly\ncouldn't set locale correctly\ncouldn't set locale correctly\nTraceback (most recent call last):\n File \"/tmp/ansible_vHkWq8/ansible_module_lacp.py\", line 27, in <module>\n main()\n File \"/tmp/ansible_vHkWq8/ansible_module_lacp.py\", line 14, in main\n m = re.match('^key: ([0-9]+) ', dladm.readline())\nAttributeError: 'Popen' object has no attribute 'readline'\ndladm: insufficient privileges\n", "module_stdout": "", "msg": "MODULE FAILURE", "parsed": false}
NO MORE HOSTS LEFT *************************************************************
[WARNING]: Could not create retry file 'lacp.retry'. [Errno 2] No such file or directory: ''
PLAY RECAP *********************************************************************
xxxxxxxx : ok=0 changed=0 unreachable=0 failed=1
如何使用JSON停止Ansible引用错误消息?或者是否有其他方法来调试Ansible模块?
答案 0 :(得分:2)
如何使用JSON停止Ansible引用错误消息?
您可以使用human_log.py插件强制Ansible在其输出中解释和打印换行符。
您将文件放入/path/to/callback_plugins/
目录并将以下内容添加到ansible.cfg
:
[defaults]
callback_plugins = /path/to/callback_plugins/
详细说明位于Human-Readable Ansible Playbook Log Output Using Callback Plugin博客文章中。
答案 1 :(得分:2)
您可以查看this和this回调插件(适用于Ansible 2.x)。
您需要稍微修改它们,因为它们不会立即转换module_stderr
。
此外,您可能希望使用ANSIBLE_KEEP_REMOTE_FILES=1
执行playbook,然后ssh到远程框并就地调试模块,然后保存到ansible库。
答案 2 :(得分:0)
调试Ansible模块将很快变得几乎不可能,并且非常非常耗时,而无需遵循推荐的方法。
推荐的方法是使用非常小的步骤来构建Ansible的东西。这样,您就可以在向已知的内容中添加内容并验证其可以正常工作时,更容易地猜测出了什么问题。
因此,当您声明该模块有故障时,您已经走了很远。您将毫无疑问地在Ansible的大海捞针中搜索。
重构并不是一个实际的选择。您基本上从头开始,逐步创建代码。
我希望您注意到Ansible甚至不用理会以人类可读的方式格式化错误输出。发生错误时,Ansible会输出相同的消息:出了点问题。
假设我有这个Ansible任务
- name: Mymodule
mymodule:
something: "something"
我的模块也很简单
#!/usr/bin/python
from ansible.module_utils.basic import *
def somefunction(data):
has_changed = False
meta = { "something": "something"}
return (has_changed, meta)
def main():
fields = {
"something": {"required": True, "type": "str"},
"state": {
"default": "perform",
"choices": ["perform"],
"type": "str"
},
}
choice_map = {
"perform2": somefunction,
}
module = AnsibleModule(argument_spec=fields)
has_changed, result = choice_map.get(module.params['state'])(module.params)
module.exit_json(changed=has_changed, meta=result)
if __name__ == '__main__':
main()
Ansible将产生以下错误消息
任务[备份:Mymodule] ****************************************************** *****致命:[myapp]:失败! => {“已更改”:false,“ module_stderr”:“共享 与127.0.0.1的连接已关闭。\ r \ n“,” module_stdout“:”跟踪 (最近通话最近):\ r \ n文件 \“ / home / vagrant / .ansible / tmp / ansible-tmp-1570188887.99-191548982937437 / AnsiballZ_mymodule.py \”, \ r \ n _ansiballz_main()\ r \ n文件中的第114行 \“ / home / vagrant / .ansible / tmp / ansible-tmp-1570188887.99-191548982937437 / AnsiballZ_mymodule.py \”, 第106行,位于_ansiballz_main \ r \ n invoke_module(zipped_mod, temp_path,ANSIBALLZ_PARAMS)\ r \ n文件 \“ / home / vagrant / .ansible / tmp / ansible-tmp-1570188887.99-191548982937437 / AnsiballZ_mymodule.py \”, 第49行,在invoke_module \ r \ n imp.load_module(' main ',mod, 模块,MOD_DESC)\ r \ n文件 \“ / tmp / ansible_mymodule_payload_XTaVPp / 主要 .py \”,第29行 \ r \ n文件 \“ / tmp / ansible_mymodule_payload_XTaVPp / 主要 .py \”,第25行,在 main \ r \ nTypeError:'NoneType'对象不可调用\ r \ n“,” msg“: “模块失败\ n请参阅stdout / stderr了解确切错误”,“ rc”:1}
我们应该关注的“消息”是
TypeError:“ NoneType”对象不可调用
这是由错误的操作 perform2 引起的。它应该执行。一个简单的错字。
choice_map = {
"perform2": somefunction,
}
第21行的模块文件 mymodule.py 中有错别字。文件和行114、106、49、29、25在某种程度上可能有用,但这些文件的用法尚不清楚完全没有。
这只是一个非常简单的例子来说明大海捞针的要点。 Ansible不会以人类可读的方式格式化错误消息。报告问题文件和行号也不是一门精确的科学方法。错误消息没有用。错误消息应该是我的choice_map引用了不存在的动作。它可以列出可用的选择。
恕我直言,这是Ansible的常见问题。输入错误可能需要一个小时才能解决。
解决此限制的唯一方法是逐步建立供应。宝贝的步骤。