Add openstack_user_config verification playbook as healthcheck
The playbook is designed to test basic sanity of resulting openstack_user_config and to ensure to weird issues are not introduced with some of latest changes. Eventually, this playbook is handy in a CI pipeline, to prevent faulty config to be published and promoted to a region. We also are to use the playbook in a molecule test to ensure we're having sane examples in docs Depends-On: https://review.opendev.org/c/openstack/openstack-ansible/+/945025 Change-Id: I50bb8b05cdf0ed8fa486f5b5d65405b3afa84bae
This commit is contained in:
29
molecule/user_config/group_vars/all.yml
Normal file
29
molecule/user_config/group_vars/all.yml
Normal file
@@ -0,0 +1,29 @@
|
||||
---
|
||||
# Copyright 2025, Cleura AB
|
||||
#
|
||||
# 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.
|
||||
|
||||
molecule_packages:
|
||||
debian:
|
||||
- git
|
||||
- python3-dev
|
||||
- python3-packaging
|
||||
- python3-pip
|
||||
- python3-setuptools
|
||||
- python3-venv
|
||||
redhat:
|
||||
- git-core
|
||||
- python3-devel
|
||||
- python3-packaging
|
||||
- python3-pip
|
||||
- python3-setuptools
|
||||
34
molecule/user_config/group_vars/deploy_host.yml
Normal file
34
molecule/user_config/group_vars/deploy_host.yml
Normal file
@@ -0,0 +1,34 @@
|
||||
---
|
||||
# Copyright 2025, Cleura AB
|
||||
#
|
||||
# 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.
|
||||
|
||||
openstack_test_service_groups_length: 3
|
||||
openstack_test_service_groups:
|
||||
- cinder_api
|
||||
- galera_all
|
||||
- glance_api
|
||||
- keystone_all
|
||||
- neutron_server
|
||||
- nova_api_os_compute
|
||||
- placement_all
|
||||
- rabbitmq_all
|
||||
|
||||
openstack_test_mutualy_exclusive_groups:
|
||||
- ['nova_api_os_compute', 'nova_compute']
|
||||
- ['neutron_server', 'neutron_ovn_northd']
|
||||
- ['neutron_server', 'neutron_ovn_controller']
|
||||
- ['neutron_ovn_gateway', 'nova_compute']
|
||||
|
||||
openstack_test_collocated_groups:
|
||||
- ['nova_compute', 'neutron_ovn_controller']
|
||||
33
molecule/user_config/molecule.yml
Normal file
33
molecule/user_config/molecule.yml
Normal file
@@ -0,0 +1,33 @@
|
||||
---
|
||||
dependency:
|
||||
name: galaxy
|
||||
|
||||
driver:
|
||||
name: docker
|
||||
|
||||
platforms:
|
||||
- name: "integrated-${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:
|
||||
- deploy_host
|
||||
|
||||
provisioner:
|
||||
name: ansible
|
||||
lint:
|
||||
name: ansible-lint
|
||||
config_options:
|
||||
defaults:
|
||||
inject_facts_as_vars: false
|
||||
inventory:
|
||||
links:
|
||||
group_vars: ./group_vars/
|
||||
playbooks:
|
||||
prepare: prepare.yml
|
||||
converge: ../../playbooks/healthcheck/user_config.yml
|
||||
|
||||
scenario:
|
||||
name: user_config
|
||||
61
molecule/user_config/prepare.yml
Normal file
61
molecule/user_config/prepare.yml
Normal file
@@ -0,0 +1,61 @@
|
||||
---
|
||||
# Copyright 2025, Cleura AB
|
||||
#
|
||||
# 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: Simulating valid deploy host
|
||||
hosts: deploy_host
|
||||
vars:
|
||||
testing_branch: "{{ lookup('ansible.builtin.env', 'TEST_BRANCH', default='master') }}"
|
||||
tasks:
|
||||
- name: Create required folders
|
||||
ansible.builtin.file:
|
||||
path: /etc/openstack_deploy
|
||||
state: directory
|
||||
mode: "0755"
|
||||
|
||||
- name: Update apt cache
|
||||
ansible.builtin.apt:
|
||||
update_cache: true
|
||||
cache_valid_time: 3600
|
||||
when:
|
||||
- ansible_facts['os_family'] | lower == 'debian'
|
||||
|
||||
- name: Install required python3 packages
|
||||
ansible.builtin.package:
|
||||
name: "{{ molecule_packages[ansible_facts['os_family'] | lower] }}"
|
||||
state: present
|
||||
|
||||
- name: Download sample openstack_user_config
|
||||
ansible.builtin.get_url:
|
||||
url: https://opendev.org/openstack/openstack-ansible/raw/branch/{{ testing_branch }}/etc/openstack_deploy/openstack_user_config.yml.prod.example
|
||||
dest: /etc/openstack_deploy/openstack_user_config.yml
|
||||
mode: "0644"
|
||||
register: download_config
|
||||
until: download_config is success
|
||||
retries: 5
|
||||
delay: 2
|
||||
|
||||
- name: Install openstack-ansible as python package
|
||||
ansible.builtin.pip:
|
||||
name: "git+https://opendev.org/openstack/openstack-ansible@{{ testing_branch }}#egg=openstack-ansible"
|
||||
extra_args: >-
|
||||
-c{{ lookup('ansible.builtin.env', 'TOX_CONSTRAINTS_FILE', default='https://releases.openstack.org/constraints/upper/master') }}
|
||||
-rhttps://opendev.org/openstack/openstack-ansible/raw/branch/{{ testing_branch }}/requirements.txt
|
||||
-e
|
||||
virtualenv: "/opt/ansible-runtime"
|
||||
virtualenv_command: "python3 -m venv"
|
||||
register: install_osa
|
||||
until: install_osa is success
|
||||
retries: 5
|
||||
delay: 2
|
||||
137
playbooks/healthcheck/user_config.yml
Normal file
137
playbooks/healthcheck/user_config.yml
Normal file
@@ -0,0 +1,137 @@
|
||||
---
|
||||
# Copyright 2025, Cleura AB
|
||||
#
|
||||
# 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.
|
||||
|
||||
# Playbook to ensure that resulting inventory is generated according to
|
||||
# deployer intentions.
|
||||
# Sample variables to control test behaviour of the playbook:
|
||||
#
|
||||
# openstack_test_user_config_dir: /etc/openstack_deploy
|
||||
# openstack_test_service_groups_length: 3
|
||||
# openstack_test_service_groups:
|
||||
# - galera_all
|
||||
# - glance_api
|
||||
# - keystone_all
|
||||
# - neutron_server
|
||||
# - nova_api_os_compute
|
||||
# - placement_all
|
||||
# - rabbitmq_all
|
||||
#
|
||||
# openstack_test_mutualy_exclusive_groups:
|
||||
# - ['nova_api_os_compute', 'nova_compute']
|
||||
# - ['neutron_server', 'neutron_ovn_northd']
|
||||
# - ['neutron_server', 'neutron_ovn_controller']
|
||||
# - ['neutron_ovn_gateway', 'nova_compute']
|
||||
#
|
||||
# openstack_test_collocated_groups:
|
||||
# - ['nova_compute', 'neutron_ovn_controller']
|
||||
|
||||
- name: Testing resulting inventory from provided openstack_user_config
|
||||
hosts: "{{ ('deploy_host' in groups) | ternary('deploy_host', 'localhost') }}"
|
||||
tasks:
|
||||
- name: Verify dynamic_inventory is not failing
|
||||
ansible.builtin.command: >-
|
||||
/opt/ansible-runtime/bin/openstack-ansible-inventory --config {{ openstack_test_user_config_dir | default('/etc/openstack_deploy') }}
|
||||
changed_when: false
|
||||
register: dynamic_inventory
|
||||
|
||||
- name: Register OSA inventory content variable
|
||||
ansible.builtin.set_fact:
|
||||
osa_inventory: "{{ dynamic_inventory.stdout | from_json }}"
|
||||
|
||||
- name: Get all real hosts out of children
|
||||
ansible.builtin.set_fact:
|
||||
service_hosts: |
|
||||
{% set hosts = {} %}
|
||||
{% for service in openstack_test_service_groups | default([]) %}
|
||||
{% if osa_inventory[service]['hosts'] | length > 0 %}
|
||||
{% set _ = hosts.update({service: osa_inventory[service]['hosts']}) %}
|
||||
{% else %}
|
||||
{% set _ = hosts.update({service: []}) %}
|
||||
{% for group in osa_inventory[service]['children'] %}
|
||||
{% set _ = hosts[service].extend(osa_inventory[group]['hosts']) %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{{ hosts }}
|
||||
|
||||
- name: Ensure that services are not running on bare metal
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- >-
|
||||
'is_metal' not in osa_inventory['_meta']['hostvars'][item]['properties'] or
|
||||
not osa_inventory['_meta']['hostvars'][item]['properties']['is_metal'] | bool
|
||||
- osa_inventory['_meta']['hostvars'][item]['container_tech'] == 'lxc'
|
||||
with_items: "{{ service_hosts.values() | flatten }}"
|
||||
tags:
|
||||
- skip_ansible_lint
|
||||
|
||||
- name: Ensure that each group has hosts {{ openstack_test_service_groups_length | default(3) }}
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- item.value | length == openstack_test_service_groups_length | default(3)
|
||||
with_dict: "{{ service_hosts }}"
|
||||
|
||||
- name: Ensure that containers are split over different physical hosts
|
||||
vars:
|
||||
physical_hosts: |
|
||||
{% set p_hosts = [] %}
|
||||
{% for service in item.value %}
|
||||
{% set _ = p_hosts.append(osa_inventory['_meta']['hostvars'][service]['physical_host']) %}
|
||||
{% endfor %}
|
||||
{{ p_hosts }}
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- physical_hosts | unique | length == openstack_test_service_groups_length | default(3)
|
||||
with_dict: "{{ service_hosts }}"
|
||||
|
||||
- name: Verify that openstack_test_mutualy_exclusive_groups are respected
|
||||
vars:
|
||||
exclusive_hosts: |
|
||||
{% set hosts = {} %}
|
||||
{% for service in openstack_test_mutualy_exclusive_groups | default([]) | flatten | unique %}
|
||||
{% if osa_inventory[service]['hosts'] | length > 0 %}
|
||||
{% set _ = hosts.update({service: osa_inventory[service]['hosts']}) %}
|
||||
{% else %}
|
||||
{% set _ = hosts.update({service: []}) %}
|
||||
{% for group in osa_inventory[service]['children'] %}
|
||||
{% set _ = hosts[service].extend(osa_inventory[group]['hosts']) %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{{ hosts }}
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- (exclusive_hosts[item[0]] | select('in', exclusive_hosts[item[1]])) | length == 0
|
||||
loop: "{{ openstack_test_mutualy_exclusive_groups | default([]) }}"
|
||||
|
||||
- name: Verify that second element of openstack_test_collocated_groups contain all hosts from first element
|
||||
vars:
|
||||
collocated_hosts: |
|
||||
{% set hosts = {} %}
|
||||
{% for service in openstack_test_collocated_groups | default([]) | flatten | unique %}
|
||||
{% if osa_inventory[service]['hosts'] | length > 0 %}
|
||||
{% set _ = hosts.update({service: osa_inventory[service]['hosts']}) %}
|
||||
{% else %}
|
||||
{% set _ = hosts.update({service: []}) %}
|
||||
{% for group in osa_inventory[service]['children'] %}
|
||||
{% set _ = hosts[service].extend(osa_inventory[group]['hosts']) %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{{ hosts }}
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- (collocated_hosts[item[0]] | select('in', collocated_hosts[item[1]])) == collocated_hosts[item[0]]
|
||||
loop: "{{ openstack_test_collocated_groups | default([]) }}"
|
||||
4
tox.ini
4
tox.ini
@@ -65,10 +65,12 @@ deps =
|
||||
-r{env:OSA_TEST_REQUIREMENTS_FILE:https://opendev.org/openstack/openstack-ansible/raw/branch/{env:TEST_BRANCH:master}/test-requirements.txt}
|
||||
|
||||
commands =
|
||||
molecule test
|
||||
molecule test -s default
|
||||
molecule test -s user_config
|
||||
|
||||
passenv =
|
||||
{[testenv]passenv}
|
||||
DOCKER_REGISTRY
|
||||
DOCKER_IMAGE_TAG
|
||||
DOCKER_COMMAND
|
||||
TEST_BRANCH
|
||||
|
||||
Reference in New Issue
Block a user