Created
December 20, 2012 22:40
-
-
Save anonymous/4349222 to your computer and use it in GitHub Desktop.
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
# Append values to a pre-defined list | |
import os | |
import pwd | |
import random | |
import traceback | |
import tempfile | |
import json | |
from ansible.callbacks import vv | |
from ansible import utils | |
from ansible.utils.template import _varFind | |
from ansible import errors | |
from ansible.runner.return_data import ReturnData | |
class ActionModule(object): | |
_opt_names = frozenset(['list', 'items', 'item']) | |
def __init__(self, runner): | |
self.runner = runner | |
def run(self, conn, tmp, module_name, module_args, inject): | |
''' | |
Append values to pre-defined list variables. Intended as a | |
means to subscribe to services which operate on some list of | |
subscriptions. | |
''' | |
# Helper function: given a path into a dict defined by a list | |
# of keys, and a dict, returns the value found at the path, or None | |
def _get(path, dct): | |
if len(path) is 0 or dct is None: | |
return dct | |
elem = path[0] | |
dct = dct.get(elem, None) | |
path = path[1::1] | |
return _get(path, dct) | |
def _varReplace(basedir, raw, vars, depth=0, expand_lists=False): | |
''' | |
Perform variable replacement of $variables in string raw using vars dictionary. This | |
is a lightly modified version of utils.varReplace() which uses json.dumps() instead of | |
unicode() | |
''' | |
if (depth > 20): | |
raise errors.AnsibleError("template recursion depth exceeded") | |
done = [] # Completed chunks to return | |
while raw: | |
m = _varFind(basedir, raw, vars, depth) | |
if not m: | |
done.append(raw) | |
break | |
# Determine replacement value (if unknown variable then preserve | |
# original) | |
replacement = m['replacement'] | |
if expand_lists and isinstance(replacement, (list, tuple)): | |
replacement = ",".join(replacement) | |
if isinstance(replacement, (str, unicode)): | |
replacement = _varReplace(basedir, replacement, vars, depth=depth+1, expand_lists=expand_lists) | |
if replacement is None: | |
replacement = raw[m['start']:m['end']] | |
start, end = m['start'], m['end'] | |
done.append(raw[:start]) # Keep stuff leading up to token | |
done.append(json.dumps(replacement, sort_keys=True)) # Append replacement value | |
raw = raw[end:] # Continue with remainder of string | |
return ''.join(done) | |
# A container for the top-level facts we want to modify | |
modified_facts = {} | |
# Parse the arguments in the standard key-value way (initially). | |
options = utils.parse_kv(self.runner.module_args) | |
# Pull out the keys we don't recognise and throw if there are any | |
invalids = [name for name in options.keys() if name not in ActionModule._opt_names] | |
if len(invalids) > 0: | |
raise errors.AnsibleError("invalid paramters to appendvar: %s" % ", ".join(invalids)) | |
listname = options.get('list', None) | |
item = options.get('item', None) | |
items = options.get('items', None) | |
if listname is None: | |
raise errors.AnsibleError("you must supply a 'list' option") | |
if item is None and items is None: | |
raise errors.AnsibleError("you must supply either an 'item' or 'items' option") | |
listname = utils.template(self.runner.basedir, listname, inject) | |
path = listname.split('.') | |
target = _get(path, inject) | |
# The value must exist already, and must be a list | |
if target is None: | |
raise errors.AnsibleError("cannot append to variable '%s', as it is not defined" % listname) | |
# target = _put([], path, inject) | |
else: | |
if not type(target) == list: | |
raise errors.AnsibleError("cannot append to variable '%s', as it is not a list" % listname) | |
if item is None: | |
items = _varReplace(self.runner.basedir, items, inject) | |
items = json.loads(items) | |
if not type(items) is list: | |
raise errors.AnsibleError("items to be added to variable '%s' must be a list, not '%s'" % (listname, type(items))) | |
else: | |
items = _varReplace(self.runner.basedir, item, inject) | |
items = [json.loads(items)] | |
for item in items: | |
target.append(item) | |
# Now we must copy the top-level variable below which we made our change, | |
# into modified_facts in entirity, so that we don't modify anything else | |
# when we redefine it | |
modified_facts[path[0]] = inject[path[0]] | |
result = {'ansible_facts': modified_facts} #, 'changed': True} | |
return ReturnData(conn=conn, result=result) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment