Standard, there are a lot of modules available that are developed by the big active Ansible community. So reinventing the wheel is not always needed. BUT, if you are using Ansible in your organization for all your applications and services you find out soon that only the basic modules are not suitable. One of the biggest reasons is that every environment is different from each other.
Why should I create custom Ansible Modules?
There are a couple of reasons why you prefer making custom modules instead of running a script within a playbook. The biggest one in my opinion is; making your scripts human-readable and bringing it all together in one framework. Another positive thing is that you can re-use your already created scripts. Creating Ansible modules sounds very difficult but it is not that hard. In the next chapter, i discuss how to create a custom Ansible module in Python.
How to create a custom Python Ansible Module?
It all starts with an empty Python (myModule.py) file which you safe for example on SCM in a folder called library. In the first lines of code, we specify the script type and importing the modules we need to talk with the Ansible Core.
1 2 |
#!/usr/bin/python3 from ansible.module_utils.basic import * |
Then add your custom function or class with functions.
1 2 3 4 |
def lastFirst(firstName, lastName): separator = ' Big Fat ' result = lastName + separator + firstName return result |
Now the Ansible Magic.
- Define the def main(): function.
- Write down your variables which you want to assign in your playbook, I like the JSON method and loading them together. You can choose what the requirements are for that variable, I added some examples.
- Load the JSON Fields with AnsibleModule module we imported earlier.
- I like to define my variables again to simplify the vars (which is not necessary).
- Then do some stuff with your variables.
- Now you can choose how to interpreter the results. Choose when returning changed and failed ones.
- Example script below
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
#!/usr/bin/python3 from ansible.module_utils.basic import * def lastFirst(firstName, lastName): separator = ' Big Fat ' result = lastName + separator + firstName return result def main(): fields = { "firstname": {"required": True, "type": "str"}, "lastname": { "default": "davids", "choices": ['davids', 'alliston','wahi'], "type": 'str' } module = AnsibleModule(argument_spec=fields) firstname = module.params['firstname'] lastname = module.params['lastname'] result = lastFirst(firstname,lastname) if result: module.exit_json(changed=True, meta=result) else: module.fail_json(changed=False, meta=result) if __name__ == '__main__': main() |
The Ansible module playbook
When it comes to your playbook it is important to use the same name as your script file name (without .py). The playbook in this example looks like this.
1 2 3 4 5 6 7 8 9 10 11 12 |
- name: FirstName hosts: all connection: local gather_facts: no tasks: - name: GetFullName myModule: firstname: Sjef lastname: davids register: nameresult - debug: var: nameresult |