Repository: ansible/ansible

Issue:
Ansible 2.4.1, 2.4.2: include_tasks does not handle a undefined conditional var correctly
##### ISSUE TYPE
 - Bug Report

##### COMPONENT NAME
module include_tasks

##### ANSIBLE VERSION
```
ansible 2.4.1.0
  config file = /home/xxxx/.ansible.cfg
  configured module search path = [u'/home/xxxx/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /opt/xxxx/venv/ansible2.4-python2.7/lib/python2.7/site-packages/ansible
  executable location = /opt/xxxx/venv/ansible2.4-python2.7/bin/ansible
  python version = 2.7.13 (default, Apr 12 2017, 06:53:51) [GCC 4.4.7 20120313 (Red Hat 4.4.7-18)]

```

##### CONFIGURATION
```
ANSIBLE_PIPELINING(/home/xxxx/.ansible.cfg) = True
DEFAULT_HOST_LIST(/home/xxxx/.ansible.cfg) = [u'/home/xxxx/checkouts/ansible-tree/inventory']
DEFAULT_LOG_PATH(/home/xxxx/.ansible.cfg) = /home/xxxx/ansible.log
HOST_KEY_CHECKING(/home/xxxx/.ansible.cfg) = False
INVENTORY_IGNORE_EXTS(/home/xxxx/.ansible.cfg) = ['~', '.orig', '.bak', '.ini', '.cfg', '.retry', '.pyc', '.pyo', '.txt', '.back', 'script']
MAX_FILE_SIZE_FOR_DIFF(/home/xxxx/.ansible.cfg) = 4194304
RETRY_FILES_SAVE_PATH(/home/xxxx/.ansible.cfg) = /home/xxxx
```
##### OS / ENVIRONMENT
Centos 6

##### SUMMARY
When you add a when condition to include_tasks which includes a undefined variable, it processes it as True instead of trowing an undefined error.

##### STEPS TO REPRODUCE
Do not define or set VAR

```yaml
- include_tasks: task.yml
  when: VAR == "yes"

- debug: msg="test"
  when: VAR == "yes"

```

##### EXPECTED RESULTS

include_tasks should fail with "'VAR' is undefined"

##### ACTUAL RESULTS

Include_tasks just gets executed and debug message fails with  "'VAR' is undefined"




Discussion:
Files identified in the description:
* [lib/ansible/modules/utilities/logic/include_tasks.py](https://github.com/ansible/ansible/blob/devel/lib/ansible/modules/utilities/logic/include_tasks.py)

If these files are inaccurate, please update the `component name` section of the description or use the `!component` bot command.

[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: components_banner --->
tested 2.4.2, it has the same issue.

Resolving patch:
diff --git a/lib/ansible/executor/task_executor.py b/lib/ansible/executor/task_executor.py
--- a/lib/ansible/executor/task_executor.py
+++ b/lib/ansible/executor/task_executor.py
@@ -471,9 +471,7 @@ def _execute(self, variables=None):
             # loop error takes precedence
             if self._loop_eval_error is not None:
                 raise self._loop_eval_error  # pylint: disable=raising-bad-type
-            # skip conditional exception in the case of includes as the vars needed might not be available except in the included tasks or due to tags
-            if self._task.action not in ['include', 'include_tasks', 'include_role']:
-                raise
+            raise
 
         # Not skipping, if we had loop error raised earlier we need to raise it now to halt the execution of this task
         if self._loop_eval_error is not None:


Test patch:
diff --git a/test/integration/targets/include_import/runme.sh b/test/integration/targets/include_import/runme.sh
--- a/test/integration/targets/include_import/runme.sh
+++ b/test/integration/targets/include_import/runme.sh
@@ -59,3 +59,7 @@ rm -f tasks/hello/*.yml
 # Inlcuded tasks should inherit attrs from non-dynamic blocks in parent chain
 # https://github.com/ansible/ansible/pull/38827
 ANSIBLE_STRATEGY='linear' ansible-playbook test_grandparent_inheritance.yml -i ../../inventory "$@"
+
+# undefined_var
+ANSIBLE_STRATEGY='linear' ansible-playbook undefined_var/playbook.yml  -i ../../inventory "$@"
+ANSIBLE_STRATEGY='free' ansible-playbook undefined_var/playbook.yml  -i ../../inventory "$@"
diff --git a/test/integration/targets/include_import/undefined_var/include_tasks.yml b/test/integration/targets/include_import/undefined_var/include_tasks.yml
new file mode 100644
--- /dev/null
+++ b/test/integration/targets/include_import/undefined_var/include_tasks.yml
@@ -0,0 +1,5 @@
+---
+
+- debug:
+    msg: "This message comes from an 'include_tasks'-task! :-)"
+  register: "_include_tasks_task_result"
diff --git a/test/integration/targets/include_import/undefined_var/include_that_defines_var.yml b/test/integration/targets/include_import/undefined_var/include_that_defines_var.yml
new file mode 100644
--- /dev/null
+++ b/test/integration/targets/include_import/undefined_var/include_that_defines_var.yml
@@ -0,0 +1,5 @@
+- vars:
+    _undefined: 'yes'
+  block:
+    - set_fact:
+        _include_defined_result: 'good'
diff --git a/test/integration/targets/include_import/undefined_var/playbook.yml b/test/integration/targets/include_import/undefined_var/playbook.yml
new file mode 100644
--- /dev/null
+++ b/test/integration/targets/include_import/undefined_var/playbook.yml
@@ -0,0 +1,36 @@
+---
+- hosts: testhost
+  gather_facts: false
+  tasks:
+    - include_tasks: "include_tasks.yml"
+      ignore_errors: True
+      register: "_include_tasks_result"
+      when:
+        - "_undefined == 'yes'"
+
+    - assert:
+        that:
+          - "_include_tasks_result is failed"
+          - "_include_tasks_task_result is not defined"
+        msg: "'include_tasks' did not evaluate it's attached condition and failed"
+
+    - include_role:
+        name: "no_log"
+      ignore_errors: True
+      register: "_include_role_result"
+      when:
+        - "_undefined == 'yes'"
+
+    - assert:
+        that:
+          - "_include_role_result is failed"
+        msg: "'include_role' did not evaluate it's attached condition and failed"
+
+    - include: include_that_defines_var.yml
+      static: yes
+      when:
+        - "_undefined == 'yes'"
+
+    - assert:
+        that:
+          - _include_defined_result == 'good'