Repository: ansible/ansible

Issue:
ansible-galaxy list errors if search directories are missing
##### ISSUE TYPE
 - Bug Report

##### COMPONENT NAME
ansible-galaxy

##### ANSIBLE VERSION
```
ansible 2.5.0
  config file = /home/lae/.ansible.cfg
  configured module search path = [u'/home/lae/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.7/site-packages/ansible
  executable location = /usr/bin/ansible
  python version = 2.7.14 (default, Jan  5 2018, 10:41:29) [GCC 7.2.1 20171224]

```

##### OS / ENVIRONMENT
Arch Linux

##### SUMMARY
Attempting to list installed roles when `/usr/share/ansible/roles` does not exist fails.

##### STEPS TO REPRODUCE
Ensure `/usr/share/ansible/roles` (or any directory in `DEFAULT_ROLES_PATH` probably) doesn't exist, then run `ansible-galaxy list`.

##### EXPECTED RESULTS
```
[lae@yuzu ~]$ ansible-galaxy list
<list of roles>
[lae@yuzu ~]$ echo $?
0
```

##### ACTUAL RESULTS
```
[lae@yuzu ~]$ ansible-galaxy list
<list of roles snipped>
Usage: ansible-galaxy list [role_name]

Options:
  -h, --help            show this help message and exit
  -c, --ignore-certs    Ignore SSL certificate validation errors.
  -p ROLES_PATH, --roles-path=ROLES_PATH
                        The path to the directory containing your roles. The
                        default is the roles_path configured in your
                        ansible.cfgfile (/etc/ansible/roles if not configured)
  -s API_SERVER, --server=API_SERVER
                        The API server destination
  -v, --verbose         verbose mode (-vvv for more, -vvvv to enable
                        connection debugging)
  --version             show program's version number and exit

 See 'ansible-galaxy <command> --help' for more information on a specific
command.
ERROR! - the path /usr/share/ansible/roles does not exist. Please specify a valid path with --roles-path
[lae@yuzu ~]$ echo $?
5
```


Discussion:
Files identified in the description:
* [lib/ansible/galaxy](https://github.com/ansible/ansible/blob/devel/lib/ansible/galaxy)

If these files are inaccurate, please update the `component name` section of the description or use the `!component` bot command.

[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: components_banner --->
cc @chouseknecht 

Resolving patch:
diff --git a/lib/ansible/cli/galaxy.py b/lib/ansible/cli/galaxy.py
--- a/lib/ansible/cli/galaxy.py
+++ b/lib/ansible/cli/galaxy.py
@@ -476,13 +476,17 @@ def execute_list(self):
         else:
             # show all valid roles in the roles_path directory
             roles_path = self.options.roles_path
+            path_found = False
             for path in roles_path:
                 role_path = os.path.expanduser(path)
                 if not os.path.exists(role_path):
-                    raise AnsibleOptionsError("- the path %s does not exist. Please specify a valid path with --roles-path" % role_path)
+                    display.warning("- the configured path %s does not exist." % role_path)
+                    continue
                 elif not os.path.isdir(role_path):
-                    raise AnsibleOptionsError("- %s exists, but it is not a directory. Please specify a valid path with --roles-path" % role_path)
+                    display.warning("- the configured path %s, exists, but it is not a directory." % role_path)
+                    continue
                 path_files = os.listdir(role_path)
+                path_found = True
                 for path_file in path_files:
                     gr = GalaxyRole(self.galaxy, path_file)
                     if gr.metadata:
@@ -493,6 +497,8 @@ def execute_list(self):
                         if not version:
                             version = "(unknown version)"
                         display.display("- %s, %s" % (path_file, version))
+            if not path_found:
+                raise AnsibleOptionsError("- None of the provided paths was usable. Please specify a valid path with --roles-path")
         return 0
 
     def execute_search(self):


Test patch: