Last active
July 3, 2017 16:36
-
-
Save brutus/ba3b110c3041777e2e976b61e924b18c to your computer and use it in GitHub Desktop.
A very basic Ansible module for toast.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
# -*- coding: UTF-8 -*- | |
""" | |
Ansible module to interact with `toast`_. | |
To use this from Ansible, copy it in your `library`_:: | |
cd path/to/library | |
git clone https://gist.github.com/brutus/ba3b110c3041777e2e976b61e924b18c toast | |
And use it in your playbook or roles like this:: | |
# install tar | |
- toast: | |
name: tar | |
# update tar | |
- toast: | |
name: tar | |
state: latest | |
# uninstall tar | |
- toast: | |
name: tar | |
state: absent | |
It returns some JSON like this (eg: install `tar` while it is already | |
installed):: | |
{ | |
"action": "nothing", | |
"changed": false, | |
"invocation": { | |
"module_args": { | |
"name": "tar", | |
"state": "present" | |
}, | |
"module_name": "toast" | |
}, | |
"status_new": { | |
"name": "tar", | |
"state": "present", | |
"version": "1.29" | |
}, | |
"status_old": { | |
"name": "tar", | |
"state": "present", | |
"version": "1.29" | |
} | |
} | |
Install new package sources | |
--------------------------- | |
To add a new URL as package source, use a `add` as *state* and the URL as *name*, e.g. for the `tree`_ utility:: | |
# add package for `tree` | |
- toast: | |
name: ftp://mama.indstate.edu/linux/tree/ | |
state: add | |
.. _toast: http://www.toastball.net/toast/ | |
.. _library: http://docs.ansible.com/ansible/intro_configuration.html#library | |
.. _tree: http://mama.indstate.edu/users/ice/tree/ | |
""" | |
from __future__ import absolute_import | |
from __future__ import unicode_literals | |
import re | |
from ansible.module_utils.basic import AnsibleModule | |
def main(): | |
REGEX_VERSION = re.compile(r'version (?P<version>[0-9\.]+): .+') | |
def get_status(name): | |
""" | |
Returns a dict with toast status information for *name*. | |
The *name*, *state* and *version* will be returned. | |
If the return code of the toast command (`rc`) is 0, the *name* is | |
found in toasts DB and the output should be similar to this:: | |
toast | |
version 1.486: stored | |
urls: | |
http://www.toastball.net/toast/toast-1.486.tar.gz | |
build 1: armed | |
""" | |
state = 'absent' | |
version = None | |
err_msg = 'failed to parse output: {0}' | |
# run command | |
cmd = ['toast', 'status', name] | |
(rc, stdout, stderr) = module.run_command(cmd, check_rc=False) | |
result = [line.strip() for line in stdout.split('\n') if line] | |
if rc == 0: # means the *name* is in the DB | |
# verify name | |
if result[0] != name: | |
module.fail_json(msg=err_msg.format(result)) | |
# check state | |
build_string = result[-1] | |
if ( | |
build_string.startswith('build') and | |
build_string.endswith('armed') | |
): | |
state = 'present' | |
# check version | |
match = REGEX_VERSION.match(result[1]) | |
if match: | |
version = match.group('version') | |
else: | |
module.fail_json(msg=err_msg.format(result)) | |
return { | |
'name': name, | |
'state': state, | |
'version': version, | |
} | |
def get_package_status(name): | |
""" | |
Returns the state for the package with *name*. | |
The *state* is either `present` or `absent`. | |
""" | |
cmd = ['toast', 'status', name] | |
(rc, stdout, stderr) = module.run_command(cmd, check_rc=False) | |
if rc == 0: | |
return 'present' | |
else: | |
return 'absent' | |
def install(name): | |
""" | |
Calls toast to install *name*. | |
""" | |
cmd = ['toast', 'arm', name] | |
module.run_command(cmd, check_rc=True) | |
def upgrade(name): | |
""" | |
Calls toast to upgrade *name*. | |
""" | |
cmd = ['toast', 'upgrade', name] | |
module.run_command(cmd, check_rc=True) | |
def uninstall(name): | |
""" | |
Calls toast to uninstall *name*. | |
""" | |
cmd = ['toast', 'disarm', name] | |
module.run_command(cmd, check_rc=True) | |
def add_package(url): | |
""" | |
Calls toast to add a new package for *url*. | |
""" | |
cmd = ['toast', 'add', url] | |
module.run_command(cmd, check_rc=True) | |
# setup module | |
args = { | |
'name': dict(required=True), | |
'state': dict( | |
choices=['present', 'absent', 'latest', 'add'], | |
default='present', | |
), | |
} | |
module = AnsibleModule( | |
argument_spec=args, | |
supports_check_mode=True, | |
) | |
# interact with toast | |
name = module.params['name'] | |
req_state = module.params['state'] | |
# add package? | |
if req_state == 'add': | |
action = 'add' | |
status_old = get_package_status(name) | |
if module.check_mode or status_old == 'present': | |
status_new = status_old | |
else: | |
add_package(name) | |
status_new = get_package_status(name) | |
# install / upgrade / uninstall | |
else: | |
status_old = get_status(name) | |
state = status_old['state'] | |
if req_state == 'absent': | |
action = 'uninstall' if state == 'present' else '' | |
elif req_state == 'latest': | |
action = 'upgrade' if state == 'present' else 'install' | |
else: # present | |
action = '' if state == 'present' else 'install' | |
if module.check_mode: | |
status_new = status_old | |
else: | |
if action == 'uninstall': | |
uninstall(name) | |
elif action == 'upgrade': | |
upgrade(name) | |
else: # install | |
install(name) | |
status_new = get_status(name) | |
# return results as JSON | |
module.exit_json( | |
changed=status_old != status_new, | |
status_old=status_old, | |
status_new=status_new, | |
action=action or 'nothing', | |
) | |
if __name__ == '__main__': | |
main() |
I guess it has to be name: tar
in the update example
# update tar
- toast:
name: tar # was "name: toast"
state: latest
I guess it has to be name: tar in the update example
Correct. Fixed it. Thanks for spotting and report!
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
To use this from Ansible, copy it in your library and use it in your playbook or roles like this:
It returns some JSON like this (eg: install
tar
while it is already installed):