Updates to interpreter discovery for 2.17 (#82420)

pull/82409/merge
Matt Martz 4 months ago committed by GitHub
parent 4bcc27ca99
commit 5566a655ae
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,2 @@
minor_changes:
- Interpreter Discovery - Remove hardcoded references to specific python interpreters to use for certain distro versions, and modify logic for python3 to become the default.

@ -1553,18 +1553,9 @@ INTERPRETER_PYTHON:
_INTERPRETER_PYTHON_DISTRO_MAP: _INTERPRETER_PYTHON_DISTRO_MAP:
name: Mapping of known included platform pythons for various Linux distros name: Mapping of known included platform pythons for various Linux distros
default: default:
redhat: # Entry only for testing
'6': /usr/bin/python ansible test:
'8': /usr/libexec/platform-python '99': /usr/bin/python99
'9': /usr/bin/python3
debian:
'8': /usr/bin/python
'10': /usr/bin/python3
fedora:
'23': /usr/bin/python3
ubuntu:
'14': /usr/bin/python
'16': /usr/bin/python3
version_added: "2.8" version_added: "2.8"
# FUTURE: add inventory override once we're sure it can't be abused by a rogue target # FUTURE: add inventory override once we're sure it can't be abused by a rogue target
# FUTURE: add a platform layer to the map so we could use for, eg, freebsd/macos/etc? # FUTURE: add a platform layer to the map so we could use for, eg, freebsd/macos/etc?
@ -1578,9 +1569,7 @@ INTERPRETER_PYTHON_FALLBACK:
- python3.8 - python3.8
- python3.7 - python3.7
- /usr/bin/python3 - /usr/bin/python3
- /usr/libexec/platform-python - python3
- /usr/bin/python
- python
vars: vars:
- name: ansible_interpreter_python_fallback - name: ansible_interpreter_python_fallback
type: list type: list

@ -53,7 +53,7 @@ def discover_interpreter(action, interpreter_name, discovery_mode, task_vars):
host = task_vars.get('inventory_hostname', 'unknown') host = task_vars.get('inventory_hostname', 'unknown')
res = None res = None
platform_type = 'unknown' platform_type = 'unknown'
found_interpreters = [u'/usr/bin/python'] # fallback value found_interpreters = [u'/usr/bin/python3'] # fallback value
is_auto_legacy = discovery_mode.startswith('auto_legacy') is_auto_legacy = discovery_mode.startswith('auto_legacy')
is_silent = discovery_mode.endswith('_silent') is_silent = discovery_mode.endswith('_silent')
@ -89,7 +89,7 @@ def discover_interpreter(action, interpreter_name, discovery_mode, task_vars):
action._discovery_warnings.append(u'No python interpreters found for ' action._discovery_warnings.append(u'No python interpreters found for '
u'host {0} (tried {1})'.format(host, bootstrap_python_list)) u'host {0} (tried {1})'.format(host, bootstrap_python_list))
# this is lame, but returning None or throwing an exception is uglier # this is lame, but returning None or throwing an exception is uglier
return u'/usr/bin/python' return u'/usr/bin/python3'
if platform_type != 'linux': if platform_type != 'linux':
raise NotImplementedError('unsupported platform for extended discovery: {0}'.format(to_native(platform_type))) raise NotImplementedError('unsupported platform for extended discovery: {0}'.format(to_native(platform_type)))
@ -106,7 +106,6 @@ def discover_interpreter(action, interpreter_name, discovery_mode, task_vars):
platform_info = json.loads(res.get('stdout')) platform_info = json.loads(res.get('stdout'))
distro, version = _get_linux_distro(platform_info) distro, version = _get_linux_distro(platform_info)
if not distro or not version: if not distro or not version:
raise NotImplementedError('unable to get Linux distribution/version info') raise NotImplementedError('unable to get Linux distribution/version info')
@ -120,15 +119,15 @@ def discover_interpreter(action, interpreter_name, discovery_mode, task_vars):
# provide a transition period for hosts that were using /usr/bin/python previously (but shouldn't have been) # provide a transition period for hosts that were using /usr/bin/python previously (but shouldn't have been)
if is_auto_legacy: if is_auto_legacy:
if platform_interpreter != u'/usr/bin/python' and u'/usr/bin/python' in found_interpreters: if platform_interpreter != u'/usr/bin/python3' and u'/usr/bin/python3' in found_interpreters:
if not is_silent: if not is_silent:
action._discovery_warnings.append( action._discovery_warnings.append(
u"Distribution {0} {1} on host {2} should use {3}, but is using " u"Distribution {0} {1} on host {2} should use {3}, but is using "
u"/usr/bin/python for backward compatibility with prior Ansible releases. " u"/usr/bin/python3 for backward compatibility with prior Ansible releases. "
u"See {4} for more information" u"See {4} for more information"
.format(distro, version, host, platform_interpreter, .format(distro, version, host, platform_interpreter,
get_versioned_doclink('reference_appendices/interpreter_discovery.html'))) get_versioned_doclink('reference_appendices/interpreter_discovery.html')))
return u'/usr/bin/python' return u'/usr/bin/python3'
if platform_interpreter not in found_interpreters: if platform_interpreter not in found_interpreters:
if platform_interpreter not in bootstrap_python_list: if platform_interpreter not in bootstrap_python_list:

@ -141,8 +141,6 @@
- name: debian assertions - name: debian assertions
assert: assert:
that: that:
# Debian 8 and older
- auto_out.ansible_facts.discovered_interpreter_python == '/usr/bin/python' and distro_version is version('8', '<=') or distro_version is version('8', '>')
# Debian 10 and newer # Debian 10 and newer
- auto_out.ansible_facts.discovered_interpreter_python == '/usr/bin/python3' and distro_version is version('10', '>=') or distro_version is version('10', '<') - auto_out.ansible_facts.discovered_interpreter_python == '/usr/bin/python3' and distro_version is version('10', '>=') or distro_version is version('10', '<')
when: distro == 'debian' when: distro == 'debian'
@ -150,27 +148,21 @@
- name: fedora assertions - name: fedora assertions
assert: assert:
that: that:
- auto_out.ansible_facts.discovered_interpreter_python == '/usr/bin/python3' - "'/bin/python3' in auto_out.ansible_facts.discovered_interpreter_python"
when: distro == 'fedora' and distro_version is version('23', '>=') when: distro == 'fedora' and distro_version is version('23', '>=')
- name: rhel assertions - name: rhel assertions
assert: assert:
that: that:
# rhel 6/7
- (auto_out.ansible_facts.discovered_interpreter_python == '/usr/bin/python' and distro_major_version is version('8','<')) or distro_major_version is version('8','>=')
# rhel 8
- (auto_out.ansible_facts.discovered_interpreter_python == '/usr/libexec/platform-python' and distro_major_version is version('8','==')) or distro_major_version is version('8','!=')
# rhel 9 # rhel 9
- (auto_out.ansible_facts.discovered_interpreter_python == '/usr/bin/python3' and distro_major_version is version('9','==')) or distro_major_version is version('9','!=') - ('/bin/python3' in auto_out.ansible_facts.discovered_interpreter_python and distro_major_version is version('9','==')) or distro_major_version is version('9','!=')
when: distro == 'redhat' when: distro == 'redhat'
- name: ubuntu assertions - name: ubuntu assertions
assert: assert:
that: that:
# ubuntu < 16
- (auto_out.ansible_facts.discovered_interpreter_python == '/usr/bin/python' and distro_version is version('16.04','<')) or distro_version is version('16.04','>=')
# ubuntu >= 16 # ubuntu >= 16
- (auto_out.ansible_facts.discovered_interpreter_python == '/usr/bin/python3' and distro_version is version('16.04','>=')) or distro_version is version('16.04','<') - ('/bin/python3' in auto_out.ansible_facts.discovered_interpreter_python and distro_version is version('16.04','>=')) or distro_version is version('16.04','<')
when: distro == 'ubuntu' when: distro == 'ubuntu'
- name: mac assertions - name: mac assertions

@ -12,63 +12,63 @@ from ansible.module_utils.common.text.converters import to_text
from ansible.errors import AnsibleConnectionFailure from ansible.errors import AnsibleConnectionFailure
mock_ubuntu_platform_res = to_text( mock_ubuntu_platform_res = to_text(
r'{"osrelease_content": "NAME=\"Ubuntu\"\nVERSION=\"16.04.5 LTS (Xenial Xerus)\"\nID=ubuntu\nID_LIKE=debian\n' r'{"osrelease_content": "NAME=\"Ansible Test\"\nVERSION=\"100\"\nID=ansible-test\nID_LIKE=debian\n'
r'PRETTY_NAME=\"Ubuntu 16.04.5 LTS\"\nVERSION_ID=\"16.04\"\nHOME_URL=\"http://www.ubuntu.com/\"\n' r'PRETTY_NAME=\"Ansible Test 100\"\nVERSION_ID=\"100\"\nHOME_URL=\"http://ansible.com/\"\n'
r'SUPPORT_URL=\"http://help.ubuntu.com/\"\nBUG_REPORT_URL=\"http://bugs.launchpad.net/ubuntu/\"\n' r'SUPPORT_URL=\"http://github.com/ansible/ansible\"\nBUG_REPORT_URL=\"http://github.com/ansible/ansible/\"\n'
r'VERSION_CODENAME=xenial\nUBUNTU_CODENAME=xenial\n", "platform_dist_result": ["Ubuntu", "16.04", "xenial"]}' r'VERSION_CODENAME=beans\nUBUNTU_CODENAME=beans\n", "platform_dist_result": ["Ansible Test", "100", "beans"]}'
) )
def test_discovery_interpreter_linux_auto_legacy(): def test_discovery_interpreter_linux_auto_legacy():
res1 = u'PLATFORM\nLinux\nFOUND\n/usr/bin/python\n/usr/bin/python3\nENDFOUND' res1 = u'PLATFORM\nLinux\nFOUND\n/usr/bin/python99\n/usr/bin/python3\nENDFOUND'
mock_action = MagicMock() mock_action = MagicMock()
mock_action._low_level_execute_command.side_effect = [{'stdout': res1}, {'stdout': mock_ubuntu_platform_res}] mock_action._low_level_execute_command.side_effect = [{'stdout': res1}, {'stdout': mock_ubuntu_platform_res}]
actual = discover_interpreter(mock_action, 'python', 'auto_legacy', {'inventory_hostname': u'host-fóöbär'}) actual = discover_interpreter(mock_action, 'python', 'auto_legacy', {'inventory_hostname': u'host-fóöbär'})
assert actual == u'/usr/bin/python' assert actual == u'/usr/bin/python3'
assert len(mock_action.method_calls) == 3 assert len(mock_action.method_calls) == 3
assert mock_action.method_calls[2][0] == '_discovery_warnings.append' assert mock_action.method_calls[2][0] == '_discovery_warnings.append'
assert u'Distribution Ubuntu 16.04 on host host-fóöbär should use /usr/bin/python3, but is using /usr/bin/python' \ assert u'Distribution Ansible Test 100 on host host-fóöbär should use /usr/bin/python99, but is using /usr/bin/python3' \
u' for backward compatibility' in mock_action.method_calls[2][1][0] u' for backward compatibility' in mock_action.method_calls[2][1][0]
def test_discovery_interpreter_linux_auto_legacy_silent(): def test_discovery_interpreter_linux_auto_legacy_silent():
res1 = u'PLATFORM\nLinux\nFOUND\n/usr/bin/python\n/usr/bin/python3\nENDFOUND' res1 = u'PLATFORM\nLinux\nFOUND\n/usr/bin/python3.9\n/usr/bin/python3\nENDFOUND'
mock_action = MagicMock() mock_action = MagicMock()
mock_action._low_level_execute_command.side_effect = [{'stdout': res1}, {'stdout': mock_ubuntu_platform_res}] mock_action._low_level_execute_command.side_effect = [{'stdout': res1}, {'stdout': mock_ubuntu_platform_res}]
actual = discover_interpreter(mock_action, 'python', 'auto_legacy_silent', {'inventory_hostname': u'host-fóöbär'}) actual = discover_interpreter(mock_action, 'python', 'auto_legacy_silent', {'inventory_hostname': u'host-fóöbär'})
assert actual == u'/usr/bin/python' assert actual == u'/usr/bin/python3'
assert len(mock_action.method_calls) == 2 assert len(mock_action.method_calls) == 2
def test_discovery_interpreter_linux_auto(): def test_discovery_interpreter_linux_auto():
res1 = u'PLATFORM\nLinux\nFOUND\n/usr/bin/python\n/usr/bin/python3\nENDFOUND' res1 = u'PLATFORM\nLinux\nFOUND\n/usr/bin/python99\n/usr/bin/python3\nENDFOUND'
mock_action = MagicMock() mock_action = MagicMock()
mock_action._low_level_execute_command.side_effect = [{'stdout': res1}, {'stdout': mock_ubuntu_platform_res}] mock_action._low_level_execute_command.side_effect = [{'stdout': res1}, {'stdout': mock_ubuntu_platform_res}]
actual = discover_interpreter(mock_action, 'python', 'auto', {'inventory_hostname': u'host-fóöbär'}) actual = discover_interpreter(mock_action, 'python', 'auto', {'inventory_hostname': u'host-fóöbär'})
assert actual == u'/usr/bin/python3' assert actual == u'/usr/bin/python99'
assert len(mock_action.method_calls) == 2 assert len(mock_action.method_calls) == 2
def test_discovery_interpreter_non_linux(): def test_discovery_interpreter_non_linux():
mock_action = MagicMock() mock_action = MagicMock()
mock_action._low_level_execute_command.return_value = \ mock_action._low_level_execute_command.return_value = \
{'stdout': u'PLATFORM\nDarwin\nFOUND\n/usr/bin/python\nENDFOUND'} {'stdout': u'PLATFORM\nDarwin\nFOUND\n/usr/bin/python3\nENDFOUND'}
actual = discover_interpreter(mock_action, 'python', 'auto_legacy', {'inventory_hostname': u'host-fóöbär'}) actual = discover_interpreter(mock_action, 'python', 'auto_legacy', {'inventory_hostname': u'host-fóöbär'})
assert actual == u'/usr/bin/python' assert actual == u'/usr/bin/python3'
assert len(mock_action.method_calls) == 2 assert len(mock_action.method_calls) == 2
assert mock_action.method_calls[1][0] == '_discovery_warnings.append' assert mock_action.method_calls[1][0] == '_discovery_warnings.append'
assert u'Platform darwin on host host-fóöbär is using the discovered Python interpreter at /usr/bin/python, ' \ assert u'Platform darwin on host host-fóöbär is using the discovered Python interpreter at /usr/bin/python3, ' \
u'but future installation of another Python interpreter could change the meaning of that path' \ u'but future installation of another Python interpreter could change the meaning of that path' \
in mock_action.method_calls[1][1][0] in mock_action.method_calls[1][1][0]
@ -79,7 +79,7 @@ def test_no_interpreters_found():
actual = discover_interpreter(mock_action, 'python', 'auto_legacy', {'inventory_hostname': u'host-fóöbär'}) actual = discover_interpreter(mock_action, 'python', 'auto_legacy', {'inventory_hostname': u'host-fóöbär'})
assert actual == u'/usr/bin/python' assert actual == u'/usr/bin/python3'
assert len(mock_action.method_calls) == 2 assert len(mock_action.method_calls) == 2
assert mock_action.method_calls[1][0] == '_discovery_warnings.append' assert mock_action.method_calls[1][0] == '_discovery_warnings.append'
assert u'No python interpreters found for host host-fóöbär (tried' \ assert u'No python interpreters found for host host-fóöbär (tried' \

Loading…
Cancel
Save