Merge "Support nodes setting 'auto' python-path"
This commit is contained in:
commit
3e63b9fe3c
|
@ -64,9 +64,8 @@ at the tops of individual source files.
|
|||
Python Version Support
|
||||
----------------------
|
||||
|
||||
Zuul v3 requires Python 3. It does not support Python 2.
|
||||
Zuul requires Python 3. It does not support Python 2.
|
||||
|
||||
Since Zuul uses Ansible to drive CI jobs, Zuul can run tests anywhere
|
||||
Ansible can, including Python 2 environments.
|
||||
|
||||
As Ansible is used for the execution of jobs, it's important to note that
|
||||
while Ansible does support Python 3, not all of Ansible's modules do. Zuul
|
||||
currently sets ``ansible_python_interpreter`` to python2 so that remote
|
||||
content will be executed with Python 2.
|
||||
|
|
|
@ -797,6 +797,42 @@ To enable or disable running Ansible in verbose mode (with the
|
|||
``-vvv`` argument to ansible-playbook) run ``zuul-executor verbose``
|
||||
and ``zuul-executor unverbose``.
|
||||
|
||||
Ansible and Python 3
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
As noted above, the executor runs Ansible playbooks against the remote
|
||||
node(s) allocated for the job. Since part of executing playbooks on
|
||||
remote hosts is running Python scripts on them, Ansible needs to know
|
||||
what Python interpreter to use on the remote host. With older
|
||||
distributions, ``/usr/bin/python2`` was a generally sensible choice.
|
||||
However, over time a heterogeneous Python ecosystem has evolved where
|
||||
older distributions may only provide Python 2, most provide a mixed
|
||||
2/3 environment and newer distributions may only provide Python 3 (and
|
||||
then others like RHEL8 may even have separate "system" Python versions
|
||||
to add to confusion!).
|
||||
|
||||
Ansible's ``ansible_python_interpreter`` variable configures the path
|
||||
to the remote Python interpreter to use during playbook execution.
|
||||
This value is set by Zuul from the ``python-path`` specified for the
|
||||
node by Nodepool; see the `nodepool configuration documentation
|
||||
<https://zuul-ci.org/docs/nodepool/configuration.html>`__.
|
||||
|
||||
This defaults to ``auto``, where Ansible will automatically discover
|
||||
the interpreter available on the remote host. However, this setting
|
||||
only became available in Ansible >=2.8, so Zuul will translate
|
||||
``auto`` into the old default of ``/usr/bin/python2`` when configured
|
||||
to use older Ansible versions.
|
||||
|
||||
Thus for modern Python 3-only hosts no further configuration is needed
|
||||
when using Ansible >=2.8 (e.g. Fedora, Bionic onwards). If using
|
||||
earlier Ansible versions you may need to explicitly set the
|
||||
``python-path`` if ``/usr/bin/python2`` is not available on the node.
|
||||
|
||||
Ansible roles/modules which include Python code are generally Python 3
|
||||
safe now, but there is still a small possibility of incompatibility.
|
||||
See also the Ansible `Python 3 support page
|
||||
<https://docs.ansible.com/ansible/latest/reference_appendices/python_3_support.html>`__.
|
||||
|
||||
.. _web-server:
|
||||
|
||||
Web Server
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
features:
|
||||
- |
|
||||
Nodes can set their ``python-path`` in nodepool configuration to
|
||||
``auto`` to allow for `automatic ansible_python_interpreter
|
||||
discovery <https://docs.ansible.com/ansible/2.8/reference_appendices/interpreter_discovery.html>`__
|
||||
when using Ansible >=2.8.
|
|
@ -2507,7 +2507,7 @@ class FakeNodepool(object):
|
|||
self.remote_ansible = False
|
||||
self.attributes = None
|
||||
self.resources = None
|
||||
self.python_path = '/usr/bin/python2'
|
||||
self.python_path = 'auto'
|
||||
|
||||
def stop(self):
|
||||
self._running = False
|
||||
|
|
2
tests/fixtures/config/inventory/git/common-config/playbooks/ansible-version.yaml
vendored
Normal file
2
tests/fixtures/config/inventory/git/common-config/playbooks/ansible-version.yaml
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
- hosts: all
|
||||
tasks: []
|
|
@ -89,4 +89,20 @@
|
|||
label: ubuntu-xenial
|
||||
run: playbooks/jinja2-message.yaml
|
||||
|
||||
- job:
|
||||
name: ansible-version27-inventory
|
||||
nodeset:
|
||||
nodes:
|
||||
- name: ubuntu-xenial
|
||||
label: ubuntu-xenial
|
||||
ansible-version: '2.7'
|
||||
run: playbooks/ansible-version.yaml
|
||||
|
||||
- job:
|
||||
name: ansible-version28-inventory
|
||||
nodeset:
|
||||
nodes:
|
||||
- name: ubuntu-xenial
|
||||
label: ubuntu-xenial
|
||||
ansible-version: '2.8'
|
||||
run: playbooks/ansible-version.yaml
|
||||
|
|
|
@ -7,3 +7,5 @@
|
|||
- executor-only-inventory
|
||||
- group-inventory
|
||||
- hostvars-inventory
|
||||
- ansible-version27-inventory
|
||||
- ansible-version28-inventory
|
||||
|
|
|
@ -76,6 +76,57 @@ class TestInventoryPythonPath(TestInventoryBase):
|
|||
self.waitUntilSettled()
|
||||
|
||||
|
||||
class TestInventoryAutoPython(TestInventoryBase):
|
||||
|
||||
def test_auto_python_ansible28_inventory(self):
|
||||
inventory = self._get_build_inventory('ansible-version28-inventory')
|
||||
|
||||
all_nodes = ('ubuntu-xenial',)
|
||||
self.assertIn('all', inventory)
|
||||
self.assertIn('hosts', inventory['all'])
|
||||
self.assertIn('vars', inventory['all'])
|
||||
for node_name in all_nodes:
|
||||
self.assertIn(node_name, inventory['all']['hosts'])
|
||||
node_vars = inventory['all']['hosts'][node_name]
|
||||
self.assertEqual(
|
||||
'auto', node_vars['ansible_python_interpreter'])
|
||||
|
||||
self.assertIn('zuul', inventory['all']['vars'])
|
||||
z_vars = inventory['all']['vars']['zuul']
|
||||
self.assertIn('executor', z_vars)
|
||||
self.assertIn('src_root', z_vars['executor'])
|
||||
self.assertIn('job', z_vars)
|
||||
self.assertEqual(z_vars['job'], 'ansible-version28-inventory')
|
||||
self.assertEqual(z_vars['message'], 'QQ==')
|
||||
|
||||
self.executor_server.release()
|
||||
self.waitUntilSettled()
|
||||
|
||||
def test_auto_python_ansible27_inventory(self):
|
||||
inventory = self._get_build_inventory('ansible-version27-inventory')
|
||||
|
||||
all_nodes = ('ubuntu-xenial',)
|
||||
self.assertIn('all', inventory)
|
||||
self.assertIn('hosts', inventory['all'])
|
||||
self.assertIn('vars', inventory['all'])
|
||||
for node_name in all_nodes:
|
||||
self.assertIn(node_name, inventory['all']['hosts'])
|
||||
node_vars = inventory['all']['hosts'][node_name]
|
||||
self.assertEqual(
|
||||
'/usr/bin/python2', node_vars['ansible_python_interpreter'])
|
||||
|
||||
self.assertIn('zuul', inventory['all']['vars'])
|
||||
z_vars = inventory['all']['vars']['zuul']
|
||||
self.assertIn('executor', z_vars)
|
||||
self.assertIn('src_root', z_vars['executor'])
|
||||
self.assertIn('job', z_vars)
|
||||
self.assertEqual(z_vars['job'], 'ansible-version27-inventory')
|
||||
self.assertEqual(z_vars['message'], 'QQ==')
|
||||
|
||||
self.executor_server.release()
|
||||
self.waitUntilSettled()
|
||||
|
||||
|
||||
class TestInventory(TestInventoryBase):
|
||||
|
||||
def test_single_inventory(self):
|
||||
|
|
|
@ -1370,9 +1370,23 @@ class AnsibleJob(object):
|
|||
private_ipv4=node.get('private_ipv4'),
|
||||
public_ipv6=node.get('public_ipv6'))))
|
||||
|
||||
host_vars.setdefault(
|
||||
'ansible_python_interpreter',
|
||||
node.get('python_path', '/usr/bin/python2'))
|
||||
# Ansible >=2.8 introduced "auto" as an
|
||||
# ansible_python_interpreter argument that looks up
|
||||
# which python to use on the remote host in an inbuilt
|
||||
# table and essentially "does the right thing"
|
||||
# (i.e. chooses python3 on 3-only hosts like later
|
||||
# Fedoras). For "auto" with prior versions, fall back
|
||||
# to the old default of /usr/bin/python2 for backwards
|
||||
# compatability.
|
||||
python = node.get('python_path', 'auto')
|
||||
compat = self.arguments.get('ansible_version') in \
|
||||
('2.5', '2.6', '2.7')
|
||||
if python == "auto" and compat:
|
||||
self.log.debug(
|
||||
"ansible_version set to auto but "
|
||||
"overriding to python2 for Ansible <2.8")
|
||||
python = '/usr/bin/python2'
|
||||
host_vars.setdefault('ansible_python_interpreter', python)
|
||||
|
||||
username = node.get('username')
|
||||
if username:
|
||||
|
|
Loading…
Reference in New Issue