I'm writing a custom Ansible module and the python works fine but I'm having trouble turning it into a module. I've created a dummy module to reduce complexity and I'm getting the same issue. So the problem is with my Ansible boiler plate code. We're using version 2.9.2 for Ansible, python 3.6.9.
I've passed the two required parameters into the module and it should return them in a dictionary with the other two two set as the default.
I've created the AnsibleModule with the parameters, pulled them out used them in the python script then checked the result and exited the module. What have I missed?
Directory structure:
ansible.cfg
inventory.ini
module_test.yml
library/module_test.py
Here is the Ansible test script:
- name: Testing module
any_errors_fatal: true
connection: local
gather_facts: false
hosts: localhost
tasks:
- name: test the ansible module
module_test:
var1: "test var 1"
var2: "test var 2"
register: output
- name: debug output
debug:
msg: "{{ output }}"
Here is the python module:
#!/usr/bin/python
from ansible.module_utils.basic import AnsibleModule
class AnsibleModuleTest(object):
def __init__(self, var1, var2, var3, var4):
self._var1 = var1
self._var2 = var2
self._var3 = var3
self._var4 = var4
def run(self, check):
if check:
return {"result": True, "data": {"var1": self._var1, "var2": self._var2, "var3": self._var3, "var4": self._var4}}
else:
return {"result": False, "error": "fail"}
def main():
module = AnsibleModule(
argument_spec=dict(
var1=dict(required=True),
var2=dict(required=True),
var3=dict(required=False, default=None),
var4=dict(required=False, default=None),
supports_check_mode=False
)
)
var1 = module.params["var1"]
var2 = module.params["var2"]
var3 = module.params["var3"]
var4 = module.params["var4"]
_test_module = AnsibleModuleTest(var1, var2, var3, var4)
_returned_data = _test_module.run(True)
if _returned_data["result"]:
result = dict(msg=_returned_data["data"], changed=False)
module.exit_json(**result)
else:
module.fail_json(msg=_returned_data["error"])
if __name__ == '__main__':
main()
Here is the traceback:
TASK [test the ansible module] **************************************************************************************************
task path: /root/test_role/module_test.yml:9
<127.0.0.1> ESTABLISH LOCAL CONNECTION FOR USER: root
<127.0.0.1> EXEC /bin/sh -c 'echo ~root && sleep 0'
<127.0.0.1> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /root/.ansible/tmp/ansible-tmp-1594296428.9225461-257853634365367 `" && echo ansible-tmp-1594296428.9225461-257853634365367="` echo /root/.ansible/tmp/ansible-tmp-1594296428.9225461-257853634365367 `" ) && sleep 0'
Using module file /root/test_role/library/module_test.py
<127.0.0.1> PUT /root/.ansible/tmp/ansible-local-34085udiksek/tmphun0ptk_ TO /root/.ansible/tmp/ansible-tmp-1594296428.9225461-257853634365367/AnsiballZ_module_test.py
<127.0.0.1> EXEC /bin/sh -c 'chmod u+x /root/.ansible/tmp/ansible-tmp-1594296428.9225461-257853634365367/ /root/.ansible/tmp/ansible-tmp-1594296428.9225461-257853634365367/AnsiballZ_module_test.py && sleep 0'
<127.0.0.1> EXEC /bin/sh -c '/usr/bin/python3 /root/.ansible/tmp/ansible-tmp-1594296428.9225461-257853634365367/AnsiballZ_module_test.py && sleep 0'
<127.0.0.1> EXEC /bin/sh -c 'rm -f -r /root/.ansible/tmp/ansible-tmp-1594296428.9225461-257853634365367/ > /dev/null 2>&1 && sleep 0'
The full traceback is:
Traceback (most recent call last):
File "/root/.ansible/tmp/ansible-tmp-1594296428.9225461-257853634365367/AnsiballZ_module_test.py", line 102, in <module>
_ansiballz_main()
File "/root/.ansible/tmp/ansible-tmp-1594296428.9225461-257853634365367/AnsiballZ_module_test.py", line 94, in _ansiballz_main
invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)
File "/root/.ansible/tmp/ansible-tmp-1594296428.9225461-257853634365367/AnsiballZ_module_test.py", line 40, in invoke_module
runpy.run_module(mod_name='ansible.modules.module_test', init_globals=None, run_name='__main__', alter_sys=True)
File "/usr/lib/python3.6/runpy.py", line 205, in run_module
return _run_module_code(code, init_globals, run_name, mod_spec)
File "/usr/lib/python3.6/runpy.py", line 96, in _run_module_code
mod_name, mod_spec, pkg_name, script_name)
File "/usr/lib/python3.6/runpy.py", line 85, in _run_code
exec(code, run_globals)
File "/tmp/ansible_module_test_payload_13zt59h5/ansible_module_test_payload.zip/ansible/modules/module_test.py", line 52, in <module>
File "/tmp/ansible_module_test_payload_13zt59h5/ansible_module_test_payload.zip/ansible/modules/module_test.py", line 32, in main
File "/tmp/ansible_module_test_payload_13zt59h5/ansible_module_test_payload.zip/ansible/module_utils/basic.py", line 639, in __init__
File "/tmp/ansible_module_test_payload_13zt59h5/ansible_module_test_payload.zip/ansible/module_utils/basic.py", line 1847, in _set_fallbacks
AttributeError: 'bool' object has no attribute 'get'
fatal: [localhost]: FAILED! => {
"changed": false,
"module_stderr": "Traceback (most recent call last):\n File \"/root/.ansible/tmp/ansible-tmp-1594296428.9225461-257853634365367/AnsiballZ_module_test.py\", line 102, in <module>\n _ansiballz_main()\n File \"/root/.ansible/tmp/ansible-tmp-1594296428.9225461-257853634365367/AnsiballZ_module_test.py\", line 94, in _ansiballz_main\n invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)\n File \"/root/.ansible/tmp/ansible-tmp-1594296428.9225461-257853634365367/AnsiballZ_module_test.py\", line 40, in invoke_module\n runpy.run_module(mod_name='ansible.modules.module_test', init_globals=None, run_name='__main__', alter_sys=True)\n File \"/usr/lib/python3.6/runpy.py\", line 205, in run_module\n return _run_module_code(code, init_globals, run_name, mod_spec)\n File \"/usr/lib/python3.6/runpy.py\", line 96, in _run_module_code\n mod_name, mod_spec, pkg_name, script_name)\n File \"/usr/lib/python3.6/runpy.py\", line 85, in _run_code\n exec(code, run_globals)\n File \"/tmp/ansible_module_test_payload_13zt59h5/ansible_module_test_payload.zip/ansible/modules/module_test.py\", line 52, in <module>\n File \"/tmp/ansible_module_test_payload_13zt59h5/ansible_module_test_payload.zip/ansible/modules/module_test.py\", line 32, in main\n File \"/tmp/ansible_module_test_payload_13zt59h5/ansible_module_test_payload.zip/ansible/module_utils/basic.py\", line 639, in __init__\n File \"/tmp/ansible_module_test_payload_13zt59h5/ansible_module_test_payload.zip/ansible/module_utils/basic.py\", line 1847, in _set_fallbacks\nAttributeError: 'bool' object has no attribute 'get'\n",
"module_stdout": "",
"msg": "MODULE FAILURE\nSee stdout/stderr for the exact error",
"rc": 1
}
Fixed, I have my boiler plate code, should've followed the Ansible page rather than other people's solutions.