Last active
November 24, 2015 06:20
-
-
Save mgedmin/aec4678b25c2734f0d57 to your computer and use it in GitHub Desktop.
"changelog" module for Ansible, wrapping new-changelog-entry from pov-admin-tools
This file contains hidden or 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
# action_plugins/changelog.py | |
import time | |
try: | |
# Ansible 2 | |
from ansible.plugins.action import ActionBase | |
class ActionModule(ActionBase): | |
'''Set default value for 'append' from the 'changelog_started' fact''' | |
def run(self, tmp=None, task_vars=dict()): | |
changelog_started = bool(task_vars.get('changelog_started', False)) | |
changelog_last_update = int(task_vars.get('changelog_last_update', 0)) | |
if changelog_last_update and changelog_last_update < time.time() - 300: | |
changelog_started = False | |
module_args = self._task.args.copy() | |
module_args.setdefault('append', changelog_started) | |
return self._execute_module(module_args=module_args, tmp=tmp, task_vars=task_vars) | |
except ImportError: | |
# Ansible 1 | |
from ansible.runner.return_data import ReturnData | |
from ansible.runner.action_plugins.normal import ActionModule as _ActionModule | |
class ActionModule(_ActionModule): | |
'''Set default value for 'append' from the 'changelog_started' fact''' | |
def run(self, conn, tmp, module_name, module_args, inject, complex_args=None, **kwargs): | |
if module_args == 'start=yes' or complex_args.get('start'): | |
# optimization | |
return ReturnData(conn=conn, comm_ok=True, result=dict(ansible_facts=dict(changelog_started=False))) | |
if self.runner.noop_on_check(inject): | |
return ReturnData(conn=conn, comm_ok=True, result=dict(skipped=True, msg='check mode not supported for this module')) | |
changelog_started = inject.get('changelog_started', False) | |
changelog_last_update = inject.get('changelog_last_update', 0) | |
if changelog_last_update and changelog_last_update < time.time() - 300: | |
changelog_started = False | |
complex_args.setdefault('append', changelog_started) | |
return super(ActionModule, self).run(conn, tmp, module_name, module_args, inject, complex_args=complex_args, **kwargs) |
This file contains hidden or 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/python | |
# library/changelog.py | |
import os | |
import subprocess | |
import time | |
DOCUMENTATION = ''' | |
--- | |
module: changelog | |
short_description: appends a message to /root/Changelog | |
description: | |
- The M(changelog) module takes single a string message and appends it | |
to /root/Changelog on the remote host, with a date and time header. | |
- This requires pov-admin-tools to be installed on the remote. | |
options: | |
msg: | |
description: | |
- the message | |
required: true | |
default: null | |
append: | |
description: | |
- append the message to the existing entry instead of starting a new entry | |
required: false | |
choices: [ true, false ] | |
default: false for the 1st invocation on each host, true for all subsequent invocations | |
blank_line_above: | |
description: | |
- prepend a blank line above the message, unless this is the 1st invocation | |
required: false | |
choices: [ true, false ] | |
default: false | |
start: | |
description: | |
- reset the state so the next invocation is considered to be 1st invocation | |
- run this first if you use fact caching, otherwise changelogs from | |
multiple playbook runs will be clumped together | |
choices: [ true, false ] | |
required: false | |
default: false | |
author: | |
- Marius Gedminas <[email protected]> | |
''' | |
EXAMPLES = ''' | |
# Prerequisite: install pov-admin-tools from ppa:pov | |
- apt_repository: repo='ppa:pov' state=present | |
- apt: name=pov-admin-tools state=present | |
# Reset the changelog state | |
- changelog: start=yes | |
# Record new installed package iff it was installed | |
- apt: name=postfix state=present | |
record: apt_result | |
- changelog: msg="apt-get install postfix" | |
when: apt_result|changed | |
# A multi-line changelog message | |
- changelog: | |
args: | |
blank_line_above: yes | |
msg: | | |
# | |
# Banner message | |
# | |
apt-get foo bar | |
# NB: the "|"-literal YAML syntax adds a blank line afterwards | |
- changelog: | |
args: | |
msg: | |
- "# multiple" | |
- "# messages" | |
- "# with no blank line after them, unlike the example above" | |
''' | |
def main(): | |
module = AnsibleModule( | |
argument_spec=dict( | |
msg=dict(required=False), | |
start=dict(type='bool', default=False), | |
append=dict(type='bool', default=False), | |
blank_line_above=dict(type='bool', default=False), | |
), | |
) | |
start = module.params['start'] | |
if start: | |
module.exit_json( | |
ansible_facts=dict( | |
changelog_started=False, | |
) | |
) | |
msg = module.params['msg'] | |
if msg is None: | |
module.fail_json(msg="message is required".format(msg)) | |
if isinstance(msg, list): | |
msg = "\n ".join(msg) | |
else: | |
msg = msg.replace('\n', '\n ') | |
append = module.params['append'] | |
blank_line_above = module.params['blank_line_above'] | |
if append and blank_line_above: | |
msg = '\n ' + msg | |
if msg in ('-a', '-e', '/root/Changelog') or os.path.exists(msg): | |
module.fail_json(msg="message cannot be '{}' due to the way new-changelog-message parses its arguments".format(msg)) | |
args = ['new-changelog-entry'] | |
if append: | |
args += ['-a'] | |
args += [msg] | |
try: | |
cmd = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) | |
out, err = cmd.communicate() | |
rc = cmd.returncode | |
except (OSError, IOError) as e: | |
module.fail_json(rc=e.errno, msg=str(e), cmd=args) | |
module.exit_json( | |
message=msg, | |
rc=rc, | |
out=out, | |
err=err, | |
changed=True, | |
ansible_facts=dict( | |
changelog_started=True, | |
changelog_last_update=time.time(), | |
) | |
) | |
from ansible.module_utils.basic import * # noqa | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment