We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN 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
```


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `lib/ansible/playbook/role_include.py`
Content:
```
1 
2 #
3 # This file is part of Ansible
4 #
5 # Ansible is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation, either version 3 of the License, or
8 # (at your option) any later version.
9 #
10 # Ansible is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with Ansible.  If not, see <http://www.gnu.org/licenses/>.
17 
18 # Make coding more python3-ish
19 from __future__ import (absolute_import, division, print_function)
20 __metaclass__ = type
21 
22 from os.path import basename
23 
24 from ansible.errors import AnsibleParserError
25 from ansible.playbook.attribute import FieldAttribute
26 from ansible.playbook.task import Task
27 from ansible.playbook.role import Role
28 from ansible.playbook.role.include import RoleInclude
29 
30 try:
31     from __main__ import display
32 except ImportError:
33     from ansible.utils.display import Display
34     display = Display()
35 
36 __all__ = ['IncludeRole']
37 
38 
39 class IncludeRole(Task):
40 
41     """
42     A Role include is derived from a regular role to handle the special
43     circumstances related to the `- include_role: ...`
44     """
45 
46     # =================================================================================
47     # ATTRIBUTES
48 
49     # private as this is a 'module options' vs a task property
50     _allow_duplicates = FieldAttribute(isa='bool', default=True, private=True)
51     _static = FieldAttribute(isa='bool', default=None, private=True)
52     _private = FieldAttribute(isa='bool', default=None, private=True)
53 
54     def __init__(self, block=None, role=None, task_include=None):
55 
56         super(IncludeRole, self).__init__(block=block, role=role, task_include=task_include)
57 
58         self.statically_loaded = False
59         self._from_files = {}
60         self._parent_role = role
61         self._role_name = None
62 
63 
64     def get_block_list(self, play=None, variable_manager=None, loader=None):
65 
66         # only need play passed in when dynamic
67         if play is None:
68             myplay =  self._parent._play
69         else:
70             myplay = play
71 
72         ri = RoleInclude.load(self._role_name, play=myplay, variable_manager=variable_manager, loader=loader)
73         ri.vars.update(self.vars)
74 
75         # build role
76         actual_role = Role.load(ri, myplay, parent_role=self._parent_role, from_files=self._from_files)
77         actual_role._metadata.allow_duplicates = self.allow_duplicates
78 
79         # compile role with parent roles as dependencies to ensure they inherit
80         # variables
81         if not self._parent_role:
82             dep_chain = []
83         else:
84             dep_chain = list(self._parent_role._parents)
85             dep_chain.extend(self._parent_role.get_all_dependencies())
86             dep_chain.append(self._parent_role)
87 
88         blocks = actual_role.compile(play=myplay, dep_chain=dep_chain)
89         for b in blocks:
90             b._parent = self
91 
92         # updated available handlers in play
93         myplay.handlers = myplay.handlers + actual_role.get_handler_blocks(play=myplay)
94 
95         return blocks
96 
97     @staticmethod
98     def load(data, block=None, role=None, task_include=None, variable_manager=None, loader=None):
99 
100         ir = IncludeRole(block, role, task_include=task_include).load_data(data, variable_manager=variable_manager, loader=loader)
101 
102         ### Process options
103         # name is needed, or use role as alias
104         ir._role_name = ir.args.get('name', ir.args.get('role'))
105         if ir._role_name is None:
106             raise AnsibleParserError("'name' is a required field for include_role.")
107 
108         # build options for role includes
109         for key in ['tasks', 'vars', 'defaults']:
110             from_key ='%s_from' % key
111             if  ir.args.get(from_key):
112                 ir._from_files[key] = basename(ir.args.get(from_key))
113 
114         #FIXME: find a way to make this list come from object ( attributes does not work as per below)
115         # manual list as otherwise the options would set other task parameters we don't want.
116         for option in ['static', 'private', 'allow_duplicates']:
117             if option in ir.args:
118                 setattr(ir, option, ir.args.get(option))
119 
120         return ir.load_data(data, variable_manager=variable_manager, loader=loader)
121 
122     def copy(self, exclude_parent=False, exclude_tasks=False):
123 
124         new_me = super(IncludeRole, self).copy(exclude_parent=exclude_parent, exclude_tasks=exclude_tasks)
125         new_me.statically_loaded = self.statically_loaded
126         new_me._from_files = self._from_files.copy()
127         new_me._parent_role = self._parent_role
128         new_me._role_name   = self._role_name
129 
130         return new_me
131 
132     def get_include_params(self):
133         v = super(IncludeRole, self).get_include_params()
134         if self._parent_role:
135             v.update(self._parent_role.get_role_params())
136         return v
137
```

Path: `lib/ansible/modules/utilities/logic/include_role.py`
Content:
```
1 #!/usr/bin/python
2 # -*- mode: python -*-
3 # Ansible is distributed in the hope that it will be useful,
4 # but WITHOUT ANY WARRANTY; without even the implied warranty of
5 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
6 # GNU General Public License for more details.
7 #
8 # You should have received a copy of the GNU General Public License
9 # along with Ansible.  If not, see <http://www.gnu.org/licenses/>.
10 
11 ANSIBLE_METADATA = {'status': ['preview'],
12                     'supported_by': 'core',
13                     'version': '1.0'}
14 
15 DOCUMENTATION = '''
16 ---
17 author:
18     - "Ansible Core Team (@ansible)"
19 module: include_role
20 short_description: Load and execute a role
21 description:
22      - "Loads and executes a role as a task, this frees roles from the `role:` directive and allows them to be treated more as tasks."
23 version_added: "2.2"
24 options:
25   name:
26     description:
27       - The name of the role to be executed.
28     required: True
29   tasks_from:
30     description:
31       - "File to load from a Role's tasks/ directory."
32     required: False
33     default: 'main'
34   vars_from:
35     description:
36       - "File to load from a Role's vars/ directory."
37     required: False
38     default: 'main'
39   defaults_from:
40     description:
41       - "File to load from a Role's defaults/ directory."
42     required: False
43     default: 'main'
44   static:
45     description:
46       - 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.
47     required: False
48     default: None
49   allow_duplicates:
50     description:
51       - Overrides the role's metadata setting to allow using a role more than once with the same parameters.
52     required: False
53     default: True
54   private:
55     description:
56       - If True the variables from defaults/ and vars/ in a role will not be made available to the rest of the play.
57     default: None
58 notes:
59     - THIS IS EARLY PREVIEW, THINGS MAY CHANGE
60     - Handlers are made available to the whole play.
61     - simple dependencies seem to work fine.
62     - "Things not tested (yet): plugin overrides, nesting includes, used as handler, other stuff I did not think of when I wrote this."
63 '''
64 
65 EXAMPLES = """
66 - include_role:
67     name: myrole
68 
69 - name: Run tasks/other.yml instead of 'main'
70   include_role:
71     name: myrole
72     tasks_from: other
73 
74 - name: Pass variables to role
75   include_role:
76     name: myrole
77   vars:
78     rolevar1: 'value from task'
79 
80 - name: Use role in loop
81   include_role:
82     name: myrole
83   with_items:
84     - '{{ roleinput1 }}'
85     - '{{ roleinput2 }}'
86   loop_control:
87     loop_var: roleinputvar
88 
89 - name: conditional role
90   include_role:
91     name: myrole
92   when: not idontwanttorun
93 """
94 
95 RETURN = """
96 # this module does not return anything except tasks to execute
97 """
98
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

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 @@
 
     # 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 @@
 
         #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))

{"golden_diff": "diff --git a/lib/ansible/modules/utilities/logic/include_role.py b/lib/ansible/modules/utilities/logic/include_role.py\n--- a/lib/ansible/modules/utilities/logic/include_role.py\n+++ b/lib/ansible/modules/utilities/logic/include_role.py\n@@ -41,11 +41,6 @@\n       - \"File to load from a Role's defaults/ directory.\"\n     required: False\n     default: 'main'\n-  static:\n-    description:\n-      - 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.\n-    required: False\n-    default: None\n   allow_duplicates:\n     description:\n       - Overrides the role's metadata setting to allow using a role more than once with the same parameters.\n@@ -56,10 +51,9 @@\n       - If True the variables from defaults/ and vars/ in a role will not be made available to the rest of the play.\n     default: None\n notes:\n-    - THIS IS EARLY PREVIEW, THINGS MAY CHANGE\n     - Handlers are made available to the whole play.\n     - simple dependencies seem to work fine.\n-    - \"Things not tested (yet): plugin overrides, nesting includes, used as handler, other stuff I did not think of when I wrote this.\"\n+    - 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.\n '''\n \n EXAMPLES = \"\"\"\ndiff --git a/lib/ansible/playbook/role_include.py b/lib/ansible/playbook/role_include.py\n--- a/lib/ansible/playbook/role_include.py\n+++ b/lib/ansible/playbook/role_include.py\n@@ -48,7 +48,6 @@\n \n     # private as this is a 'module options' vs a task property\n     _allow_duplicates = FieldAttribute(isa='bool', default=True, private=True)\n-    _static = FieldAttribute(isa='bool', default=None, private=True)\n     _private = FieldAttribute(isa='bool', default=None, private=True)\n \n     def __init__(self, block=None, role=None, task_include=None):\n@@ -113,7 +112,7 @@\n \n         #FIXME: find a way to make this list come from object ( attributes does not work as per below)\n         # manual list as otherwise the options would set other task parameters we don't want.\n-        for option in ['static', 'private', 'allow_duplicates']:\n+        for option in ['private', 'allow_duplicates']:\n             if option in ir.args:\n                 setattr(ir, option, ir.args.get(option))\n", "issue": "include_role tasks has ansible-playbook seek roles before the actual task is run\n##### ISSUE TYPE\r\n - Bug Report\r\n\r\n##### COMPONENT NAME\r\ninclude_role\r\n\r\n##### ANSIBLE VERSION\r\n```\r\nansible 2.2.0.0\r\nreproduced on ansible 2.2.1.0 (rc2) as well\r\n```\r\n\r\n##### CONFIGURATION\r\nNot relevant\r\n\r\n##### OS / ENVIRONMENT\r\nNot relevant\r\n\r\n##### SUMMARY\r\nIf 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).\r\n\r\nIt'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.\r\n\r\nThere *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.\r\n\r\nThe 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.\r\n\r\nIt's like ``ansible-playbook`` tries to \"compile\" all the roles before starting the run.\r\n\r\nThe obvious answer would be:\r\n\r\n> Why don't you use ansible-galaxy and requirements.yml file and *\\<insert other alternative here\\>* before running your playbook ?\r\n\r\nThis is a more complicated use case where there are actual setup tasks required and I would like them to be embedded as ansible tasks.\r\n\r\n##### STEPS TO REPRODUCE\r\n```yaml\r\n- name: Setup and use a role\r\n  hosts: localhost\r\n  tasks:\r\n    - name: Get geerlingguy.apache\r\n      command: ansible-galaxy install geerlingguy.apache\r\n\r\n    - name: Include geerlingguy.apache\r\n      include_role:\r\n        name: geerlingguy.apache\r\n```\r\n\r\n##### EXPECTED RESULTS\r\nI 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.\r\n\r\n##### ACTUAL RESULTS\r\n```\r\n# ansible-playbook -i 'localhost' playbook.yml \r\n [WARNING]: Host file not found: localhost\r\n\r\n [WARNING]: provided hosts list is empty, only localhost is available\r\n\r\nERROR! the role 'geerlingguy.apache' was not found in /home/centos/roles:/etc/ansible/roles:/home/centos\r\n\r\nThe error appears to have been in '/home/centos/playbook.yml': line 9, column 15, but may\r\nbe elsewhere in the file depending on the exact syntax problem.\r\n\r\nThe offending line appears to be:\r\n\r\n      include_role:\r\n        name: geerlingguy.apache\r\n              ^ here\r\n```\r\n\n", "before_files": [{"content": "\n#\n# This file is part of Ansible\n#\n# Ansible is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# Ansible is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with Ansible.  If not, see <http://www.gnu.org/licenses/>.\n\n# Make coding more python3-ish\nfrom __future__ import (absolute_import, division, print_function)\n__metaclass__ = type\n\nfrom os.path import basename\n\nfrom ansible.errors import AnsibleParserError\nfrom ansible.playbook.attribute import FieldAttribute\nfrom ansible.playbook.task import Task\nfrom ansible.playbook.role import Role\nfrom ansible.playbook.role.include import RoleInclude\n\ntry:\n    from __main__ import display\nexcept ImportError:\n    from ansible.utils.display import Display\n    display = Display()\n\n__all__ = ['IncludeRole']\n\n\nclass IncludeRole(Task):\n\n    \"\"\"\n    A Role include is derived from a regular role to handle the special\n    circumstances related to the `- include_role: ...`\n    \"\"\"\n\n    # =================================================================================\n    # ATTRIBUTES\n\n    # private as this is a 'module options' vs a task property\n    _allow_duplicates = FieldAttribute(isa='bool', default=True, private=True)\n    _static = FieldAttribute(isa='bool', default=None, private=True)\n    _private = FieldAttribute(isa='bool', default=None, private=True)\n\n    def __init__(self, block=None, role=None, task_include=None):\n\n        super(IncludeRole, self).__init__(block=block, role=role, task_include=task_include)\n\n        self.statically_loaded = False\n        self._from_files = {}\n        self._parent_role = role\n        self._role_name = None\n\n\n    def get_block_list(self, play=None, variable_manager=None, loader=None):\n\n        # only need play passed in when dynamic\n        if play is None:\n            myplay =  self._parent._play\n        else:\n            myplay = play\n\n        ri = RoleInclude.load(self._role_name, play=myplay, variable_manager=variable_manager, loader=loader)\n        ri.vars.update(self.vars)\n\n        # build role\n        actual_role = Role.load(ri, myplay, parent_role=self._parent_role, from_files=self._from_files)\n        actual_role._metadata.allow_duplicates = self.allow_duplicates\n\n        # compile role with parent roles as dependencies to ensure they inherit\n        # variables\n        if not self._parent_role:\n            dep_chain = []\n        else:\n            dep_chain = list(self._parent_role._parents)\n            dep_chain.extend(self._parent_role.get_all_dependencies())\n            dep_chain.append(self._parent_role)\n\n        blocks = actual_role.compile(play=myplay, dep_chain=dep_chain)\n        for b in blocks:\n            b._parent = self\n\n        # updated available handlers in play\n        myplay.handlers = myplay.handlers + actual_role.get_handler_blocks(play=myplay)\n\n        return blocks\n\n    @staticmethod\n    def load(data, block=None, role=None, task_include=None, variable_manager=None, loader=None):\n\n        ir = IncludeRole(block, role, task_include=task_include).load_data(data, variable_manager=variable_manager, loader=loader)\n\n        ### Process options\n        # name is needed, or use role as alias\n        ir._role_name = ir.args.get('name', ir.args.get('role'))\n        if ir._role_name is None:\n            raise AnsibleParserError(\"'name' is a required field for include_role.\")\n\n        # build options for role includes\n        for key in ['tasks', 'vars', 'defaults']:\n            from_key ='%s_from' % key\n            if  ir.args.get(from_key):\n                ir._from_files[key] = basename(ir.args.get(from_key))\n\n        #FIXME: find a way to make this list come from object ( attributes does not work as per below)\n        # manual list as otherwise the options would set other task parameters we don't want.\n        for option in ['static', 'private', 'allow_duplicates']:\n            if option in ir.args:\n                setattr(ir, option, ir.args.get(option))\n\n        return ir.load_data(data, variable_manager=variable_manager, loader=loader)\n\n    def copy(self, exclude_parent=False, exclude_tasks=False):\n\n        new_me = super(IncludeRole, self).copy(exclude_parent=exclude_parent, exclude_tasks=exclude_tasks)\n        new_me.statically_loaded = self.statically_loaded\n        new_me._from_files = self._from_files.copy()\n        new_me._parent_role = self._parent_role\n        new_me._role_name   = self._role_name\n\n        return new_me\n\n    def get_include_params(self):\n        v = super(IncludeRole, self).get_include_params()\n        if self._parent_role:\n            v.update(self._parent_role.get_role_params())\n        return v\n", "path": "lib/ansible/playbook/role_include.py"}, {"content": "#!/usr/bin/python\n# -*- mode: python -*-\n# Ansible is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with Ansible.  If not, see <http://www.gnu.org/licenses/>.\n\nANSIBLE_METADATA = {'status': ['preview'],\n                    'supported_by': 'core',\n                    'version': '1.0'}\n\nDOCUMENTATION = '''\n---\nauthor:\n    - \"Ansible Core Team (@ansible)\"\nmodule: include_role\nshort_description: Load and execute a role\ndescription:\n     - \"Loads and executes a role as a task, this frees roles from the `role:` directive and allows them to be treated more as tasks.\"\nversion_added: \"2.2\"\noptions:\n  name:\n    description:\n      - The name of the role to be executed.\n    required: True\n  tasks_from:\n    description:\n      - \"File to load from a Role's tasks/ directory.\"\n    required: False\n    default: 'main'\n  vars_from:\n    description:\n      - \"File to load from a Role's vars/ directory.\"\n    required: False\n    default: 'main'\n  defaults_from:\n    description:\n      - \"File to load from a Role's defaults/ directory.\"\n    required: False\n    default: 'main'\n  static:\n    description:\n      - 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.\n    required: False\n    default: None\n  allow_duplicates:\n    description:\n      - Overrides the role's metadata setting to allow using a role more than once with the same parameters.\n    required: False\n    default: True\n  private:\n    description:\n      - If True the variables from defaults/ and vars/ in a role will not be made available to the rest of the play.\n    default: None\nnotes:\n    - THIS IS EARLY PREVIEW, THINGS MAY CHANGE\n    - Handlers are made available to the whole play.\n    - simple dependencies seem to work fine.\n    - \"Things not tested (yet): plugin overrides, nesting includes, used as handler, other stuff I did not think of when I wrote this.\"\n'''\n\nEXAMPLES = \"\"\"\n- include_role:\n    name: myrole\n\n- name: Run tasks/other.yml instead of 'main'\n  include_role:\n    name: myrole\n    tasks_from: other\n\n- name: Pass variables to role\n  include_role:\n    name: myrole\n  vars:\n    rolevar1: 'value from task'\n\n- name: Use role in loop\n  include_role:\n    name: myrole\n  with_items:\n    - '{{ roleinput1 }}'\n    - '{{ roleinput2 }}'\n  loop_control:\n    loop_var: roleinputvar\n\n- name: conditional role\n  include_role:\n    name: myrole\n  when: not idontwanttorun\n\"\"\"\n\nRETURN = \"\"\"\n# this module does not return anything except tasks to execute\n\"\"\"\n", "path": "lib/ansible/modules/utilities/logic/include_role.py"}], "after_files": [{"content": "\n#\n# This file is part of Ansible\n#\n# Ansible is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# Ansible is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with Ansible.  If not, see <http://www.gnu.org/licenses/>.\n\n# Make coding more python3-ish\nfrom __future__ import (absolute_import, division, print_function)\n__metaclass__ = type\n\nfrom os.path import basename\n\nfrom ansible.errors import AnsibleParserError\nfrom ansible.playbook.attribute import FieldAttribute\nfrom ansible.playbook.task import Task\nfrom ansible.playbook.role import Role\nfrom ansible.playbook.role.include import RoleInclude\n\ntry:\n    from __main__ import display\nexcept ImportError:\n    from ansible.utils.display import Display\n    display = Display()\n\n__all__ = ['IncludeRole']\n\n\nclass IncludeRole(Task):\n\n    \"\"\"\n    A Role include is derived from a regular role to handle the special\n    circumstances related to the `- include_role: ...`\n    \"\"\"\n\n    # =================================================================================\n    # ATTRIBUTES\n\n    # private as this is a 'module options' vs a task property\n    _allow_duplicates = FieldAttribute(isa='bool', default=True, private=True)\n    _private = FieldAttribute(isa='bool', default=None, private=True)\n\n    def __init__(self, block=None, role=None, task_include=None):\n\n        super(IncludeRole, self).__init__(block=block, role=role, task_include=task_include)\n\n        self.statically_loaded = False\n        self._from_files = {}\n        self._parent_role = role\n        self._role_name = None\n\n\n    def get_block_list(self, play=None, variable_manager=None, loader=None):\n\n        # only need play passed in when dynamic\n        if play is None:\n            myplay =  self._parent._play\n        else:\n            myplay = play\n\n        ri = RoleInclude.load(self._role_name, play=myplay, variable_manager=variable_manager, loader=loader)\n        ri.vars.update(self.vars)\n\n        # build role\n        actual_role = Role.load(ri, myplay, parent_role=self._parent_role, from_files=self._from_files)\n        actual_role._metadata.allow_duplicates = self.allow_duplicates\n\n        # compile role with parent roles as dependencies to ensure they inherit\n        # variables\n        if not self._parent_role:\n            dep_chain = []\n        else:\n            dep_chain = list(self._parent_role._parents)\n            dep_chain.extend(self._parent_role.get_all_dependencies())\n            dep_chain.append(self._parent_role)\n\n        blocks = actual_role.compile(play=myplay, dep_chain=dep_chain)\n        for b in blocks:\n            b._parent = self\n\n        # updated available handlers in play\n        myplay.handlers = myplay.handlers + actual_role.get_handler_blocks(play=myplay)\n\n        return blocks\n\n    @staticmethod\n    def load(data, block=None, role=None, task_include=None, variable_manager=None, loader=None):\n\n        ir = IncludeRole(block, role, task_include=task_include).load_data(data, variable_manager=variable_manager, loader=loader)\n\n        ### Process options\n        # name is needed, or use role as alias\n        ir._role_name = ir.args.get('name', ir.args.get('role'))\n        if ir._role_name is None:\n            raise AnsibleParserError(\"'name' is a required field for include_role.\")\n\n        # build options for role includes\n        for key in ['tasks', 'vars', 'defaults']:\n            from_key ='%s_from' % key\n            if  ir.args.get(from_key):\n                ir._from_files[key] = basename(ir.args.get(from_key))\n\n        #FIXME: find a way to make this list come from object ( attributes does not work as per below)\n        # manual list as otherwise the options would set other task parameters we don't want.\n        for option in ['private', 'allow_duplicates']:\n            if option in ir.args:\n                setattr(ir, option, ir.args.get(option))\n\n        return ir.load_data(data, variable_manager=variable_manager, loader=loader)\n\n    def copy(self, exclude_parent=False, exclude_tasks=False):\n\n        new_me = super(IncludeRole, self).copy(exclude_parent=exclude_parent, exclude_tasks=exclude_tasks)\n        new_me.statically_loaded = self.statically_loaded\n        new_me._from_files = self._from_files.copy()\n        new_me._parent_role = self._parent_role\n        new_me._role_name   = self._role_name\n\n        return new_me\n\n    def get_include_params(self):\n        v = super(IncludeRole, self).get_include_params()\n        if self._parent_role:\n            v.update(self._parent_role.get_role_params())\n        return v\n", "path": "lib/ansible/playbook/role_include.py"}, {"content": "#!/usr/bin/python\n# -*- mode: python -*-\n# Ansible is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with Ansible.  If not, see <http://www.gnu.org/licenses/>.\n\nANSIBLE_METADATA = {'status': ['preview'],\n                    'supported_by': 'core',\n                    'version': '1.0'}\n\nDOCUMENTATION = '''\n---\nauthor:\n    - \"Ansible Core Team (@ansible)\"\nmodule: include_role\nshort_description: Load and execute a role\ndescription:\n     - \"Loads and executes a role as a task, this frees roles from the `role:` directive and allows them to be treated more as tasks.\"\nversion_added: \"2.2\"\noptions:\n  name:\n    description:\n      - The name of the role to be executed.\n    required: True\n  tasks_from:\n    description:\n      - \"File to load from a Role's tasks/ directory.\"\n    required: False\n    default: 'main'\n  vars_from:\n    description:\n      - \"File to load from a Role's vars/ directory.\"\n    required: False\n    default: 'main'\n  defaults_from:\n    description:\n      - \"File to load from a Role's defaults/ directory.\"\n    required: False\n    default: 'main'\n  allow_duplicates:\n    description:\n      - Overrides the role's metadata setting to allow using a role more than once with the same parameters.\n    required: False\n    default: True\n  private:\n    description:\n      - If True the variables from defaults/ and vars/ in a role will not be made available to the rest of the play.\n    default: None\nnotes:\n    - Handlers are made available to the whole play.\n    - simple dependencies seem to work fine.\n    - 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.\n'''\n\nEXAMPLES = \"\"\"\n- include_role:\n    name: myrole\n\n- name: Run tasks/other.yml instead of 'main'\n  include_role:\n    name: myrole\n    tasks_from: other\n\n- name: Pass variables to role\n  include_role:\n    name: myrole\n  vars:\n    rolevar1: 'value from task'\n\n- name: Use role in loop\n  include_role:\n    name: myrole\n  with_items:\n    - '{{ roleinput1 }}'\n    - '{{ roleinput2 }}'\n  loop_control:\n    loop_var: roleinputvar\n\n- name: conditional role\n  include_role:\n    name: myrole\n  when: not idontwanttorun\n\"\"\"\n\nRETURN = \"\"\"\n# this module does not return anything except tasks to execute\n\"\"\"\n", "path": "lib/ansible/modules/utilities/logic/include_role.py"}]}