Move Ansible components to validations_common directory
* Add missing Ansible & Yamllint configuration files * Fix requirements issues * Add tools/validate-files.py Signed-off-by: Gael Chamoulaud (Strider) <gchamoul@redhat.com>
This commit is contained in:
parent
59a9e69f47
commit
ba5e10832e
23
.ansible-lint
Normal file
23
.ansible-lint
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
exclude_paths:
|
||||||
|
- releasenotes/
|
||||||
|
parseable: true
|
||||||
|
quiet: false
|
||||||
|
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
|
11
.yamllint
Normal file
11
.yamllint
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
---
|
||||||
|
extends: default
|
||||||
|
|
||||||
|
rules:
|
||||||
|
line-length:
|
||||||
|
# matches hardcoded 160 value from ansible-lint
|
||||||
|
max: 160
|
||||||
|
|
||||||
|
ignore: |
|
||||||
|
zuul.d/*.yaml
|
||||||
|
releasenotes/notes/*.yaml
|
@ -3,14 +3,4 @@
|
|||||||
# process, which may cause wedges in the gate later.
|
# process, which may cause wedges in the gate later.
|
||||||
|
|
||||||
pbr>=3.1.1 # Apache-2.0
|
pbr>=3.1.1 # Apache-2.0
|
||||||
oslo.config>=5.2.0 # Apache-2.0
|
PyYAML
|
||||||
keystoneauth1>=3.12.0 # Apache-2.0
|
|
||||||
python-novaclient>=15.1.0 # Apache-2.0
|
|
||||||
python-heatclient>=1.10.0 # Apache-2.0
|
|
||||||
python-glanceclient>=2.9.1 # Apache-2.0
|
|
||||||
python-ironicclient>=2.7.0 # Apache-2.0
|
|
||||||
python-ironic-inspector-client>=3.1.1 # Apache-2.0
|
|
||||||
os-net-config>=7.1.0 # Apache-2.0
|
|
||||||
oslo.utils>=3.40.2 # Apache-2.0
|
|
||||||
six>=1.11.0 # MIT
|
|
||||||
tripleo-common>=7.1.0 # Apache-2.0
|
|
||||||
|
@ -26,10 +26,10 @@ packages =
|
|||||||
validations_common
|
validations_common
|
||||||
|
|
||||||
data_files =
|
data_files =
|
||||||
share/validations-common/roles = roles/*
|
share/validations-common/roles = validations_common/roles/*
|
||||||
share/validations-common/callback_plugins = callback_plugins/*
|
share/validations-common/callback_plugins = validations_common/callback_plugins/*
|
||||||
share/validations-common/lookup_plugins = lookup_plugins/*
|
share/validations-common/lookup_plugins = validations_common/lookup_plugins/*
|
||||||
share/validations-common/library = library/*
|
share/validations-common/library = validations_common/library/*
|
||||||
|
|
||||||
[build_sphinx]
|
[build_sphinx]
|
||||||
source-dir = doc/source
|
source-dir = doc/source
|
||||||
|
@ -7,8 +7,6 @@ hacking<0.12,>=0.11.0 # Apache-2.0
|
|||||||
|
|
||||||
coverage!=4.4,>=4.0 # Apache-2.0
|
coverage!=4.4,>=4.0 # Apache-2.0
|
||||||
python-subunit>=1.0.0 # Apache-2.0/BSD
|
python-subunit>=1.0.0 # Apache-2.0/BSD
|
||||||
sphinx>=1.8.0,<2.0.0;python_version=='2.7' # BSD
|
|
||||||
sphinx>=1.8.0,!=2.1.0;python_version>='3.4' # BSD
|
|
||||||
oslotest>=3.2.0 # Apache-2.0
|
oslotest>=3.2.0 # Apache-2.0
|
||||||
testrepository>=0.0.18 # Apache-2.0/BSD
|
testrepository>=0.0.18 # Apache-2.0/BSD
|
||||||
testscenarios>=0.4 # Apache-2.0/BSD
|
testscenarios>=0.4 # Apache-2.0/BSD
|
||||||
|
@ -66,9 +66,7 @@ for base_path in path_args:
|
|||||||
if f.endswith('.py') \
|
if f.endswith('.py') \
|
||||||
and not f == '__init__.py' \
|
and not f == '__init__.py' \
|
||||||
and subdir in [os.path.join(base_path,
|
and subdir in [os.path.join(base_path,
|
||||||
'validations',
|
'validations_common',
|
||||||
'library'),
|
|
||||||
os.path.join(base_path,
|
|
||||||
'library')]:
|
'library')]:
|
||||||
file_path = os.path.join(subdir, f)
|
file_path = os.path.join(subdir, f)
|
||||||
if quiet < 1:
|
if quiet < 1:
|
||||||
|
12
tox.ini
12
tox.ini
@ -7,10 +7,10 @@ skipdist = True
|
|||||||
usedevelop = True
|
usedevelop = True
|
||||||
passenv = *
|
passenv = *
|
||||||
setenv =
|
setenv =
|
||||||
ANSIBLE_CALLBACK_PLUGINS={toxinidir}/callback_plugins
|
ANSIBLE_CALLBACK_PLUGINS={toxinidir}/validations_common/callback_plugins
|
||||||
ANSIBLE_LOOKUP_PLUGINS={toxinidir}/lookup_plugins
|
ANSIBLE_LOOKUP_PLUGINS={toxinidir}/validations_common/lookup_plugins
|
||||||
ANSIBLE_LIBRARY={toxinidir}/library
|
ANSIBLE_LIBRARY={toxinidir}/validations_common/library
|
||||||
ANSIBLE_ROLES_PATH={toxinidir}/roles
|
ANSIBLE_ROLES_PATH={toxinidir}/validations_common/roles
|
||||||
ANSIBLE_NOCOWS=1
|
ANSIBLE_NOCOWS=1
|
||||||
ANSIBLE_RETRY_FILES_ENABLED=0
|
ANSIBLE_RETRY_FILES_ENABLED=0
|
||||||
ANSIBLE_STDOUT_CALLBACK=debug
|
ANSIBLE_STDOUT_CALLBACK=debug
|
||||||
@ -49,8 +49,8 @@ envdir = {toxworkdir}/linters
|
|||||||
deps =
|
deps =
|
||||||
{[testenv:linters]deps}
|
{[testenv:linters]deps}
|
||||||
commands =
|
commands =
|
||||||
bash -c "ANSIBLE_ROLES_PATH='{toxinidir}/roles'"
|
bash -c "ANSIBLE_ROLES_PATH='{toxinidir}/validations_common/roles'"
|
||||||
bash -c "ANSIBLE_LIBRARY='{toxinidir}/library'"
|
bash -c "ANSIBLE_LIBRARY='{toxinidir}/validations_common/library'"
|
||||||
python -m pre_commit run ansible-lint -a
|
python -m pre_commit run ansible-lint -a
|
||||||
|
|
||||||
[testenv:yamllint]
|
[testenv:yamllint]
|
||||||
|
97
validations_common/library/advanced_format.py
Normal file
97
validations_common/library/advanced_format.py
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# Copyright 2016 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.
|
||||||
|
|
||||||
|
from os import path
|
||||||
|
from yaml import safe_load as yaml_safe_load
|
||||||
|
|
||||||
|
from ansible.module_utils.basic import AnsibleModule
|
||||||
|
|
||||||
|
DOCUMENTATION = '''
|
||||||
|
---
|
||||||
|
module: advanced_format
|
||||||
|
short_description: Check for advanced disk format
|
||||||
|
description:
|
||||||
|
- Check whether a drive uses advanced format
|
||||||
|
options:
|
||||||
|
drive:
|
||||||
|
required: true
|
||||||
|
description:
|
||||||
|
- drive name
|
||||||
|
type: str
|
||||||
|
author: "Martin Andre (@mandre)"
|
||||||
|
'''
|
||||||
|
|
||||||
|
EXAMPLES = '''
|
||||||
|
- hosts: webservers
|
||||||
|
tasks:
|
||||||
|
- name: Detect whether the drive uses Advanced Format
|
||||||
|
advanced_format: drive=vda
|
||||||
|
'''
|
||||||
|
|
||||||
|
|
||||||
|
def read_int(module, file_path):
|
||||||
|
'''Read a file and convert its value to int.
|
||||||
|
|
||||||
|
Raise ansible failure otherwise.
|
||||||
|
'''
|
||||||
|
try:
|
||||||
|
with open(file_path) as f:
|
||||||
|
file_contents = f.read()
|
||||||
|
return int(file_contents)
|
||||||
|
except IOError:
|
||||||
|
module.fail_json(msg="Cannot open '%s'" % file_path)
|
||||||
|
except ValueError:
|
||||||
|
module.fail_json(msg="The '%s' file doesn't contain an integer value" %
|
||||||
|
file_path)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
module = AnsibleModule(
|
||||||
|
argument_spec=yaml_safe_load(DOCUMENTATION)['options']
|
||||||
|
)
|
||||||
|
|
||||||
|
drive = module.params.get('drive')
|
||||||
|
queue_path = path.join('/sys/class/block', drive, 'queue')
|
||||||
|
|
||||||
|
physical_block_size_path = path.join(queue_path, 'physical_block_size')
|
||||||
|
logical_block_size_path = path.join(queue_path, 'logical_block_size')
|
||||||
|
|
||||||
|
physical_block_size = read_int(module, physical_block_size_path)
|
||||||
|
logical_block_size = read_int(module, logical_block_size_path)
|
||||||
|
|
||||||
|
if physical_block_size == logical_block_size:
|
||||||
|
module.exit_json(
|
||||||
|
changed=False,
|
||||||
|
msg="The disk %s probably doesn't use Advance Format." % drive,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
module.exit_json(
|
||||||
|
# NOTE(shadower): we're marking this as `changed`, to make it
|
||||||
|
# visually stand out when running via Ansible directly instead of
|
||||||
|
# using the API.
|
||||||
|
#
|
||||||
|
# The API & UI is planned to look for the `warnings` field and
|
||||||
|
# display it differently.
|
||||||
|
changed=True,
|
||||||
|
warnings=["Physical and logical block sizes of drive %s differ "
|
||||||
|
"(%s vs. %s). This can mean the disk uses Advance "
|
||||||
|
"Format." %
|
||||||
|
(drive, physical_block_size, logical_block_size)],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
145
validations_common/library/check_package_update.py
Executable file
145
validations_common/library/check_package_update.py
Executable file
@ -0,0 +1,145 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# Copyright 2017 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.
|
||||||
|
|
||||||
|
""" Check for available updates for a given package."""
|
||||||
|
|
||||||
|
import collections
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
from ansible.module_utils.basic import AnsibleModule
|
||||||
|
from yaml import safe_load as yaml_safe_load
|
||||||
|
|
||||||
|
DOCUMENTATION = '''
|
||||||
|
---
|
||||||
|
module: check_package_update
|
||||||
|
short_description: Check for available updates for a given package
|
||||||
|
description:
|
||||||
|
- Check for available updates for a given package
|
||||||
|
options:
|
||||||
|
package:
|
||||||
|
required: true
|
||||||
|
description:
|
||||||
|
- The name of the package you want to check
|
||||||
|
type: str
|
||||||
|
pkg_mgr:
|
||||||
|
required: true
|
||||||
|
description:
|
||||||
|
- Supported Package Manager, DNF or YUM
|
||||||
|
type: str
|
||||||
|
author: "Florian Fuchs"
|
||||||
|
'''
|
||||||
|
|
||||||
|
EXAMPLES = '''
|
||||||
|
- hosts: webservers
|
||||||
|
tasks:
|
||||||
|
- name: Get available updates for packages
|
||||||
|
check_package_update:
|
||||||
|
package: python-tripleoclient
|
||||||
|
pkg_mgr: "{{ ansible_pkg_mgr}}"
|
||||||
|
'''
|
||||||
|
|
||||||
|
SUPPORTED_PKG_MGRS = (
|
||||||
|
'yum',
|
||||||
|
'dnf',
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
PackageDetails = collections.namedtuple('PackageDetails',
|
||||||
|
['name', 'version', 'release', 'arch'])
|
||||||
|
|
||||||
|
|
||||||
|
def get_package_details(output):
|
||||||
|
if output:
|
||||||
|
return PackageDetails(
|
||||||
|
output.split('|')[0],
|
||||||
|
output.split('|')[1],
|
||||||
|
output.split('|')[2],
|
||||||
|
output.split('|')[3],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _command(command):
|
||||||
|
# Return the result of a subprocess call
|
||||||
|
# as [stdout, stderr]
|
||||||
|
process = subprocess.Popen(command,
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.PIPE,
|
||||||
|
universal_newlines=True)
|
||||||
|
return process.communicate()
|
||||||
|
|
||||||
|
|
||||||
|
def check_update(module, package, pkg_mgr):
|
||||||
|
if pkg_mgr not in SUPPORTED_PKG_MGRS:
|
||||||
|
module.fail_json(
|
||||||
|
msg='Package manager "{}" is not supported.'.format(pkg_mgr))
|
||||||
|
return
|
||||||
|
|
||||||
|
installed_stdout, installed_stderr = _command(
|
||||||
|
['rpm', '-qa', '--qf',
|
||||||
|
'%{NAME}|%{VERSION}|%{RELEASE}|%{ARCH}',
|
||||||
|
package])
|
||||||
|
|
||||||
|
# Fail the module if for some reason we can't lookup the current package.
|
||||||
|
if installed_stderr != '':
|
||||||
|
module.fail_json(msg=installed_stderr)
|
||||||
|
return
|
||||||
|
elif not installed_stdout:
|
||||||
|
module.fail_json(
|
||||||
|
msg='"{}" is not an installed package.'.format(package))
|
||||||
|
return
|
||||||
|
|
||||||
|
installed = get_package_details(installed_stdout)
|
||||||
|
|
||||||
|
pkg_mgr_option = 'available'
|
||||||
|
if pkg_mgr == 'dnf':
|
||||||
|
pkg_mgr_option = '--available'
|
||||||
|
|
||||||
|
available_stdout, available_stderr = _command(
|
||||||
|
[pkg_mgr, '-q', 'list', pkg_mgr_option, installed.name])
|
||||||
|
|
||||||
|
if available_stdout:
|
||||||
|
new_pkg_info = available_stdout.split('\n')[1].rstrip().split()[:2]
|
||||||
|
new_ver, new_rel = new_pkg_info[1].split('-')
|
||||||
|
|
||||||
|
module.exit_json(
|
||||||
|
changed=False,
|
||||||
|
name=installed.name,
|
||||||
|
current_version=installed.version,
|
||||||
|
current_release=installed.release,
|
||||||
|
new_version=new_ver,
|
||||||
|
new_release=new_rel)
|
||||||
|
else:
|
||||||
|
module.exit_json(
|
||||||
|
changed=False,
|
||||||
|
name=installed.name,
|
||||||
|
current_version=installed.version,
|
||||||
|
current_release=installed.release,
|
||||||
|
new_version=None,
|
||||||
|
new_release=None)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
module = AnsibleModule(
|
||||||
|
argument_spec=yaml_safe_load(DOCUMENTATION)['options']
|
||||||
|
)
|
||||||
|
|
||||||
|
check_update(module,
|
||||||
|
module.params.get('package'),
|
||||||
|
module.params.get('pkg_mgr'))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user