Repository: ansible/ansible

Issue:
ansible failed if (other?) version of ansible installed on target host
##### ISSUE TYPE
- Bug Report
##### ANSIBLE VERSION

```
ansible 2.1.0.0
  config file = ansible.cfg
  configured module search path = Default w/o overrides
```
##### SUMMARY

ansible cannot execute modules on target host, if other version of ansible installed on it
##### STEPS TO REPRODUCE

```
target: sudo pip install ansible
ansible -m ping target
```
##### ACTUAL RESULTS

```
target | FAILED! => {
    "changed": false,
    "failed": true,
    "msg": "Error: Module unable to locate ANSIBLE_MODULE_ARGS and ANSIBLE_MODULE_CONSTANTS in json data from stdin.  Unable to figure out what parameters were passed"
}
```



Discussion:
I'm unable to reproduce this.

```
$ ansible --version                 [stable-2.1]  (15:56:23)
ansible 2.1.0.0
  config file = /etc/ansible/ansible.cfg
  configured module search path = Default w/o overrides
$ ansible -m ping -i 'fedora22-test,' all
fedora22-test | SUCCESS => {
    "changed": false, 
    "ping": "pong"
```

I've tried with pip installs of ansible==2.1.0, ansible==2.0.2.0, and ansible==1.9.6 on the remote machines.

This is a problem that may have occurred with git checkouts of ansible before 2.1.0 final, can you verify what versions of ansible are present on your controller and targets when you run this?

I have ansible 2.1.0.0 release on my controller machine

on the target it says "ansible 2.2.0", i guess it's snapshot from ~ 4 May 2016

How is the snapshot installed?

i found in bash_history:

```
git clone https://github.com/ansible/ansible.git
cd ansible/
sudo make install
```

git describe in this workdir says:
v2.0.0-0.5.beta3-2194-g56ba103

which ansible -> /usr/local/bin/ansible

ls -l /usr/local/lib/python2.7/dist-packages

```
total 12
drwxr-sr-x 4 root staff 4096 May  4 22:48 ansible-2.2.0-py2.7.egg
-rw-r--r-- 1 root staff  244 May  4 22:17 easy-install.pth
-rw-r--r-- 1 root staff   33 May  4 22:48 setuptools.pth
```

cat easy-install.pth

```
import sys; sys.__plen = len(sys.path)
./ansible-2.2.0-py2.7.egg
/usr/lib/python2.7/dist-packages
import sys; new=sys.path[sys.__plen:]; del sys.path[sys.__plen:]; p=getattr(sys,'__egginsert',0); sys.path[p:p]=new; sys.__egginsert = p+len(new)
```

Reproduced by installing the way you specified... I think it has to do with setuptools doing its own path munging :-(  Looking into what we can do about that.

Yeah, it's the easy-install.pth that's messing things up.  That .pth file is injecting ansible-2.2.0-py2.7.egg into the path earlier than anything that we've already done.  setuptools is the worst :-(


Resolving patch:
diff --git a/lib/ansible/executor/module_common.py b/lib/ansible/executor/module_common.py
--- a/lib/ansible/executor/module_common.py
+++ b/lib/ansible/executor/module_common.py
@@ -270,18 +270,33 @@ def debug(command, zipped_mod, json_params):
         # remote_tmpdir and this module executing under async.  So we cannot
         # store this in remote_tmpdir (use system tempdir instead)
         temp_path = tempfile.mkdtemp(prefix='ansible_')
+
         zipped_mod = os.path.join(temp_path, 'ansible_modlib.zip')
         modlib = open(zipped_mod, 'wb')
         modlib.write(base64.b64decode(ZIPDATA))
         modlib.close()
+
         if len(sys.argv) == 2:
             exitcode = debug(sys.argv[1], zipped_mod, ZIPLOADER_PARAMS)
         else:
-            z = zipfile.ZipFile(zipped_mod)
+            z = zipfile.ZipFile(zipped_mod, mode='r')
             module = os.path.join(temp_path, 'ansible_module_%(ansible_module)s.py')
             f = open(module, 'wb')
             f.write(z.read('ansible_module_%(ansible_module)s.py'))
             f.close()
+
+            # When installed via setuptools (including python setup.py install),
+            # ansible may be installed with an easy-install.pth file.  That file
+            # may load the system-wide install of ansible rather than the one in
+            # the module.  sitecustomize is the only way to override that setting.
+            z = zipfile.ZipFile(zipped_mod, mode='a')
+            # py3: zipped_mod will be text, py2: it's bytes.  Need bytes at the end
+            z = zipfile.ZipFile(zipped_mod, mode='a')
+            sitecustomize = u'import sys\\nsys.path.insert(0,"%%s")\\n' %%  zipped_mod
+            sitecustomize = sitecustomize.encode('utf-8')
+            z.writestr('sitecustomize.py', sitecustomize)
+            z.close()
+
             exitcode = invoke_module(module, zipped_mod, ZIPLOADER_PARAMS)
     finally:
         try:


Test patch: