调试Ansible模块

时间:2016-09-12 15:14:04

标签: ansible

我试着写一个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模块?

3 个答案:

答案 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)

您可以查看thisthis回调插件(适用于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的常见问题。输入错误可能需要一个小时才能解决。

解决此限制的唯一方法是逐步建立供应。宝贝的步骤。