Repository: ansible/ansible

Issue:
errors is undefined in subelements.py
Issue Type:

Bug Report

Ansible Configuration:

[defaults]
command_warnings = False
forks            = 64
gathering        = smart
nocows           = 1
pattern          = *
remote_tmp       = $HOME/.ansible/tmp
transport        = smart
inventory        = inventory
hash_behaviour   = merge

Ansible Version:

ansible 2.0.0 (devel ba7243c5f9) last updated 2015/07/16 15:01:11 (GMT +100)
  lib/ansible/modules/core: (detached HEAD 291fef3b34) last updated 2015/07/16 15:01:36 (GMT +100)
  lib/ansible/modules/extras: (detached HEAD ff2386faf4) last updated 2015/07/16 15:01:40 (GMT +100)
  v1/ansible/modules/core: (detached HEAD f8d8af17cd) last updated 2015/07/16 15:01:45 (GMT +100)
  v1/ansible/modules/extras: (detached HEAD 495ad450e5) last updated 2015/07/16 15:01:49 (GMT +100)
  configured module search path = None

Environment:

CentOS 6

Summary:

Python stack trace received when running an incorrectly configured playbook.  Expected to see the human readable error message.

Steps To Reproduce:

Trying to iterate over a dictionary using with_subelements rather than a list.  

```
with_subelements:
  - my_dict
  - subfield_also_a_dict
```

Expected Results:

``` python
fatal: [localhost]: FAILED! => {
    "failed": true,
    "msg": "ERROR! the key details should point to a list, got '{u'description': u'', u'vars': None}'"
}
```

Actual Results:

``` python
An exception occurred during task execution. The full traceback is:
Traceback (most recent call last):
  File "/export/home/developer/ansible/lib/ansible/executor/process/worker.py", line 118, in run
    executor_result = TaskExecutor(host, task, job_vars, new_connection_info, self._new_stdin, self._loader, shared_loader_obj).run()
  File "/export/home/developer/ansible/lib/ansible/executor/task_executor.py", line 80, in run
    items = self._get_loop_items()
  File "/export/home/developer/ansible/lib/ansible/executor/task_executor.py", line 134, in _get_loop_items
    items = lookup_loader.get(self._task.loop, loader=self._loader).run(terms=loop_terms, variables=self._job_vars)
  File "/export/home/developer/ansible/lib/ansible/plugins/lookup/subelements.py", line 96, in run
    raise errors.AnsibleError("the key %s should point to a list, got '%s'" % (subkey, subvalue[subkey]))
NameError: global name 'errors' is not defined

fatal: [localhost]: FAILED! => {
    "failed": true,
    "stdout": ""
}
```

I believe the issue is the "from ansible.errors import *" statement in subelements.py which can be replaced with "from ansible import errors"



Discussion:

Resolving patch:
diff --git a/lib/ansible/plugins/lookup/subelements.py b/lib/ansible/plugins/lookup/subelements.py
--- a/lib/ansible/plugins/lookup/subelements.py
+++ b/lib/ansible/plugins/lookup/subelements.py
@@ -30,7 +30,7 @@ class LookupModule(LookupBase):
     def run(self, terms, variables, **kwargs):
 
         def _raise_terms_error(msg=""):
-            raise errors.AnsibleError(
+            raise AnsibleError(
                 "subelements lookup expects a list of two or three items, "
                 + msg)
         terms = listify_lookup_plugin_terms(terms, variables, loader=self._loader)
@@ -66,7 +66,7 @@ def _raise_terms_error(msg=""):
         ret = []
         for item0 in elementlist:
             if not isinstance(item0, dict):
-                raise errors.AnsibleError("subelements lookup expects a dictionary, got '%s'" % item0)
+                raise AnsibleError("subelements lookup expects a dictionary, got '%s'" % item0)
             if item0.get('skipped', False) is not False:
                 # this particular item is to be skipped
                 continue
@@ -82,18 +82,18 @@ def _raise_terms_error(msg=""):
                     if skip_missing:
                         continue
                     else:
-                        raise errors.AnsibleError("could not find '%s' key in iterated item '%s'" % (subkey, subvalue))
+                        raise AnsibleError("could not find '%s' key in iterated item '%s'" % (subkey, subvalue))
                 if not lastsubkey:
                     if not isinstance(subvalue[subkey], dict):
                         if skip_missing:
                             continue
                         else:
-                            raise errors.AnsibleError("the key %s should point to a dictionary, got '%s'" % (subkey, subvalue[subkey]))
+                            raise AnsibleError("the key %s should point to a dictionary, got '%s'" % (subkey, subvalue[subkey]))
                     else:
                         subvalue = subvalue[subkey]
                 else:  # lastsubkey
                     if not isinstance(subvalue[subkey], list):
-                        raise errors.AnsibleError("the key %s should point to a list, got '%s'" % (subkey, subvalue[subkey]))
+                        raise AnsibleError("the key %s should point to a list, got '%s'" % (subkey, subvalue[subkey]))
                     else:
                         sublist = subvalue.pop(subkey, [])
             for item1 in sublist:


Test patch: