Repository: ansible/ansible

Issue:
include_role tasks has ansible-playbook seek roles before the actual task is run
##### ISSUE TYPE
 - Bug Report

##### COMPONENT NAME
include_role

##### ANSIBLE VERSION
```
ansible 2.2.0.0
reproduced on ansible 2.2.1.0 (rc2) as well
```

##### CONFIGURATION
Not relevant

##### OS / ENVIRONMENT
Not relevant

##### SUMMARY
If a role is installed as part of a playbook run (i.e, a task that runs ``ansible-galaxy`` or something similar) and then we attempt to use ``include_role`` in a later task, ansible-playbook will not run at all because the role from ``include_role`` is missing (has not been installed yet).

It's sort of like the static parameter of the ``include`` task where a ``static: no`` on the include can allow you to add a ``when: <something>`` clause to conditionally/dynamically run the include.

There *is* a [documented](https://github.com/ansible/ansible/blob/devel/lib/ansible/modules/utilities/logic/include_role.py) static parameter in the ``include_role`` task, however it does not alleviate this issue.

The issue is present even when running the role setup and the include role in two different plays of the same playbook. The only workaround for now is to run completely separated playbooks.

It's like ``ansible-playbook`` tries to "compile" all the roles before starting the run.

The obvious answer would be:

> Why don't you use ansible-galaxy and requirements.yml file and *\<insert other alternative here\>* before running your playbook ?

This is a more complicated use case where there are actual setup tasks required and I would like them to be embedded as ansible tasks.

##### STEPS TO REPRODUCE
```yaml
- name: Setup and use a role
  hosts: localhost
  tasks:
    - name: Get geerlingguy.apache
      command: ansible-galaxy install geerlingguy.apache

    - name: Include geerlingguy.apache
      include_role:
        name: geerlingguy.apache
```

##### EXPECTED RESULTS
I would expect the include_role task to seek the role only when running the actual include_role task and thus this example playbook should work.

##### ACTUAL RESULTS
```
# ansible-playbook -i 'localhost' playbook.yml 
 [WARNING]: Host file not found: localhost

 [WARNING]: provided hosts list is empty, only localhost is available

ERROR! the role 'geerlingguy.apache' was not found in /home/centos/roles:/etc/ansible/roles:/home/centos

The error appears to have been in '/home/centos/playbook.yml': line 9, column 15, but may
be elsewhere in the file depending on the exact syntax problem.

The offending line appears to be:

      include_role:
        name: geerlingguy.apache
              ^ here
```



Discussion:

Resolving patch:
diff --git a/lib/ansible/modules/utilities/logic/include_role.py b/lib/ansible/modules/utilities/logic/include_role.py
--- a/lib/ansible/modules/utilities/logic/include_role.py
+++ b/lib/ansible/modules/utilities/logic/include_role.py
@@ -41,11 +41,6 @@
       - "File to load from a Role's defaults/ directory."
     required: False
     default: 'main'
-  static:
-    description:
-      - Gives Ansible a hint if this is a 'static' include or not. If static it implies that it won't need templating nor loops nor conditionals and will show included tasks in the --list options.
-    required: False
-    default: None
   allow_duplicates:
     description:
       - Overrides the role's metadata setting to allow using a role more than once with the same parameters.
@@ -56,10 +51,9 @@
       - If True the variables from defaults/ and vars/ in a role will not be made available to the rest of the play.
     default: None
 notes:
-    - THIS IS EARLY PREVIEW, THINGS MAY CHANGE
     - Handlers are made available to the whole play.
     - simple dependencies seem to work fine.
-    - "Things not tested (yet): plugin overrides, nesting includes, used as handler, other stuff I did not think of when I wrote this."
+    - As with C(include) this task can be static or dynamic, If static it implies that it won't need templating nor loops nor conditionals and will show included tasks in the --list options. Ansible will try to autodetect what is needed, but you can set `static: yes|no` at task level to control this.
 '''
 
 EXAMPLES = """
diff --git a/lib/ansible/playbook/role_include.py b/lib/ansible/playbook/role_include.py
--- a/lib/ansible/playbook/role_include.py
+++ b/lib/ansible/playbook/role_include.py
@@ -48,7 +48,6 @@ class IncludeRole(Task):
 
     # private as this is a 'module options' vs a task property
     _allow_duplicates = FieldAttribute(isa='bool', default=True, private=True)
-    _static = FieldAttribute(isa='bool', default=None, private=True)
     _private = FieldAttribute(isa='bool', default=None, private=True)
 
     def __init__(self, block=None, role=None, task_include=None):
@@ -113,7 +112,7 @@ def load(data, block=None, role=None, task_include=None, variable_manager=None,
 
         #FIXME: find a way to make this list come from object ( attributes does not work as per below)
         # manual list as otherwise the options would set other task parameters we don't want.
-        for option in ['static', 'private', 'allow_duplicates']:
+        for option in ['private', 'allow_duplicates']:
             if option in ir.args:
                 setattr(ir, option, ir.args.get(option))
 


Test patch: