From cdaa2085ee9d045c06ae0da0c48e71d40818f13d Mon Sep 17 00:00:00 2001 From: Michael DeHaan Date: Wed, 3 Apr 2013 01:03:30 -0400 Subject: [PATCH] Preliminary ability to use Jinja2 {{ }} to replace ${foo.bar} in playbooks. Can't use both at the same time per line. --- lib/ansible/runner/action_plugins/debug.py | 2 +- lib/ansible/utils/__init__.py | 5 ++-- lib/ansible/utils/template.py | 30 ++++++++++++++++++++++ test/TestPlayBook.py | 1 + test/playbook1.yml | 2 +- 5 files changed, 36 insertions(+), 4 deletions(-) diff --git a/lib/ansible/runner/action_plugins/debug.py b/lib/ansible/runner/action_plugins/debug.py index 61ed449624..d7fd455a80 100644 --- a/lib/ansible/runner/action_plugins/debug.py +++ b/lib/ansible/runner/action_plugins/debug.py @@ -39,6 +39,6 @@ class ActionModule(object): if 'fail' in args and utils.boolean(args['fail']): result = dict(failed=True, msg=args['msg']) else: - result = dict(msg=str(args['msg'])) + result = dict(msg=args['msg']) return ReturnData(conn=conn, result=result) diff --git a/lib/ansible/utils/__init__.py b/lib/ansible/utils/__init__.py index 40d42ba146..639680cf1a 100644 --- a/lib/ansible/utils/__init__.py +++ b/lib/ansible/utils/__init__.py @@ -279,11 +279,12 @@ def parse_yaml_from_file(path): def parse_kv(args): ''' convert a string of key/value items to a dict ''' - options = {} if args is not None: # attempting to split a unicode here does bad things - vargs = shlex.split(str(args), posix=True) + args = args.encode('utf-8') + vargs = [x.decode('utf-8') for x in shlex.split(args, posix=True)] + #vargs = shlex.split(str(args), posix=True) for x in vargs: if x.find("=") != -1: k, v = x.split("=",1) diff --git a/lib/ansible/utils/template.py b/lib/ansible/utils/template.py index 8e134f403e..84f4b4db6f 100644 --- a/lib/ansible/utils/template.py +++ b/lib/ansible/utils/template.py @@ -30,6 +30,7 @@ import pwd # TODO: refactor this file +FILTER_PLUGINS = {} _LISTRE = re.compile(r"(\w+)\[(\d+)\]") JINJA2_OVERRIDE='#jinja2:' @@ -231,6 +232,8 @@ def template(basedir, varname, vars, lookup_fatal=True, depth=0, expand_lists=Tr ''' templates a data structure by traversing it and substituting for other data structures ''' if isinstance(varname, basestring): + if '{{' in varname: + return template_from_string(basedir, varname, vars) m = _varFind(basedir, varname, vars, lookup_fatal, depth, expand_lists) if not m: return varname @@ -386,3 +389,30 @@ def template_from_file(basedir, path, vars): res = res + '\n' return template(basedir, res, vars) +def _get_filter_plugins(): + global FILTER_PLUGINS + if FILTER_PLUGINS is not None: + return FILTER_PLUGINS + environment = jinja2.Environment(trim_blocks=True) + FILTER_PLUGINS = {} + from ansible import utils + for filter_plugin in utils.plugins.filter_loader.all(): + filters = filter_plugin.filters() + if not isinstance(filters, dict): + raise errors.AnsibleError("FilterModule.filters should return a dict.") + FILTER_PLUGINS.update(filters) + return FILTER_PLUGINS + +def template_from_string(basedir, data, vars): + ''' run a file through the (Jinja2) templating engine ''' + if type(data) == str: + data = unicode(data, 'utf-8') + environment = jinja2.Environment(trim_blocks=True) + environment.filters.update(_get_filter_plugins()) + # TODO: may need some way of using lookup plugins here seeing we aren't calling + # the legacy engine, lookup() as a function, perhaps? + environment.template_class = J2Template + t = environment.from_string(data) + res = jinja2.utils.concat(t.root_render_func(t.new_context(_jinja2_vars(basedir, vars, t.globals), shared=True))) + return res + diff --git a/test/TestPlayBook.py b/test/TestPlayBook.py index 4d070a8d53..b95f1ca455 100644 --- a/test/TestPlayBook.py +++ b/test/TestPlayBook.py @@ -135,6 +135,7 @@ class TestPlaybook(unittest.TestCase): runner_callbacks = self.test_callbacks ) result = self.playbook.run() + print EVENTS return result def test_one(self): diff --git a/test/playbook1.yml b/test/playbook1.yml index 677e6d32db..dbb29051dc 100644 --- a/test/playbook1.yml +++ b/test/playbook1.yml @@ -25,7 +25,7 @@ action: command true - name: test basic shell, plus two ways to dereference a variable - action: shell echo $HOME $port {{ port }} + action: shell echo $HOME $port - name: test vars_files imports action: shell echo $duck $cow $testing