From 7602a2a030b73063368de3d627fcdad47a860e8f Mon Sep 17 00:00:00 2001
From: James Cammarata <jimi@sngx.net>
Date: Tue, 15 Nov 2016 10:02:07 -0600
Subject: [PATCH] Catch loop eval errors and only raise them again if the task
 is not skipped

This should help on issues like #16222.

(cherry picked from commit 57cf5e431c69e7f8bb8607ff37fd51418249d03c)
---
 lib/ansible/executor/task_executor.py | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/lib/ansible/executor/task_executor.py b/lib/ansible/executor/task_executor.py
index d4835d98508..59759245a83 100644
--- a/lib/ansible/executor/task_executor.py
+++ b/lib/ansible/executor/task_executor.py
@@ -71,6 +71,7 @@ class TaskExecutor:
         self._shared_loader_obj = shared_loader_obj
         self._connection        = None
         self._rslt_q            = rslt_q
+        self._loop_eval_error   = None
 
         self._task.squash()
 
@@ -85,7 +86,13 @@ class TaskExecutor:
         display.debug("in run()")
 
         try:
-            items = self._get_loop_items()
+            try:
+                items = self._get_loop_items()
+            except AnsibleUndefinedVariable as e:
+                # save the error raised here for use later
+                items = None
+                self._loop_eval_error = e
+
             if items is not None:
                 if len(items) > 0:
                     item_results = self._run_loop(items)
@@ -402,6 +409,11 @@ class TaskExecutor:
             if not self._task.evaluate_conditional(templar, variables):
                 display.debug("when evaluation failed, skipping this task")
                 return dict(changed=False, skipped=True, skip_reason='Conditional check failed', _ansible_no_log=self._play_context.no_log)
+            # since we're not skipping, if there was a loop evaluation error
+            # raised earlier we need to raise it now to halt the execution of
+            # this task
+            if self._loop_eval_error is not None:
+                raise self._loop_eval_error
         except AnsibleError:
             # skip conditional exception in the case of includes as the vars needed might not be avaiable except in the included tasks or due to tags
             if self._task.action not in ['include', 'include_role']: