generated from ansible-collections/collection_template
-
Notifications
You must be signed in to change notification settings - Fork 25
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix import logic trying to load incorrect module (#102)
Fix import logic trying to load incorrect module SUMMARY There is currently a bug in the import logic that manifests when two Ansible modules try to load a python module from somewhere in module_utils. If the python module shares the same name as the second (or subsequent) Ansible modules, turbo mode will attempt to load the python module instead of the Ansible module. This fixes the logic by removing the meta_path modification, which was the root of the problem. Instead, it keeps the sys.path modification as before, but attempts to reload any ansible_collection package modules. We can't reload every module as this would overwrite any shared state in the module cache, defeating the whole purpose of turbo mode. By reloading only the package modules we force it to reexamine its contents, which should now be pointing to the new zip archive since we changed the loader for the package module. One caveat to this is that if shared state were being stored in a package's __init__.py, it would be written over from the package reload. This can be worked around by conditionally defining any shared state in __init__.py with something like: try: state except NameError: state = {} ISSUE TYPE Bugfix Pull Request COMPONENT NAME ADDITIONAL INFORMATION The underlying problem with the current implementation is that it adds a zipimporter to the meta_path for every loaded module in the ansible_collections namespace. A zipimporter only examines that last portion of the module fullname. This can be seen in a simple example. Assuming a zip archive that looks like: foo.zip |-- foo |-- __init__.py |-- a | |-- __init__.py | |-- c.py |-- b |-- __init__.py |-- c.py Now, create a zipimporter for this, pointing to a subpackage and see that it loads the wrong module: loader = zipimporter("foo.zip/foo/a") mod = loader.load_module("foo.b.c") assert mod.__name__ == "foo.b.c" # True assert mod.__file__ == "foo.zip/foo/a/c.py" # True By adding zipimporters to the meta_path, when we try to load a module that isn't yet in the module cache, we add finders that will load the wrong module. This is a problem, for example, when you have a collection that looks like: collection/plugins/modules/a.py collection/plugins/modules/b.py collection/plugins/module_utils/b.py If modules a and b both import b from module_utils, a playbook that first runs module a and then runs module b will fail with an error that it can't find main(), because in the second task it has loaded module_utils/b.py instead of modules/b.py. It's not enough to just change the __path__ on a package module that has already been imported. This is only examined the first time a package is loaded. When the package is loaded any modules inside __path__ are added as attributes to the package module. Subsequent attempts to access a new module in that package that isn't in the module cache will fail because it is only checking package's current attributes. We have to reload the package modules to be able to load any new modules that may now be in that package namespace. As stated above, this does mean any shared state held on the package (__init__.py) will be overwritten. I can't see a perfect solution for this, but I think this change is the best one. Closes: ansible-collections/vmware.vmware_rest#308 Reviewed-by: Gonéri Le Bouder <[email protected]> Reviewed-by: None <None>
- Loading branch information
Showing
11 changed files
with
98 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
--- | ||
bugfixes: | ||
- fix turbo mode loading incorrect module (https://github.com/ansible-collections/cloud.common/pull/102). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
# This module is part of the test suite to check the import logic of turbo mode |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
#!/usr/bin/python | ||
# -*- coding: utf-8 -*- | ||
|
||
# Copyright: (C) 2022, Red Hat | ||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) | ||
|
||
DOCUMENTATION = r""" | ||
--- | ||
module: turbo_import | ||
short_description: A demo module to test import logic for turbo mode | ||
version_added: "1.0.0" | ||
description: | ||
- "This module tests the import logic for turbo mode." | ||
author: | ||
- Mike Graves (@gravesm) | ||
""" | ||
|
||
EXAMPLES = r""" | ||
- name: Run the module | ||
cloud.common.turbo_import: | ||
""" | ||
|
||
|
||
from ansible_collections.cloud.common.plugins.module_utils.turbo.module import ( | ||
AnsibleTurboModule as AnsibleModule, | ||
) | ||
|
||
|
||
def run_module(): | ||
module = AnsibleModule(argument_spec={}) | ||
module.collection_name = "cloud.common" | ||
module.exit_json(changed=False) | ||
|
||
|
||
def main(): | ||
from ansible_collections.cloud.common.plugins.module_utils import turbo_demo | ||
|
||
run_module() | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
- cloud.common.turbo_import: | ||
|
||
- cloud.common.turbo_demo: | ||
with_sequence: count=10 | ||
register: _result | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters