From 8a8ffa23424bc7ed13dff3a55d726806fed1fd8e Mon Sep 17 00:00:00 2001 From: Daniel Hokka Zakrisson Date: Sun, 30 Sep 2012 13:40:52 +0200 Subject: [PATCH] Allow task includes to work with with_items --- lib/ansible/playbook/play.py | 28 ++++++++++++++++----------- lib/ansible/runner/__init__.py | 2 +- lib/ansible/utils.py | 35 +++++++++++++++++++++++----------- 3 files changed, 42 insertions(+), 23 deletions(-) diff --git a/lib/ansible/playbook/play.py b/lib/ansible/playbook/play.py index d02cfc0d13..2d1f8856c0 100644 --- a/lib/ansible/playbook/play.py +++ b/lib/ansible/playbook/play.py @@ -101,23 +101,29 @@ class Play(object): tasks = ds.get(keyname, []) results = [] for x in tasks: - task_vars = self.vars.copy() if 'include' in x: + task_vars = self.vars.copy() tokens = shlex.split(x['include']) - for t in tokens[1:]: - (k,v) = t.split("=", 1) - task_vars[k] = utils.template(self.basedir, v, task_vars) - include_file = utils.template(self.basedir, tokens[0], task_vars) - data = utils.parse_yaml_from_file(utils.path_dwim(self.basedir, include_file)) + if 'with_items' in x: + items = utils.varReplaceWithItems(self.basedir, x['with_items'], task_vars) + else: + items = [''] + for item in items: + mv = task_vars.copy() + mv['item'] = item + for t in tokens[1:]: + (k,v) = t.split("=", 1) + mv[k] = utils.varReplaceWithItems(self.basedir, v, mv) + include_file = utils.template(self.basedir, tokens[0], mv) + data = utils.parse_yaml_from_file(utils.path_dwim(self.basedir, include_file)) + for y in data: + results.append(Task(self,y,module_vars=mv)) elif type(x) == dict: - data = [x] + task_vars = self.vars.copy() + results.append(Task(self,x,module_vars=task_vars)) else: raise Exception("unexpected task type") - for y in data: - mv = task_vars.copy() - results.append(Task(self,y,module_vars=mv)) - for x in results: if self.tags is not None: x.tags.extend(self.tags) diff --git a/lib/ansible/runner/__init__.py b/lib/ansible/runner/__init__.py index 50f0a3934d..5d231b0370 100644 --- a/lib/ansible/runner/__init__.py +++ b/lib/ansible/runner/__init__.py @@ -261,7 +261,7 @@ class Runner(object): items = self.module_vars.get('items', []) if isinstance(items, basestring) and items.startswith("$"): - items = utils.varLookup(items, inject) + items = utils.varReplaceWithItems(self.basedir, items, inject) if type(items) != list: raise errors.AnsibleError("with_items only takes a list: %s" % items) diff --git a/lib/ansible/utils.py b/lib/ansible/utils.py index f07075746a..1122d1ac4f 100644 --- a/lib/ansible/utils.py +++ b/lib/ansible/utils.py @@ -278,17 +278,6 @@ def _varFind(text): path.append(text[part_start[0]:var_end]) return {'path': path, 'start': start, 'end': end} -def varLookup(varname, vars): - ''' helper function used by with_items ''' - - m = _varFind(varname) - if not m: - return None - try: - return _varLookup(m['path'], vars) - except VarNotFoundException: - return None - def varReplace(raw, vars, depth=0): ''' Perform variable replacement of $variables in string raw using vars dictionary ''' # this code originally from yum @@ -358,6 +347,30 @@ def varReplaceFilesAndPipes(basedir, raw): return ''.join(done) +def varReplaceWithItems(basedir, varname, vars): + ''' helper function used by with_items ''' + + if isinstance(varname, basestring): + m = _varFind(varname) + if not m: + return varname + if m['start'] == 0 and m['end'] == len(varname): + try: + return varReplaceWithItems(basedir, _varLookup(m['path'], vars), vars) + except VarNotFoundException: + return varname + else: + return template(basedir, varname, vars) + elif isinstance(varname, (list, tuple)): + return [varReplaceWithItems(basedir, v, vars) for v in varname] + elif isinstance(varname, dict): + d = {} + for (k, v) in varname.iteritems(): + d[k] = varReplaceWithItems(basedir, v, vars) + return d + else: + raise Exception("invalid with_items type") + def template(basedir, text, vars): ''' run a text buffer through the templating engine until it no longer changes '''