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