Repository: ansible/ansible

Issue:
with_fileglob no longer returns an empty list
##### ISSUE TYPE

Bug Report.
##### ANSIBLE VERSION

```
root@ip-10-65-53-7:~# ansible --version
ansible 2.2.0
  config file = /etc/ansible/ansible.cfg
  configured module search path = Default w/o overrides
```
##### CONFIGURATION

All defaults.
##### OS / ENVIRONMENT

Ubuntu 12.04.
##### SUMMARY

In our following example, `with_fileglob` used to return an empty list. Now, when `with_fileglob` finds no results, our task simply fails.
##### STEPS TO REPRODUCE
- Create the following playbook:

```
- hosts: all
  gather_facts: no

  tasks:

    # this will copy a bunch of config files over -- dir must be created first

    - file: dest=/etc/fooapp state=directory

    - copy: src={{ item }} dest=/etc/fooapp/ owner=root mode=600
      with_fileglob: /playbooks/files/fooapp/*
```
- Create the following inventory file:

```
[local]
127.0.0.1 ansible_connection=local ansible_python_interpreter='/usr/bin/env python'
```
- Invoke with the following:

```
ansible-playbook -i inventory test.yml -vvvvvv
```
##### EXPECTED RESULTS

On ansible-2.1.1.0, we get the following:

```
Using /etc/ansible/ansible.cfg as config file
Loaded callback default of type stdout, v2.0

PLAYBOOK: test.yml *************************************************************
1 plays in test.yml

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

TASK [file] ********************************************************************
task path: /root/test.yml:8
<127.0.0.1> ESTABLISH LOCAL CONNECTION FOR USER: root
<127.0.0.1> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo $HOME/.ansible/tmp/ansible-tmp-1469214142.12-38141711481161 `" && echo ansible-tmp-1469214142.12-38141711481161="` echo $HOME/.ansible/tmp/ansible-tmp-1469214142.12-38141711481161 `" ) && sleep 0'
<127.0.0.1> PUT /tmp/tmpToDNz7 TO /root/.ansible/tmp/ansible-tmp-1469214142.12-38141711481161/file
<127.0.0.1> EXEC /bin/sh -c 'LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8 /usr/bin/env python /root/.ansible/tmp/ansible-tmp-1469214142.12-38141711481161/file; rm -rf "/root/.ansible/tmp/ansible-tmp-1469214142.12-38141711481161/" > /dev/null 2>&1 && sleep 0'
ok: [127.0.0.1] => {"changed": false, "diff": {"after": {"path": "/etc/fooapp"}, "before": {"path": "/etc/fooapp"}}, "gid": 0, "group": "root", "invocation": {"module_args": {"backup": null, "content": null, "delimiter": null, "dest": "/etc/fooapp", "diff_peek": null, "directory_mode": null, "follow": false, "force": false, "group": null, "mode": null, "original_basename": null, "owner": null, "path": "/etc/fooapp", "recurse": false, "regexp": null, "remote_src": null, "selevel": null, "serole": null, "setype": null, "seuser": null, "src": null, "state": "directory", "validate": null}, "module_name": "file"}, "mode": "0755", "owner": "root", "path": "/etc/fooapp", "secontext": "unconfined_u:object_r:etc_t:s0", "size": 4096, "state": "directory", "uid": 0}

TASK [copy] ********************************************************************
task path: /root/test.yml:10

PLAY RECAP *********************************************************************
127.0.0.1                  : ok=1    changed=0    unreachable=0    failed=0   
```
##### ACTUAL RESULTS

On ansible-2.2, we get the following:

```
Using /etc/ansible/ansible.cfg as config file
Loaded callback default of type stdout, v2.0

PLAYBOOK: test.yml *************************************************************
1 plays in test.yml

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

TASK [file] ********************************************************************
task path: /root/test.yml:8
Using module file /usr/lib/pymodules/python2.7/ansible/modules/core/files/file.py
<127.0.0.1> ESTABLISH LOCAL CONNECTION FOR USER: root
<127.0.0.1> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo $HOME/.ansible/tmp/ansible-tmp-1469214111.01-34598698201553 `" && echo ansible-tmp-1469214111.01-34598698201553="` echo $HOME/.ansible/tmp/ansible-tmp-1469214111.01-34598698201553 `" ) && sleep 0'
<127.0.0.1> PUT /tmp/tmpO5rlZ9 TO /root/.ansible/tmp/ansible-tmp-1469214111.01-34598698201553/file.py
<127.0.0.1> EXEC /bin/sh -c 'chmod -R u+x /root/.ansible/tmp/ansible-tmp-1469214111.01-34598698201553/ && sleep 0'
<127.0.0.1> EXEC /bin/sh -c '/usr/bin/env python /root/.ansible/tmp/ansible-tmp-1469214111.01-34598698201553/file.py; rm -rf "/root/.ansible/tmp/ansible-tmp-1469214111.01-34598698201553/" > /dev/null 2>&1 && sleep 0'
ok: [127.0.0.1] => {"changed": false, "diff": {"after": {"path": "/etc/fooapp"}, "before": {"path": "/etc/fooapp"}}, "gid": 0, "group": "root", "invocation": {"module_args": {"backup": null, "content": null, "delimiter": null, "dest": "/etc/fooapp", "diff_peek": null, "directory_mode": null, "follow": false, "force": false, "group": null, "mode": null, "original_basename": null, "owner": null, "path": "/etc/fooapp", "recurse": false, "regexp": null, "remote_src": null, "selevel": null, "serole": null, "setype": null, "seuser": null, "src": null, "state": "directory", "validate": null}, "module_name": "file"}, "mode": "0755", "owner": "root", "path": "/etc/fooapp", "size": 4096, "state": "directory", "uid": 0}

TASK [copy] ********************************************************************
task path: /root/test.yml:10
fatal: [127.0.0.1]: FAILED! => {"failed": true, "msg": "Unable to find '/playbooks/files/fooapp' in expected paths."}

NO MORE HOSTS LEFT *************************************************************
    to retry, use: --limit @test.retry

PLAY RECAP *********************************************************************
127.0.0.1                  : ok=1    changed=0    unreachable=0    failed=1   
```



Discussion:

Resolving patch:
diff --git a/lib/ansible/plugins/lookup/__init__.py b/lib/ansible/plugins/lookup/__init__.py
--- a/lib/ansible/plugins/lookup/__init__.py
+++ b/lib/ansible/plugins/lookup/__init__.py
@@ -22,7 +22,6 @@
 from abc import ABCMeta, abstractmethod
 
 from ansible.compat.six import with_metaclass
-from ansible.errors import AnsibleFileNotFound
 
 try:
     from __main__ import display
@@ -115,6 +114,6 @@ def find_file_in_search_path(self, myvars, subdir, needle):
 
         result = self._loader.path_dwim_relative_stack(paths, subdir, needle)
         if result is None:
-            raise AnsibleFileNotFound("Unable to find '%s' in expected paths." % needle)
+            self._display.warning("Unable to find '%s' in expected paths." % needle)
 
         return result
diff --git a/lib/ansible/plugins/lookup/fileglob.py b/lib/ansible/plugins/lookup/fileglob.py
--- a/lib/ansible/plugins/lookup/fileglob.py
+++ b/lib/ansible/plugins/lookup/fileglob.py
@@ -32,10 +32,7 @@ def run(self, terms, variables=None, **kwargs):
         ret = []
         for term in terms:
             term_file = os.path.basename(term)
-            try:
-                dwimmed_path = self.find_file_in_search_path(variables, 'files', os.path.dirname(term))
-            except AnsibleFileNotFound:
-                dwimmed_path = None
+            dwimmed_path = self.find_file_in_search_path(variables, 'files', os.path.dirname(term))
             if dwimmed_path:
                 globbed = glob.glob(to_bytes(os.path.join(dwimmed_path, term_file), errors='surrogate_or_strict'))
                 ret.extend(to_text(g, errors='surrogate_or_strict') for g in globbed if os.path.isfile(g))
diff --git a/lib/ansible/plugins/lookup/first_found.py b/lib/ansible/plugins/lookup/first_found.py
--- a/lib/ansible/plugins/lookup/first_found.py
+++ b/lib/ansible/plugins/lookup/first_found.py
@@ -181,11 +181,9 @@ def run(self, terms, variables, **kwargs):
              # get subdir if set by task executor, default to files otherwise
             subdir = getattr(self, '_subdir', 'files')
             path = None
-            try:
-                path = self.find_file_in_search_path(variables, subdir, fn)
+            path = self.find_file_in_search_path(variables, subdir, fn)
+            if path is not None:
                 return [path]
-            except AnsibleFileNotFound:
-                continue
         else:
             if skip:
                 return []


Test patch: