1
votes

I am trying to learn how to build a module. The goal is to be able to send variables to be processed by a module and return the result as a different variable to be used in a jinja2 template. I think I am missing something very basic and I can't find any examples that highlight what I am doing wrong.

This is my first try in building a module and I have little python experience. I am running Ansible 2.7 with Python 2.7. I have looked at several examples on the web and the Ansible documents so I think I am close but I am not understanding how to pass the variable correctly or how the python commands work within the module.

Here is the playbook: split.yml


    - hosts: localhost

      tasks:
      - name: split a coumpound variable into parts
        split:
          excel: 'data1 data2'
        register: result

      - debug: var=result

And here is the module in library/split.py


    #!/usr/bin/python

    from ansible.module_utils.basic import *

    def main():
        module = AnsibleModule(argument_spec={})
        splitcell = (excel.split()[0])
        module.exit_json(changed=False, meta=splitcell)

    if __name__ == '__main__':
        main()

Here is the error when running the playbook:

fatal: [localhost]: FAILED! => { "changed": false, "invocation": { "module_args": { "excel": "data1 data2" } }, "msg": "Unsupported parameters for (split) module: excel Supported parameters include: " } to retry, use: --limit @/root/ansible/split.retry

PLAY RECAP ************************************************************************************************************************************************** localhost : ok=1 changed=0 unreachable=0
failed=1

I also tried a different function with similar results:

Playbook: processip.yml


    - hosts: localhost

      tasks:
      - name: Test ip module
        processip: ip_string="192.168.0.2/24"
        register: result

      - debug: var=result

Module: library/processip.py


    #!/usr/bin/python

    import ipaddress
    from ansible.module_utils.basic import *

    def main():
        module = AnsibleModule(argument_spec={})
        get_netmask = {ipaddress.IPv4Interface(ip_string).netmask}
        module.exit_json(changed=False, meta=get_netmask)

    if __name__ == '__main__':
        main()

Error output:

fatal: [localhost]: FAILED! => { "changed": false, "invocation": { "module_args": { "ip_string": "192.168.0.2/24" } }, "msg": "Unsupported parameters for (processip) module: ip_string Supported parameters include: " } to retry, use: --limit @/root/ansible/processip.retry

PLAY RECAP ************************************************************************************************************************************************** localhost : ok=1 changed=0 unreachable=0
failed=1

For try number 1 I was simply trying to pass a variable "data1 data2" and split it at the space and return the first string in the list (data1)

The second attempt was to take an IP address 192.168.0.2/24 and process it with the python ipaddress module to return 192.168.0.2 255.255.255.0.

1

1 Answers

2
votes

You have told Ansible that your module takes no arguments:

module = AnsibleModule(argument_spec={})

If you want to accept an excel argument, you need to declare that in your code:

module = AnsibleModule(argument_spec={
    'excel': {'type': 'str', 'required': True},
})

In your code, you attempt to access a variable named excel, but no such variable exists. You could get the parameter value like this:

excel = module.params['excel']

With these changes, your module would look like this:

#!/usr/bin/python

from ansible.module_utils.basic import *

def main():
    module = AnsibleModule(argument_spec={
        'excel': {'type': 'str', 'required': True},
    })
    excel = module.params['excel']
    splitcell = (excel.split()[0])
    module.exit_json(changed=False, meta=splitcell)

if __name__ == '__main__':
    main()

And running your example would produce:

TASK [debug] **********************************************************************************************************************************************************************************
ok: [localhost] => {
    "result": {
        "changed": false, 
        "failed": false, 
        "meta": "data1"
    }
}