Repository: ansible/ansible

Issue:
yaml inventory plugin ignores files w/o extension
##### ISSUE TYPE
 - Bug Report

##### COMPONENT NAME
Inventory

##### ANSIBLE VERSION
```
ansible --version                                                             
ansible 2.5.0                                                                                        
  config file = None                                                                                 
  configured module search path = ['/nfs/home/thmarble/.ansible/plugins/modules', '/usr/share/ansibl\
e/plugins/modules']                                                                                  
  ansible python module location = /usr/local/lib/python3.5/dist-packages/ansible                    
  executable location = /usr/local/bin/ansible                                                       
  python version = 3.5.2 (default, Nov 17 2016, 17:05:23) [GCC 5.4.0 20160609]                       
```

##### CONFIGURATION
N/A

##### OS / ENVIRONMENT
Ubuntu Xenial

##### SUMMARY
The fix for #30663 merged into **devel** as 72bdf7a does not seem to resolve the issue for me.

##### STEPS TO REPRODUCE

Update ansible to **devel** via pip3:

```
root@ubuntu:/etc/ansible# pip3 install git+git://github.com/ansible/ansible.git@devel
Collecting git+git://github.com/ansible/ansible.git@devel
  Cloning git://github.com/ansible/ansible.git (to devel) to /tmp/pip-9ybcq7w0-build
Requirement already satisfied (use --upgrade to upgrade): jinja2 in /usr/lib/python3/dist-packages (\
from ansible===2.5.0)
Requirement already satisfied (use --upgrade to upgrade): PyYAML in /usr/lib/python3/dist-packages (\
from ansible===2.5.0)
Requirement already satisfied (use --upgrade to upgrade): paramiko in /usr/lib/python3/dist-packages\
 (from ansible===2.5.0)
Requirement already satisfied (use --upgrade to upgrade): cryptography in /usr/local/lib/python3.5/d\
ist-packages (from ansible===2.5.0)
Requirement already satisfied (use --upgrade to upgrade): setuptools in /usr/lib/python3/dist-packag\
es (from ansible===2.5.0)
Requirement already satisfied (use --upgrade to upgrade): MarkupSafe in /usr/lib/python3/dist-packag\
es (from jinja2->ansible===2.5.0)
Requirement already satisfied (use --upgrade to upgrade): asn1crypto>=0.21.0 in /usr/local/lib/pytho\
n3.5/dist-packages (from cryptography->ansible===2.5.0)
Requirement already satisfied (use --upgrade to upgrade): cffi>=1.7 in /usr/local/lib/python3.5/dist\
-packages (from cryptography->ansible===2.5.0)
Requirement already satisfied (use --upgrade to upgrade): idna>=2.1 in /usr/local/lib/python3.5/dist\
-packages (from cryptography->ansible===2.5.0)
Requirement already satisfied (use --upgrade to upgrade): six>=1.4.1 in /usr/lib/python3/dist-packag\
es (from cryptography->ansible===2.5.0)
Requirement already satisfied (use --upgrade to upgrade): pycparser in /usr/local/lib/python3.5/dist\
-packages (from cffi>=1.7->cryptography->ansible===2.5.0)
Installing collected packages: ansible
  Found existing installation: ansible 2.4.0.0
    Uninstalling ansible-2.4.0.0:
      Successfully uninstalled ansible-2.4.0.0
  Running setup.py install for ansible ... ^[[?25ldone
^[[?25hSuccessfully installed ansible-2.5.0
You are using pip version 8.1.1, however version 9.0.1 is available.                                 
You should consider upgrading via the 'pip install --upgrade pip' command.
root@ubuntu:/etc/ansible# m
```

inventory.yml

```yaml
local:
  hosts:
    localhost
```
`# ANSIBLE_DEBUG=1 ansible local -i inventory.yml -m ping`

##### EXPECTED RESULTS
A successful run against localhost.

##### ACTUAL RESULTS
See full output in [inventory.log](https://github.com/ansible/ansible/files/1329880/inventory.log)
```
 24141 1506349683.29077: Attempting to use plugin script (/usr/local/lib/python3.5/dist-packages/ansible/plugins/inventory/script.py)
 24141 1506349683.30162: /nfs/home1/thmarble/src/bitbucket-eng-sjc1/thmarble/nanohttpd/NOT/inventory.yml did not meet script requirements
```



Discussion:
cc @dagnello @emonty @j2sol @juliakreger @rcarrillocruz @shrews @thingee
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->
can you please specify the error you are seeing? 
@boca hmmm it turns out that `inventory.yml` is OK, but using my `/etc/ansible/hosts` file which has an `ansible_user` key fails.  When run with ANSIBLE_DEBUG=1 the only detail given is `/etc/ansible/hosts did not meet yaml requirements`:

```
thmarble@ubuntu 799 :) ansible local -i inventory.yml -m ping
localhost | SUCCESS => {
    "changed": false,
    "failed": false,
    "ping": "pong"
}
thmarble@ubuntu 800 :) cat /etc/ansible/hosts
---
demo-machines:
  hosts:
    localhost:
      ansible_user: admin
    vfmc622:
      ansible_user: admin

 thmarble@ubuntu 801 :) ansible demo-machines -m ping
 [WARNING]:  * Failed to parse /etc/ansible/hosts with ini plugin:
/etc/ansible/hosts:5: Expected key=value host variable assignment, got: admin
 [WARNING]: Unable to parse /etc/ansible/hosts as an inventory source
 [WARNING]: No inventory was parsed, only implicit localhost is available
 [WARNING]: Could not match supplied host pattern, ignoring: demo-machines
 [WARNING]: No hosts matched, nothing to do
thmarble@ubuntu 802 :) 
```
@boca OK this bug seems to be specific to Python3 and the YAML format for Inventory WHEN the **ansible_user** key is set. Switching to *.ini format seems to be a workaround:

```
thmarble@ubuntu 806 :) cat /etc/ansible/hosts
[demo-machines]
localhost ansible_user=admin
vfmc622   ansible_user=admin
thmarble@ubuntu 807 :) ansible demo-machines -m ping
vfmc622 | SUCCESS => {
    "changed": false,
    "failed": false,
    "ping": "pong"
}
localhost | SUCCESS => {
    "changed": false,
    "failed": false,
    "ping": "pong"
}
thmarble@ubuntu 808 :) 
```

@tmarble, I'm still waiting or an actual error or an example of what is not working, all you have shown me is either a warning (which seem correct) or a normal debug statement.
@bcoca I have tried to characterize what is not working as `/etc/ansible/hosts` in YAML format fails with "No hosts matched, nothing to do".

The warning "Failed to parse /etc/ansible/hosts with ini plugin" may be correct and even expected when parsing an inventory in YAML format, *however* the detailed debug string 
```
24648 1506359998.23222: Attempting to use plugin yaml (/usr/local/lib/python3.5/dist-packages/ansible/plugins/inventory/yaml.py)
24648 1506359998.23228: /etc/ansible/hosts did not meet yaml requirements
```
provides a hint of a FAILURE of `ansible/plugins/inventory/yaml.py` to properly parse the inventory.

It's odd/inconsistent that (without ANSIBLE_DEBUG=1) failure of `ansible/plugins/inventory/ini.py` manages to bubble up to a WARNING whereas the analogous problem with yaml.py does not.

In an attempt to further debug this it now seems like parsing a YAML file that has the **.yml** extension succeeds, but a file without that extension fails (e.g. /etc/ansible/hosts):

```
thmarble@ubuntu 827 :) cat inventory.yml
local:
  hosts:
    localhost
thmarble@ubuntu 828 :) cat /etc/ansible/hosts
local:
  hosts:
    localhost
thmarble@ubuntu 829 :) diff inventory.yml /etc/ansible/hosts
thmarble@ubuntu 830 :) ansible local -i inventory.yml -m ping
localhost | SUCCESS => {
    "changed": false,
    "failed": false,
    "ping": "pong"
}
thmarble@ubuntu 831 :) ansible local -i /etc/ansible/hosts -m ping
 [WARNING]: Could not match supplied host pattern, ignoring: local
 [WARNING]: No hosts matched, nothing to do
thmarble@ubuntu 832 :) 
```


So, what you are saying, is that `/etc/ansible/hosts` is a YAML inventory, and it isn't picked up as being a YAML inventory.

Whereas if you specify `inventory.yml` which has the same contents as `/etc/ansible/hosts`, everything works fine.
@sivel that is correct. If this is indeed the bug it should be easy to reproduce.
the yaml plugin requires a yaml extension
The same problem is present also in ansible 2.4.0.0:

```
[root@localhost ~]# ansible --version
ansible 2.4.0.0
  config file = /etc/ansible/ansible.cfg
  configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.7/site-packages/ansible
  executable location = /bin/ansible
  python version = 2.7.5 (default, Aug  4 2017, 00:39:18) [GCC 4.8.5 20150623 (Red Hat 4.8.5-16)]
```
```
[root@localhost ~]# rpm -qi ansible
Name        : ansible
Version     : 2.4.0.0
Release     : 1.el7
Architecture: noarch
Install Date: Wed 27 Sep 2017 11:56:55 AM UTC
Group       : Development/Libraries
Size        : 39783704
License     : GPLv3+
Signature   : (none)
Source RPM  : ansible-2.4.0.0-1.el7.src.rpm
Build Date  : Fri 22 Sep 2017 09:46:27 AM UTC
Build Host  : arm64-01.rdu2.centos.org
Relocations : (not relocatable)
Packager    : CBS <cbs@centos.org>
Vendor      : CentOS
URL         : http://ansible.com
Summary     : SSH-based configuration management, deployment, and task execution system
Description :
```

Taking an example from https://github.com/ansible/ansible/blob/devel/examples/hosts.yaml

```
[root@localhost ~]# cat inventory
all:
  hosts:
      green.example.com:
          ansible_ssh_host: 191.168.100.32
          anyvariable: value
      blue.example.com:
      192.168.100.1:
      192.168.100.10:
```

```
[root@localhost ~]# ansible -i inventory all --list-hosts
 [WARNING]:  * Failed to parse /root/inventory with ini plugin: /root/inventory:4: Expected key=value host variable assignment, got: 191.168.100.32

 [WARNING]: Unable to parse /root/inventory as an inventory source

 [WARNING]: No inventory was parsed, only implicit localhost is available

  hosts (3):
    all:
    hosts:
    green.example.com:
```

but

```
[root@localhost ~]# mv inventory inventory.yml
[root@localhost ~]# ansible -i inventory.yaml all --list-hosts
  hosts (4):
    192.168.100.1
    green.example.com
    192.168.100.10
    blue.example.com
```

The yml format is recognized automatically by ansible 2.3.2.0.

```
[root@localhost ~]# ansible --version
ansible 2.3.2.0
  config file = /etc/ansible/ansible.cfg
  configured module search path = Default w/o overrides
  python version = 2.7.5 (default, Aug  4 2017, 00:39:18) [GCC 4.8.5 20150623 (Red Hat 4.8.5-16)]
```

```
[root@localhost ~]# mv -f inventory.yaml inventory
[root@localhost ~]# ansible -i inventory all --list-hosts
  hosts (4):
    192.168.100.1
    green.example.com
    192.168.100.10
    blue.example.com
```

Resolving patch:
diff --git a/lib/ansible/plugins/inventory/yaml.py b/lib/ansible/plugins/inventory/yaml.py
--- a/lib/ansible/plugins/inventory/yaml.py
+++ b/lib/ansible/plugins/inventory/yaml.py
@@ -74,7 +74,7 @@ def verify_file(self, path):
         valid = False
         if super(InventoryModule, self).verify_file(path):
             file_name, ext = os.path.splitext(path)
-            if ext and ext in C.YAML_FILENAME_EXTENSIONS:
+            if not ext or ext in C.YAML_FILENAME_EXTENSIONS:
                 valid = True
         return valid
 


Test patch: