Retire Tripleo: remove repo content

TripleO project is retiring
- https://review.opendev.org/c/openstack/governance/+/905145

this commit remove the content of this project repo

Change-Id: I4c7d62a3a3ef5601d04375677e1ea07f9cd9eff9
This commit is contained in:
Ghanshyam Mann 2024-02-24 11:34:32 -08:00
parent 44fdc64724
commit 9080d003d9
627 changed files with 8 additions and 25639 deletions

View File

@ -1,37 +0,0 @@
exclude_paths:
- releasenotes/
- ci/playbooks/
parseable: true
quiet: false
rulesdir:
- .ansible-lint_rules/
# Mock modules or roles in order to pass ansible-playbook --syntax-check
mock_modules:
- hiera # Modules can only be installed by rpm
- validations_read_ini # Modules can only be installed by rpm
- warn # Modules can only be installed by rpm
- tripleo_overcloud_role_list # Modules can only be installed by rpm
- tripleo_overcloud_role_show # Modules can only be installed by rpm
mock_roles:
- check_latest_packages_version
skip_list:
# Lines should be no longer than 120 chars.
- '204'
# Using command rather module we have where
# we need to use curl or rsync.
- '303'
# shell tasks uses pipeline without pipefail,
# this requires refactoring, skip for now.
- '306'
# Tasks that run when changed should likely be handlers
# this requires refactoring, skip for now.
- '503'
# meta/main.yml should contain relevant info
- '701'
# Tags must contain lowercase letters and digits only
- '702'
# meta/main.yml default values should be changed
- '703'
verbosity: 1

View File

@ -1,197 +0,0 @@
import os
import yaml
from ansiblelint.errors import MatchError
from ansiblelint.rules import AnsibleLintRule
class ValidationHasMetadataRule(AnsibleLintRule):
id = '750'
shortdesc = 'Validation playbook must have mandatory metadata'
info = """
---
- hosts: localhost
vars:
metadata:
name: Validation Name
description: >
A full description of the validation.
groups:
- group1
- group2
- group3
categories:
- category1
- category2
- category3
products:
- product1
- product2
- product3
"""
description = (
"The Validation playbook must have mandatory metadata:\n"
"```{}```".format(info)
)
severity = 'HIGH'
tags = ['metadata']
no_vars_found = "The validation playbook must contain a 'vars' dictionary"
no_meta_found = (
"The validation playbook must contain "
"a 'metadata' dictionary under vars"
)
no_classification_found = \
"*metadata* should contain a list of {classification}"
unknown_classifications_found = (
"Unkown {classification_key}(s) '{unknown_classification}' found! "
"The official list of {classification_key} are '{known_classification}'. "
)
how_to_add_classification = {
'groups': (
"To add a new validation group, please add it in the groups.yaml "
"file at the root of the tripleo-validations project."
)
}
def get_classifications(self, classification='groups'):
"""Returns a list classification names
defined for tripleo-validations in the '{classification}.yaml' file
located in the base repo directory.
"""
file_path = os.path.abspath(classification + '.yaml')
try:
with open(file_path, "r") as definitions:
contents = yaml.safe_load(definitions)
except (PermissionError, OSError):
raise RuntimeError(
"{}.yaml file at '{}' inacessible.".format(
classification,
file_path))
results = [name for name, _ in contents.items()]
return results
def check_classification(self, metadata, path,
classification_key, strict=False):
"""Check validatity of validation classifications,
such as groups, categories and products.
This one is tricky.
Empty lists in python evaluate as false
So we can't just check for truth value of returned list.
Instead we have to compare the returned value with `None`.
"""
classification = metadata.get(classification_key, None)
if classification is None:
return MatchError(
message=self.no_classification_found.format(
classification=classification_key
),
filename=path,
details=str(metadata))
else:
if not isinstance(classification, list):
return MatchError(
message="*{}* must be a list".format(classification_key),
filename=path,
details=str(metadata))
elif strict:
classifications = self.get_classifications(classification_key)
unknown_classifications = list(
set(classification) - set(classifications))
if unknown_classifications:
message = self.unknown_classifications_found.format(
unknown_classification=unknown_classifications,
known_classification=classifications,
classification_key=classification_key)
message += self.how_to_add_classification.get(classification_key, "")
return MatchError(
message=message,
filename=path,
details=str(metadata))
def matchplay(self, file, data):
results = []
path = file['path']
if file['type'] == 'playbook':
if path.startswith("playbooks/") \
or "tripleo-validations/playbooks/" in path:
# *hosts* line check
hosts = data.get('hosts', None)
if not hosts:
results.append(
MatchError(
message="No *hosts* key found in the playbook",
filename=path,
details=str(data)))
# *vars* lines check
vars = data.get('vars', None)
if not vars:
results.append(
MatchError(
message=self.no_vars_found,
filename=path,
details=str(data)))
else:
if not isinstance(vars, dict):
results.append(
MatchError(
message='*vars* must be a dictionary',
filename=path,
details=str(data)))
# *metadata* lines check
metadata = data['vars'].get('metadata', None)
if metadata:
if not isinstance(metadata, dict):
results.append(
MatchError(
message='*metadata* must be a dictionary',
filename=path,
details=str(data)))
else:
results.append(
MatchError(
message=self.no_meta_found,
filename=path,
details=str(data)))
# *metadata>[name|description] lines check
for info in ['name', 'description']:
if not metadata.get(info, None):
results.append(
MatchError(
message='*metadata* must contain a %s key' % info,
filename=path,
details=str(data)))
continue
if not isinstance(metadata.get(info), str):
results.append(
MatchError(
message='*%s* should be a string' % info,
filename=path,
details=str(data)))
#Checks for metadata we use to classify validations.
#Groups, categories and products
for classification in ['categories', 'products', 'groups']:
classification_error = self.check_classification(
metadata,
path,
classification,
strict=(classification == 'groups'))
if classification_error:
results.append(classification_error)
return results

View File

@ -1,37 +0,0 @@
# Molecule managed
# Copyright 2021 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.
{% if item.registry is defined %}
FROM {{ item.registry.url }}/{{ item.image }}
{% else %}
FROM {{ item.image }}
{% endif %}
RUN if [ $(command -v apt-get) ]; then apt-get update && apt-get install -y python sudo bash ca-certificates && apt-get clean; \
elif [ $(command -v dnf) ]; then dnf makecache && dnf --assumeyes install sudo python*-devel python*-dnf bash epel-release {{ item.pkg_extras | default('') }} && dnf clean all; \
elif [ $(command -v yum) ]; then yum makecache fast && yum install -y python sudo yum-plugin-ovl python-setuptools bash {{ item.pkg_extras | default('') }} && sed -i 's/plugins=0/plugins=1/g' /etc/yum.conf && yum clean all; \
elif [ $(command -v zypper) ]; then zypper refresh && zypper install -y python sudo bash python-xml {{ item.pkg_extras | default('') }} && zypper clean -a; \
elif [ $(command -v apk) ]; then apk update && apk add --no-cache python sudo bash ca-certificates {{ item.pkg_extras | default('') }}; \
elif [ $(command -v xbps-install) ]; then xbps-install -Syu && xbps-install -y python sudo bash ca-certificates {{ item.pkg_extras | default('') }} && xbps-remove -O; fi
{% for pkg in item.easy_install | default([]) %}
# install pip for centos where there is no python-pip rpm in default repos
RUN easy_install {{ pkg }}
{% endfor %}
CMD ["sh", "-c", "while true; do sleep 10000; done"]

View File

@ -1,70 +0,0 @@
---
# Tripleo-validations uses a shared molecule configuration file to avoid
# repetition. That configuration file is located at the repository level
# ({REPO}/.config/molecule/config.yml) and defines all the default values for
# all the molecule.yml files across all the roles. By default, the role-addition
# process will produce an empty molecule.yml inheriting this config.yml file.
#
# Any key defined in the role molecule.yml file will override values from this
# config.yml file.
#
# IMPORTANT: if you want to override the default values set here in this file,
# you will have to redefine them completely in your molecule.yml (at the role
# level) and add your extra configuration!
#
# For instance, if you need to add an extra package in your CentOS 8 Stream
# container, you will have to add the entire "platforms" key into your
# molecule.yml file and add your package name in the pkg_extras key.
#
# No merge will happen between your molecule.yml and this config.yml
# files. That's why you will have to redefine them completely.
driver:
name: podman
log: true
platforms:
- name: centos
hostname: centos
image: centos/centos:stream8
registry:
url: quay.io
dockerfile: ../../../../.config/molecule/Dockerfile
pkg_extras: python*-setuptools python*-pyyaml
volumes:
- /etc/ci/mirror_info.sh:/etc/ci/mirror_info.sh:ro
privileged: true
environment: &env
http_proxy: "{{ lookup('env', 'http_proxy') }}"
https_proxy: "{{ lookup('env', 'https_proxy') }}"
ulimits: &ulimit
- host
provisioner:
name: ansible
inventory:
hosts:
all:
hosts:
centos:
ansible_python_interpreter: /usr/bin/python3
log: true
options:
vvv: true
env:
ANSIBLE_STDOUT_CALLBACK: yaml
ANSIBLE_ROLES_PATH: "${ANSIBLE_ROLES_PATH}:${HOME}/zuul-jobs/roles"
ANSIBLE_LIBRARY: "${ANSIBLE_LIBRARY:-/usr/share/ansible/plugins/modules}"
scenario:
test_sequence:
- destroy
- create
- prepare
- converge
- verify
- destroy
verifier:
name: ansible

View File

@ -1,13 +0,0 @@
[run]
branch = True
source =
tripleo_validations
library
lookup_plugins
omit = tripleo-validations/openstack/*
[report]
ignore_errors = True
omit =
tripleo_validations/tests/*
tests/*

View File

@ -1,55 +0,0 @@
# Docker/Podman image doesn't need any files that git doesn't track.
#Therefore the .dockerignore largely follows the structure of .gitignore.
# C extensions
*.so
# Packages
*.egg*
*.egg-info
dist
build
eggs
parts
bin
var
sdist
develop-eggs
.installed.cfg
lib
lib64
# Installer logs
pip-log.txt
# Unit test / coverage reports
cover/
.coverage*
!.coveragerc
.tox
nosetests.xml
.testrepository
.venv
.stestr/*
# Translations
*.mo
# Mr Developer
.mr.developer.cfg
.project
.pydevproject
# Complexity
output/*.html
output/*/index.html
# Sphinx
doc/build
doc/source/reference/api/
# pbr generates these
AUTHORS
ChangeLog
# Editors
*~
.*.swp
.*sw?
# Files created by releasenotes build
releasenotes/build
# Ansible specific
hosts
*.retry
#Vagrantfiles, since we are using docker
Vagrantfile.*

67
.gitignore vendored
View File

@ -1,67 +0,0 @@
*.py[cod]
# C extensions
*.so
# Packages
*.egg*
*.egg-info
dist
build
eggs
parts
bin
var
sdist
develop-eggs
.installed.cfg
lib
lib64
# Installer logs
pip-log.txt
# Unit test / coverage reports
cover/
.coverage*
!.coveragerc
.tox
nosetests.xml
.testrepository
.venv
.stestr/*
# Translations
*.mo
# Mr Developer
.mr.developer.cfg
.project
.pydevproject
# Complexity
output/*.html
output/*/index.html
# Sphinx
doc/build
# pbr generates these
AUTHORS
ChangeLog
# Editors
*~
.*.swp
.*sw?
doc/source/validations-*.rst
# Files created by releasenotes build
releasenotes/build
# Ansible specific
hosts
*.retry
# Roles testing
roles/roles.galaxy

View File

@ -1,3 +0,0 @@
# Format is:
# <preferred e-mail> <other e-mail 1>
# <preferred e-mail> <other e-mail 2>

View File

@ -1,53 +0,0 @@
---
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v3.4.0
hooks:
- id: end-of-file-fixer
- id: trailing-whitespace
- id: mixed-line-ending
- id: check-byte-order-marker
- id: check-executables-have-shebangs
- id: check-merge-conflict
- id: check-symlinks
- id: debug-statements
files: .*\.(yaml|yml)$
- repo: https://github.com/pycqa/flake8
rev: 3.9.1
hooks:
- id: flake8
additional_dependencies: [flake8-typing-imports==1.12.0]
entry: flake8 --ignore=E24,E121,E122,E123,E124,E126,E226,E265,E305,E402,F401,F405,E501,E704,F403,F841,W503,W605
- repo: https://github.com/adrienverge/yamllint.git
rev: v1.33.0
hooks:
- id: yamllint
files: \.(yaml|yml)$
types: [file, yaml]
entry: yamllint --strict -f parsable
- repo: https://github.com/ansible-community/ansible-lint
rev: v5.3.2
hooks:
- id: ansible-lint
always_run: true
pass_filenames: false
additional_dependencies:
- 'ansible-core<2.12'
verbose: true
entry: ansible-lint --force-color -p -v
- repo: https://github.com/openstack-dev/bashate.git
rev: 2.0.0
hooks:
- id: bashate
entry: bashate --error . --verbose --ignore=E006,E040
# Run bashate check for all bash scripts
# Ignores the following rules:
# E006: Line longer than 79 columns (as many scripts use jinja
# templating, this is very difficult)
# E040: Syntax error determined using `bash -n` (as many scripts
# use jinja templating, this will often fail and the syntax
# error will be discovered in execution anyway)

View File

@ -1,3 +0,0 @@
[DEFAULT]
test_path=${TEST_PATH:-./tripleo_validations/tests}
top_dir=./

View File

@ -1,7 +0,0 @@
[DEFAULT]
test_command=OS_STDOUT_CAPTURE=${OS_STDOUT_CAPTURE:-1} \
OS_STDERR_CAPTURE=${OS_STDERR_CAPTURE:-1} \
OS_TEST_TIMEOUT=${OS_TEST_TIMEOUT:-60} \
${PYTHON:-python} -m subunit.run discover -t ./ . $LISTOPT $IDOPTION
test_id_option=--load-list $IDFILE
test_list_option=--list

View File

@ -1,14 +0,0 @@
---
extends: default
rules:
line-length:
# matches hardcoded 160 value from ansible-lint
max: 160
indentation:
spaces: consistent
indent-sequences: true
check-multi-line-strings: false
ignore: |
zuul.d/molecule.yaml
releasenotes/notes/*.yaml

View File

@ -1,56 +0,0 @@
For general information on contributing to OpenStack, please check out the
`contributor guide <https://docs.openstack.org/contributors/>`_ to get started.
It covers all the basics that are common to all OpenStack projects: the accounts
you need, the basics of interacting with our Gerrit review system, how we
communicate as a community, etc.
The information below will cover the project specific information you need to get started with TripleO.
Documentation
=============
Documentation for the TripleO project can be found `here <https://docs.openstack.org/tripleo-docs/latest/index.html>`_
Communication
=============
* IRC channel ``#validation-framework`` at `Libera`_ (For all subject-matters)
* IRC channel ``#tripleo`` at `OFTC`_ (OpenStack and TripleO discussions)
* Mailing list (prefix subjects with ``[tripleo][validations]`` for faster responses)
http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-discuss
.. _Libera: https://libera.chat/
.. _OFTC: https://www.oftc.net/
Contacting the Core Team
========================
Please refer to the `TripleO Core Team
<https://review.opendev.org/#/admin/groups/190,members>`_ contacts.
Bug Tracking
=============
We track our tasks in `Launchpad <https://bugs.launchpad.net/tripleo/+bugs?field.tag=validations>`_ and in
`StoryBoard <https://storyboard.openstack.org/#!/project_group/76>`_
Reporting a Bug
===============
You found an issue and want to make sure we are aware of it? You can do so on
`Launchpad <https://bugs.launchpad.net/tripleo/+filebug>`__. Please, add the
validations tag to your bug.
More info about Launchpad usage can be found on `OpenStack docs page
<https://docs.openstack.org/contributors/common/task-tracking.html#launchpad>`_
Getting Your Patch Merged
=========================
All changes proposed to the TripleO requires two ``Code-Review +2`` votes from
TripleO core reviewers before one of the core reviewers can approve patch by
giving ``Workflow +1`` vote.
Project Team Lead Duties
========================
All common PTL duties are enumerated in the `PTL guide
<https://docs.openstack.org/project-team-guide/ptl.html>`_.
The Release Process for TripleO is documented in `Release Management
<https://docs.openstack.org/tripleo-docs/latest/developer/release.html>`_.
Documentation for the TripleO project can be found `here <https://docs.openstack.org/tripleo-docs/latest/index.html>`_

View File

@ -1,4 +0,0 @@
tripleo-validations Style Commandments
===============================================
Read the OpenStack Style Commandments https://docs.openstack.org/hacking/latest/

175
LICENSE
View File

@ -1,175 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.

View File

@ -1,6 +0,0 @@
include AUTHORS
include ChangeLog
exclude .gitignore
exclude .gitreview
global-exclude *.pyc

View File

@ -1,22 +1,10 @@
.. image:: https://governance.openstack.org/tc/badges/tripleo-validations.svg
:target: https://governance.openstack.org/tc/reference/tags/index.html
This project is no longer maintained.
.. Change things from this point on
The contents of this repository are still available in the Git
source code management system. To see the contents of this
repository before it reached its end of life, please check out the
previous commit with "git checkout HEAD^1".
A collection of Ansible roles and playbooks to detect and report potential
issues during TripleO deployments.
The validations will help detect issues early in the deployment process and
prevent field engineers from wasting time on misconfiguration or hardware
issues in their environments.
All validations are written in Ansible and are written in a way that's
consumable by the `Validation Framework Command Line Interface (CLI)
<https://docs.openstack.org/validations-libs/latest/reference/api/validations_libs.cli.html>`_
or by Ansible directly.
* Free software: Apache license
* Documentation: https://docs.openstack.org/tripleo-validations/latest/
* Release notes: https://docs.openstack.org/releasenotes/tripleo-validations/
* Source: https://opendev.org/openstack/tripleo-validations
* Bugs: https://storyboard.openstack.org/#!/project/openstack/tripleo-validations
For any further questions, please email
openstack-discuss@lists.openstack.org or join #openstack-dev on
OFTC.

View File

@ -1,7 +0,0 @@
---
collections:
- containers.podman
- community.general
- community.crypto
- ansible.posix
- openstack.cloud

View File

@ -1,27 +0,0 @@
export TRIPLEO_VALIDATIONS_WORKPATH="$(dirname $(readlink -f ${BASH_SOURCE[0]}))"
export ANSIBLE_STDOUT_CALLBACK=debug
export ANSIBLE_CALLBACK_PLUGINS="${TRIPLEO_VALIDATIONS_WORKPATH}/callback_plugins"
ANSIBLE_LIBRARY="${TRIPLEO_VALIDATIONS_WORKPATH}/library"
export ANSIBLE_LIBRARY="${ANSIBLE_LIBRARY}:${TRIPLEO_VALIDATIONS_WORKPATH}/roles/roles.galaxy/validations-common/validations_common/library"
export ANSIBLE_LOOKUP_PLUGINS="${TRIPLEO_VALIDATIONS_WORKPATH}/lookup_plugins"
export ANSIBLE_ROLES_PATH="${TRIPLEO_VALIDATIONS_WORKPATH}/roles"
export ANSIBLE_ROLES_PATH="${ANSIBLE_ROLES_PATH}:${TRIPLEO_VALIDATIONS_WORKPATH}/roles/roles.galaxy/tripleo-ansible/tripleo_ansible/roles"
export ANSIBLE_INVENTORY="${TRIPLEO_VALIDATIONS_WORKPATH}/tests/hosts.ini"
export ANSIBLE_RETRY_FILES_ENABLED="0"
export ANSIBLE_LOAD_CALLBACK_PLUGINS="1"
export ANSIBLE_HOST_KEY_CHECKING=False
function unset-ansible-test-env {
for i in $(env | grep ANSIBLE_ | awk -F'=' '{print $1}'); do
unset ${i}
done
unset TRIPLEO_VALIDATIONS_WORKPATH
echo -e "Ansible test environment deactivated.\n"
unset -f unset-ansible-test-env
}
echo -e "Ansible test environment is now active"
echo -e "Run 'unset-ansible-test-env' to deactivate.\n"

View File

@ -1,4 +0,0 @@
[defaults]
retry_files_enabled = False
host_key_checking=False
stdout_callback = default

View File

@ -1 +0,0 @@
[python: **.py]

View File

@ -1,41 +0,0 @@
# This file facilitates OpenStack-CI package installation
# before the execution of any tests.
#
# See the following for details:
# - https://docs.openstack.org/infra/bindep/
# - https://opendev.org/opendev/bindep/
#
# Even if the role does not make use of this facility, it
# is better to have this file empty, otherwise OpenStack-CI
# will fall back to installing its default packages which
# will potentially be detrimental to the tests executed.
# The gcc compiler
gcc
# Base requirements for RPM distros
gcc-c++ [platform:rpm]
git [platform:rpm]
libffi-devel [platform:rpm]
openssl-devel [platform:rpm]
podman [platform:rpm]
python3-devel [platform:rpm !platform:rhel-7 !platform:centos-7]
PyYAML [platform:rpm !platform:rhel-8 !platform:centos-8 !platform:fedora]
python3-pyyaml [platform:rpm !platform:rhel-7 !platform:centos-7]
python3-dnf [platform:rpm !platform:rhel-7 !platform:centos-7]
# RH Mechanisms
python-rhsm-certificates [platform:redhat]
# SELinux cent7
libselinux-python3 [platform:rpm !platform:rhel-8 !platform:centos-8]
libsemanage-python3 [platform:redhat !platform:rhel-8 !platform:centos-8]
# SELinux cent8
python3-libselinux [platform:rpm !platform:rhel-7 !platform:centos-7]
python3-libsemanage [platform:redhat !platform:rhel-7 !platform:centos-7]
# Required for compressing collected log files in CI
gzip
# Required to build language docs
gettext

View File

View File

@ -1,111 +0,0 @@
---
- hosts: all
pre_tasks:
- name: Set project path fact
set_fact:
tripleo_validations_project_path: "{{ ansible_user_dir }}/{{ zuul.projects['opendev.org/openstack/tripleo-validations'].src_dir }}"
- name: Ensure output dirs
file:
path: "{{ ansible_user_dir }}/zuul-output/logs"
state: directory
- name: Ensure pip is available
include_role:
name: ensure-pip
- name: Ensure virtualenv is available
include_role:
name: ensure-virtualenv
- name: Setup bindep
pip:
name: "bindep"
virtualenv: "{{ ansible_user_dir }}/test-python"
virtualenv_command: "{{ ensure_pip_virtualenv_command }}"
virtualenv_site_packages: true
- name: Set containers module to 3.0
become: true
shell: |
dnf module disable container-tools:rhel8 -y
dnf module enable container-tools:3.0 -y
dnf clean metadata
- name: Run bindep
shell: |-
. {{ ansible_user_dir }}/test-python/bin/activate
{{ tripleo_validations_project_path }}/scripts/bindep-install
become: true
changed_when: false
- name: Ensure a recent version of pip is installed in virtualenv
pip:
name: "pip>=19.1.1"
virtualenv: "{{ ansible_user_dir }}/test-python"
virtualenv_command: "{{ ensure_pip_virtualenv_command }}"
- name: Setup test-python
pip:
requirements: "{{ tripleo_validations_project_path }}/molecule-requirements.txt"
virtualenv: "{{ ansible_user_dir }}/test-python"
virtualenv_command: "{{ ensure_pip_virtualenv_command }}"
virtualenv_site_packages: true
- name: Set up collections
command: "{{ ansible_user_dir }}/test-python/bin/ansible-galaxy install -fr {{ tripleo_validations_project_path }}/ansible-collections-requirements.yml"
- name: Display test-python virtualenv package versions
shell: |-
. {{ ansible_user_dir }}/test-python/bin/activate
pip freeze
- name: Basic ci setup
become: true
block:
- name: Ensure ci directories
file:
path: "/etc/ci"
state: "directory"
- name: Ensure ci mirror file
file:
path: "/etc/ci/mirror_info.sh"
state: "touch"
- name: Set an appropriate fs.file-max
sysctl:
name: fs.file-max
value: 2048000
sysctl_set: true
state: present
reload: true
- name: Set container_manage_cgroup boolean
seboolean:
name: container_manage_cgroup
state: true
persistent: true
failed_when: false
- name: Create limits file for containers
copy:
content: |
* soft nofile 102400
* hard nofile 204800
* soft nproc 2048
* hard nproc 4096
dest: /etc/security/limits.d/containers.conf
- name: Reset ssh connection
meta: reset_connection
tasks:
- name: Get necessary git repos
git:
repo: https://opendev.org/openstack/{{ item }}
dest: "{{ tripleo_validations_project_path }}/roles/roles.galaxy/{{ item }}"
version: master
force: true
with_items:
- tripleo-ansible
- validations-common

View File

@ -1,14 +0,0 @@
---
- hosts: all
tasks:
- name: set basic zuul fact
set_fact:
zuul:
projects:
"opendev.org/openstack/tripleo-validations":
src_dir: "{{ tripleo_src }}"
ansible_connection: ssh
- import_playbook: pre.yml
- import_playbook: run.yml

View File

@ -1,42 +0,0 @@
---
- hosts: all
environment:
ANSIBLE_LOG_PATH: "{{ ansible_user_dir }}/zuul-output/logs/ansible-execution.log"
pre_tasks:
- name: Set project path fact
set_fact:
tripleo_validations_project_path: "{{ ansible_user_dir }}/{{ zuul.projects['opendev.org/openstack/tripleo-validations'].src_dir }}"
- name: Set roles path fact
set_fact:
tripleo_validations_roles_paths:
- "{{ tripleo_validations_project_path }}/roles/roles.galaxy/tripleo-ansible/tripleo_ansible/roles"
- "{{ tripleo_validations_project_path }}/roles/roles.galaxy/validations-common/validations_common/roles"
- "{{ tripleo_validations_project_path }}/roles"
- "/usr/share/ansible/roles"
- name: Set library path fact
set_fact:
tripleo_validations_library_paths:
- "{{ tripleo_validations_project_path }}/roles/roles.galaxy/validations-common/validations_common/library"
- "{{ tripleo_validations_project_path }}/library"
- "/usr/share/ansible/library"
tasks:
- name: Run role test job
shell: |-
. {{ ansible_user_dir }}/test-python/bin/activate
. {{ tripleo_validations_project_path }}/ansible-test-env.rc
pytest --color=yes \
--html={{ ansible_user_dir }}/zuul-output/logs/reports.html \
--self-contained-html \
--ansible-args='{{ tripleo_job_ansible_args | default("") }}' \
{{ tripleo_validations_project_path }}/tests/test_molecule.py
args:
chdir: "{{ tripleo_validations_project_path }}/roles/{{ tripleo_validations_role_name }}"
executable: /bin/bash
environment:
ANSIBLE_ROLES_PATH: "{{ tripleo_validations_roles_paths | join(':') }}"
ANSIBLE_LIBRARY: "{{ tripleo_validations_library_paths | join(':') }}"

View File

@ -1,7 +0,0 @@
# this is required for the docs build jobs
sphinx>=2.0.0,!=2.1.0 # BSD
openstackdocstheme>=2.2.2 # Apache-2.0
reno>=3.1.0 # Apache-2.0
doc8>=0.8.0 # Apache-2.0
bashate>=0.6.0 # Apache-2.0
ruamel.yaml>=0.15.5 # MIT

View File

@ -1,402 +0,0 @@
# 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.
import imp
import os
from docutils import core
from docutils import nodes
from docutils.parsers.rst import Directive
from docutils.parsers import rst
from docutils.writers.html4css1 import Writer
from sphinx import addnodes
import yaml
from ruamel.yaml import YAML as RYAML
try:
import io
StringIO = io.StringIO
except ImportError:
import StringIO
class DocYaml(RYAML):
def _license_filter(self, data):
"""This will filter out our boilerplate license heading in return data.
The filter is used to allow documentation we're creating in variable
files to be rendered more beautifully.
"""
lines = list()
mark = True
for line in data.splitlines():
if '# Copyright' in line:
mark = False
if mark:
lines.append(line)
if '# under the License' in line:
mark = True
return '\n'.join(lines)
def dump(self, data, stream=None, **kw):
if not stream:
stream = StringIO()
try:
RYAML.dump(self, data, stream, **kw)
return self._license_filter(stream.getvalue().strip())
finally:
stream.close()
DOCYAML = DocYaml()
DOCYAML.default_flow_style = False
class AnsibleAutoPluginDirective(Directive):
directive_name = "ansibleautoplugin"
has_content = True
option_spec = {
'module': rst.directives.unchanged,
'role': rst.directives.unchanged,
'documentation': rst.directives.unchanged,
'examples': rst.directives.unchanged
}
@staticmethod
def _render_html(source):
return core.publish_parts(
source=source,
writer=Writer(),
writer_name='html',
settings_overrides={'no_system_messages': True}
)
def make_node(self, title, contents, content_type=None):
section = self._section_block(title=title)
if not content_type:
# Doc section
for content in contents['docs']:
for paragraph in content.split('\n'):
retnode = nodes.paragraph()
retnode.append(self._raw_html_block(data=paragraph))
section.append(retnode)
# Options Section
options_list = nodes.field_list()
options_section = self._section_block(title='Options')
for key, value in contents['options'].items():
options_list.append(
self._raw_fields(
data=value['description'],
field_name=key
)
)
else:
options_section.append(options_list)
section.append(options_section)
# Authors Section
authors_list = nodes.field_list()
authors_list.append(
self._raw_fields(
data=contents['author']
)
)
authors_section = self._section_block(title='Authors')
authors_section.append(authors_list)
section.append(authors_section)
elif content_type == 'yaml':
for content in contents:
section.append(
self._literal_block(
data=content,
dump_data=False
)
)
return section
@staticmethod
def load_module(filename):
return imp.load_source('__ansible_module__', filename)
@staticmethod
def build_documentation(module):
docs = DOCYAML.load(module.DOCUMENTATION)
doc_data = dict()
doc_data['docs'] = docs['description']
doc_data['author'] = docs.get('author', list())
doc_data['options'] = docs.get('options', dict())
return doc_data
@staticmethod
def build_examples(module):
examples = DOCYAML.load(module.EXAMPLES)
return_examples = list()
for example in examples:
return_examples.append(DOCYAML.dump([example]))
return return_examples
def _raw_html_block(self, data):
html = self._render_html(source=data)
return nodes.raw('', html['body'], format='html')
def _raw_fields(self, data, field_name=''):
body = nodes.field_body()
if isinstance(data, list):
for item in data:
body.append(self._raw_html_block(data=item))
else:
body.append(self._raw_html_block(data=data))
field = nodes.field()
field.append(nodes.field_name(text=field_name))
field.append(body)
return field
@staticmethod
def _literal_block(data, language='yaml', dump_data=True):
if dump_data:
literal = nodes.literal_block(
text=DOCYAML.dump(data)
)
else:
literal = nodes.literal_block(text=data)
literal['language'] = 'yaml'
return literal
@staticmethod
def _section_block(title, text=None):
section = nodes.section(
title,
nodes.title(text=title),
ids=[nodes.make_id('-'.join(title))],
)
if text:
section_body = nodes.field_body()
section_body.append(nodes.paragraph(text=text))
section.append(section_body)
return section
def _yaml_section(self, to_yaml_data, section_title, section_text=None):
yaml_section = self._section_block(
title=section_title,
text=section_text
)
yaml_section.append(self._literal_block(data=to_yaml_data))
return yaml_section
def _run_role(self, role):
section = self._section_block(
title="Role Documentation",
text='Welcome to the "{}" role documentation.'.format(
os.path.basename(role)
),
)
molecule_defaults = None
abspath_role = os.path.dirname(os.path.abspath(role))
molecule_shared_file = os.path.join(
os.path.dirname(abspath_role), ".config/molecule/config.yml"
)
if os.path.exists(molecule_shared_file):
with open(molecule_shared_file) as msf:
molecule_defaults = DOCYAML.load(msf.read())
defaults_file = os.path.join(role, "defaults", "main.yml")
if os.path.exists(defaults_file):
with open(defaults_file) as f:
role_defaults = DOCYAML.load(f.read())
section.append(
self._yaml_section(
to_yaml_data=role_defaults,
section_title="Role Defaults",
section_text="This section highlights all of the defaults"
' and variables set within the "{}"'
" role.".format(os.path.basename(role)),
)
)
vars_path = os.path.join(role, "vars")
if os.path.exists(vars_path):
for v_file in os.listdir(vars_path):
vars_file = os.path.join(vars_path, v_file)
with open(vars_file) as f:
vars_values = DOCYAML.load(f.read())
section.append(
self._yaml_section(
to_yaml_data=vars_values,
section_title="Role Variables: {}".format(v_file),
)
)
test_list = nodes.field_list()
test_section = self._section_block(
title="Molecule Scenarios",
text='Molecule is being used to test the "{}" role. The'
" following section highlights the drivers in service"
" and provides an example playbook showing how the role"
" is leveraged.".format(os.path.basename(role)),
)
molecule_path = os.path.join(role, "molecule")
if os.path.exists(molecule_path):
for test in os.listdir(molecule_path):
molecule_section = self._section_block(
title="Scenario: {}".format(test)
)
molecule_file = os.path.join(molecule_path, test, "molecule.yml")
if not os.path.exists(molecule_file):
continue
with open(molecule_file) as f:
molecule_conf = DOCYAML.load(f.read())
# if molecule.yml file from the scenarios, we get the
# information from the molecule shared configuration file.
if not molecule_conf:
molecule_conf = molecule_defaults
# Now that we use a shared molecule configuration file, the
# molecule.yml file in the role scenarios could be empty or
# contains only overriding keys.
driver_data = molecule_conf.get('driver',
molecule_defaults.get('driver'))
if driver_data:
molecule_section.append(
nodes.field_name(text="Driver: {}".format(driver_data["name"]))
)
options = driver_data.get("options")
if options:
molecule_section.append(
self._yaml_section(
to_yaml_data=options, section_title="Molecule Options"
)
)
platforms_data = molecule_conf.get('platforms',
molecule_defaults.get('platforms'))
if platforms_data:
molecule_section.append(
self._yaml_section(
to_yaml_data=platforms_data,
section_title="Molecule Platform(s)",
)
)
default_playbook = [molecule_path, test, "converge.yml"]
provisioner_data = molecule_conf.get('provisioner',
molecule_defaults.get('provisioner'))
if provisioner_data:
inventory = provisioner_data.get('inventory')
if inventory:
molecule_section.append(
self._yaml_section(
to_yaml_data=inventory,
section_title="Molecule Inventory",
)
)
try:
converge = provisioner_data['playbooks']['converge']
default_playbook = default_playbook[:-1] + [converge]
except KeyError:
pass
molecule_playbook_path = os.path.join(*default_playbook)
with open(molecule_playbook_path) as f:
molecule_playbook = DOCYAML.load(f.read())
molecule_section.append(
self._yaml_section(
to_yaml_data=molecule_playbook,
section_title="Example {} playbook".format(test),
)
)
test_list.append(molecule_section)
else:
test_section.append(test_list)
section.append(test_section)
self.run_returns.append(section)
# Document any libraries nested within the role
library_path = os.path.join(role, "library")
if os.path.exists(library_path):
self.options['documentation'] = True
self.options['examples'] = True
for lib in os.listdir(library_path):
if lib.endswith(".py"):
self._run_module(
module=self.load_module(
filename=os.path.join(library_path, lib)
),
module_title="Embedded module: {}".format(lib),
example_title="Examples for embedded module",
)
def _run_module(self, module, module_title="Module Documentation",
example_title="Example Tasks"):
if self.options.get('documentation'):
docs = self.build_documentation(module=module)
self.run_returns.append(
self.make_node(
title=module_title,
contents=docs
)
)
if self.options.get('examples'):
examples = self.build_examples(module=module)
self.run_returns.append(
self.make_node(
title=example_title,
contents=examples,
content_type='yaml'
)
)
def run(self):
self.run_returns = list()
if self.options.