From 15cbe1472dcb17ccae5efb10ed628fd2cb1f2ecf Mon Sep 17 00:00:00 2001 From: Brian Coca Date: Wed, 14 Feb 2018 15:52:19 -0500 Subject: [PATCH] fix loop_control templating (#36124) * fix loop_control templating - properly template ALL properites for loop_control - loop_control inherits from base, it should not, but needs validate/attribute functionality fixes #24719 (cherry picked from commit 8de4f7cd9fb9406ab1b476cc762f5b87c0f7819e) --- lib/ansible/executor/task_executor.py | 21 +++++++++++++-------- lib/ansible/playbook/loop_control.py | 1 + 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/lib/ansible/executor/task_executor.py b/lib/ansible/executor/task_executor.py index ee9ec6fdd62..2e9ffa4e455 100644 --- a/lib/ansible/executor/task_executor.py +++ b/lib/ansible/executor/task_executor.py @@ -16,7 +16,7 @@ from ansible.errors import AnsibleError, AnsibleParserError, AnsibleUndefinedVar from ansible.executor.task_result import TaskResult from ansible.module_utils.six import iteritems, string_types, binary_type from ansible.module_utils.six.moves import cPickle -from ansible.module_utils._text import to_text +from ansible.module_utils._text import to_text, to_native from ansible.playbook.conditional import Conditional from ansible.playbook.task import Task from ansible.template import Templar @@ -272,12 +272,15 @@ class TaskExecutor: index_var = None label = None loop_pause = 0 + templar = Templar(loader=self._loader, shared_loader_obj=self._shared_loader_obj, variables=self._job_vars) if self._task.loop_control: - loop_var = self._task.loop_control.loop_var - index_var = self._task.loop_control.index_var - loop_pause = self._task.loop_control.pause + # FIXME: move this to the object itself to allow post_validate to take care of templating + loop_var = templar.template(self._task.loop_control.loop_var) + index_var = templar.template(self._task.loop_control.index_var) + loop_pause = templar.template(self._task.loop_control.pause) # the these may be 'None', so we still need to default to something useful - label = self._task.loop_control.label or ('{{' + loop_var + '}}') + # this is tempalted below after an item is assigned + label = (self._task.loop_control.label or ('{{' + loop_var + '}}')) if loop_var in task_vars: display.warning(u"The loop variable '%s' is already in use. " @@ -296,7 +299,10 @@ class TaskExecutor: # pause between loop iterations if loop_pause and ran_once: - time.sleep(loop_pause) + try: + time.sleep(float(loop_pause)) + except ValueError as e: + raise AnsibleError('Invalid pause value: %s, produced error: %s' % (loop_pause, to_native(e))) else: ran_once = True @@ -326,7 +332,6 @@ class TaskExecutor: res['_ansible_ignore_errors'] = task_fields.get('ignore_errors') if label is not None: - templar = Templar(loader=self._loader, shared_loader_obj=self._shared_loader_obj, variables=self._job_vars) res['_ansible_item_label'] = templar.template(label) self._rslt_q.put( @@ -402,7 +407,7 @@ class TaskExecutor: # * lists can be squashed together # * dicts could squash entries that match in all cases except the # name or pkg field. - except: + except Exception: # Squashing is an optimization. If it fails for any reason, # simply use the unoptimized list of items. diff --git a/lib/ansible/playbook/loop_control.py b/lib/ansible/playbook/loop_control.py index b34c6552fe8..59594b31f94 100644 --- a/lib/ansible/playbook/loop_control.py +++ b/lib/ansible/playbook/loop_control.py @@ -23,6 +23,7 @@ from ansible.playbook.attribute import FieldAttribute from ansible.playbook.base import Base +# FIXME: loopcontrol should not inherit attributes from base, just uses it for load class LoopControl(Base): _loop_var = FieldAttribute(isa='str', default='item')