Repository: ansible/ansible

Issue:
List index out of range while doing setup step
##### ISSUE TYPE
Bug Report

##### COMPONENT NAME
gather_facts

##### ANSIBLE VERSION
2.3

##### SUMMARY
This problem is recurring as of 404b2864efa89f97f3bb14bf1448461d0c9de52f

Same as #13359 

```
$ ansible -vvvv -i inventory -m setup earner -k
Loading callback plugin minimal of type stdout, v2.0 from /home/will/src/ansible-work/ansible/lib/ansible/plugins/callback/__init__.py
META: ran handlers
Using module file /home/will/src/ansible-work/ansible/lib/ansible/modules/system/setup.py
<172.30.0.158> ESTABLISH SSH CONNECTION FOR USER: None
<172.30.0.158> SSH: EXEC sshpass -d12 ssh -vvv -C -o ControlMaster=auto -o ControlPersist=60s -o ConnectTimeout=10 -o ControlPath=/home/will/.ansible/cp/65edfbb9dc 172.30.0.158 '/bin/sh -c '"'"'echo ~ && sleep 0'"'"''
An exception occurred during task execution. The full traceback is:
Traceback (most recent call last):
  File "/home/will/src/ansible-work/ansible/lib/ansible/executor/task_executor.py", line 126, in run
    res = self._execute()
  File "/home/will/src/ansible-work/ansible/lib/ansible/executor/task_executor.py", line 512, in _execute
    result = self._handler.run(task_vars=variables)
  File "/home/will/src/ansible-work/ansible/lib/ansible/plugins/action/normal.py", line 45, in run
    results = merge_hash(results, self._execute_module(tmp=tmp, task_vars=task_vars, wrap_async=wrap_async))
  File "/home/will/src/ansible-work/ansible/lib/ansible/plugins/action/__init__.py", line 634, in _execute_module
    tmp = self._make_tmp_path()
  File "/home/will/src/ansible-work/ansible/lib/ansible/plugins/action/__init__.py", line 248, in _make_tmp_path
    tmpdir =  self._remote_expand_user(C.DEFAULT_REMOTE_TMP, sudoable=False)
  File "/home/will/src/ansible-work/ansible/lib/ansible/plugins/action/__init__.py", line 546, in _remote_expand_user
    initial_fragment = data['stdout'].strip().splitlines()[-1]
IndexError: list index out of range

a503c218-2549-459a-8a67-6a8f82ae52f5 | FAILED! => {
    "failed": true, 
    "msg": "Unexpected failure during module execution.", 
    "stdout": ""
}
```


Discussion:
Ok so I debugged this - the problem is bad error messages. If you connect with the wrong SSH user, or authentication fails, or basically anything else happens, you'll get this error because the `data['stdout']` will container a blank string, whereas the undisplayed `stderr` will have the SSH error in it.

The module desperately needs some logic to detect these common situations and display a more helpful error message.

Resolving patch:
diff --git a/lib/ansible/plugins/action/__init__.py b/lib/ansible/plugins/action/__init__.py
--- a/lib/ansible/plugins/action/__init__.py
+++ b/lib/ansible/plugins/action/__init__.py
@@ -543,7 +543,10 @@ def _remote_expand_user(self, path, sudoable=True):
 
         cmd = self._connection._shell.expand_user(expand_path)
         data = self._low_level_execute_command(cmd, sudoable=False)
-        initial_fragment = data['stdout'].strip().splitlines()[-1]
+        try:
+            initial_fragment = data['stdout'].strip().splitlines()[-1]
+        except IndexError:
+            initial_fragment = None
 
         if not initial_fragment:
             # Something went wrong trying to expand the path remotely.  Return


Test patch: