Repository: ansible/ansible

Issue:
[1.6.1] Value getting lost when a variable name is HOME
##### Issue Type:

“Bug Report”
##### Ansible Version:

ansible 1.6.1
##### Environment:

Debian / local connection
##### Summary:

I am creating a variable named HOME and setting it to user's home directory by looking up environment. In ansible 1.6.1, the value of this variable is becoming empty string during the playbook execution.
##### Steps To Reproduce:

Run the following playbook and checkout the result of second debug task.

ansible-playbook homedir.yml 

```

---
- hosts: all
  gather_facts: False
  vars:
    HOME: "{{lookup('env','HOME')}}"
  tasks:
    - debug: var=HOME
    - debug: var=HOME
```
##### Expected Results:

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

TASK: [debug var=HOME] ******************************************************** 
ok: [localhost] => {
    "HOME": "/home/jay"
}

TASK: [debug var=HOME] ******************************************************** 
ok: [localhost] => {
    "HOME": "/home/jay"
}

PLAY RECAP ******************************************************************** 
localhost                  : ok=2    changed=0    unreachable=0    failed=0   
```
##### Actual Results:

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

TASK: [debug var=HOME] ******************************************************** 
ok: [localhost] => {
    "HOME": "/home/jay"
}

TASK: [debug var=HOME] ******************************************************** 
ok: [localhost] => {
    "HOME": ""
}

PLAY RECAP ******************************************************************** 
localhost                  : ok=2    changed=0    unreachable=0    failed=0   
```



Discussion:
I can't reproduce this. On my system, I get an empty string for both cases, however if I use the lookup to get SHELL instead it works fine and I see the same value for both debugs. Can you provide any other information regarding your setup that might help in debugging this?

Provisioned a new ubuntu 13.10 64-bit server and installed ansible 1.6.1. And I am able to reproduce the issue for SHELL lookup as well.

It happens when ansible variable name is same as the environment variable name.

```
---
- hosts: all
  gather_facts: False
  vars:
    SHELL: "{{lookup('env','SHELL')}}"
  tasks:
    - debug: var=SHELL
    - debug: var=SHELL
```

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

TASK: [debug var=SHELL] ******************************************************* 
ok: [localhost] => {
    "SHELL": "/bin/bash"
}

TASK: [debug var=SHELL] ******************************************************* 
ok: [localhost] => {
    "SHELL": ""
}

PLAY RECAP ******************************************************************** 
localhost                  : ok=2    changed=0    unreachable=0    failed=0   
```

This is turning out to be an odd bug, however I see why it is happening. Each time the variable is accessed, the lookup plugin is run. During each run, the return value is passed through the template engine, in case the lookup was specified with variables (ie. lookup('env', "{{ FOO }}")). Because of this, on subsequent passes the variable is overwritten by a blank value, which is the part I'm still debugging.

For now, the workaround for this is to avoid using a variable name which exactly matches the value of the lookup you're doing (ie. use ENV_HOME or something similar). I will continue debugging this to see if we can short-circuit the templating of the value.

Thank you. I'm already doing workaround by using different variable name.

BTW it used to work even in the development branch of 1.6. I suspect this
is a regression from recent commits.
On May 17, 2014 1:58 AM, "James Cammarata" notifications@github.com wrote:

> This is turning out to be an odd bug, however I see why it is happening.
> Each time the variable is accessed, the lookup plugin is run. During each
> run, the return value is passed through the template engine, in case the
> lookup was specified with variables (ie. lookup('env', "{{ FOO }}")).
> Because of this, on subsequent passes the variable is overwritten by a
> blank value, which is the part I'm still debugging.
> 
> For now, the workaround for this is to avoid using a variable name which
> exactly matches the value of the lookup you're doing (ie. use ENV_HOME or
> something similar). I will continue debugging this to see if we can
> short-circuit the templating of the value.
> 
> —
> Reply to this email directly or view it on GitHubhttps://github.com/ansible/ansible/issues/7396#issuecomment-43375766
> .

Thanks, I'll do a bisect and see if I can see where it started acting this way.

I have a preliminary patch for this, though it may still need some additional testing:

<pre>
diff --git a/lib/ansible/runner/lookup_plugins/env.py b/lib/ansible/runner/lookup_plugins/env.py
index 6acc5f5..d4f8535 100644
--- a/lib/ansible/runner/lookup_plugins/env.py
+++ b/lib/ansible/runner/lookup_plugins/env.py
@@ -16,6 +16,7 @@
 # along with Ansible.  If not, see <http://www.gnu.org/licenses/>.
 
 from ansible import utils, errors
+from ansible.utils import template
 import os
 
 class LookupModule(object):
@@ -25,7 +26,10 @@ class LookupModule(object):
 
     def run(self, terms, inject=None, **kwargs):
 
-        terms = utils.listify_lookup_plugin_terms(terms, self.basedir, inject) 
+        try:
+            terms = template.template(self.basedir, terms, inject)
+        except Exception, e:
+            pass
 
         if isinstance(terms, basestring):
             terms = [ terms ]
</pre>


Resolving patch:
diff --git a/lib/ansible/runner/lookup_plugins/env.py b/lib/ansible/runner/lookup_plugins/env.py
--- a/lib/ansible/runner/lookup_plugins/env.py
+++ b/lib/ansible/runner/lookup_plugins/env.py
@@ -16,6 +16,7 @@
 # along with Ansible.  If not, see <http://www.gnu.org/licenses/>.
 
 from ansible import utils, errors
+from ansible.utils import template
 import os
 
 class LookupModule(object):
@@ -25,7 +26,10 @@ def __init__(self, basedir=None, **kwargs):
 
     def run(self, terms, inject=None, **kwargs):
 
-        terms = utils.listify_lookup_plugin_terms(terms, self.basedir, inject) 
+        try:
+            terms = template.template(self.basedir, terms, inject)
+        except Exception, e:
+            pass
 
         if isinstance(terms, basestring):
             terms = [ terms ]


Test patch: