Repository: ansible/ansible

Issue:
ansible-config tracebacks if there is no config file. 'stat: path should be string, bytes, os.PathLike or integer, not NoneType'

##### ISSUE TYPE

 - Bug Report
 
##### COMPONENT NAME
lib/ansible/cli/config.py


##### ANSIBLE VERSION
<!--- Paste verbatim output from "ansible --version" between quotes below -->
```
ansible 2.5.0b1
  config file = None
  configured module search path = ['/home/adrian/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/adrian/.local/lib/python3.6/site-packages/ansible
  executable location = /home/adrian/.local/bin/ansible
  python version = 3.6.4 (default, Jan 23 2018, 22:28:37) [GCC 7.2.1 20170915 (Red Hat 7.2.1-2)]

```

##### CONFIGURATION

No config file or env config.

```
[newswoop:F27:~]$ ansible-config dump --only-changed
[newswoop:F27:~]$ 
```

##### OS / ENVIRONMENT
<!---
Mention the OS you are running Ansible from, and the OS you are
managing, or say "N/A" for anything that is not platform-specific.
Also mention the specific version of what you are trying to control,
e.g. if this is a network bug the version of firmware on the network device.
-->

controller OS:
Fedora 27 x86_64
python3.6

controller shell env:
```
[newswoop:F27:~]$ env | grep ANSIBLE
ANSIBLE_MODULES_CORE_SRC_DIR=/home/adrian/src/ansible-modules-core
ANSIBLE_SRC_DIR=/home/adrian/src/ansible
ANSIBLE_MODULES_EXTRAS_SRC_DIR=/home/adrian/src/ansible-modules-extras
```

(Those are env vars for my build/devel/test helpers)



##### SUMMARY
<!--- Explain the problem briefly -->
After a pip install of the 2.5.0b1 release, 'ansible-config view' throws an error/traceback
about 'stat: path should be string, bytes, os.PathLike or integer, not NoneType'

```
[newswoop:F27:~]$ ansible-config view -vvv
ansible-config 2.5.0b1
  config file = None
  configured module search path = ['/home/adrian/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/adrian/.local/lib/python3.6/site-packages/ansible
  executable location = /home/adrian/.local/bin/ansible-config
  python version = 3.6.4 (default, Jan 23 2018, 22:28:37) [GCC 7.2.1 20170915 (Red Hat 7.2.1-2)]
No config file found; using defaults
ERROR! Unexpected Exception, this is probably a bug: stat: path should be string, bytes, os.PathLike or integer, not NoneType
the full traceback was:

Traceback (most recent call last):
  File "/home/adrian/.local/bin/ansible-config", line 118, in <module>
    exit_code = cli.run()
  File "/home/adrian/.local/lib/python3.6/site-packages/ansible/cli/config.py", line 77, in run
    if not os.path.exists(self.config_file):
  File "/usr/lib64/python3.6/genericpath.py", line 19, in exists
    os.stat(path)
TypeError: stat: path should be string, bytes, os.PathLike or integer, not NoneType
```

##### STEPS TO REPRODUCE

(start a new shell with no ANSIBLE_HOME or ANSIBLE_CONFIG set)
(for my case, `pip3.6 install -v ansible==2.5.0b1 --user` was the exact command)

`pip install ansible==2.5.0b1 --user`

`ansible-config view`

(and to see traceback)

`ansible-config view -vvv`

##### EXPECTED RESULTS
<!--- What did you expect to happen when running the steps above? -->
Current config to be shown, which in this case would be nothing, so just no output and no error.

##### ACTUAL RESULTS
<!--- What actually happened? If possible run with extra verbosity (-vvvv) -->

<!--- Paste verbatim command output between quotes below -->
```
[newswoop:F27:~]$ ansible-config view -vvv
ansible-config 2.5.0b1
  config file = None
  configured module search path = ['/home/adrian/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/adrian/.local/lib/python3.6/site-packages/ansible
  executable location = /home/adrian/.local/bin/ansible-config
  python version = 3.6.4 (default, Jan 23 2018, 22:28:37) [GCC 7.2.1 20170915 (Red Hat 7.2.1-2)]
No config file found; using defaults
ERROR! Unexpected Exception, this is probably a bug: stat: path should be string, bytes, os.PathLike or integer, not NoneType
the full traceback was:

Traceback (most recent call last):
  File "/home/adrian/.local/bin/ansible-config", line 118, in <module>
    exit_code = cli.run()
  File "/home/adrian/.local/lib/python3.6/site-packages/ansible/cli/config.py", line 77, in run
    if not os.path.exists(self.config_file):
  File "/usr/lib64/python3.6/genericpath.py", line 19, in exists
    os.stat(path)
TypeError: stat: path should be string, bytes, os.PathLike or integer, not NoneType

```



Discussion:

Resolving patch:
diff --git a/lib/ansible/cli/config.py b/lib/ansible/cli/config.py
--- a/lib/ansible/cli/config.py
+++ b/lib/ansible/cli/config.py
@@ -73,18 +73,23 @@ def run(self):
         else:
             self.config = ConfigManager()
             self.config_file = find_ini_config_file()
-        try:
-            if not os.path.exists(self.config_file):
-                raise AnsibleOptionsError("%s does not exist or is not accessible" % (self.config_file))
-            elif not os.path.isfile(self.config_file):
-                raise AnsibleOptionsError("%s is not a valid file" % (self.config_file))
-
-            os.environ['ANSIBLE_CONFIG'] = to_native(self.config_file)
-        except:
-            if self.action in ['view']:
-                raise
-            elif self.action in ['edit', 'update']:
-                display.warning("File does not exist, used empty file: %s" % self.config_file)
+
+        if self.config_file:
+            try:
+                if not os.path.exists(self.config_file):
+                    raise AnsibleOptionsError("%s does not exist or is not accessible" % (self.config_file))
+                elif not os.path.isfile(self.config_file):
+                    raise AnsibleOptionsError("%s is not a valid file" % (self.config_file))
+
+                os.environ['ANSIBLE_CONFIG'] = to_native(self.config_file)
+            except:
+                if self.action in ['view']:
+                    raise
+                elif self.action in ['edit', 'update']:
+                    display.warning("File does not exist, used empty file: %s" % self.config_file)
+
+        elif self.action == 'view':
+            raise AnsibleError('Invalid or no config file was supplied')
 
         self.execute()
 


Test patch: