Manage ansible installations within zuul

As a first step towards supporting multiple ansible versions we need
tooling to manage ansible installations. This moves the installation
of ansible from the requirements.txt into zuul. This is called as a
setup hook to install the ansible versions into
<prefix>/lib/zuul/ansible. Further this tooling abstracts knowledge
that the executor must know in order to actually run the correct
version of ansible.

The actual usage of multiple ansible versions will be done in
follow-ups.

For better maintainability the ansible plugins live in
zuul/ansible/base where plugins can be kept in different versions if
necessary. For each supported ansible version there is a specific
folder that symlinks the according plugins.

Change-Id: I5ce1385245c76818777aa34230786a9dbaf723e5
Depends-On: https://review.openstack.org/623927
This commit is contained in:
Tobias Henkel 2019-01-19 13:33:39 +01:00
parent c91335b527
commit cd9827e664
No known key found for this signature in database
GPG Key ID: 03750DEC158E5FA2
412 changed files with 627 additions and 86 deletions

View File

@ -22,12 +22,16 @@
post-run:
- playbooks/zuul-stream/post.yaml
- playbooks/zuul-stream/post-ara.yaml
required-projects:
- openstack/ara
files:
- zuul/ansible/.*
- zuul/lib/ansible*
- playbooks/zuul-stream/.*
- requirements.txt
- job:
name: zuul-stream-functional-2.5
parent: zuul-stream-functional
vars:
zuul_ansible_version: 2.5
- job:
name: zuul-tox-remote
@ -192,7 +196,7 @@
success-url: 'npm/reports/bundle.html'
files:
- web/.*
- zuul-stream-functional
- zuul-stream-functional-2.5
- zuul-tox-remote
- zuul-quick-start
- nodepool-zuul-functional:
@ -223,7 +227,7 @@
success-url: 'npm/reports/bundle.html'
files:
- web/.*
- zuul-stream-functional
- zuul-stream-functional-2.5
- zuul-tox-remote
- zuul-quick-start
- zuul-upload-image

View File

@ -24,6 +24,11 @@ COPY . /tmp/src
RUN /tmp/src/tools/install-js-tools.sh
RUN assemble
# The wheel install method doesn't run the setup hooks as the source based
# installations do so we have to call zuul-manage-ansible here.
RUN /output/install-from-bindep && zuul-manage-ansible
FROM opendevorg/python-base as zuul
COPY --from=builder /output/ /output
@ -40,8 +45,10 @@ CMD ["/usr/local/bin/zuul"]
FROM zuul as zuul-executor
COPY --from=builder /output/ /output
COPY --from=builder /usr/local/lib/zuul/ /usr/local/lib/zuul
RUN pip install --cache-dir=/output/wheels -r /output/zuul_executor/requirements.txt \
&& rm -rf /output
CMD ["/usr/local/bin/zuul-executor"]
FROM zuul as zuul-fingergw

View File

@ -30,6 +30,9 @@ libffi6 [platform:dpkg]
libffi-devel [compile test platform:rpm]
python3-dev [compile test platform:dpkg platform:apk]
python3-devel [compile test platform:rpm]
python-virtualenv [platform:dpkg]
python3-virtualenv [platform:rpm]
py3-virtualenv [compile test platform:apk]
bubblewrap [!platform:ubuntu-xenial]
libre2-dev [compile test platform:dpkg]
libre2-4 [platform:ubuntu-bionic]

View File

@ -1,3 +1,4 @@
ansible
sphinx>=1.6.1
sphinxcontrib-blockdiag>=1.1.0
sphinxcontrib-programoutput

View File

@ -16,7 +16,7 @@ services:
git config -f /var/gerrit/etc/gerrit.config noteDb.changes.autoMigrate true && \
/var/gerrit/bin/gerrit.sh run'
gerritconfig:
image: zuul/zuul
image: zuul/zuul-executor
environment:
no_proxy: "${no_proxy},gerrit"
depends_on:
@ -25,7 +25,7 @@ services:
- "sshkey:/var/ssh:z"
- "nodessh:/var/node:z"
- "./playbooks/:/var/playbooks/:z"
command: "ansible-playbook /var/playbooks/setup.yaml"
command: "/usr/local/lib/zuul/ansible/2.5/bin/ansible-playbook /var/playbooks/setup.yaml"
zk:
image: zookeeper
mysql:
@ -42,7 +42,9 @@ services:
- mysql
environment:
no_proxy: "${no_proxy},gerrit"
command: "sh -c 'ansible-playbook /var/playbooks/wait-to-start.yaml; zuul-scheduler -d'"
command: "sh -c '/var/playbooks/wait-to-start.sh && zuul-scheduler -d'"
# FIXME: The scheduler has no ansible anymore so use the executor image.
# This needs to be changes such that ansible is not required for startup.
image: zuul/zuul-scheduler
volumes:
- "./etc_zuul/:/etc/zuul/:z"
@ -50,7 +52,7 @@ services:
- "sshkey:/var/ssh:z"
- /var/lib/zuul
web:
command: "sh -c 'ansible-playbook /var/playbooks/wait-to-start.yaml; zuul-web -d'"
command: "sh -c '/var/playbooks/wait-to-start-gearman.sh && zuul-web -d'"
depends_on:
- scheduler
- mysql
@ -59,6 +61,7 @@ services:
image: zuul/zuul-web
volumes:
- "./etc_zuul/:/etc/zuul/:z"
- "./playbooks/:/var/playbooks/:z"
executor:
privileged: true
environment:

View File

@ -0,0 +1,17 @@
#!/bin/bash
# Zuul needs to be able to connect to the remote systems in order to
# start.
wait_for_gearman() {
echo "Wait for gearman to start"
for i in $(seq 1 120); do
cat < /dev/null > /dev/tcp/scheduler/4730 && return
sleep 1
done
echo "Timeout waiting for mysql"
exit 1
}
wait_for_gearman

View File

@ -0,0 +1,29 @@
#!/bin/bash
# Zuul needs to be able to connect to the remote systems in order to
# start.
wait_for_mysql() {
echo "Wait for mysql to start"
for i in $(seq 1 120); do
cat < /dev/null > /dev/tcp/mysql/3306 && return
sleep 1
done
echo "Timeout waiting for mysql"
exit 1
}
wait_for_gerrit() {
echo "Wait for zuul user to be created"
for i in $(seq 1 120); do
[ $(curl -s -o /dev/null -w "%{http_code}" http://admin:secret@gerrit:8080/a/accounts/zuul/sshkeys) = "200" ] && return
sleep 1
done
echo "Timeout waiting for gerrit"
exit 1
}
wait_for_mysql
wait_for_gerrit

View File

@ -1,24 +0,0 @@
# Zuul needs to be able to connect to the remote systems in order to
# start.
- hosts: localhost
gather_facts: false
tasks:
- name: Wait for Gerrit to start
wait_for:
host: gerrit
port: 29418
- name: Wait for mysql to start
wait_for:
host: mysql
port: 3306
- name: Wait for zuul user to be created
uri:
url: http://gerrit:8080/a/accounts/zuul/sshkeys
method: GET
user: admin
password: secret
register: result
until: result.status == 200 and result.redirected == false
delay: 1
retries: 120

View File

@ -20,6 +20,9 @@ Zuul has several system-level dependencies as well. You can find a
list of operating system packages in ``bindep.txt`` in Zuul's source
directory.
It is further required to run ``zuul-manage-ansible`` on the zuul-executor
in order to install all supported ansible versions so zuul can use them.
Zuul Components
---------------

View File

@ -43,6 +43,7 @@ required.
# All:
$ sudo pip3 install .
$ sudo zuul-manage-ansible
$ popd
Service Files

View File

@ -23,7 +23,7 @@ execution to ensure local actions are not executed or that for operations that
are desirable to allow locally that they only interact with files in the zuul
work directory.
.. autoclass:: zuul.ansible.action.normal.ActionModule
.. autoclass:: zuul.ansible.base.action.normal.ActionModule
:members:
Build Log Support
@ -38,16 +38,16 @@ for the command to finish.
Zuul contains a modified version of the :ansible:module:`command`
that starts a log streaming daemon on the build node.
.. automodule:: zuul.ansible.library.command
.. automodule:: zuul.ansible.base.library.command
All jobs run with the :py:mod:`zuul.ansible.callback.zuul_stream` callback
All jobs run with the :py:mod:`zuul.ansible.base.callback.zuul_stream` callback
plugin enabled, which writes the build log to a file so that the
:py:class:`zuul.lib.log_streamer.LogStreamer` can provide the data on demand
over the finger protocol. Finally, :py:class:`zuul.web.LogStreamHandler`
exposes that log stream over a websocket connection as part of
:py:class:`zuul.web.ZuulWeb`.
.. autoclass:: zuul.ansible.callback.zuul_stream.CallbackModule
.. autoclass:: zuul.ansible.base.callback.zuul_stream.CallbackModule
:members:
.. autoclass:: zuul.lib.log_streamer.LogStreamer
@ -55,7 +55,7 @@ exposes that log stream over a websocket connection as part of
.. autoclass:: zuul.web.ZuulWeb
In addition to real-time streaming, Zuul also installs another callback module,
:py:mod:`zuul.ansible.callback.zuul_json.CallbackModule` that collects all
:py:mod:`zuul.ansible.base.callback.zuul_json.CallbackModule` that collects all
of the information about a given run into a json file which is written to the
work dir so that it can be published along with build logs. Since the streaming
log is by necessity a single text stream, choices have to be made for
@ -63,4 +63,4 @@ readability about what data is shown and what is not shown. The json log file
is intended to allow for a richer more interactive set of data to be displayed
to the user.
.. autoclass:: zuul.ansible.callback.zuul_json.CallbackModule
.. autoclass:: zuul.ansible.base.callback.zuul_json.CallbackModule

View File

@ -6,6 +6,10 @@
setup:
register: setupvar
- name: Output ansible version
debug:
var: ansible_version
- name: Output debug for a var
debug:
var: setupvar

View File

@ -1,21 +1,31 @@
- hosts: controller
tasks:
- name: Set python path fact
set_fact:
python_path: "/usr/local/lib/python3.5/dist-packages"
- name: Run ansible that should succeed
command: ansible-playbook src/git.openstack.org/openstack-infra/zuul/playbooks/zuul-stream/fixtures/test-stream.yaml
command: >
/usr/lib/zuul/ansible/{{ zuul_ansible_version }}/bin/ansible-playbook
src/git.openstack.org/openstack-infra/zuul/playbooks/zuul-stream/fixtures/test-stream.yaml
environment:
ZUUL_JOB_LOG_CONFIG: "{{ ansible_user_dir}}/logging.json"
ZUUL_JOBDIR: "{{ ansible_user_dir}}"
ARA_LOG_CONFIG: "{{ ansible_user_dir}}/logging.json"
PYTHONPATH: "{{ python_path }}"
- name: Run ansible playbook that should fail
command: ansible-playbook src/git.openstack.org/openstack-infra/zuul/playbooks/zuul-stream/fixtures/test-stream-failure.yaml
command: >
/usr/lib/zuul/ansible/{{ zuul_ansible_version }}/bin/ansible-playbook
src/git.openstack.org/openstack-infra/zuul/playbooks/zuul-stream/fixtures/test-stream-failure.yaml
register: failed_results
failed_when: "failed_results.rc != 2"
environment:
ZUUL_JOB_LOG_CONFIG: "{{ ansible_user_dir}}/logging.json"
ZUUL_JOBDIR: "{{ ansible_user_dir}}"
ARA_LOG_CONFIG: "{{ ansible_user_dir}}/logging.json"
PYTHONPATH: "{{ python_path }}"
- name: Validate output - setupvar
shell: |

View File

@ -2,7 +2,7 @@
tasks:
- name: Generate ARA html
command: ara generate html ara-output
command: /usr/lib/zuul/ansible/{{ zuul_ansible_version }}/bin/ara generate html ara-output
- name: Compress ARA html
command: gzip --recursive --best ara-output

View File

@ -11,7 +11,11 @@
post_tasks:
- name: Install software
command: python3 -m pip install src/git.openstack.org/openstack-infra/zuul src/git.openstack.org/openstack/ara
command: python3 -m pip install src/git.openstack.org/openstack-infra/zuul
become: yes
- name: Install managed ansible versions
command: /usr/local/bin/zuul-manage-ansible -v
become: yes
- name: Copy inventory

View File

@ -2,10 +2,9 @@
inventory = {{ ansible_user_dir }}/inventory.yaml
gathering = smart
gather_subset = !all
lookup_plugins = {{ ansible_user_dir }}/src/git.openstack.org/openstack-infra/zuul/zuul/ansible/lookup
action_plugins = {{ ansible_user_dir }}/src/git.openstack.org/openstack-infra/zuul/zuul/ansible/actiongeneral:{{ ansible_user_dir }}/src/git.openstack.org/openstack-infra/zuul/zuul/ansible/action
callback_plugins = {{ ansible_user_dir }}/src/git.openstack.org/openstack-infra/zuul/zuul/ansible/callback:{{ ansible_user_dir }}/src/git.openstack.org/openstack/ara/ara/plugins/callbacks
module_utils = {{ ansible_user_dir }}/src/git.openstack.org/openstack-infra/zuul/zuul/ansible/module_utils
lookup_plugins = {{ ansible_user_dir }}/src/git.openstack.org/openstack-infra/zuul/zuul/ansible/{{ zuul_ansible_version }}/lookup
action_plugins = {{ ansible_user_dir }}/src/git.openstack.org/openstack-infra/zuul/zuul/ansible/{{ zuul_ansible_version }}/actiongeneral:{{ ansible_user_dir }}/src/git.openstack.org/openstack-infra/zuul/zuul/ansible/action
callback_plugins = {{ ansible_user_dir }}/src/git.openstack.org/openstack-infra/zuul/zuul/ansible/{{ zuul_ansible_version }}/callback:/usr/lib/zuul/ansible/{{ zuul_ansible_version }}/lib/python3.5/site-packages/ara/plugins/callbacks
stdout_callback = zuul_stream
library = {{ ansible_user_dir }}/src/git.openstack.org/openstack-infra/zuul/zuul/ansible/library
library = {{ ansible_user_dir }}/src/git.openstack.org/openstack-infra/zuul/zuul/ansible/{{ zuul_ansible_version }}/library
retry_files_enabled = False

View File

@ -12,7 +12,6 @@ gear>=0.13.0,<1.0.0
apscheduler>=3.0
PrettyTable>=0.6,<0.8
babel>=1.0
ansible>=2.5.1,<2.6
netaddr
kazoo
sqlalchemy

View File

@ -33,6 +33,7 @@ console_scripts =
zuul-web = zuul.cmd.web:main
zuul-migrate = zuul.cmd.migrate:main
zuul-fingergw = zuul.cmd.fingergw:main
zuul-manage-ansible = zuul.cmd.manage_ansible:main
[build_sphinx]
source-dir = doc/source

View File

@ -25,6 +25,7 @@ install_command = pip install {opts} {packages}
whitelist_externals = bash
deps = -r{toxinidir}/requirements.txt
-r{toxinidir}/test-requirements.txt
commands_pre = zuul-manage-ansible -v
commands = stestr run {posargs}
stestr slowest
@ -49,6 +50,7 @@ commands = bindep test
# --ignore-missing-imports tells mypy to not try to follow imported modules
# out of the current tree. As you might expect, we don't want to run static
# type checking on the world - just on ourselves.
commands_pre =
commands =
flake8 {posargs}
mypy --ignore-missing-imports zuul
@ -67,6 +69,7 @@ commands =
[testenv:docs]
deps = -r{toxinidir}/doc/requirements.txt
-r{toxinidir}/test-requirements.txt
commands_pre =
commands =
sphinx-build -E -W -d doc/build/doctrees -b html doc/source/ doc/build/html
@ -74,10 +77,12 @@ commands =
commands = {posargs}
[testenv:nodepool]
commands_pre =
install_command = {[nodeenv]install_command}
commands = stestr run --concurrency=1 --test-path ./tests/nodepool {posargs}
[testenv:remote]
commands_pre = zuul-manage-ansible -v
commands = stestr run --concurrency=1 --test-path ./tests/remote {posargs}
passenv = ZUUL_TEST_ROOT OS_STDOUT_CAPTURE OS_STDERR_CAPTURE OS_LOG_CAPTURE OS_LOG_DEFAULTS ZUUL_REMOTE_IPV4 ZUUL_SSH_KEY NODEPOOL_ZK_HOST
install_command = {[nodeenv]install_command}

View File

@ -0,0 +1 @@
../../base/action/__init__.py

View File

@ -0,0 +1 @@
../../base/action/add_host.py

View File

@ -0,0 +1 @@
../../base/action/add_host.pyi

View File

@ -0,0 +1 @@
../../base/action/aireos.py

View File

@ -0,0 +1 @@
../../base/action/aireos.pyi

View File

@ -0,0 +1 @@
../../base/action/aireos_config.py

View File

@ -0,0 +1 @@
../../base/action/aireos_config.pyi

View File

@ -0,0 +1 @@
../../base/action/aruba.py

View File

@ -0,0 +1 @@
../../base/action/aruba.pyi

View File

@ -0,0 +1 @@
../../base/action/aruba_config.py

View File

@ -0,0 +1 @@
../../base/action/aruba_config.pyi

View File

@ -0,0 +1 @@
../../base/action/asa.py

View File

@ -0,0 +1 @@
../../base/action/asa.pyi

View File

@ -0,0 +1 @@
../../base/action/asa_config.py

View File

@ -0,0 +1 @@
../../base/action/asa_config.pyi

View File

@ -0,0 +1 @@
../../base/action/asa_template.py

View File

@ -0,0 +1 @@
../../base/action/asa_template.pyi

View File

@ -0,0 +1 @@
../../base/action/assemble.py

View File

@ -0,0 +1 @@
../../base/action/assemble.pyi

View File

@ -0,0 +1 @@
../../base/action/ce.py

View File

@ -0,0 +1 @@
../../base/action/ce.pyi

View File

@ -0,0 +1 @@
../../base/action/ce_config.py

View File

@ -0,0 +1 @@
../../base/action/ce_config.pyi

View File

@ -0,0 +1 @@
../../base/action/ce_template.py

View File

@ -0,0 +1 @@
../../base/action/ce_template.pyi

View File

@ -0,0 +1 @@
../../base/action/copy.py

View File

@ -0,0 +1 @@
../../base/action/copy.pyi

View File

@ -0,0 +1 @@
../../base/action/dellos10_config.py

View File

@ -0,0 +1 @@
../../base/action/dellos10_config.pyi

View File

@ -0,0 +1 @@
../../base/action/dellos6_config.py

View File

@ -0,0 +1 @@
../../base/action/dellos6_config.pyi

View File

@ -0,0 +1 @@
../../base/action/dellos9_config.py

View File

@ -0,0 +1 @@
../../base/action/dellos9_config.pyi

View File

@ -0,0 +1 @@
../../base/action/eos_config.py

View File

@ -0,0 +1 @@
../../base/action/eos_config.pyi

View File

@ -0,0 +1 @@
../../base/action/eos_template.py

View File

@ -0,0 +1 @@
../../base/action/eos_template.pyi

View File

@ -0,0 +1 @@
../../base/action/fetch.py

View File

@ -0,0 +1 @@
../../base/action/fetch.pyi

View File

@ -0,0 +1 @@
../../base/action/fortios_config.py

View File

@ -0,0 +1 @@
../../base/action/fortios_config.pyi

View File

@ -0,0 +1 @@
../../base/action/include_vars.py

View File

@ -0,0 +1 @@
../../base/action/include_vars.pyi

View File

@ -0,0 +1 @@
../../base/action/ios_config.py

View File

@ -0,0 +1 @@
../../base/action/ios_config.pyi

View File

@ -0,0 +1 @@
../../base/action/ios_template.py

View File

@ -0,0 +1 @@
../../base/action/ios_template.pyi

View File

@ -0,0 +1 @@
../../base/action/iosxr_config.py

View File

@ -0,0 +1 @@
../../base/action/iosxr_config.pyi

View File

@ -0,0 +1 @@
../../base/action/iosxr_template.py

View File

@ -0,0 +1 @@
../../base/action/iosxr_template.pyi

View File

@ -0,0 +1 @@
../../base/action/junos_config.py

View File

@ -0,0 +1 @@
../../base/action/junos_config.pyi

View File

@ -0,0 +1 @@
../../base/action/junos_template.py

View File

@ -0,0 +1 @@
../../base/action/junos_template.pyi

View File

@ -0,0 +1 @@
../../base/action/net_banner.py

View File

@ -0,0 +1 @@
../../base/action/net_banner.pyi

View File

@ -0,0 +1 @@
../../base/action/net_base.py

View File

@ -0,0 +1 @@
../../base/action/net_base.pyi

View File

@ -0,0 +1 @@
../../base/action/net_config.py

View File

@ -0,0 +1 @@
../../base/action/net_config.pyi

View File

@ -0,0 +1 @@
../../base/action/net_interface.py

View File

@ -0,0 +1 @@
../../base/action/net_interface.pyi

View File

@ -0,0 +1 @@
../../base/action/net_l2_interface.py

View File

@ -0,0 +1 @@
../../base/action/net_l2_interface.pyi

View File

@ -0,0 +1 @@
../../base/action/net_l3_interface.py

View File

@ -0,0 +1 @@
../../base/action/net_l3_interface.pyi

View File

@ -0,0 +1 @@
../../base/action/net_linkagg.py

View File

@ -0,0 +1 @@
../../base/action/net_linkagg.pyi

View File

@ -0,0 +1 @@
../../base/action/net_lldp.py

View File

@ -0,0 +1 @@
../../base/action/net_lldp.pyi

View File

@ -0,0 +1 @@
../../base/action/net_lldp_interface.py

View File

@ -0,0 +1 @@
../../base/action/net_lldp_interface.pyi

View File

@ -0,0 +1 @@
../../base/action/net_logging.py

View File

@ -0,0 +1 @@
../../base/action/net_logging.pyi

View File

@ -0,0 +1 @@
../../base/action/net_ping.py

View File

@ -0,0 +1 @@
../../base/action/net_ping.pyi

View File

@ -0,0 +1 @@
../../base/action/net_static_route.py

View File

@ -0,0 +1 @@
../../base/action/net_static_route.pyi

View File

@ -0,0 +1 @@
../../base/action/net_system.py

View File

@ -0,0 +1 @@
../../base/action/net_system.pyi

Some files were not shown because too many files have changed in this diff Show More