summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorToshio Kuratomi <a.badger@gmail.com>2017-05-01 08:52:25 -0700
committerToshio Kuratomi <a.badger@gmail.com>2017-05-01 08:57:31 -0700
commitaf018b75f0c4d2e51be9009e71c8b2083cc21da1 (patch)
tree8d94601f4676ecc3a9c6fa8671b4a18d17e107e9 /test
parent778173ec07fda7dc0fd2b4f3dc8bb892e3a6e1df (diff)
downloadansible-af018b75f0c4d2e51be9009e71c8b2083cc21da1.tar.gz
Add integration test that modules are loaded from the expected locations (#24170)
* Add integration test that modules are loaded from the expected locations * Fix ping module to pass PEP8 (cherry picked from commit 3428f42120bb35f9b46f19326d44497a55f8ccd4)
Diffstat (limited to 'test')
-rw-r--r--test/integration/targets/module_precedence/aliases1
-rw-r--r--test/integration/targets/module_precedence/lib_no_extension/ping69
-rw-r--r--test/integration/targets/module_precedence/lib_with_extension/ping.py69
-rw-r--r--test/integration/targets/module_precedence/modules_test.yml10
-rw-r--r--test/integration/targets/module_precedence/modules_test_envvar.yml11
-rw-r--r--test/integration/targets/module_precedence/modules_test_multiple_roles.yml17
-rw-r--r--test/integration/targets/module_precedence/modules_test_multiple_roles_reverse_order.yml16
-rw-r--r--test/integration/targets/module_precedence/modules_test_role.yml13
-rw-r--r--test/integration/targets/module_precedence/multiple_roles/bar/library/ping.py69
-rw-r--r--test/integration/targets/module_precedence/multiple_roles/bar/tasks/main.yml10
-rw-r--r--test/integration/targets/module_precedence/multiple_roles/foo/library/ping.py69
-rw-r--r--test/integration/targets/module_precedence/multiple_roles/foo/tasks/main.yml10
-rw-r--r--test/integration/targets/module_precedence/roles_no_extension/foo/library/ping69
-rw-r--r--test/integration/targets/module_precedence/roles_no_extension/foo/tasks/main.yml10
-rw-r--r--test/integration/targets/module_precedence/roles_with_extension/foo/library/ping.py69
-rw-r--r--test/integration/targets/module_precedence/roles_with_extension/foo/tasks/main.yml10
-rwxr-xr-xtest/integration/targets/module_precedence/runme.sh30
-rwxr-xr-xtest/sanity/code-smell/shebang.sh1
18 files changed, 553 insertions, 0 deletions
diff --git a/test/integration/targets/module_precedence/aliases b/test/integration/targets/module_precedence/aliases
new file mode 100644
index 0000000000..79d8b9285e
--- /dev/null
+++ b/test/integration/targets/module_precedence/aliases
@@ -0,0 +1 @@
+posix/ci/group3
diff --git a/test/integration/targets/module_precedence/lib_no_extension/ping b/test/integration/targets/module_precedence/lib_no_extension/ping
new file mode 100644
index 0000000000..b5bee2044c
--- /dev/null
+++ b/test/integration/targets/module_precedence/lib_no_extension/ping
@@ -0,0 +1,69 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# (c) 2012, Michael DeHaan <michael.dehaan@gmail.com>
+# (c) 2016, Toshio Kuratomi <tkuratomi@ansible.com>
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+
+
+ANSIBLE_METADATA = {'metadata_version': '1.0',
+ 'status': ['stableinterface'],
+ 'supported_by': 'core'}
+
+
+DOCUMENTATION = '''
+---
+module: ping
+version_added: historical
+short_description: Try to connect to host, verify a usable python and return C(pong) on success.
+description:
+ - A trivial test module, this module always returns C(pong) on successful
+ contact. It does not make sense in playbooks, but it is useful from
+ C(/usr/bin/ansible) to verify the ability to login and that a usable python is configured.
+ - This is NOT ICMP ping, this is just a trivial test module.
+options: {}
+author:
+ - "Ansible Core Team"
+ - "Michael DeHaan"
+'''
+
+EXAMPLES = '''
+# Test we can logon to 'webservers' and execute python with json lib.
+ansible webservers -m ping
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+
+
+def main():
+ module = AnsibleModule(
+ argument_spec=dict(
+ data=dict(required=False, default=None),
+ ),
+ supports_check_mode=True
+ )
+ result = dict(ping='pong')
+ if module.params['data']:
+ if module.params['data'] == 'crash':
+ raise Exception("boom")
+ result['ping'] = module.params['data']
+ result['location'] = 'library'
+ module.exit_json(**result)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/test/integration/targets/module_precedence/lib_with_extension/ping.py b/test/integration/targets/module_precedence/lib_with_extension/ping.py
new file mode 100644
index 0000000000..b5bee2044c
--- /dev/null
+++ b/test/integration/targets/module_precedence/lib_with_extension/ping.py
@@ -0,0 +1,69 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# (c) 2012, Michael DeHaan <michael.dehaan@gmail.com>
+# (c) 2016, Toshio Kuratomi <tkuratomi@ansible.com>
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+
+
+ANSIBLE_METADATA = {'metadata_version': '1.0',
+ 'status': ['stableinterface'],
+ 'supported_by': 'core'}
+
+
+DOCUMENTATION = '''
+---
+module: ping
+version_added: historical
+short_description: Try to connect to host, verify a usable python and return C(pong) on success.
+description:
+ - A trivial test module, this module always returns C(pong) on successful
+ contact. It does not make sense in playbooks, but it is useful from
+ C(/usr/bin/ansible) to verify the ability to login and that a usable python is configured.
+ - This is NOT ICMP ping, this is just a trivial test module.
+options: {}
+author:
+ - "Ansible Core Team"
+ - "Michael DeHaan"
+'''
+
+EXAMPLES = '''
+# Test we can logon to 'webservers' and execute python with json lib.
+ansible webservers -m ping
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+
+
+def main():
+ module = AnsibleModule(
+ argument_spec=dict(
+ data=dict(required=False, default=None),
+ ),
+ supports_check_mode=True
+ )
+ result = dict(ping='pong')
+ if module.params['data']:
+ if module.params['data'] == 'crash':
+ raise Exception("boom")
+ result['ping'] = module.params['data']
+ result['location'] = 'library'
+ module.exit_json(**result)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/test/integration/targets/module_precedence/modules_test.yml b/test/integration/targets/module_precedence/modules_test.yml
new file mode 100644
index 0000000000..ab783fdbaa
--- /dev/null
+++ b/test/integration/targets/module_precedence/modules_test.yml
@@ -0,0 +1,10 @@
+- hosts: localhost
+ gather_facts: no
+ tasks:
+ - name: Use standard ping module
+ ping:
+ register: result
+
+ - assert:
+ that:
+ - '"location" not in result'
diff --git a/test/integration/targets/module_precedence/modules_test_envvar.yml b/test/integration/targets/module_precedence/modules_test_envvar.yml
new file mode 100644
index 0000000000..5b6338a375
--- /dev/null
+++ b/test/integration/targets/module_precedence/modules_test_envvar.yml
@@ -0,0 +1,11 @@
+- hosts: localhost
+ gather_facts: no
+ tasks:
+ - name: Use ping from library path
+ ping:
+ register: result
+
+ - assert:
+ that:
+ - '"location" in result'
+ - 'result["location"] == "library"'
diff --git a/test/integration/targets/module_precedence/modules_test_multiple_roles.yml b/test/integration/targets/module_precedence/modules_test_multiple_roles.yml
new file mode 100644
index 0000000000..855afb7710
--- /dev/null
+++ b/test/integration/targets/module_precedence/modules_test_multiple_roles.yml
@@ -0,0 +1,17 @@
+- hosts: localhost
+ gather_facts: no
+ vars:
+ expected_location: "role: foo"
+ roles:
+ - foo
+ - bar
+
+ tasks:
+ - name: Use ping from role
+ ping:
+ register: result
+
+ - assert:
+ that:
+ - '"location" in result'
+ - 'result["location"] == "{{ expected_location}}"'
diff --git a/test/integration/targets/module_precedence/modules_test_multiple_roles_reverse_order.yml b/test/integration/targets/module_precedence/modules_test_multiple_roles_reverse_order.yml
new file mode 100644
index 0000000000..5c57801566
--- /dev/null
+++ b/test/integration/targets/module_precedence/modules_test_multiple_roles_reverse_order.yml
@@ -0,0 +1,16 @@
+- hosts: localhost
+ gather_facts: no
+ vars:
+ expected_location: "role: bar"
+ roles:
+ - bar
+ - foo
+ tasks:
+ - name: Use ping from role
+ ping:
+ register: result
+
+ - assert:
+ that:
+ - '"location" in result'
+ - 'result["location"] == "{{ expected_location}}"'
diff --git a/test/integration/targets/module_precedence/modules_test_role.yml b/test/integration/targets/module_precedence/modules_test_role.yml
new file mode 100644
index 0000000000..9a71598875
--- /dev/null
+++ b/test/integration/targets/module_precedence/modules_test_role.yml
@@ -0,0 +1,13 @@
+- hosts: localhost
+ gather_facts: no
+ roles:
+ - foo
+ tasks:
+ - name: Use ping from role
+ ping:
+ register: result
+
+ - assert:
+ that:
+ - '"location" in result'
+ - 'result["location"] == "role: foo"'
diff --git a/test/integration/targets/module_precedence/multiple_roles/bar/library/ping.py b/test/integration/targets/module_precedence/multiple_roles/bar/library/ping.py
new file mode 100644
index 0000000000..17f1f810b1
--- /dev/null
+++ b/test/integration/targets/module_precedence/multiple_roles/bar/library/ping.py
@@ -0,0 +1,69 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# (c) 2012, Michael DeHaan <michael.dehaan@gmail.com>
+# (c) 2016, Toshio Kuratomi <tkuratomi@ansible.com>
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+
+
+ANSIBLE_METADATA = {'metadata_version': '1.0',
+ 'status': ['stableinterface'],
+ 'supported_by': 'core'}
+
+
+DOCUMENTATION = '''
+---
+module: ping
+version_added: historical
+short_description: Try to connect to host, verify a usable python and return C(pong) on success.
+description:
+ - A trivial test module, this module always returns C(pong) on successful
+ contact. It does not make sense in playbooks, but it is useful from
+ C(/usr/bin/ansible) to verify the ability to login and that a usable python is configured.
+ - This is NOT ICMP ping, this is just a trivial test module.
+options: {}
+author:
+ - "Ansible Core Team"
+ - "Michael DeHaan"
+'''
+
+EXAMPLES = '''
+# Test we can logon to 'webservers' and execute python with json lib.
+ansible webservers -m ping
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+
+
+def main():
+ module = AnsibleModule(
+ argument_spec=dict(
+ data=dict(required=False, default=None),
+ ),
+ supports_check_mode=True
+ )
+ result = dict(ping='pong')
+ if module.params['data']:
+ if module.params['data'] == 'crash':
+ raise Exception("boom")
+ result['ping'] = module.params['data']
+ result['location'] = 'role: bar'
+ module.exit_json(**result)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/test/integration/targets/module_precedence/multiple_roles/bar/tasks/main.yml b/test/integration/targets/module_precedence/multiple_roles/bar/tasks/main.yml
new file mode 100644
index 0000000000..52c3402013
--- /dev/null
+++ b/test/integration/targets/module_precedence/multiple_roles/bar/tasks/main.yml
@@ -0,0 +1,10 @@
+---
+- name: Use ping from inside foo role
+ ping:
+ register: result
+
+- name: Make sure that we used the ping module from the foo role
+ assert:
+ that:
+ - '"location" in result'
+ - 'result["location"] == "{{ expected_location }}"'
diff --git a/test/integration/targets/module_precedence/multiple_roles/foo/library/ping.py b/test/integration/targets/module_precedence/multiple_roles/foo/library/ping.py
new file mode 100644
index 0000000000..d12c6ce26e
--- /dev/null
+++ b/test/integration/targets/module_precedence/multiple_roles/foo/library/ping.py
@@ -0,0 +1,69 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# (c) 2012, Michael DeHaan <michael.dehaan@gmail.com>
+# (c) 2016, Toshio Kuratomi <tkuratomi@ansible.com>
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+
+
+ANSIBLE_METADATA = {'metadata_version': '1.0',
+ 'status': ['stableinterface'],
+ 'supported_by': 'core'}
+
+
+DOCUMENTATION = '''
+---
+module: ping
+version_added: historical
+short_description: Try to connect to host, verify a usable python and return C(pong) on success.
+description:
+ - A trivial test module, this module always returns C(pong) on successful
+ contact. It does not make sense in playbooks, but it is useful from
+ C(/usr/bin/ansible) to verify the ability to login and that a usable python is configured.
+ - This is NOT ICMP ping, this is just a trivial test module.
+options: {}
+author:
+ - "Ansible Core Team"
+ - "Michael DeHaan"
+'''
+
+EXAMPLES = '''
+# Test we can logon to 'webservers' and execute python with json lib.
+ansible webservers -m ping
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+
+
+def main():
+ module = AnsibleModule(
+ argument_spec=dict(
+ data=dict(required=False, default=None),
+ ),
+ supports_check_mode=True
+ )
+ result = dict(ping='pong')
+ if module.params['data']:
+ if module.params['data'] == 'crash':
+ raise Exception("boom")
+ result['ping'] = module.params['data']
+ result['location'] = 'role: foo'
+ module.exit_json(**result)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/test/integration/targets/module_precedence/multiple_roles/foo/tasks/main.yml b/test/integration/targets/module_precedence/multiple_roles/foo/tasks/main.yml
new file mode 100644
index 0000000000..52c3402013
--- /dev/null
+++ b/test/integration/targets/module_precedence/multiple_roles/foo/tasks/main.yml
@@ -0,0 +1,10 @@
+---
+- name: Use ping from inside foo role
+ ping:
+ register: result
+
+- name: Make sure that we used the ping module from the foo role
+ assert:
+ that:
+ - '"location" in result'
+ - 'result["location"] == "{{ expected_location }}"'
diff --git a/test/integration/targets/module_precedence/roles_no_extension/foo/library/ping b/test/integration/targets/module_precedence/roles_no_extension/foo/library/ping
new file mode 100644
index 0000000000..d12c6ce26e
--- /dev/null
+++ b/test/integration/targets/module_precedence/roles_no_extension/foo/library/ping
@@ -0,0 +1,69 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# (c) 2012, Michael DeHaan <michael.dehaan@gmail.com>
+# (c) 2016, Toshio Kuratomi <tkuratomi@ansible.com>
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+
+
+ANSIBLE_METADATA = {'metadata_version': '1.0',
+ 'status': ['stableinterface'],
+ 'supported_by': 'core'}
+
+
+DOCUMENTATION = '''
+---
+module: ping
+version_added: historical
+short_description: Try to connect to host, verify a usable python and return C(pong) on success.
+description:
+ - A trivial test module, this module always returns C(pong) on successful
+ contact. It does not make sense in playbooks, but it is useful from
+ C(/usr/bin/ansible) to verify the ability to login and that a usable python is configured.
+ - This is NOT ICMP ping, this is just a trivial test module.
+options: {}
+author:
+ - "Ansible Core Team"
+ - "Michael DeHaan"
+'''
+
+EXAMPLES = '''
+# Test we can logon to 'webservers' and execute python with json lib.
+ansible webservers -m ping
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+
+
+def main():
+ module = AnsibleModule(
+ argument_spec=dict(
+ data=dict(required=False, default=None),
+ ),
+ supports_check_mode=True
+ )
+ result = dict(ping='pong')
+ if module.params['data']:
+ if module.params['data'] == 'crash':
+ raise Exception("boom")
+ result['ping'] = module.params['data']
+ result['location'] = 'role: foo'
+ module.exit_json(**result)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/test/integration/targets/module_precedence/roles_no_extension/foo/tasks/main.yml b/test/integration/targets/module_precedence/roles_no_extension/foo/tasks/main.yml
new file mode 100644
index 0000000000..985fc34115
--- /dev/null
+++ b/test/integration/targets/module_precedence/roles_no_extension/foo/tasks/main.yml
@@ -0,0 +1,10 @@
+---
+- name: Use ping from inside foo role
+ ping:
+ register: result
+
+- name: Make sure that we used the ping module from the foo role
+ assert:
+ that:
+ - '"location" in result'
+ - 'result["location"] == "role: foo"'
diff --git a/test/integration/targets/module_precedence/roles_with_extension/foo/library/ping.py b/test/integration/targets/module_precedence/roles_with_extension/foo/library/ping.py
new file mode 100644
index 0000000000..d12c6ce26e
--- /dev/null
+++ b/test/integration/targets/module_precedence/roles_with_extension/foo/library/ping.py
@@ -0,0 +1,69 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# (c) 2012, Michael DeHaan <michael.dehaan@gmail.com>
+# (c) 2016, Toshio Kuratomi <tkuratomi@ansible.com>
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+
+
+ANSIBLE_METADATA = {'metadata_version': '1.0',
+ 'status': ['stableinterface'],
+ 'supported_by': 'core'}
+
+
+DOCUMENTATION = '''
+---
+module: ping
+version_added: historical
+short_description: Try to connect to host, verify a usable python and return C(pong) on success.
+description:
+ - A trivial test module, this module always returns C(pong) on successful
+ contact. It does not make sense in playbooks, but it is useful from
+ C(/usr/bin/ansible) to verify the ability to login and that a usable python is configured.
+ - This is NOT ICMP ping, this is just a trivial test module.
+options: {}
+author:
+ - "Ansible Core Team"
+ - "Michael DeHaan"
+'''
+
+EXAMPLES = '''
+# Test we can logon to 'webservers' and execute python with json lib.
+ansible webservers -m ping
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+
+
+def main():
+ module = AnsibleModule(
+ argument_spec=dict(
+ data=dict(required=False, default=None),
+ ),
+ supports_check_mode=True
+ )
+ result = dict(ping='pong')
+ if module.params['data']:
+ if module.params['data'] == 'crash':
+ raise Exception("boom")
+ result['ping'] = module.params['data']
+ result['location'] = 'role: foo'
+ module.exit_json(**result)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/test/integration/targets/module_precedence/roles_with_extension/foo/tasks/main.yml b/test/integration/targets/module_precedence/roles_with_extension/foo/tasks/main.yml
new file mode 100644
index 0000000000..985fc34115
--- /dev/null
+++ b/test/integration/targets/module_precedence/roles_with_extension/foo/tasks/main.yml
@@ -0,0 +1,10 @@
+---
+- name: Use ping from inside foo role
+ ping:
+ register: result
+
+- name: Make sure that we used the ping module from the foo role
+ assert:
+ that:
+ - '"location" in result'
+ - 'result["location"] == "role: foo"'
diff --git a/test/integration/targets/module_precedence/runme.sh b/test/integration/targets/module_precedence/runme.sh
new file mode 100755
index 0000000000..a9af3ca2bc
--- /dev/null
+++ b/test/integration/targets/module_precedence/runme.sh
@@ -0,0 +1,30 @@
+#!/usr/bin/env bash
+
+set -eux
+
+# Standard ping module
+ansible-playbook modules_test.yml -i ../../inventory -v "$@"
+
+# Library path ping module
+ANSIBLE_LIBRARY=$(pwd)/lib_with_extension ansible-playbook modules_test_envvar.yml -i ../../inventory -v "$@"
+ANSIBLE_LIBRARY=$(pwd)/lib_no_extension ansible-playbook modules_test_envvar.yml -i ../../inventory -v "$@"
+
+# ping module from role
+ANSIBLE_ROLES_PATH=$(pwd)/roles_with_extension ansible-playbook modules_test_role.yml -i ../../inventory -v "$@"
+ANSIBLE_ROLES_PATH=$(pwd)/roles_no_extension ansible-playbook modules_test_role.yml -i ../../inventory -v "$@"
+
+# ping module from role when there's a library path module too
+ANSIBLE_LIBRARY=$(pwd)/lib_no_extension ANSIBLE_ROLES_PATH=$(pwd)/roles_with_extension ansible-playbook modules_test_role.yml -i ../../inventory -v "$@"
+ANSIBLE_LIBRARY=$(pwd)/lib_with_extension ANSIBLE_ROLES_PATH=$(pwd)/roles_with_extension ansible-playbook modules_test_role.yml -i ../../inventory -v "$@"
+ANSIBLE_LIBRARY=$(pwd)/lib_no_extension ANSIBLE_ROLES_PATH=$(pwd)/roles_no_extension ansible-playbook modules_test_role.yml -i ../../inventory -v "$@"
+ANSIBLE_LIBRARY=$(pwd)/lib_with_extension ANSIBLE_ROLES_PATH=$(pwd)/roles_no_extension ansible-playbook modules_test_role.yml -i ../../inventory -v "$@"
+
+# ping module in multiple roles: Note that this will use the first module found
+# which is the current way things work but may not be the best way
+ANSIBLE_LIBRARY=$(pwd)/lib_no_extension ANSIBLE_ROLES_PATH=$(pwd)/multiple_roles ansible-playbook modules_test_multiple_roles.yml -i ../../inventory -v "$@"
+ANSIBLE_LIBRARY=$(pwd)/lib_with_extension ANSIBLE_ROLES_PATH=$(pwd)/multiple_roles ansible-playbook modules_test_multiple_roles.yml -i ../../inventory -v "$@"
+ANSIBLE_LIBRARY=$(pwd)/lib_no_extension ANSIBLE_ROLES_PATH=$(pwd)/multiple_roles ansible-playbook modules_test_multiple_roles.yml -i ../../inventory -v "$@"
+ANSIBLE_LIBRARY=$(pwd)/lib_with_extension ANSIBLE_ROLES_PATH=$(pwd)/multiple_roles ansible-playbook modules_test_multiple_roles.yml -i ../../inventory -v "$@"
+
+# And prove that with multiple roles, it's the order the roles are listed in the play that matters
+ANSIBLE_LIBRARY=$(pwd)/lib_with_extension ANSIBLE_ROLES_PATH=$(pwd)/multiple_roles ansible-playbook modules_test_multiple_roles_reverse_order.yml -i ../../inventory -v "$@"
diff --git a/test/sanity/code-smell/shebang.sh b/test/sanity/code-smell/shebang.sh
index 0bc77b818d..76d72c1ff9 100755
--- a/test/sanity/code-smell/shebang.sh
+++ b/test/sanity/code-smell/shebang.sh
@@ -7,6 +7,7 @@ grep '^#!' -rIn . \
-e '^\./lib/ansible/modules/' \
-e '^\./test/integration/targets/[^/]*/library/[^/]*:#!powershell$' \
-e '^\./test/integration/targets/[^/]*/library/[^/]*:#!/usr/bin/python$' \
+ -e '^\./test/integration/targets/module_precedence/.*lib.*:#!/usr/bin/python$' \
-e '^\./hacking/cherrypick.py:#!/usr/bin/env python3$' \
-e ':#!/bin/sh$' \
-e ':#!/bin/bash( -[eux]|$)' \