<p dir="auto">I have quite a large number of hosts to manage and they can be categorised into different groups depending on how you work on them. So I'd like to be able to do the following which currently seems impossible:</p>
<p dir="auto">[dc1-frontend-slaves]<br>
f-slave-[01:10].dc1.domain.com</p>
<p dir="auto">[dc1-backend-slaves]<br>
b-slave-[01:10].dc1.domain.com</p>
<p dir="auto">[dc2-frontend-slaves]<br>
f-slave-[01:10].dc2.domain.com</p>
<p dir="auto">[dc2-backend-slaves]<br>
b-slave-[01:10].dc2.domain.com</p>
<p dir="auto">[dc1-slaves]<br>
dc1-frontend-slaves<br>
dc1-backend-slaves</p>
<p dir="auto">[dc2-slaves]<br>
dc2-frontend-slaves<br>
dc2-backend-slaves</p>
<p dir="auto">[all-slaves]<br>
dc1-slaves<br>
dc2-slaves</p>
<p dir="auto">or</p>
<p dir="auto">[all-slaves]<br>
dc1-frontend-slaves<br>
dc1-backend-slaves<br>
dc2-frontend-slaves<br>
dc2-backend-slaves</p>
<p dir="auto">which would have the same result.</p>
<p dir="auto">This avoids duplication of names anywhere and also allows a more hierarchical definition.</p>
<p dir="auto">The example may look far fetched but real-life usage, at least where I work, would allow me to simplify somewhat the rather large ansible file I'm currently using.</p>
<h5 dir="auto">Issue Type:</h5>
<p dir="auto">Bug Report</p>
<h5 dir="auto">Ansible Version:</h5>
<p dir="auto">ansible 1.8.4<br>
configured module search path = None</p>
<h5 dir="auto">Environment:</h5>
<p dir="auto">OSX 10.10.2, using homebrew to install ansible.</p>
<h5 dir="auto">Summary:</h5>
<p dir="auto">When a playlist has two plays with <code class="notranslate">hosts: 127.0.0.1</code>, facts or registered variables from the first play fall out of scope for the second play.</p>
<h5 dir="auto">Steps To Reproduce:</h5>
<p dir="auto">Evaluate this playbook <code class="notranslate">test.yml</code>:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="# test.yml
- hosts: 127.0.0.1
  tasks:
    - set_fact: hostname_test='fubar'
    - add_host: name='{{ hostname_test }}'
      register: resp
    - debug: msg='{{ resp }}'

- hosts: 127.0.0.1
  tasks:
    - debug: msg='resp={{ resp|default(&quot;None&quot;) }}'
    - debug: msg='hostname_test={{ hostname_test|default(&quot;None&quot;) }}'
    - debug: msg='resp={{ hostvars[&quot;127.0.0.1&quot;][&quot;resp&quot;]|default(&quot;None&quot;) }}'
    - debug:
        msg='hostname_test={{ hostvars[&quot;127.0.0.1&quot;][&quot;hostname_test&quot;]
        |default(&quot;None&quot;) }}'
# end
$ ansible-playbook test.yml "><pre class="notranslate"><code class="notranslate"># test.yml
- hosts: 127.0.0.1
  tasks:
    - set_fact: hostname_test='fubar'
    - add_host: name='{{ hostname_test }}'
      register: resp
    - debug: msg='{{ resp }}'

- hosts: 127.0.0.1
  tasks:
    - debug: msg='resp={{ resp|default("None") }}'
    - debug: msg='hostname_test={{ hostname_test|default("None") }}'
    - debug: msg='resp={{ hostvars["127.0.0.1"]["resp"]|default("None") }}'
    - debug:
        msg='hostname_test={{ hostvars["127.0.0.1"]["hostname_test"]
        |default("None") }}'
# end
$ ansible-playbook test.yml 
</code></pre></div>
<p dir="auto">The ansible inventory may also be relevant:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="localhost ansible_connection=local ansible_python_interpreter=/usr/local/bin/python"><pre class="notranslate"><code class="notranslate">localhost ansible_connection=local ansible_python_interpreter=/usr/local/bin/python
</code></pre></div>
<h5 dir="auto">Expected Results:</h5>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="PLAY [127.0.0.1] **************************************************************

GATHERING FACTS ***************************************************************
ok: [127.0.0.1]

TASK: [set_fact hostname_test='fubar'] ****************************************
ok: [127.0.0.1]

TASK: [add_host name='{{ hostname_test }}'] ***********************************
ok: [127.0.0.1]

TASK: [debug msg='{{ resp }}'] ************************************************
ok: [127.0.0.1] =&gt; {
    &quot;msg&quot;: &quot;{'invocation': {'module_name': u'add_host', 'module_args': u\&quot;name='fubar'\&quot;}, 'new_host': u'fubar'}&quot;
}

PLAY [127.0.0.1] **************************************************************

GATHERING FACTS ***************************************************************
ok: [127.0.0.1]

TASK: [debug msg='resp=None'] *************************************************
ok: [127.0.0.1] =&gt; {
    &quot;msg&quot;: &quot;resp={'invocation': {'module_name': u'add_host', 'module_args': u\&quot;name='fubar'\&quot;}, 'new_host': u'fubar'}&quot;
}

TASK: [debug msg='hostname_test=None'] ****************************************
ok: [127.0.0.1] =&gt; {
    &quot;msg&quot;: &quot;hostname_test=fubar&quot;
}

TASK: [debug msg='resp={{ hostvars[&quot;127.0.0.1&quot;][&quot;resp&quot;]|default(&quot;None&quot;) }}'] ***
ok: [127.0.0.1] =&gt; {
    &quot;msg&quot;: &quot;resp={'invocation': {'module_name': u'add_host', 'module_args': u\&quot;name='fubar'\&quot;}, 'new_host': u'fubar'}&quot;
}

TASK: [debug msg='hostname_test={{ hostvars[&quot;127.0.0.1&quot;][&quot;hostname_test&quot;] |default(&quot;None&quot;) }}'] ***
ok: [127.0.0.1] =&gt; {
    &quot;msg&quot;: &quot;hostname_test=fubar&quot;
}

PLAY RECAP ********************************************************************
127.0.0.1                  : ok=4    changed=0    unreachable=0    failed=0
127.0.0.1                  : ok=5    changed=0    unreachable=0    failed=0"><pre class="notranslate"><code class="notranslate">PLAY [127.0.0.1] **************************************************************

GATHERING FACTS ***************************************************************
ok: [127.0.0.1]

TASK: [set_fact hostname_test='fubar'] ****************************************
ok: [127.0.0.1]

TASK: [add_host name='{{ hostname_test }}'] ***********************************
ok: [127.0.0.1]

TASK: [debug msg='{{ resp }}'] ************************************************
ok: [127.0.0.1] =&gt; {
    "msg": "{'invocation': {'module_name': u'add_host', 'module_args': u\"name='fubar'\"}, 'new_host': u'fubar'}"
}

PLAY [127.0.0.1] **************************************************************

GATHERING FACTS ***************************************************************
ok: [127.0.0.1]

TASK: [debug msg='resp=None'] *************************************************
ok: [127.0.0.1] =&gt; {
    "msg": "resp={'invocation': {'module_name': u'add_host', 'module_args': u\"name='fubar'\"}, 'new_host': u'fubar'}"
}

TASK: [debug msg='hostname_test=None'] ****************************************
ok: [127.0.0.1] =&gt; {
    "msg": "hostname_test=fubar"
}

TASK: [debug msg='resp={{ hostvars["127.0.0.1"]["resp"]|default("None") }}'] ***
ok: [127.0.0.1] =&gt; {
    "msg": "resp={'invocation': {'module_name': u'add_host', 'module_args': u\"name='fubar'\"}, 'new_host': u'fubar'}"
}

TASK: [debug msg='hostname_test={{ hostvars["127.0.0.1"]["hostname_test"] |default("None") }}'] ***
ok: [127.0.0.1] =&gt; {
    "msg": "hostname_test=fubar"
}

PLAY RECAP ********************************************************************
127.0.0.1                  : ok=4    changed=0    unreachable=0    failed=0
127.0.0.1                  : ok=5    changed=0    unreachable=0    failed=0
</code></pre></div>
<h5 dir="auto">Actual Results:</h5>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="PLAY [127.0.0.1] ************************************************************** 

GATHERING FACTS *************************************************************** 
ok: [127.0.0.1]

TASK: [set_fact hostname_test='fubar'] **************************************** 
ok: [127.0.0.1]

TASK: [add_host name='{{ hostname_test }}'] *********************************** 
ok: [127.0.0.1]

TASK: [debug msg='{{ resp }}'] ************************************************ 
ok: [127.0.0.1] =&gt; {
    &quot;msg&quot;: &quot;{'invocation': {'module_name': u'add_host', 'module_args': u\&quot;name='fubar'\&quot;}, 'new_host': u'fubar'}&quot;
}

PLAY [127.0.0.1] ************************************************************** 

GATHERING FACTS *************************************************************** 
ok: [localhost]

TASK: [debug msg='resp=None'] ************************************************* 
ok: [localhost] =&gt; {
    &quot;msg&quot;: &quot;resp=None&quot;
}

TASK: [debug msg='hostname_test=None'] **************************************** 
ok: [localhost] =&gt; {
    &quot;msg&quot;: &quot;hostname_test=None&quot;
}

TASK: [debug msg='resp={{ hostvars[&quot;127.0.0.1&quot;][&quot;resp&quot;]|default(&quot;None&quot;) }}'] *** 
ok: [localhost] =&gt; {
    &quot;msg&quot;: &quot;resp={'invocation': {'module_name': u'add_host', 'module_args': u\&quot;name='fubar'\&quot;}, 'new_host': u'fubar'}&quot;
}

TASK: [debug msg='hostname_test={{ hostvars[&quot;127.0.0.1&quot;][&quot;hostname_test&quot;] |default(&quot;None&quot;) }}'] *** 
ok: [localhost] =&gt; {
    &quot;msg&quot;: &quot;hostname_test=fubar&quot;
}

PLAY RECAP ******************************************************************** 
127.0.0.1                  : ok=4    changed=0    unreachable=0    failed=0   
localhost                  : ok=5    changed=0    unreachable=0    failed=0   "><pre class="notranslate"><code class="notranslate">PLAY [127.0.0.1] ************************************************************** 

GATHERING FACTS *************************************************************** 
ok: [127.0.0.1]

TASK: [set_fact hostname_test='fubar'] **************************************** 
ok: [127.0.0.1]

TASK: [add_host name='{{ hostname_test }}'] *********************************** 
ok: [127.0.0.1]

TASK: [debug msg='{{ resp }}'] ************************************************ 
ok: [127.0.0.1] =&gt; {
    "msg": "{'invocation': {'module_name': u'add_host', 'module_args': u\"name='fubar'\"}, 'new_host': u'fubar'}"
}

PLAY [127.0.0.1] ************************************************************** 

GATHERING FACTS *************************************************************** 
ok: [localhost]

TASK: [debug msg='resp=None'] ************************************************* 
ok: [localhost] =&gt; {
    "msg": "resp=None"
}

TASK: [debug msg='hostname_test=None'] **************************************** 
ok: [localhost] =&gt; {
    "msg": "hostname_test=None"
}

TASK: [debug msg='resp={{ hostvars["127.0.0.1"]["resp"]|default("None") }}'] *** 
ok: [localhost] =&gt; {
    "msg": "resp={'invocation': {'module_name': u'add_host', 'module_args': u\"name='fubar'\"}, 'new_host': u'fubar'}"
}

TASK: [debug msg='hostname_test={{ hostvars["127.0.0.1"]["hostname_test"] |default("None") }}'] *** 
ok: [localhost] =&gt; {
    "msg": "hostname_test=fubar"
}

PLAY RECAP ******************************************************************** 
127.0.0.1                  : ok=4    changed=0    unreachable=0    failed=0   
localhost                  : ok=5    changed=0    unreachable=0    failed=0   
</code></pre></div>
<p dir="auto">Both plays are declared as <code class="notranslate">host: 127.0.0.1</code> but the second play runs as if it were <code class="notranslate">hosts: localhost</code>. Possibly this is done after a reverse lookup somewhere inside ansible? Because of this the variable scope appears to change for the second play. This causes the variables <code class="notranslate">resp</code> and <code class="notranslate">hostname_test</code> to be undefined.</p>
<p dir="auto">Possible workarounds: Use <code class="notranslate">hostvars["127.0.0.1"]</code> as in the test case, or declare <code class="notranslate">hosts: localhost</code> for both plays. However there may be similar situations where ansible quietly remaps a hostname to some other value. If the value is not easily determined, that may be difficult to work around.</p>