From e9a331b0eda2de174fe2156a6bb002cdbfacc79f Mon Sep 17 00:00:00 2001 From: "Gael Chamoulaud (Strider)" Date: Wed, 4 Mar 2020 17:19:18 +0100 Subject: [PATCH] Add zuul and molecule tests structure Signed-off-by: Gael Chamoulaud (Strider) --- scripts/bindep-install | 45 ++++++++++++ scripts/run-local-test | 70 +++++++++++++++++++ tests/conftest.py | 18 +++++ tests/hosts.ini | 1 + tests/prepare-test-host.yml | 68 ++++++++++++++++++ tests/test_molecule.py | 44 ++++++++++++ zuul.d/base.yaml | 15 ++++ zuul.d/layout.yaml | 15 ++++ zuul.d/molecule.yaml | 124 +++++++++++++++++++++++++++++++++ zuul.d/playbooks/pre.yml | 28 ++++++++ zuul.d/playbooks/run-local.yml | 13 ++++ zuul.d/playbooks/run.yml | 19 +++++ 12 files changed, 460 insertions(+) create mode 100755 scripts/bindep-install create mode 100755 scripts/run-local-test create mode 100644 tests/conftest.py create mode 100644 tests/hosts.ini create mode 100644 tests/prepare-test-host.yml create mode 100644 tests/test_molecule.py create mode 100644 zuul.d/base.yaml create mode 100644 zuul.d/layout.yaml create mode 100644 zuul.d/molecule.yaml create mode 100644 zuul.d/playbooks/pre.yml create mode 100644 zuul.d/playbooks/run-local.yml create mode 100644 zuul.d/playbooks/run.yml diff --git a/scripts/bindep-install b/scripts/bindep-install new file mode 100755 index 0000000..5cc239a --- /dev/null +++ b/scripts/bindep-install @@ -0,0 +1,45 @@ +#!/usr/bin/env bash +# Copyright 2019 Red Hat, Inc. +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + + +## Shell Opts ---------------------------------------------------------------- + +set -o pipefail +set -xeuo + + +## Vars ---------------------------------------------------------------------- + +export BINDEP_FILE="${BINDEP_FILE:-$(dirname $(readlink -f ${BASH_SOURCE[0]}))/../bindep.txt}" + + +## Main ---------------------------------------------------------------------- + +# Source distribution information +source /etc/os-release || source /usr/lib/os-release +RHT_PKG_MGR=$(command -v dnf || command -v yum) + +# NOTE(cloudnull): Get a list of packages to install with bindep. If packages +# need to be installed, bindep exits with an exit code of 1. +BINDEP_PKGS=$(bindep -b -f "${BINDEP_FILE}" test || true) + +if [[ ${#BINDEP_PKGS} > 0 ]]; then + case "${ID,,}" in + amzn|rhel|centos|fedora) + sudo "${RHT_PKG_MGR}" install -y ${BINDEP_PKGS} + ;; + esac +fi \ No newline at end of file diff --git a/scripts/run-local-test b/scripts/run-local-test new file mode 100755 index 0000000..5bba19d --- /dev/null +++ b/scripts/run-local-test @@ -0,0 +1,70 @@ +#!/usr/bin/env bash +# Copyright 2019 Red Hat, Inc. +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + + +## Shell Opts ---------------------------------------------------------------- + +set -o pipefail +set -xeuo + +## Vars ---------------------------------------------------------------------- + +export PROJECT_DIR="$(dirname $(readlink -f ${BASH_SOURCE[0]}))/../" +export ROLE_NAME="${ROLE_NAME:-$1}" +export TRIPLEO_JOB_ANSIBLE_ARGS=${TRIPLEO_JOB_ANSIBLE_ARGS:-"-v"} + +## Main ---------------------------------------------------------------------- + +# Source distribution information +source /etc/os-release || source /usr/lib/os-release +RHT_PKG_MGR=$(command -v dnf || command -v yum) +PYTHON_EXEC=$(command -v python3 || command -v python) + +# Install the one requirement we need to run any local test +case "${ID,,}" in + amzn|rhel|centos|fedora) + sudo "${RHT_PKG_MGR}" install -y python*-virtualenv + ;; +esac + +# Create a virtual env +"${PYTHON_EXEC}" -m virtualenv --system-site-packages "${HOME}/test-python" + +# Run bindep +"${HOME}/test-python/bin/pip" install pip setuptools bindep --upgrade +"${PROJECT_DIR}/scripts/bindep-install" + +# Install local requirements +if [[ -d "${HOME}/.cache/pip/wheels" ]]; then + rm -rf "${HOME}/.cache/pip/wheels" +fi +"${HOME}/test-python/bin/pip" install \ + -r "${PROJECT_DIR}/requirements.txt" \ + -r "${PROJECT_DIR}/test-requirements.txt" \ + -r "${PROJECT_DIR}/molecule-requirements.txt" + +# Run local test +PS1="[\u@\h \W]\$" source "${HOME}/test-python/bin/activate" +source "${PROJECT_DIR}/ansible-test-env.rc" +export ANSIBLE_ROLES_PATH="${ANSIBLE_ROLES_PATH}:${HOME}/zuul-jobs/roles" +ansible-playbook -i "${PROJECT_DIR}/tests/hosts.ini" \ + -e "tripleo_src=$(realpath --relative-to="${HOME}" "${PROJECT_DIR}")" \ + -e "validations_common_role_name=${ROLE_NAME}" \ + -e "tripleo_job_ansible_args='${TRIPLEO_JOB_ANSIBLE_ARGS}'" \ + -e "ansible_user=${USER}" \ + -e "ansible_user_dir=${HOME}" \ + "${PROJECT_DIR}/tests/prepare-test-host.yml" \ + "${PROJECT_DIR}/zuul.d/playbooks/run-local.yml" diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..b88a113 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,18 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +def pytest_addoption(parser): + parser.addoption('--scenario', help='scenario setting') + parser.addoption( + '--ansible-args', help='ansible args passed into test runner.') diff --git a/tests/hosts.ini b/tests/hosts.ini new file mode 100644 index 0000000..8365a58 --- /dev/null +++ b/tests/hosts.ini @@ -0,0 +1 @@ +test ansible_connection=local ansible_host=localhost \ No newline at end of file diff --git a/tests/prepare-test-host.yml b/tests/prepare-test-host.yml new file mode 100644 index 0000000..e870fc2 --- /dev/null +++ b/tests/prepare-test-host.yml @@ -0,0 +1,68 @@ +--- +# Copyright 2019 Red Hat, Inc. +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + + +- name: pre prepare + hosts: all + gather_facts: false + tasks: + - name: set basic user fact + fail: + msg: >- + The variable `ansible_user` set this option and try again. On the + CLI this can be defined with "-e ansible_user=${USER}" + when: + - ansible_user is undefined + + - name: set basic home fact + fail: + msg: >- + The variable `ansible_user_dir` set this option and try again. On + the CLI this can be defined with "-e ansible_user_dir=${HOME}" + when: + - ansible_user_dir is undefined + + - name: Ensure the user has a .ssh directory + file: + path: "{{ ansible_user_dir }}/.ssh" + state: directory + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + mode: "0700" + + - name: Create ssh key pair + user: + name: "{{ ansible_user }}" + generate_ssh_key: true + ssh_key_bits: 2048 + ssh_key_file: "{{ ansible_user_dir }}/.ssh/id_rsa" + + - name: Slurp pub key + slurp: + src: "{{ ansible_user_dir ~ '/.ssh/id_rsa.pub' }}" + register: pub_key + + - name: Ensure can ssh to can connect to localhost + authorized_key: + user: "{{ ansible_user }}" + key: "{{ pub_key['content'] | b64decode }}" + + - name: Get the zuul/zuul-jobs repo + git: + repo: https://opendev.org/zuul/zuul-jobs + dest: "{{ ansible_user_dir }}/zuul-jobs" + version: master + force: true diff --git a/tests/test_molecule.py b/tests/test_molecule.py new file mode 100644 index 0000000..edc40c6 --- /dev/null +++ b/tests/test_molecule.py @@ -0,0 +1,44 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +import pytest +import subprocess + + +def test_molecule(pytestconfig): + cmd = ['python', '-m', 'molecule'] + scenario = pytestconfig.getoption("scenario") + ansible_args = pytestconfig.getoption("ansible_args") + + if ansible_args: + cmd.append('converge') + if scenario: + cmd.extend(['--scenario-name', scenario]) + cmd.append('--') + cmd.extend(ansible_args.split()) + else: + cmd.append('test') + if scenario: + cmd.extend(['--scenario-name', scenario]) + else: + cmd.append('--all') + + try: + assert subprocess.call(cmd) == 0 + finally: + if ansible_args: + cmd = ['python', '-m', 'molecule', 'destroy'] + if scenario: + cmd.extend(['--scenario-name', scenario]) + subprocess.call(cmd) diff --git a/zuul.d/base.yaml b/zuul.d/base.yaml new file mode 100644 index 0000000..e9bb2e4 --- /dev/null +++ b/zuul.d/base.yaml @@ -0,0 +1,15 @@ +--- +- job: + description: Base validations-common job + name: validations-common-centos-7-base + nodeset: centos-7 + parent: base + success-url: "reports.html" + failure-url: "reports.html" + pre-run: + - tests/prepare-test-host.yml + - zuul.d/playbooks/pre.yml + run: + - zuul.d/playbooks/run.yml + timeout: 1800 + voting: true diff --git a/zuul.d/layout.yaml b/zuul.d/layout.yaml new file mode 100644 index 0000000..b837a1b --- /dev/null +++ b/zuul.d/layout.yaml @@ -0,0 +1,15 @@ +- project: + templates: + - tripleo-multinode-container-minimal + - openstack-python3-ussuri-jobs + - validations-common-molecule-jobs + - check-requirements + - release-notes-jobs-python3 + check: + jobs: + - openstack-tox-linters + - openstack-tox-lower-constraints + gate: + jobs: + - openstack-tox-linters + - openstack-tox-lower-constraints diff --git a/zuul.d/molecule.yaml b/zuul.d/molecule.yaml new file mode 100644 index 0000000..f1f74dd --- /dev/null +++ b/zuul.d/molecule.yaml @@ -0,0 +1,124 @@ +--- +- project-template: + check: + jobs: + - validations-common-centos-7-molecule-advanced_format_512e_support + - validations-common-centos-7-molecule-check_latest_packages_version + - validations-common-centos-7-molecule-dns + - validations-common-centos-7-molecule-haproxy + - validations-common-centos-7-molecule-ntp + - validations-common-centos-7-molecule-service_status + - validations-common-centos-7-molecule-stonith_exists + - validations-common-centos-7-molecule-undercloud_cpu + - validations-common-centos-7-molecule-undercloud_disk_space + - validations-common-centos-7-molecule-undercloud_ram + - validations-common-centos-7-molecule-undercloud_selinux_mode + - validations-common-centos-7-molecule-validate_selinux + - validations-common-centos-7-molecule-xfs_check_ftype + gate: + jobs: + - validations-common-centos-7-molecule-check_latest_packages_version + - validations-common-centos-7-molecule-dns + - validations-common-centos-7-molecule-haproxy + - validations-common-centos-7-molecule-stonith_exists + - validations-common-centos-7-molecule-undercloud_cpu + - validations-common-centos-7-molecule-undercloud_disk_space + - validations-common-centos-7-molecule-undercloud_ram + - validations-common-centos-7-molecule-validate_selinux + name: validations-common-molecule-jobs +- job: + files: + - ^roles/undercloud_selinux_mode/.* + name: validations-common-centos-7-molecule-undercloud_selinux_mode + parent: validations-common-centos-7-base + vars: + validations_common_role_name: undercloud_selinux_mode + voting: false +- job: + files: + - ^roles/ntp/.* + name: validations-common-centos-7-molecule-ntp + parent: validations-common-centos-7-base + vars: + validations_common_role_name: ntp + voting: false +- job: + files: + - ^roles/service_status/.* + name: validations-common-centos-7-molecule-service_status + parent: validations-common-centos-7-base + vars: + validations_common_role_name: service_status + voting: false +- job: + files: + - ^roles/advanced_format_512e_support/.* + name: validations-common-centos-7-molecule-advanced_format_512e_support + parent: validations-common-centos-7-base + vars: + validations_common_role_name: advanced_format_512e_support + voting: false +- job: + files: + - ^roles/dns/.* + name: validations-common-centos-7-molecule-dns + parent: validations-common-centos-7-base + vars: + validations_common_role_name: dns +- job: + files: + - ^roles/haproxy/.* + name: validations-common-centos-7-molecule-haproxy + parent: validations-common-centos-7-base + vars: + validations_common_role_name: haproxy +- job: + files: + - ^roles/undercloud_cpu/.* + name: validations-common-centos-7-molecule-undercloud_cpu + parent: validations-common-centos-7-base + vars: + validations_common_role_name: undercloud_cpu +- job: + files: + - ^roles/undercloud_ram/.* + name: validations-common-centos-7-molecule-undercloud_ram + parent: validations-common-centos-7-base + vars: + validations_common_role_name: undercloud_ram +- job: + files: + - ^roles/undercloud_disk_space/.* + name: validations-common-centos-7-molecule-undercloud_disk_space + parent: validations-common-centos-7-base + vars: + validations_common_role_name: undercloud_disk_space +- job: + files: + - ^roles/xfs_check_ftype/.* + name: validations-common-centos-7-molecule-xfs_check_ftype + parent: validations-common-centos-7-base + vars: + validations_common_role_name: xfs_check_ftype + voting: false +- job: + files: + - ^roles/stonith_exists/.* + name: validations-common-centos-7-molecule-stonith_exists + parent: validations-common-centos-7-base + vars: + validations_common_role_name: stonith_exists +- job: + files: + - ^roles/check_latest_packages_version/.* + name: validations-common-centos-7-molecule-check_latest_packages_version + parent: validations-common-centos-7-base + vars: + validations_common_role_name: check_latest_packages_version +- job: + files: + - ^roles/validate_selinux/.* + name: validations-common-centos-7-molecule-validate_selinux + parent: validations-common-centos-7-base + vars: + validations_common_role_name: validate_selinux diff --git a/zuul.d/playbooks/pre.yml b/zuul.d/playbooks/pre.yml new file mode 100644 index 0000000..aa46e5e --- /dev/null +++ b/zuul.d/playbooks/pre.yml @@ -0,0 +1,28 @@ +--- +- hosts: all + pre_tasks: + - name: Ensure output dirs + file: + path: "{{ ansible_user_dir }}/zuul-output/logs" + state: directory + + - name: Setup bindep + pip: + name: "bindep" + virtualenv: "{{ ansible_user_dir }}/test-python" + virtualenv_site_packages: true + + - name: Run bindep + shell: |- + . {{ ansible_user_dir }}/test-python/bin/activate + {{ ansible_user_dir }}/{{ zuul.project.src_dir }}/scripts/bindep-install + become: true + changed_when: false + + - name: Setup test-python + pip: + requirements: "{{ ansible_user_dir }}/{{ zuul.project.src_dir }}/molecule-requirements.txt" + virtualenv: "{{ ansible_user_dir }}/test-python" + virtualenv_site_packages: true + roles: + - role: install-docker diff --git a/zuul.d/playbooks/run-local.yml b/zuul.d/playbooks/run-local.yml new file mode 100644 index 0000000..cd0f83e --- /dev/null +++ b/zuul.d/playbooks/run-local.yml @@ -0,0 +1,13 @@ +--- +- hosts: all + tasks: + - name: set basic zuul fact + set_fact: + zuul: + project: + src_dir: "{{ tripleo_src }}" + ansible_connection: ssh + +- import_playbook: pre.yml + +- import_playbook: run.yml diff --git a/zuul.d/playbooks/run.yml b/zuul.d/playbooks/run.yml new file mode 100644 index 0000000..9df83dc --- /dev/null +++ b/zuul.d/playbooks/run.yml @@ -0,0 +1,19 @@ +--- + +- hosts: all + environment: + ANSIBLE_LOG_PATH: "{{ ansible_user_dir }}/zuul-output/logs/ansible-execution.log" + tasks: + - name: Run role test job + shell: |- + . {{ ansible_user_dir }}/test-python/bin/activate + . {{ ansible_user_dir }}/{{ zuul.project.src_dir }}/ansible-test-env.rc + pytest --color=no \ + --html={{ ansible_user_dir }}/zuul-output/logs/reports.html \ + --self-contained-html \ + --ansible-args='{{ tripleo_job_ansible_args | default("") }}' \ + {{ ansible_user_dir }}/{{ zuul.project.src_dir }}/tests/test_molecule.py + args: + chdir: "{{ ansible_user_dir }}/{{ zuul.project.src_dir }}/roles/{{ validations_common_role_name }}" + executable: /bin/bash + changed_when: false