[module_utils.distro] Fall back to bundled (#74229)
Change: - When a "distro" package exists in PYTHONPATH but isn't what we expect, fall back to our own vendored one and use it. This prevents a traceback if someone has some random thing that provides "distro" but isn't actually the "distro" library we need. Test Plan: - new tests Tickets: - Fixes #74228 Signed-off-by: Rick Elrod <rick@elrod.me> * nuke playbook test file Signed-off-by: Rick Elrod <rick@elrod.me> * test fixes Signed-off-by: Rick Elrod <rick@elrod.me>
This commit is contained in:
parent
aae5bc5b9e
commit
fa0bccf6a1
5 changed files with 39 additions and 0 deletions
2
changelogs/fragments/nonstandard-distro-fallback.yml
Normal file
2
changelogs/fragments/nonstandard-distro-fallback.yml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
minor_changes:
|
||||||
|
- module_utils distro - when a 'distro' package/module is in PYTHONPATH but isn't the real 'distro' package/module that we expect, gracefully fall back to our own bundled distro.
|
|
@ -32,15 +32,25 @@ _BUNDLED_METADATA = {"pypi_name": "distro", "version": "1.5.0"}
|
||||||
|
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
import types
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import distro as _system_distro
|
import distro as _system_distro
|
||||||
except ImportError:
|
except ImportError:
|
||||||
_system_distro = None
|
_system_distro = None
|
||||||
|
else:
|
||||||
|
# There could be a 'distro' package/module that isn't what we expect, on the
|
||||||
|
# PYTHONPATH. Rather than erroring out in this case, just fall back to ours.
|
||||||
|
# We require more functions than distro.id(), but this is probably a decent
|
||||||
|
# test that we have something we can reasonably use.
|
||||||
|
if not hasattr(_system_distro, 'id') or \
|
||||||
|
not isinstance(_system_distro.id, types.FunctionType):
|
||||||
|
_system_distro = None
|
||||||
|
|
||||||
if _system_distro:
|
if _system_distro:
|
||||||
distro = _system_distro
|
distro = _system_distro
|
||||||
else:
|
else:
|
||||||
# Our bundled copy
|
# Our bundled copy
|
||||||
from ansible.module_utils.distro import _distro as distro
|
from ansible.module_utils.distro import _distro as distro
|
||||||
|
|
||||||
sys.modules['ansible.module_utils.distro'] = distro
|
sys.modules['ansible.module_utils.distro'] = distro
|
||||||
|
|
1
test/integration/targets/module_utils_distro/aliases
Normal file
1
test/integration/targets/module_utils_distro/aliases
Normal file
|
@ -0,0 +1 @@
|
||||||
|
shippable/posix/group3
|
|
@ -0,0 +1,2 @@
|
||||||
|
dependencies:
|
||||||
|
- setup_remote_tmp_dir
|
24
test/integration/targets/module_utils_distro/runme.sh
Executable file
24
test/integration/targets/module_utils_distro/runme.sh
Executable file
|
@ -0,0 +1,24 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -eux
|
||||||
|
|
||||||
|
# Ensure that when a non-distro 'distro' package is in PYTHONPATH, we fallback
|
||||||
|
# to our bundled one.
|
||||||
|
new_pythonpath="$OUTPUT_DIR/pythonpath"
|
||||||
|
mkdir -p "$new_pythonpath/distro"
|
||||||
|
touch "$new_pythonpath/distro/__init__.py"
|
||||||
|
|
||||||
|
export PYTHONPATH="$new_pythonpath:$PYTHONPATH"
|
||||||
|
|
||||||
|
# Sanity test to make sure the above worked
|
||||||
|
set +e
|
||||||
|
distro_id_fail="$(python -c 'import distro; distro.id' 2>&1)"
|
||||||
|
set -e
|
||||||
|
grep -q "AttributeError:.*has no attribute 'id'" <<< "$distro_id_fail"
|
||||||
|
|
||||||
|
# ansible.module_utils.common.sys_info imports distro, and itself gets imported
|
||||||
|
# in DataLoader, so all we have to do to test the fallback is run `ansible`.
|
||||||
|
ansirun="$(ansible -i ../../inventory -a "echo \$PYTHONPATH" localhost)"
|
||||||
|
grep -q "$new_pythonpath" <<< "$ansirun"
|
||||||
|
|
||||||
|
rm -rf "$new_pythonpath"
|
Loading…
Reference in a new issue