Repository: ansible/molecule

Issue:
Current directory being inadvertently added to ANSIBLE_LIBRARY
<!--- Verify first that your issue is not already reported on GitHub -->
<!--- Do not report bugs before reproducing them with the code of the master branch! -->
<!--- Please also check https://molecule.readthedocs.io/en/latest/faq.html --->
<!--- Please use https://groups.google.com/forum/#!forum/molecule-users for usage questions -->

# Issue Type

- Bug report

# Molecule and Ansible details

```
ansible --version && molecule --version

ansible 2.10.7.post0
  config file = None
  configured module search path = ['/home/mgraves/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/mgraves/git/ansible/lib/ansible
  executable location = /home/mgraves/git/ansible/bin/ansible
  python version = 3.8.8 (default, Mar  5 2021, 11:47:01) [GCC 10.2.1 20210110]
molecule 3.3.0 using python 3.8 
    ansible:2.10.7.post0
    delegated:3.3.0 from molecule
    docker:0.2.4 from molecule_docker
```

Molecule installation method (one of):

- pip

Ansible installation method (one of):

- source

Detail any linters or test runners used:

# Desired Behavior

Molecule should successfully complete.

# Actual Behaviour

```
~/git/ansible_collections/community/kubernetes $ molecule --debug converge -- -vvv

DEBUG    Validating schema /home/mgraves/git/ansible_collections/community/kubernetes/molecule/default/molecule.yml.
INFO     default scenario test matrix: dependency, create, prepare, converge
INFO     Performing prerun...
INFO     Added ANSIBLE_LIBRARY=:plugins/modules
INFO     Added ANSIBLE_COLLECTIONS_PATH=/home/mgraves/git:/home/mgraves/.ansible/collections:/home/mgraves/git:/home/mgraves/.ansible/collections:./.cache/collections
INFO     Running default > dependency
WARNING  Skipping, missing the requirements file.
WARNING  Skipping, missing the requirements file.
INFO     Running default > create
WARNING  Skipping, instances are delegated.
INFO     Running default > prepare
WARNING  Skipping, prepare playbook not configured.
INFO     Running default > converge
DEBUG: ANSIBLE ENVIRONMENT:
ANSIBLE_COLLECTIONS_PATH: /home/mgraves/.cache/molecule/kubernetes/default/collections:/home/mgraves/git:/home/mgraves/.ansible/collections:/usr/share/ansible/collections:/etc/ansible/collections
ANSIBLE_CONFIG: /home/mgraves/.cache/molecule/kubernetes/default/ansible.cfg
ANSIBLE_FILTER_PLUGINS: /home/mgraves/git/ansible/venv/lib/python3.8/site-packages/molecule/provisioner/ansible/plugins/filter:/home/mgraves/.cache/molecule/kubernetes/default/plugins/filter:/home/mgraves/git/ansible_collections/community/kubernetes/plugins/filter:/home/mgraves/.ansible/plugins/filter:/usr/share/ansible/plugins/filter
ANSIBLE_FORCE_COLOR: 'true'
ANSIBLE_HOME: /home/mgraves/git/ansible
ANSIBLE_LIBRARY: /home/mgraves/git/ansible/venv/lib/python3.8/site-packages/molecule/provisioner/ansible/plugins/modules:/home/mgraves/.cache/molecule/kubernetes/default/library:/home/mgraves/git/ansible_collections/community/kubernetes/library:/home/mgraves/.ansible/plugins/modules:/usr/share/ansible/plugins/modules:/home/mgraves/git/ansible_collections/community/kubernetes/:plugins/modules
ANSIBLE_ROLES_PATH: '/home/mgraves/.cache/molecule/kubernetes/default/roles:/home/mgraves/git/ansible_collections/community:/home/mgraves/.ansible/roles:/usr/share/ansible/roles:/etc/ansible/roles:'

DEBUG: MOLECULE ENVIRONMENT:
MOLECULE_DEBUG: 'True'
MOLECULE_DEPENDENCY_NAME: galaxy
MOLECULE_DRIVER_NAME: delegated
MOLECULE_ENV_FILE: /home/mgraves/git/ansible_collections/community/kubernetes/.env.yml
MOLECULE_EPHEMERAL_DIRECTORY: /home/mgraves/.cache/molecule/kubernetes/default
MOLECULE_FILE: /home/mgraves/.cache/molecule/kubernetes/default/molecule.yml
MOLECULE_INSTANCE_CONFIG: /home/mgraves/.cache/molecule/kubernetes/default/instance_config.yml
MOLECULE_INVENTORY_FILE: /home/mgraves/.cache/molecule/kubernetes/default/inventory/ansible_inventory.yml
MOLECULE_PROJECT_DIRECTORY: /home/mgraves/git/ansible_collections/community/kubernetes
MOLECULE_PROVISIONER_NAME: ansible
MOLECULE_SCENARIO_DIRECTORY: /home/mgraves/git/ansible_collections/community/kubernetes/molecule/default
MOLECULE_SCENARIO_NAME: default
MOLECULE_STATE_FILE: /home/mgraves/.cache/molecule/kubernetes/default/state.yml
MOLECULE_VERIFIER_NAME: ansible
MOLECULE_VERIFIER_TEST_DIRECTORY: /home/mgraves/git/ansible_collections/community/kubernetes/molecule/default/tests

DEBUG: SHELL REPLAY:
ANSIBLE_COLLECTIONS_PATH=/home/mgraves/.cache/molecule/kubernetes/default/collections:/home/mgraves/git:/home/mgraves/.ansible/collections:/usr/share/ansible/collections:/etc/ansible/collections ANSIBLE_CONFIG=/home/mgraves/.cache/molecule/kubernetes/default/ansible.cfg ANSIBLE_FILTER_PLUGINS=/home/mgraves/git/ansible/venv/lib/python3.8/site-packages/molecule/provisioner/ansible/plugins/filter:/home/mgraves/.cache/molecule/kubernetes/default/plugins/filter:/home/mgraves/git/ansible_collections/community/kubernetes/plugins/filter:/home/mgraves/.ansible/plugins/filter:/usr/share/ansible/plugins/filter ANSIBLE_FORCE_COLOR=true ANSIBLE_HOME=/home/mgraves/git/ansible ANSIBLE_LIBRARY=/home/mgraves/git/ansible/venv/lib/python3.8/site-packages/molecule/provisioner/ansible/plugins/modules:/home/mgraves/.cache/molecule/kubernetes/default/library:/home/mgraves/git/ansible_collections/community/kubernetes/library:/home/mgraves/.ansible/plugins/modules:/usr/share/ansible/plugins/modules:/home/mgraves/git/ansible_collections/community/kubernetes/:plugins/modules ANSIBLE_ROLES_PATH=/home/mgraves/.cache/molecule/kubernetes/default/roles:/home/mgraves/git/ansible_collections/community:/home/mgraves/.ansible/roles:/usr/share/ansible/roles:/etc/ansible/roles: MOLECULE_DEBUG=True MOLECULE_DEPENDENCY_NAME=galaxy MOLECULE_DRIVER_NAME=delegated MOLECULE_ENV_FILE=/home/mgraves/git/ansible_collections/community/kubernetes/.env.yml MOLECULE_EPHEMERAL_DIRECTORY=/home/mgraves/.cache/molecule/kubernetes/default MOLECULE_FILE=/home/mgraves/.cache/molecule/kubernetes/default/molecule.yml MOLECULE_INSTANCE_CONFIG=/home/mgraves/.cache/molecule/kubernetes/default/instance_config.yml MOLECULE_INVENTORY_FILE=/home/mgraves/.cache/molecule/kubernetes/default/inventory/ansible_inventory.yml MOLECULE_PROJECT_DIRECTORY=/home/mgraves/git/ansible_collections/community/kubernetes MOLECULE_PROVISIONER_NAME=ansible MOLECULE_SCENARIO_DIRECTORY=/home/mgraves/git/ansible_collections/community/kubernetes/molecule/default MOLECULE_SCENARIO_NAME=default MOLECULE_STATE_FILE=/home/mgraves/.cache/molecule/kubernetes/default/state.yml MOLECULE_VERIFIER_NAME=ansible MOLECULE_VERIFIER_TEST_DIRECTORY=/home/mgraves/git/ansible_collections/community/kubernetes/molecule/default/tests

COMMAND: ansible-playbook --diff --inventory /home/mgraves/.cache/molecule/kubernetes/default/inventory --skip-tags molecule-notest,notest -vvv /home/mgraves/git/ansible_collections/community/kubernetes/molecule/default/converge.yml
ansible-playbook 2.10.7.post0
  config file = /home/mgraves/.cache/molecule/kubernetes/default/ansible.cfg
  configured module search path = ['/home/mgraves/git/ansible/venv/lib/python3.8/site-packages/molecule/provisioner/ansible/plugins/modules', '/home/mgraves/.cache/molecule/kubernetes/default/library', '/home/mgraves/git/ansible_collections/community/kubernetes/library', '/home/mgraves/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules', '/home/mgraves/git/ansible_collections/community/kubernetes', '/home/mgraves/git/ansible_collections/community/kubernetes/plugins/modules']
  ansible python module location = /home/mgraves/git/ansible/lib/ansible
  executable location = /home/mgraves/git/ansible/bin/ansible-playbook
  python version = 3.8.8 (default, Mar  5 2021, 11:47:01) [GCC 10.2.1 20210110]
Using /home/mgraves/.cache/molecule/kubernetes/default/ansible.cfg as config file
[WARNING]: running playbook inside collection community.kubernetes
[WARNING]:  * Failed to parse /home/mgraves/.cache/molecule/kubernetes/default/
inventory/ansible_inventory.yml with
ansible_collections.community.kubernetes.plugins.inventory.k8s plugin:
Incorrect plugin name in file: none found
  File "/home/mgraves/git/ansible/lib/ansible/inventory/manager.py", line 289, in parse_source
    plugin.parse(self._inventory, self._loader, source, cache=cache)
  File "/home/mgraves/git/ansible_collections/community/kubernetes/plugins/inventory/k8s.py", line 153, in parse
    config_data = self._read_config_data(path)
  File "/home/mgraves/git/ansible/lib/ansible/plugins/inventory/__init__.py", line 227, in _read_config_data
    raise AnsibleParserError("Incorrect plugin name in file: %s" % config.get('plugin', 'none found'))
[WARNING]: Unable to parse /home/mgraves/.cache/molecule/kubernetes/default/inv
entory/ansible_inventory.yml as an inventory source
[WARNING]: Invalid characters were found in group names but not replaced, use
-vvvv to see details
Parsed /home/mgraves/.cache/molecule/kubernetes/default/inventory/hosts inventory source with ansible_collections.community.kubernetes.plugins.inventory.k8s plugin
Read vars_file 'vars/main.yml'
Read vars_file 'vars/main.yml'
redirecting (type: action) community.kubernetes.k8s to community.kubernetes.k8s_info
redirecting (type: action) community.kubernetes.k8s to community.kubernetes.k8s_info
Read vars_file 'vars/main.yml'
Read vars_file 'vars/main.yml'
Read vars_file 'vars/main.yml'
Read vars_file 'vars/main.yml'
Read vars_file 'vars/main.yml'
Read vars_file 'vars/main.yml'
Read vars_file 'vars/main.yml'
Read vars_file 'vars/main.yml'
Read vars_file 'vars/main.yml'
Read vars_file 'vars/main.yml'
Read vars_file 'vars/main.yml'
redirecting (type: action) community.kubernetes.k8s to community.kubernetes.k8s_info
Skipping callback 'default', as we already have a stdout callback.
Skipping callback 'minimal', as we already have a stdout callback.
Skipping callback 'oneline', as we already have a stdout callback.

PLAYBOOK: converge.yml *********************************************************
3 plays in /home/mgraves/git/ansible_collections/community/kubernetes/molecule/default/converge.yml
Read vars_file 'vars/main.yml'
Read vars_file 'vars/main.yml'
Read vars_file 'vars/main.yml'

PLAY [Converge] ****************************************************************
Read vars_file 'vars/main.yml'

TASK [Gathering Facts] *********************************************************
task path: /home/mgraves/git/ansible_collections/community/kubernetes/molecule/default/converge.yml:2
<127.0.0.1> ESTABLISH LOCAL CONNECTION FOR USER: mgraves
<127.0.0.1> EXEC /bin/sh -c 'echo ~mgraves && sleep 0'
<127.0.0.1> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /home/mgraves/.ansible/tmp `"&& mkdir "` echo /home/mgraves/.ansible/tmp/ansible-tmp-1616596936.7291377-1244769-237862218132468 `" && echo ansible-tmp-1616596936.7291377-1244769-237862218132468="` echo /home/mgraves/.ansible/tmp/ansible-tmp-1616596936.7291377-1244769-237862218132468 `" ) && sleep 0'
Using module file /home/mgraves/git/ansible_collections/community/kubernetes/setup.cfg
<127.0.0.1> EXEC /bin/sh -c 'rm -f -r /home/mgraves/.ansible/tmp/ansible-tmp-1616596936.7291377-1244769-237862218132468/ > /dev/null 2>&1 && sleep 0'
fatal: [localhost]: FAILED! => {
    "msg": "module (ansible.legacy.setup) is missing interpreter line"
}

PLAY RECAP *********************************************************************
localhost                  : ok=0    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0

CRITICAL Ansible return code was 2, command was: ansible-playbook --diff --inventory /home/mgraves/.cache/molecule/kubernetes/default/inventory --skip-tags molecule-notest,notest -vvv /home/mgraves/git/ansible_collections/community/kubernetes/molecule/default/converge.yml
Please give some details of what is actually happening.
Include a [minimum complete verifiable example](https://stackoverflow.com/help/mcve) with
output of running `molecule --debug`.
```
Our test suite started failing with the 3.3.0 version of molecule. The prerun change that was added in #3077 started adding the current directory to `ANSIBLE_LIBRARY`. This can cause ansible to fail when there is a file with the same name as a module as can be seen here where ansible is trying to read `setup.cfg` in our project root as the setup module.

The problem seems to be in https://github.com/ansible-community/molecule/blob/60b68140fb5c650c47019f5db238c0864dbd43ed/src/molecule/provisioner/ansible.py#L943 In our case, after ansible-lint has run `prepare_environment` the `ANSIBLE_LIBRARY` envvar is `:plugin/modules`. I would think calling `abs_path` on this probably not appropriate since this is a colon separated path string and should just be read in unprocessed.


Discussion:

Resolving patch:
diff --git a/src/molecule/provisioner/ansible.py b/src/molecule/provisioner/ansible.py
--- a/src/molecule/provisioner/ansible.py
+++ b/src/molecule/provisioner/ansible.py
@@ -940,7 +940,7 @@ def _get_modules_directories(self):
         )
 
         if os.environ.get("ANSIBLE_LIBRARY"):
-            paths.extend([util.abs_path(os.environ.get("ANSIBLE_LIBRARY"))])
+            paths.extend(map(util.abs_path, os.environ["ANSIBLE_LIBRARY"].split(":")))
 
         return paths
 


Test patch:
diff --git a/src/molecule/test/unit/provisioner/test_ansible.py b/src/molecule/test/unit/provisioner/test_ansible.py
--- a/src/molecule/test/unit/provisioner/test_ansible.py
+++ b/src/molecule/test/unit/provisioner/test_ansible.py
@@ -20,6 +20,7 @@
 
 import collections
 import os
+import re
 
 import pytest
 
@@ -684,22 +685,36 @@ def test_get_plugin_directory(_instance):
     assert ("molecule", "provisioner", "ansible", "plugins") == parts[-4:]
 
 
-def test_get_modules_directories(_instance, monkeypatch):
-    result = _instance._get_modules_directories()[0]
-    parts = pytest.helpers.os_split(result)
-    x = ("molecule", "provisioner", "ansible", "plugins", "modules")
+def test_get_modules_directories_default(_instance, monkeypatch):
+    monkeypatch.delenv("ANSIBLE_LIBRARY", raising=False)
+
+    paths = _instance._get_modules_directories()
+
+    assert len(paths) == 5
+    assert re.search(r"molecule/provisioner/ansible/plugins/modules$", paths[0])
+    assert re.search(r"\.cache/molecule/[^/]+/default/library$", paths[1])
+    assert re.search(r"/library$", paths[2])
+    assert re.search(r"\.ansible/plugins/modules$", paths[3])
+    assert re.search(r"/usr/share/ansible/plugins/modules$", paths[4])
+
+
+def test_get_modules_directories_single_ansible_library(_instance, monkeypatch):
+    monkeypatch.setenv("ANSIBLE_LIBRARY", "/abs/path/lib")
+
+    paths = _instance._get_modules_directories()
+
+    assert len(paths) == 6
+    assert paths[-1] == "/abs/path/lib"
 
-    assert x == parts[-5:]
 
-    lib_prev = os.environ.get("ANSIBLE_LIBRARY")
-    monkeypatch.setenv("ANSIBLE_LIBRARY", "/foo/bar")
-    result = _instance._get_modules_directories()[-1]
-    monkeypatch.setenv("ANSIBLE_LIBRARY", lib_prev if lib_prev else "")
+def test_get_modules_directories_multi_ansible_library(_instance, monkeypatch):
+    monkeypatch.setenv("ANSIBLE_LIBRARY", "relpath/lib:/abs/path/lib")
 
-    env_lib_result_parts = pytest.helpers.os_split(result)
-    env_lib_expected_parts = ("foo", "bar")
+    paths = _instance._get_modules_directories()
 
-    assert env_lib_result_parts == env_lib_expected_parts[-2:]
+    assert len(paths) == 7
+    assert paths[-2].endswith("relpath/lib")
+    assert paths[-1] == "/abs/path/lib"
 
 
 def test_get_filter_plugin_directory(_instance):