https://github.com/xsb/ansible-modules-talk
Ansible modules are reusable units of magic that can be used by the Ansible API, or by the ansible or ansible-playbook programs.
$ ansible webservers -m apt -a "name=nginx state=present"
- name: install nginx
apt: name=nginx state=present
/home/user/.ansible/tmp/ansible-tmp-1452255538.77-268151667579996/arguments
Usually idempotent actions to ensure state
ie: {"changed":"true"}, other additional info to be used as variables later in the playbook
$ find .
.
./playbook.yml
./library
./library/timesync
#!/bin/sh
# sync time using ntp
diff=$(ntpd -q | tail -n 1 | cut -d' ' -f4)
echo -n "{\"changed\":\"true\",\"diff\":\"$diff\"}"
---
- hosts: 127.0.0.1
sudo: True
tasks:
- timesync:
$ ansible-playbook playbook.yml -v
PLAY [127.0.0.1] **************************************************************
GATHERING FACTS ***************************************************************
ok: [127.0.0.1]
TASK: [timesync ] *************************************************************
changed: [127.0.0.1] => {"changed": "true", "diff": "+0.000726s"}
PLAY RECAP ********************************************************************
127.0.0.1 : ok=2 changed=1 unreachable=0 failed=0
$ find .
.
./playbook.yml
./library
./library/print_params
#!/bin/sh
# outputs its own input params
jq -R 'split(" ") | map(split("=") | {key: .[0], value: .[1]}) | from_entries' $1
---
- hosts: 127.0.0.1
tasks:
- print_params: name=xavi twitter=@xavi_xsb github=xsb
$ ansible-playbook playbook.yml -v
PLAY [127.0.0.1] **************************************************************
GATHERING FACTS ***************************************************************
ok: [127.0.0.1]
TASK: [print_params name=xavi twitter=@xavi_xsb github=xsb] *******************
ok: [127.0.0.1] => {"github": "xsb", "name": "xavi", "twitter": "@xavi_xsb"}
PLAY RECAP ********************************************************************
127.0.0.1 : ok=2 changed=0 unreachable=0 failed=0
We will implement a simple module:
1) Uploads a file to GitHub Gist
2) Return URL
TASK: [gist src=hello_ansible.md] *********************************************
changed: [127.0.0.1] => {"changed": true,
"filename": "hello_ansible.md",
"url": "https://gist.github.com/6d67067f049fbcf443a4"}
#!/usr/bin/python
import urllib2
import json
def copy_to_gist(public, filename, content):
data = {"public":public,'files':{filename:{'content':content}}}
req = urllib2.Request('https://api.github.com/gists')
req.add_header('Content-Type', 'application/json')
response = urllib2.urlopen(req, json.dumps(data))
return response
(...)
(...)
def main():
module = AnsibleModule(
argument_spec = dict(
src = dict(required=True, type='str'),
public = dict(required=False, default='false',
choices=['true', 'false']),
),
supports_check_mode = False
)
src = module.params['src']
filename = os.path.basename(src)
public = module.params['public']
f = open(os.path.expanduser(src))
content = f.read()
try:
response = copy_to_gist(public, filename, content)
except Exception as e:
module.fail_json(msg=str(e), changed=False)
j = json.load(response)
module.exit_json(changed=True, filename=filename, url=j['html_url'])
(...)
(...)
# import module snippets
from ansible.module_utils.basic import *
if __name__ == '__main__':
main()
$ git clone git://github.com/ansible/ansible.git --recursive
$ source ansible/hacking/env-setup
$ chmod +x ansible/hacking/test-module
$ ansible/hacking/test-module -m ./mymodule.py -a "key=value"
DOCUMENTATION = '''
---
module: gist
author: "Xavi S.B. @xsb"
short_description: create Github Gists
description:
- Copy files to Github Gist
options:
src:
description:
- File Path
required: true
public:
description:
- Is this Gist public or not?
required: false
default: false
choices: [ "true", "false" ]
'''
EXAMPLES = '''
# Upload a config file
- gist: src=/etc/pacman.conf public=false
'''
RETURN = '''
url:
description: gist url
returned: success
type: string
sample: https://gist.github.com/anonymous/4124f3e2d5441c141796
'''