def test_discovery_interpreter_linux_auto(): res1 = u'PLATFORM\nLinux\nFOUND\n/usr/bin/python\n/usr/bin/python3.5\n/usr/bin/python3\nENDFOUND' mock_action = MagicMock() 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'}) assert actual == u'/usr/bin/python3' assert len(mock_action.method_calls) == 2
def test_no_interpreters_found(): mock_action = MagicMock() mock_action._low_level_execute_command.return_value = {'stdout': u'PLATFORM\nWindows\nFOUND\nENDFOUND'} actual = discover_interpreter(mock_action, 'python', 'auto_legacy', {'inventory_hostname': u'host-fóöbär'}) assert actual == u'/usr/bin/python' assert len(mock_action.method_calls) == 2 assert mock_action.method_calls[1][0] == '_discovery_warnings.append' assert u'No python interpreters found for host host-fóöbär (tried' \ in mock_action.method_calls[1][1][0]
def run_interpreter_discovery_if_necessary(s, task_vars, action, rediscover_python): """ Triggers ansible python interpreter discovery if requested. Caches this value the same way Ansible does it. For connections like `docker`, we want to rediscover the python interpreter because it could be different than what's ran on the host """ # keep trying different interpreters until we don't error if action._finding_python_interpreter: return action._possible_python_interpreter if s in ['auto', 'auto_legacy', 'auto_silent', 'auto_legacy_silent']: # python is the only supported interpreter_name as of Ansible 2.8.8 interpreter_name = 'python' discovered_interpreter_config = u'discovered_interpreter_%s' % interpreter_name if task_vars.get('ansible_facts') is None: task_vars['ansible_facts'] = {} if rediscover_python and task_vars.get( 'ansible_facts', {}).get(discovered_interpreter_config): # if we're rediscovering python then chances are we're running something like a docker connection # this will handle scenarios like running a playbook that does stuff + then dynamically creates a docker container, # then runs the rest of the playbook inside that container, and then rerunning the playbook again action._rediscovered_python = True # blow away the discovered_interpreter_config cache and rediscover del task_vars['ansible_facts'][discovered_interpreter_config] if discovered_interpreter_config not in task_vars['ansible_facts']: action._finding_python_interpreter = True # fake pipelining so discover_interpreter can be happy action._connection.has_pipelining = True s = AnsibleUnsafeText( discover_interpreter(action=action, interpreter_name=interpreter_name, discovery_mode=s, task_vars=task_vars)) # cache discovered interpreter task_vars['ansible_facts'][discovered_interpreter_config] = s action._connection.has_pipelining = False else: s = task_vars['ansible_facts'][discovered_interpreter_config] # propagate discovered interpreter as fact action._discovered_interpreter_key = discovered_interpreter_config action._discovered_interpreter = s action._finding_python_interpreter = False return s
def test_discovery_interpreter_non_linux(): mock_action = MagicMock() mock_action._low_level_execute_command.return_value = \ {'stdout': u'PLATFORM\nDarwin\nFOUND\n/usr/bin/python\nENDFOUND'} actual = discover_interpreter(mock_action, 'python', 'auto_legacy', {'inventory_hostname': u'host-fóöbär'}) assert actual == u'/usr/bin/python' assert len(mock_action.method_calls) == 2 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, ' \ u'but future installation of another Python interpreter could change the meaning of that path' \ in mock_action.method_calls[1][1][0]
def test_discovery_interpreter_linux_auto_legacy(): res1 = u'PLATFORM\nLinux\nFOUND\n/usr/bin/python\n/usr/bin/python3.5\n/usr/bin/python3\nENDFOUND' mock_action = MagicMock() 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'}) assert actual == u'/usr/bin/python' assert len(mock_action.method_calls) == 3 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' \ u' for backward compatibility' in mock_action.method_calls[2][1][0]