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
This commit is contained in:
Brian Coca 2018-02-14 15:52:19 -05:00 committed by GitHub
parent b403653bd2
commit 8de4f7cd9f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 14 additions and 8 deletions

View file

@ -16,7 +16,7 @@ from ansible.errors import AnsibleError, AnsibleParserError, AnsibleUndefinedVar
from ansible.executor.task_result import TaskResult from ansible.executor.task_result import TaskResult
from ansible.module_utils.six import iteritems, string_types, binary_type from ansible.module_utils.six import iteritems, string_types, binary_type
from ansible.module_utils.six.moves import cPickle 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.conditional import Conditional
from ansible.playbook.task import Task from ansible.playbook.task import Task
from ansible.template import Templar from ansible.template import Templar
@ -272,12 +272,15 @@ class TaskExecutor:
index_var = None index_var = None
label = None label = None
loop_pause = 0 loop_pause = 0
templar = Templar(loader=self._loader, shared_loader_obj=self._shared_loader_obj, variables=self._job_vars)
if self._task.loop_control: if self._task.loop_control:
loop_var = self._task.loop_control.loop_var # FIXME: move this to the object itself to allow post_validate to take care of templating
index_var = self._task.loop_control.index_var loop_var = templar.template(self._task.loop_control.loop_var)
loop_pause = self._task.loop_control.pause 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 # 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: if loop_var in task_vars:
display.warning(u"The loop variable '%s' is already in use. " display.warning(u"The loop variable '%s' is already in use. "
@ -296,7 +299,10 @@ class TaskExecutor:
# pause between loop iterations # pause between loop iterations
if loop_pause and ran_once: 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: else:
ran_once = True ran_once = True
@ -326,7 +332,6 @@ class TaskExecutor:
res['_ansible_ignore_errors'] = task_fields.get('ignore_errors') res['_ansible_ignore_errors'] = task_fields.get('ignore_errors')
if label is not None: 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) res['_ansible_item_label'] = templar.template(label)
self._rslt_q.put( self._rslt_q.put(
@ -402,7 +407,7 @@ class TaskExecutor:
# * lists can be squashed together # * lists can be squashed together
# * dicts could squash entries that match in all cases except the # * dicts could squash entries that match in all cases except the
# name or pkg field. # name or pkg field.
except: except Exception:
# Squashing is an optimization. If it fails for any reason, # Squashing is an optimization. If it fails for any reason,
# simply use the unoptimized list of items. # simply use the unoptimized list of items.

View file

@ -23,6 +23,7 @@ from ansible.playbook.attribute import FieldAttribute
from ansible.playbook.base import Base from ansible.playbook.base import Base
# FIXME: loopcontrol should not inherit attributes from base, just uses it for load
class LoopControl(Base): class LoopControl(Base):
_loop_var = FieldAttribute(isa='str', default='item') _loop_var = FieldAttribute(isa='str', default='item')