From 711caf62e4624800997ec5049d04be16f904095f Mon Sep 17 00:00:00 2001 From: Dmitriy Rabotyagov Date: Fri, 8 Aug 2025 17:31:02 +0200 Subject: [PATCH] Add molecule testing to the role This adopts old functional tests to be launched with molecule. Patch does not intend to extend or refactor set of existing tests, but to provide a baseline to iterate on and ability to improve coverage with important usecases. Change-Id: Ia93b5adb313d5b930086ce90dafe6a63da092aba Signed-off-by: Dmitriy Rabotyagov --- Vagrantfile | 46 --------------- manual-test.rc | 33 ----------- molecule/default/molecule.yml | 47 +++++++++++++++ requirements.yml | 13 +++++ run_tests.sh | 88 ----------------------------- tasks/haproxy_pre_install.yml | 6 +- tests/ansible-role-requirements.yml | 5 -- tests/host_vars/localhost.yml | 15 ----- tests/inventory | 5 -- tests/prepare.yml | 14 +++++ tests/test-vars.yml | 3 +- tests/test.yml | 52 +---------------- tests/test_service_updates.yml | 12 ++++ tests/verify.yml | 9 +++ tests/verify_service_updates.yml | 9 +++ tox.ini | 17 ++++++ vars/main.yml | 8 +-- zuul.d/project.yaml | 1 + 18 files changed, 134 insertions(+), 249 deletions(-) delete mode 100644 Vagrantfile delete mode 100644 manual-test.rc create mode 100644 molecule/default/molecule.yml create mode 100644 requirements.yml delete mode 100755 run_tests.sh delete mode 100644 tests/ansible-role-requirements.yml delete mode 100644 tests/host_vars/localhost.yml delete mode 100644 tests/inventory create mode 100644 tests/prepare.yml create mode 100644 tests/test_service_updates.yml create mode 100644 tests/verify.yml create mode 100644 tests/verify_service_updates.yml diff --git a/Vagrantfile b/Vagrantfile deleted file mode 100644 index 2a83de4..0000000 --- a/Vagrantfile +++ /dev/null @@ -1,46 +0,0 @@ -# Note: -# This file is maintained in the openstack-ansible-tests repository. -# https://opendev.org/openstack/openstack-ansible-tests/src/Vagrantfile -# -# If you need to perform any change on it, you should modify the central file, -# then, an OpenStack CI job will propagate your changes to every OSA repository -# since every repo uses the same Vagrantfile - -# Verify whether required plugins are installed. -required_plugins = [ "vagrant-disksize" ] -required_plugins.each do |plugin| - if not Vagrant.has_plugin?(plugin) - raise "The vagrant plugin #{plugin} is required. Please run `vagrant plugin install #{plugin}`" - end -end - -Vagrant.configure(2) do |config| - config.vm.provider "virtualbox" do |v| - v.memory = 6144 - v.cpus = 2 - # https://github.com/hashicorp/vagrant/issues/9524 - v.customize ["modifyvm", :id, "--audio", "none"] - end - - config.vm.synced_folder ".", "/vagrant", type: "rsync" - - config.vm.provision "shell", - privileged: false, - inline: <<-SHELL - cd /vagrant - ./run_tests.sh - SHELL - - config.vm.define "centos8" do |centos8| - centos8.vm.box = "centos/8" - end - - config.vm.define "debian10" do |debian10| - debian10.vm.box = "debian/buster64" - end - - config.vm.define "ubuntu2004" do |focal| - focal.disksize.size = "40GB" - focal.vm.box = "ubuntu/focal64" - end -end diff --git a/manual-test.rc b/manual-test.rc deleted file mode 100644 index 7016c45..0000000 --- a/manual-test.rc +++ /dev/null @@ -1,33 +0,0 @@ -export VIRTUAL_ENV=$(pwd) -export ANSIBLE_HOST_KEY_CHECKING=False -export ANSIBLE_SSH_CONTROL_PATH=/tmp/%%h-%%r - -# TODO (odyssey4me) These are only here as they are non-standard folder -# names for Ansible 1.9.x. We are using the standard folder names for -# Ansible v2.x. We can remove this when we move to Ansible 2.x. -export ANSIBLE_ACTION_PLUGINS=${HOME}/.ansible/plugins/action -export ANSIBLE_CALLBACK_PLUGINS=${HOME}/.ansible/plugins/callback -export ANSIBLE_FILTER_PLUGINS=${HOME}/.ansible/plugins/filter -export ANSIBLE_LOOKUP_PLUGINS=${HOME}/.ansible/plugins/lookup - -# This is required as the default is the current path or a path specified -# in ansible.cfg -export ANSIBLE_LIBRARY=${HOME}/.ansible/plugins/library - -# This is required as the default is '/etc/ansible/roles' or a path -# specified in ansible.cfg -export ANSIBLE_ROLES_PATH=${HOME}/.ansible/roles:$(pwd)/.. - -export ANSIBLE_SSH_ARGS="-o ControlMaster=no \ - -o UserKnownHostsFile=/dev/null \ - -o StrictHostKeyChecking=no \ - -o ServerAliveInterval=64 \ - -o ServerAliveCountMax=1024 \ - -o Compression=no \ - -o TCPKeepAlive=yes \ - -o VerifyHostKeyDNS=no \ - -o ForwardX11=no \ - -o ForwardAgent=yes" - -echo "Run manual functional tests by executing the following:" -echo "# ./.tox/functional/bin/ansible-playbook -i tests/inventory tests/test.yml" diff --git a/molecule/default/molecule.yml b/molecule/default/molecule.yml new file mode 100644 index 0000000..7139b0d --- /dev/null +++ b/molecule/default/molecule.yml @@ -0,0 +1,47 @@ +--- +dependency: + name: galaxy + options: + requirements-file: requirements.yml + +driver: + name: docker + +platforms: + - name: "haproxy-${MOLECULE_SCENARIO_NAME}" + image: "${DOCKER_REGISTRY:-quay.io/gotmax23}/${DOCKER_IMAGE_TAG:-debian-systemd:bookworm}" + command: ${DOCKER_COMMAND:-""} + pre_build_image: true + privileged: true + systemd: true + groups: + - service_hosts + +provisioner: + name: ansible + lint: + name: ansible-lint + playbooks: + prepare: ../../tests/prepare.yml + converge: ../../tests/test.yml + side_effect: ../../tests/test_service_updates.yml + config_options: + defaults: + inject_facts_as_vars: false + +scenario: + name: default + test_sequence: + - dependency + - cleanup + - destroy + - syntax + - create + - prepare + - converge + - idempotence + - verify ../../tests/verify.yml + - side_effect + - verify ../../tests/verify_service_updates.yml + - cleanup + - destroy diff --git a/requirements.yml b/requirements.yml new file mode 100644 index 0000000..bb5bee1 --- /dev/null +++ b/requirements.yml @@ -0,0 +1,13 @@ +--- +roles: + - name: pki + src: https://opendev.org/openstack/ansible-role-pki + scm: git + version: master +collections: + - name: community.crypto + source: https://github.com/ansible-collections/community.crypto + type: git + - name: ansible.utils + source: https://github.com/ansible-collections/ansible.utils + type: git diff --git a/run_tests.sh b/run_tests.sh deleted file mode 100755 index 35280c8..0000000 --- a/run_tests.sh +++ /dev/null @@ -1,88 +0,0 @@ -#!/usr/bin/env bash -# Copyright 2015, Rackspace US, Inc. -# -# 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. - -# PURPOSE: -# This script clones the openstack-ansible-tests repository to the -# tests/common folder in order to be able to re-use test components -# for role testing. This is intended to be the thinnest possible -# shim for test execution outside of OpenStack CI. - -# WARNING: -# This file is maintained in the openstack-ansible-tests repository. -# https://opendev.org/openstack/openstack-ansible-tests/src/run_tests.sh -# If you need to modify this file, update the one in the openstack-ansible-tests -# repository and then update this file as well. The purpose of this file is to -# prepare the host and then execute all the tox tests. -# - -## Shell Opts ---------------------------------------------------------------- -set -xeu - -## Vars ---------------------------------------------------------------------- - -WORKING_DIR="$(readlink -f $(dirname $0))" -OSA_PROJECT_NAME="$(sed -n 's|^project=openstack/\(.*\).git$|\1|p' $(pwd)/.gitreview)" - -COMMON_TESTS_PATH="${WORKING_DIR}/tests/common" -TESTING_HOME=${TESTING_HOME:-$HOME} -ZUUL_TESTS_CLONE_LOCATION="/home/zuul/src/opendev.org/openstack/openstack-ansible-tests" - -# Use .gitreview as the key to determine the appropriate -# branch to clone for tests. -TESTING_BRANCH=$(awk -F'=' '/defaultbranch/ {print $2}' "${WORKING_DIR}/.gitreview") -if [[ "${TESTING_BRANCH}" == "" ]]; then - TESTING_BRANCH="master" -fi - -## Main ---------------------------------------------------------------------- - -# Source distribution information -source /etc/os-release || source /usr/lib/os-release - -# Figure out the appropriate package install command -case ${ID,,} in - centos|rhel|fedora|rocky) pkg_mgr_cmd="dnf install -y" ;; - ubuntu|debian) pkg_mgr_cmd="apt-get install -y" ;; - *) echo "unsupported distribution: ${ID,,}"; exit 1 ;; -esac - -# Install git so that we can clone the tests repo if git is not available -which git &>/dev/null || eval sudo "${pkg_mgr_cmd}" git - -# Clone the tests repo for access to the common test script -if [[ ! -d "${COMMON_TESTS_PATH}" ]]; then - # The tests repo doesn't need a clone, we can just - # symlink it. - if [[ "${OSA_PROJECT_NAME}" == "openstack-ansible-tests" ]]; then - ln -s "${WORKING_DIR}" "${COMMON_TESTS_PATH}" - - # In zuul v3 any dependent repository is placed into - # /home/zuul/src/opendev.org, so we check to see - # if there is a tests checkout there already. If so, we - # symlink that and use it. - elif [[ -d "${ZUUL_TESTS_CLONE_LOCATION}" ]]; then - ln -s "${ZUUL_TESTS_CLONE_LOCATION}" "${COMMON_TESTS_PATH}" - - # Otherwise we're clearly not in zuul or using a previously setup - # repo in some way, so just clone it from upstream. - else - git clone -b "${TESTING_BRANCH}" \ - https://opendev.org/openstack/openstack-ansible-tests \ - "${COMMON_TESTS_PATH}" - fi -fi - -# Execute the common test script -source tests/common/run_tests_common.sh diff --git a/tasks/haproxy_pre_install.yml b/tasks/haproxy_pre_install.yml index b184115..a52908d 100644 --- a/tasks/haproxy_pre_install.yml +++ b/tasks/haproxy_pre_install.yml @@ -43,13 +43,13 @@ tags: - haproxy-user -- name: Create haproxy conf.d dir +- name: Create haproxy config directories ansible.builtin.file: path: "{{ item }}" state: directory mode: "0755" - owner: haproxy - group: haproxy + owner: root + group: root with_items: - /etc/haproxy/conf.d - "{{ haproxy_ssl_cert_path }}" diff --git a/tests/ansible-role-requirements.yml b/tests/ansible-role-requirements.yml deleted file mode 100644 index 2f1040b..0000000 --- a/tests/ansible-role-requirements.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -- name: apt_package_pinning - src: https://opendev.org/openstack/openstack-ansible-apt_package_pinning - scm: git - version: master diff --git a/tests/host_vars/localhost.yml b/tests/host_vars/localhost.yml deleted file mode 100644 index f63ad9e..0000000 --- a/tests/host_vars/localhost.yml +++ /dev/null @@ -1,15 +0,0 @@ ---- -# Copyright 2017, Rackspace US, Inc. -# -# 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. -ansible_host: 127.0.0.1 diff --git a/tests/inventory b/tests/inventory deleted file mode 100644 index eab343f..0000000 --- a/tests/inventory +++ /dev/null @@ -1,5 +0,0 @@ -[all] -localhost - -[haproxy_all] -localhost diff --git a/tests/prepare.yml b/tests/prepare.yml new file mode 100644 index 0000000..854841b --- /dev/null +++ b/tests/prepare.yml @@ -0,0 +1,14 @@ +--- +- name: Prepare environment for testing + hosts: service_hosts + vars: + procps_package_name: + redhat: procps-ng + debian: procps + tasks: + - name: Install required packages + ansible.builtin.package: + name: + - python3-cryptography + - "{{ procps_package_name[ansible_facts['os_family'] | lower] }}" + update_cache: "{{ (ansible_facts['os_family'] | lower == 'debian') | ternary(true, omit) }}" diff --git a/tests/test-vars.yml b/tests/test-vars.yml index 9fd2ccc..37b56f7 100644 --- a/tests/test-vars.yml +++ b/tests/test-vars.yml @@ -1,6 +1,7 @@ --- external_lb_vip_address: 127.0.0.1 internal_lb_vip_address: 127.0.0.1 +haproxy_pki_setup_host: "{{ inventory_hostname }}" haproxy_service_configs: - service: haproxy_service_name: test_group @@ -38,4 +39,4 @@ haproxy_service_configs: ip_addr: "127.0.0.1" haproxy_port: 65535 haproxy_balance_type: tcp - state: "{{ absent_service_state }}" + state: present diff --git a/tests/test.yml b/tests/test.yml index 49e1915..f3cae63 100644 --- a/tests/test.yml +++ b/tests/test.yml @@ -14,54 +14,8 @@ # limitations under the License. - name: Playbook for role testing - hosts: localhost - connection: local - user: root - become: true + hosts: service_hosts vars_files: - test-vars.yml - tasks: - - name: Create marker file for idempotence - copy: - content: mark - dest: /tmp/haproxy_pass1 - register: haproxy_pass1 - - - name: Set fact for idempotence test - set_fact: - idempotence_pass_1: "{{ haproxy_pass1 is changed }}" - - - name: Set fact for absent service state - set_fact: - absent_service_state: "{{ (haproxy_pass1 is changed) | ternary('present', 'absent') }}" - - - name: Run the haproxy_server role - include_role: - name: "haproxy_server" - - - name: Run role again on first pass - when: - - "idempotence_pass_1 | bool" - block: - - name: Ensure the absent service is present - stat: - path: "/etc/haproxy/conf.d/test_absent_service" - register: absent_services - failed_when: not absent_services.stat.exists - - - name: Set fact for absent service state - set_fact: - absent_service_state: "absent" - - - name: Run the haproxy_server role (again) - include_role: - name: "haproxy_server" - - - name: Ensure the absent service is missing - stat: - path: "/etc/haproxy/conf.d/test_absent_service" - register: absent_services - when: - - "not (idempotence_pass_1 | bool)" - failed_when: absent_services.stat.exists - + roles: + - "{{ playbook_dir | dirname | basename }}" diff --git a/tests/test_service_updates.yml b/tests/test_service_updates.yml new file mode 100644 index 0000000..9e781d5 --- /dev/null +++ b/tests/test_service_updates.yml @@ -0,0 +1,12 @@ +--- +- name: Playbook for role testing + hosts: service_hosts + vars: + external_lb_vip_address: 127.0.0.1 + internal_lb_vip_address: 127.0.0.1 + haproxy_pki_setup_host: "{{ inventory_hostname }}" + haproxy_service_configs: + - haproxy_service_name: test_absent_service + state: absent + roles: + - "{{ playbook_dir | dirname | basename }}" diff --git a/tests/verify.yml b/tests/verify.yml new file mode 100644 index 0000000..5648751 --- /dev/null +++ b/tests/verify.yml @@ -0,0 +1,9 @@ +--- +- name: Testing result after role re-run + hosts: service_hosts + tasks: + - name: Ensure the absent service is present + ansible.builtin.stat: + path: "/etc/haproxy/conf.d/test_absent_service" + register: absent_services + failed_when: not absent_services.stat.exists diff --git a/tests/verify_service_updates.yml b/tests/verify_service_updates.yml new file mode 100644 index 0000000..bc1d381 --- /dev/null +++ b/tests/verify_service_updates.yml @@ -0,0 +1,9 @@ +--- +- name: Testing result after role re-run + hosts: service_hosts + tasks: + - name: Ensure the absent service is missing + ansible.builtin.stat: + path: "/etc/haproxy/conf.d/test_absent_service" + register: absent_services + failed_when: absent_services.stat.exists diff --git a/tox.ini b/tox.ini index e14fca7..72bf2e2 100644 --- a/tox.ini +++ b/tox.ini @@ -94,3 +94,20 @@ commands = {[testenv:bashate]commands} {[testenv:ansible-lint]commands} {[testenv:ansible-syntax]commands} + +[testenv:molecule] +# You can use DOCKER_REGISTRY and DOCKER_IMAGE_TAG to switch between +# tested distros. I.e: +# DOCKER_IMAGE_TAG=ubuntu-systemd:jammy tox -e molecule +deps = + -c{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master} + -r{env:OSA_TEST_REQUIREMENTS_FILE:https://opendev.org/openstack/openstack-ansible/raw/branch/{env:TEST_BRANCH:master}/test-requirements.txt} + +commands = + molecule test + +passenv = + {[testenv]passenv} + DOCKER_REGISTRY + DOCKER_IMAGE_TAG + DOCKER_COMMAND diff --git a/vars/main.yml b/vars/main.yml index 26a3867..a9968b2 100644 --- a/vars/main.yml +++ b/vars/main.yml @@ -65,7 +65,7 @@ _haproxy_pki_install_certificates: | 'src': haproxy_user_ssl_cert | default(haproxy_pki_certs_path ~ _cert_basename ~ '.crt'), 'dest': haproxy_ssl_temp_path ~ _cert_basename ~ '.crt', 'owner': 'root', - 'group': 'root', + 'group': 'haproxy', 'mode': '0644' } ) @@ -75,8 +75,8 @@ _haproxy_pki_install_certificates: | 'src': haproxy_user_ssl_key | default(haproxy_pki_keys_path ~ _cert_basename ~ '.key.pem'), 'dest': haproxy_ssl_temp_path ~ _cert_basename ~ '.key', 'owner': 'root', - 'group': 'root', - 'mode': '0644' + 'group': 'haproxy', + 'mode': '0640' } ) %} @@ -87,7 +87,7 @@ _haproxy_pki_install_certificates: | 'src': haproxy_user_ssl_ca_cert | default(haproxy_pki_intermediate_cert_path), 'dest': haproxy_ssl_temp_path ~ _cert_basename ~ '-ca.crt', 'owner': 'root', - 'group': 'root', + 'group': 'haproxy', 'mode': '0644' }) %} diff --git a/zuul.d/project.yaml b/zuul.d/project.yaml index 5a7f0fc..875b36e 100644 --- a/zuul.d/project.yaml +++ b/zuul.d/project.yaml @@ -16,6 +16,7 @@ - project: templates: - openstack-ansible-linters-jobs + - openstack-ansible-molecule - openstack-ansible-deploy-infra_lxc-jobs - openstack-ansible-deploy-aio_metal-jobs - openstack-ansible-upgrade-infra_lxc-jobs