[PYTHON] Ansible self-made module creation-Part 1: Life you want to receive arguments-

When I tried to use Ansible, there was no equivalent of a named pipe ( makefifo), so I decided to do my best with my own module.

Reference site

-Ansible module development (Python implementation) ――I like it because it's so easy to understand! --How to pass multiple module arguments (parameters) with the ansible command --How to give multiple arguments when executing the `ʻansible`` command

environment

$ cat /etc/redhat-release
CentOS Linux release 7.7.1908 (Core)

$ ansible --version
ansible 2.9.7
  config file = /etc/ansible/ansible.cfg
  configured module search path = [u'/home/ansi/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.7/site-packages/ansible
  executable location = /bin/ansible
  python version = 2.7.5 (default, Aug  7 2019, 00:51:29) [GCC 4.8.5 20150623 (Red Hat 4.8.5-39)]

Make a template

While looking at the reference site

makefifo.py


#!/usr/bin/python
# -*- coding: utf-8 -*-

from ansible.module_utils.basic import AnsibleModule
module = AnsibleModule(
    dict=(
        message=dict()
    )
)
print '{"message_key":"%s"}' % (module.params['message'])

I wonder if it's okay like this. Let's run it right away.

$ ansible -i test_grp 192.168.56.104 -m makefifo -M library -u root -a message=test
192.168.56.104 | FAILED! => {
    "msg": "Unable to import makefifo due to invalid syntax"
}

OOPS !! That. .. Suddenly I stumbled.

Is there a difference depending on the version of Ansible? So I shifted the direction to try to disassemble the existing module and make it.

$ find /usr/lib/python2.7/site-packages -type f -name ping.py
/usr/lib/python2.7/site-packages/ansible/modules/system/ping.py

Copy this guy and rename it to pong.py and check the normal operation first.

$ ansible -i test_grp 192.168.56.104 -m pong -M library -u root -a data=hoge
192.168.56.104 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "ping": "hoge"
}

Yeah, it's working.

As a result of scraping the unnecessary part of the contents from here, I was able to scrape to the following.

pong.py


#!/usr/bin/python
# -*- coding: utf-8 -*-

from ansible.module_utils.basic import AnsibleModule

#Main processing
#-----------------------------------------------------------
def main():
    #AnsibleModule class:Create module
    module = AnsibleModule(

        #Argument reception
        argument_spec=dict(

            #argument: data(str type,def:pong)
            data=dict(type='str', default='pong'),
        ),
        #Argument check enabled
        supports_check_mode=True
    )

    #Result dict:Create result
    result = dict(
        # key:The key given as an argument to ping:Store the value of data
        ping=module.params['data'],
    )

    #The contents of result is key=value,Output in the form of
    module.exit_json(**result)

if __name__ == '__main__':
    main()
$ ansible -i test_grp 192.168.56.104 -m pong -M library -u root -a data=hoge
192.168.56.104 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "ping": "hoge"
}

Let's use this as a template.

Receive arguments

I think the parameters required for makefifo are as follows.

Parameters Variable name(key name) Mold Mandatory
File Path path str
owner(User) owner str
owner(group) group str
permission mode str

First, let's create a module that just receives these guys and returns them to the results.

makefifo.py


#!/usr/bin/python
# -*- coding: utf-8 -*-

from ansible.module_utils.basic import AnsibleModule

#Main processing
#-----------------------------------------------------------
def main():
    #AnsibleModule class:Create module
    module = AnsibleModule(

        #Argument reception
        argument_spec=dict(

            #argument: path(str type,Mandatory)
            path=dict(type='str', required=True),
            #argument: owner(str type,Mandatory)
            owner=dict(type='str', required=True),
            #argument: group(str type,Mandatory)
            group=dict(type='str', required=True),
            #argument: mode(str type,Mandatory)
            mode=dict(type='str', required=True),
        ),
        #Argument check enabled
        supports_check_mode=True
    )

    #Result dict:Create result
    result = dict(
        path=module.params['path'],
        owner=module.params['owner'],
        group=module.params['group'],
        mode=module.params['mode'],
    )

    #The contents of result is key=value,Output in the form of
    module.exit_json(**result)

if __name__ == '__main__':
    main()

For required and its surroundings, refer to Ansible module development (Python implementation).

Now, check the operation ... How about giving multiple arguments? I found the following when I looked it up in.

--How to pass multiple module arguments (parameters) with ansible command

Thank you, thank you.

$ ansible -i test_grp 192.168.56.104 -m makefifo -M library -u root -a "path=/tmp/hoge owner=root group=root mode=0644"
192.168.56.104 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "group": "root",
    "mode": "0644",
    "owner": "root",
    "path": "/tmp/hoge"
}

did it! Alright, all you have to do is implement it in Python. For the time being, here is today.

Recommended Posts

Ansible self-made module creation-Part 1: Life you want to receive arguments-
Ansible self-made module creation-Part 2: Life just wanting to execute commands-
Ansible self-made module rpm operation
Gist repository to use when you want to try a little with ansible
Let's summarize what you want to do.
[Ansible] I want to call my own function from the template module (macro)
What to do when you want to receive files from a Windows client remotely