Repository: ansible/ansible

Issue:
Exception when variable name and delegate_to hostname match
##### Issue Type:

Bugfix Pull Request
##### Ansible Version:

``` bash
ansible 1.9 (devel 2bf269568b) last updated 2014/12/02 15:46:49 (GMT -700)
  lib/ansible/modules/core: (detached HEAD 3a80b734e6) last updated 2014/12/02 09:45:53 (GMT -700)
  lib/ansible/modules/extras: (detached HEAD 317654dba5) last updated 2014/12/01 10:08:51 (GMT -700)
  v2/ansible/modules/core: (detached HEAD cb69744bce) last updated 2014/11/08 19:22:54 (GMT -700)
  v2/ansible/modules/extras: (detached HEAD 8a4f07eecd) last updated 2014/11/08 19:22:55 (GMT -700)
  configured module search path = <>
```
##### Environment:

Running on Mac OS X 10.10.1.
Running against Debian Squeeze.
##### Summary:

I am using a variable to designate my delegate host. The variable name I was using was "bastion" and the hostname returned was also "bastion" (it's in my SSH config file under that name). When these two values are the same, looking up the variable in the hostvars comes back successful but fails when trying to lookup a value inside of the dict it believes is available.
##### Steps To Reproduce:

Have a host named something such as "bastion". Currently I have one setup in my SSH config.

Playbook to reproduce this bug:

``` bash

---
# Test
- hosts: localhost
  vars:
    - bastion: bastion
  tasks:
    - debug: msg="Test message"
      delegate_to: "{{ bastion }}"
```
##### Expected Results:

``` bash
PLAY [localhost] **************************************************************

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

TASK: [debug msg="Test message"] **********************************************
ok: [localhost -> bastion] => {
    "msg": "Test message"
}

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

``` bash
PLAY [localhost] **************************************************************

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

TASK: [debug msg="Test message"] **********************************************
fatal: [localhost -> bastion] => Traceback (most recent call last):
  File "/Users/andrew/workspace/ansible/lib/ansible/runner/__init__.py", line 590, in _executor
    exec_rc = self._executor_internal(host, new_stdin)
  File "/Users/andrew/workspace/ansible/lib/ansible/runner/__init__.py", line 788, in _executor_internal
    return self._executor_internal_inner(host, self.module_name, self.module_args, inject, port, complex_args=complex_args)
  File "/Users/andrew/workspace/ansible/lib/ansible/runner/__init__.py", line 920, in _executor_internal_inner
    delegate = self._compute_delegate(actual_pass, inject)
  File "/Users/andrew/workspace/ansible/lib/ansible/runner/__init__.py", line 368, in _compute_delegate
    delegate['user'] = self._compute_delegate_user(self.delegate_to, delegate['inject'])
  File "/Users/andrew/workspace/ansible/lib/ansible/runner/__init__.py", line 398, in _compute_delegate_user
    if inject['hostvars'][host].get('ansible_ssh_user'):
  File "/Users/andrew/workspace/ansible/lib/ansible/runner/__init__.py", line 103, in __getitem__
    result = self.inventory.get_variables(host, vault_password=self.vault_password).copy()
  File "/Users/andrew/workspace/ansible/lib/ansible/inventory/__init__.py", line 442, in get_variables
    raise Exception("host not found: %s" % hostname)
Exception: host not found: bastion


FATAL: all hosts have already failed -- aborting

PLAY RECAP ********************************************************************
           to retry, use: --limit @/Users/andrew/setup.retry

localhost                  : ok=1    changed=0    unreachable=1    failed=0
```



Discussion:

Resolving patch:
diff --git a/lib/ansible/inventory/__init__.py b/lib/ansible/inventory/__init__.py
--- a/lib/ansible/inventory/__init__.py
+++ b/lib/ansible/inventory/__init__.py
@@ -420,7 +420,7 @@ def _get_group_variables(self, groupname, vault_password=None):
 
         group = self.get_group(groupname)
         if group is None:
-            raise Exception("group not found: %s" % groupname)
+            raise errors.AnsibleError("group not found: %s" % groupname)
 
         vars = {}
 
@@ -439,7 +439,7 @@ def get_variables(self, hostname, update_cached=False, vault_password=None):
 
         host = self.get_host(hostname)
         if not host:
-            raise Exception("host not found: %s" % hostname)
+            raise errors.AnsibleError("host not found: %s" % hostname)
         return host.get_variables()
 
     def get_host_variables(self, hostname, update_cached=False, vault_password=None):
diff --git a/lib/ansible/runner/__init__.py b/lib/ansible/runner/__init__.py
--- a/lib/ansible/runner/__init__.py
+++ b/lib/ansible/runner/__init__.py
@@ -394,20 +394,20 @@ def _compute_delegate_user(self, host, inject):
         actual_user = inject.get('ansible_ssh_user', self.remote_user)
         thisuser = None
 
-        if host in inject['hostvars']:
-            if inject['hostvars'][host].get('ansible_ssh_user'):
-                # user for delegate host in inventory
-                thisuser = inject['hostvars'][host].get('ansible_ssh_user')
-        else:
-            # look up the variables for the host directly from inventory
-            try:
-                host_vars = self.inventory.get_variables(host, vault_password=self.vault_pass)
-                if 'ansible_ssh_user' in host_vars:
-                    thisuser = host_vars['ansible_ssh_user']
-            except Exception, e:
-                # the hostname was not found in the inventory, so
-                # we just ignore this and try the next method
-                pass
+        try:
+            if host in inject['hostvars']:
+                if inject['hostvars'][host].get('ansible_ssh_user'):
+                    # user for delegate host in inventory
+                    thisuser = inject['hostvars'][host].get('ansible_ssh_user')
+                else:
+                    # look up the variables for the host directly from inventory
+                    host_vars = self.inventory.get_variables(host, vault_password=self.vault_pass)
+                    if 'ansible_ssh_user' in host_vars:
+                        thisuser = host_vars['ansible_ssh_user']
+        except errors.AnsibleError, e:
+            # the hostname was not found in the inventory, so
+            # we just ignore this and try the next method
+            pass
 
         if thisuser is None and self.remote_user:
             # user defined by play/runner


Test patch: