Repository: ansible/ansible

Issue:
Scope issue with Playbook level includes
<!--- Verify first that your issue/request is not already reported in GitHub -->
##### ISSUE TYPE

<!--- Pick one below and delete the rest: -->
- Bug Report
##### ANSIBLE VERSION

```
ansible 2.1.0.0 (detached HEAD 5954a82dd6) last updated 2016/05/03 02:37:44 (GMT +000)
  lib/ansible/modules/core: (detached HEAD ce79e7c72d) last updated 2016/05/03 02:38:14 (GMT +000)
  lib/ansible/modules/extras: (detached HEAD 156a8cd0b3) last updated 2016/05/03 02:38:15 (GMT +000)
  config file = /home/user/project/ansible.cfg
  configured module search path = ['action_plugins', 'externals/libraries', '/usr/share/ansible', '/usr/local/share/ansible']

```
##### CONFIGURATION

[ssh_connection]
timeout = 5
ssh_args = -o ControlMaster=auto -o ConnectTimeout=3
[defaults]
gathering = no
DISPLAY_SKIPPED_HOSTS=0
host_key_checking = false
roles_path = externals/roles
forks = 20
##### OS / ENVIRONMENT

Ansible ran from a RHEL 6 box
Manages RHEL 6 boxes 
##### SUMMARY

Playbook level includes (includes that are not nested within a task segment) don't properly handle conditional "when" statements.  Instead of limiting the included file only to hosts who meet the "when" conditions, it instead only limits the TASK section of the included file, while applying no limits to any roles, pre_tasks or post_tasks.  This appears to be a Scoping Issue.

Meaning:

```

---
- include: test_include.yml
  when: "'limiting_group' in group_names"
```

Will only limit the included task content to "limiting_group" but will have no limits to any role, pre_task, post_task content in the included file.
##### STEPS TO REPRODUCE

```
###### test_bug.yml ######

---
- include: test_include.yml
  when: "'limiting_group' in group_names"


###### test_include.yml ######

---
- hosts: all
  gather_facts: no
  pre_tasks:
    - name: testing pretasks
      shell: hostname
  roles:
    - { role: test }
  tasks:
    - name: testing normal tasks
      shell: hostname
  post_tasks:
    - name: testing post tasks
      shell: hostname


###### roles/test/tasks/main.yml ######

---
- name: test roles
  shell: hostname


###### test.ini ######

[limiting_group]
limited1
limited2

[other_group]
host1
host2
host3
host3


###### Playbook Exec ######

[user@host]$ ansible-playbook -i test.ini test_bug.yml 


PLAY [all] *********************************************************************

TASK [testing pretasks] ********************************************************
changed: [host4]
changed: [host3]
changed: [host2]
changed: [limited1]
changed: [host1]
changed: [limited2]

TASK [test : test roles] *******************************************************
changed: [host3]
changed: [host1]
changed: [limited1]
changed: [host4]
changed: [limited2]
changed: [host2]

TASK [testing normal tasks] ****************************************************
changed: [limited1]
changed: [limited2]

TASK [testing post tasks] ******************************************************
changed: [host4]
changed: [host2]
changed: [host1]
changed: [limited1]
changed: [host3]
changed: [limited2]

PLAY RECAP *********************************************************************
limited1 : ok=4    changed=4    unreachable=0    failed=0   
limited2 : ok=4    changed=4    unreachable=0    failed=0   
host1 : ok=3    changed=3    unreachable=0    failed=0   
host2 : ok=3    changed=3    unreachable=0    failed=0   
host3 : ok=3    changed=3    unreachable=0    failed=0   
host4 : ok=3    changed=3    unreachable=0    failed=0   
```
##### EXPECTED RESULTS

The expected results would be to have an effect similar to appending "--limit limiting_group" to the playbook call.  This would mean that only hosts that match the WHEN condition would drop down into the included plays.

The playbook output should have been:

```
TASK [testing pretasks] ********************************************************
changed: [limited1]
changed: [limited2]

TASK [test : test roles] *******************************************************
changed: [limited1]
changed: [limited2]

TASK [testing normal tasks] ****************************************************
changed: [limited1]
changed: [limited2]

TASK [testing post tasks] ******************************************************
changed: [limited1]
changed: [limited2]
```
##### ACTUAL RESULTS

<!--- What actually happened? If possible run with high verbosity (-vvvv) -->

The Actual Results ended up being that only the main "TASK" stanza had the condition applied to it.  The other stanzas (pre_task,role,post_task) all had no conditions

```
TASK [testing pretasks] ********************************************************
changed: [host4]
changed: [host3]
changed: [host2]
changed: [limited1]
changed: [host1]
changed: [limited2]

TASK [test : test roles] *******************************************************
changed: [host3]
changed: [host1]
changed: [limited1]
changed: [host4]
changed: [limited2]
changed: [host2]

TASK [testing normal tasks] ****************************************************
changed: [limited1]
changed: [limited2]

TASK [testing post tasks] ******************************************************
changed: [host4]
changed: [host2]
changed: [host1]
changed: [limited1]
changed: [host3]
changed: [limited2]
```

As a note:
This drastically reduces re-usability, and forces the need for "wrapper scripts" that just call playbooks with limits.  

My current work around is doing things like the following:

```
### site.yml ###
- include: install.yml TARGET_GROUP=limiting_group

### install.yml ###
- hosts: '{{ TARGET_GROUP | default("all") }}'
  become: yes
  any_errors_fatal: True
  roles:
    - blah
```



Discussion:

Resolving patch:
diff --git a/lib/ansible/playbook/playbook_include.py b/lib/ansible/playbook/playbook_include.py
--- a/lib/ansible/playbook/playbook_include.py
+++ b/lib/ansible/playbook/playbook_include.py
@@ -96,7 +96,7 @@ def load_data(self, ds, basedir, variable_manager=None, loader=None):
             # plays. If so, we can take a shortcut here and simply prepend them to
             # those attached to each block (if any)
             if forward_conditional:
-                for task_block in entry.tasks:
+                for task_block in entry.pre_tasks + entry.roles + entry.tasks + entry.post_tasks:
                     task_block.when = self.when[:] + task_block.when
 
         return pb


Test patch: