Repository: ansible/ansible

Issue:
If an inventory script throws an error, don't try to parse it as an ini
##### ISSUE TYPE
- Bugfix Pull Request
##### ANSIBLE VERSION

```
ansible 2.2.0
  config file = /home/ec2-user/repos/infosec-ansible/ansible.cfg
  configured module search path = Default w/o overrides
```
##### SUMMARY

It's a script. We ran it and and threw and error; no need to be naive and hope against hope it was really an ini file. Most of the time this is just going to result in another indecipherable 'Error parsing host definition' message that obscures the initial script failure.
##### Before:

```
(ansible-env)[ec2-user@l257387-vm infosec-ansible]$ ansible localhost -m ping
ERROR! Inventory script (/home/ec2-user/repos/infosec-ansible/inventory/ec2.py) had an execution error: ERROR: "Error connecting to AWS backend.
Request has expired", while: getting EC2 instances
/home/ec2-user/repos/infosec-ansible/inventory/ec2.py:3: Error parsing host definition ''''': No closing quotation
(ansible-env)[ec2-user@l257387-vm infosec-ansible]$ head -n 3 /home/ec2-user/repos/infosec-ansible/inventory/ec2.py
#!/usr/bin/env python

'''
```
##### After:

```
(ansible-env)[ec2-user@l257387-vm infosec-ansible]$ ansible localhost -m ping
ERROR! Inventory script (/home/ec2-user/repos/infosec-ansible/inventory/ec2.py) had an execution error: ERROR: "Error connecting to AWS backend.
Request has expired", while: getting EC2 instances
```



Discussion:
sadly many users have their inventory set as executable and cannot change this, so we do 'best effort' and if the script execution fails we try to read as an INI.

since we cannot really determine the difference or which type of inventory should have succeeded we present all the errors and let the user determine which one applies.

As per above, I'm going to close this ticket as we cannot really do what you ask w/o breaking existing setups.

@bcoca would you consider this if I added an additional check for 'shebang_present' when skipping ini handling for failed scripts? Valid ini files, even if executable, would not likely start with a shebang.

that would be good

@bcoca Updated and squashed.


Resolving patch:
diff --git a/lib/ansible/inventory/dir.py b/lib/ansible/inventory/dir.py
--- a/lib/ansible/inventory/dir.py
+++ b/lib/ansible/inventory/dir.py
@@ -65,7 +65,7 @@ def get_file_parser(hostsfile, groups, loader):
         myerr.append("The file %s looks like it should be an executable inventory script, but is not marked executable. Perhaps you want to correct this with `chmod +x %s`?" % (hostsfile, hostsfile))
 
     # YAML/JSON
-    if not processed and os.path.splitext(hostsfile)[-1] in C.YAML_FILENAME_EXTENSIONS:
+    if not processed and not shebang_present and os.path.splitext(hostsfile)[-1] in C.YAML_FILENAME_EXTENSIONS:
         try:
             parser = InventoryYAMLParser(loader=loader, groups=groups, filename=hostsfile)
             processed = True
@@ -73,7 +73,7 @@ def get_file_parser(hostsfile, groups, loader):
             myerr.append(str(e))
 
     # ini
-    if not processed:
+    if not processed and not shebang_present:
         try:
             parser = InventoryINIParser(loader=loader, groups=groups, filename=hostsfile)
             processed = True


Test patch: