diff options
Diffstat (limited to 'roles')
18 files changed, 1578 insertions, 75 deletions
diff --git a/roles/lib_openshift/src/sources.yml b/roles/lib_openshift/src/sources.yml index 8a825a402..28929c02a 100644 --- a/roles/lib_openshift/src/sources.yml +++ b/roles/lib_openshift/src/sources.yml @@ -8,6 +8,7 @@ oadm_manage_node.py: - lib/base.py - class/oadm_manage_node.py - ansible/oadm_manage_node.py + oc_edit.py: - doc/generated - doc/license @@ -17,6 +18,7 @@ oc_edit.py: - lib/base.py - class/oc_edit.py - ansible/oc_edit.py + oc_obj.py: - doc/generated - doc/license @@ -26,6 +28,7 @@ oc_obj.py: - lib/base.py - class/oc_obj.py - ansible/oc_obj.py + oc_route.py: - doc/generated - doc/license @@ -36,6 +39,7 @@ oc_route.py: - lib/route.py - class/oc_route.py - ansible/oc_route.py + oc_secret.py: - doc/generated - doc/license @@ -46,6 +50,7 @@ oc_secret.py: - lib/secret.py - class/oc_secret.py - ansible/oc_secret.py + oc_scale.py: - doc/generated - doc/license @@ -57,6 +62,7 @@ oc_scale.py: - lib/replicationcontroller.py - class/oc_scale.py - ansible/oc_scale.py + oc_version.py: - doc/generated - doc/license @@ -66,6 +72,7 @@ oc_version.py: - lib/base.py - class/oc_version.py - ansible/oc_version.py + oc_serviceaccount.py: - doc/generated - doc/license diff --git a/roles/lib_openshift/src/test/unit/oc_secret.py b/roles/lib_openshift/src/test/unit/oc_secret.py index 221f00ed6..835918b95 100755 --- a/roles/lib_openshift/src/test/unit/oc_secret.py +++ b/roles/lib_openshift/src/test/unit/oc_secret.py @@ -81,7 +81,7 @@ class OCSecretTest(unittest.TestCase): # Making sure our mock was called as we expected mock_openshift_cmd.assert_has_calls([ - mock.call(['get', 'secrets', '-o', 'json', 'secretname'], output=True), + mock.call(['get', 'secrets', 'secretname', '-o', 'json'], output=True), mock.call(['secrets', 'new', 'secretname', 'somesecret.json=/tmp/somesecret.json']), ]) diff --git a/roles/lib_utils/library/repoquery.py b/roles/lib_utils/library/repoquery.py new file mode 100644 index 000000000..7f0105290 --- /dev/null +++ b/roles/lib_utils/library/repoquery.py @@ -0,0 +1,607 @@ +#!/usr/bin/env python +# pylint: disable=missing-docstring +# ___ ___ _ _ ___ ___ _ _____ ___ ___ +# / __| __| \| | __| _ \ /_\_ _| __| \ +# | (_ | _|| .` | _|| / / _ \| | | _|| |) | +# \___|___|_|\_|___|_|_\/_/_\_\_|_|___|___/_ _____ +# | \ / _ \ | \| |/ _ \_ _| | __| \_ _|_ _| +# | |) | (_) | | .` | (_) || | | _|| |) | | | | +# |___/ \___/ |_|\_|\___/ |_| |___|___/___| |_| +# +# Copyright 2016 Red Hat, Inc. and/or its affiliates +# and other contributors as indicated by the @author tags. +# +# 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. +# + +# -*- -*- -*- Begin included fragment: lib/import.py -*- -*- -*- + +# pylint: disable=wrong-import-order,wrong-import-position,unused-import + +from __future__ import print_function # noqa: F401 +import json # noqa: F401 +import os # noqa: F401 +import re # noqa: F401 +# pylint: disable=import-error +import ruamel.yaml as yaml # noqa: F401 +import shutil # noqa: F401 + +from ansible.module_utils.basic import AnsibleModule + +# -*- -*- -*- End included fragment: lib/import.py -*- -*- -*- + +# -*- -*- -*- Begin included fragment: doc/repoquery -*- -*- -*- + +DOCUMENTATION = ''' +--- +module: repoquery +short_description: Query package information from Yum repositories +description: + - Query package information from Yum repositories. +options: + state: + description: + - The expected state. Currently only supports list. + required: false + default: list + choices: ["list"] + aliases: [] + name: + description: + - The name of the package to query + required: true + default: None + aliases: [] + query_type: + description: + - Narrows the packages queried based off of this value. + - If repos, it narrows the query to repositories defined on the machine. + - If installed, it narrows the query to only packages installed on the machine. + - If available, it narrows the query to packages that are available to be installed. + - If recent, it narrows the query to only recently edited packages. + - If updates, it narrows the query to only packages that are updates to existing installed packages. + - If extras, it narrows the query to packages that are not present in any of the available repositories. + - If all, it queries all of the above. + required: false + default: repos + aliases: [] + verbose: + description: + - Shows more detail for the requested query. + required: false + default: false + aliases: [] + show_duplicates: + description: + - Shows multiple versions of a package. + required: false + default: false + aliases: [] + match_version: + description: + - Match the specific version given to the package. + required: false + default: None + aliases: [] +author: +- "Matt Woodson <mwoodson@redhat.com>" +extends_documentation_fragment: [] +''' + +EXAMPLES = ''' +# Example 1: Get bash versions + - name: Get bash version + repoquery: + name: bash + show_duplicates: True + register: bash_out + +# Results: +# ok: [localhost] => { +# "bash_out": { +# "changed": false, +# "results": { +# "cmd": "/usr/bin/repoquery --quiet --pkgnarrow=repos --queryformat=%{version}|%{release}|%{arch}|%{repo}|%{version}-%{release} --show-duplicates bash", +# "package_found": true, +# "package_name": "bash", +# "returncode": 0, +# "versions": { +# "available_versions": [ +# "4.2.45", +# "4.2.45", +# "4.2.45", +# "4.2.46", +# "4.2.46", +# "4.2.46", +# "4.2.46" +# ], +# "available_versions_full": [ +# "4.2.45-5.el7", +# "4.2.45-5.el7_0.2", +# "4.2.45-5.el7_0.4", +# "4.2.46-12.el7", +# "4.2.46-19.el7", +# "4.2.46-20.el7_2", +# "4.2.46-21.el7_3" +# ], +# "latest": "4.2.46", +# "latest_full": "4.2.46-21.el7_3" +# } +# }, +# "state": "present" +# } +# } + + + +# Example 2: Get bash versions verbosely + - name: Get bash versions verbosely + repoquery: + name: bash + show_duplicates: True + verbose: True + register: bash_out + +# Results: +# ok: [localhost] => { +# "bash_out": { +# "changed": false, +# "results": { +# "cmd": "/usr/bin/repoquery --quiet --pkgnarrow=repos --queryformat=%{version}|%{release}|%{arch}|%{repo}|%{version}-%{release} --show-duplicates bash", +# "package_found": true, +# "package_name": "bash", +# "raw_versions": { +# "4.2.45-5.el7": { +# "arch": "x86_64", +# "release": "5.el7", +# "repo": "rhel-7-server-rpms", +# "version": "4.2.45", +# "version_release": "4.2.45-5.el7" +# }, +# "4.2.45-5.el7_0.2": { +# "arch": "x86_64", +# "release": "5.el7_0.2", +# "repo": "rhel-7-server-rpms", +# "version": "4.2.45", +# "version_release": "4.2.45-5.el7_0.2" +# }, +# "4.2.45-5.el7_0.4": { +# "arch": "x86_64", +# "release": "5.el7_0.4", +# "repo": "rhel-7-server-rpms", +# "version": "4.2.45", +# "version_release": "4.2.45-5.el7_0.4" +# }, +# "4.2.46-12.el7": { +# "arch": "x86_64", +# "release": "12.el7", +# "repo": "rhel-7-server-rpms", +# "version": "4.2.46", +# "version_release": "4.2.46-12.el7" +# }, +# "4.2.46-19.el7": { +# "arch": "x86_64", +# "release": "19.el7", +# "repo": "rhel-7-server-rpms", +# "version": "4.2.46", +# "version_release": "4.2.46-19.el7" +# }, +# "4.2.46-20.el7_2": { +# "arch": "x86_64", +# "release": "20.el7_2", +# "repo": "rhel-7-server-rpms", +# "version": "4.2.46", +# "version_release": "4.2.46-20.el7_2" +# }, +# "4.2.46-21.el7_3": { +# "arch": "x86_64", +# "release": "21.el7_3", +# "repo": "rhel-7-server-rpms", +# "version": "4.2.46", +# "version_release": "4.2.46-21.el7_3" +# } +# }, +# "results": "4.2.45|5.el7|x86_64|rhel-7-server-rpms|4.2.45-5.el7\n4.2.45|5.el7_0.2|x86_64|rhel-7-server-rpms|4.2.45-5.el7_0.2\n4.2.45|5.el7_0.4|x86_64|rhel-7-server-rpms|4.2.45-5.el7_0.4\n4.2.46|12.el7|x86_64|rhel-7-server-rpms|4.2.46-12.el7\n4.2.46|19.el7|x86_64|rhel-7-server-rpms|4.2.46-19.el7\n4.2.46|20.el7_2|x86_64|rhel-7-server-rpms|4.2.46-20.el7_2\n4.2.46|21.el7_3|x86_64|rhel-7-server-rpms|4.2.46-21.el7_3\n", +# "returncode": 0, +# "versions": { +# "available_versions": [ +# "4.2.45", +# "4.2.45", +# "4.2.45", +# "4.2.46", +# "4.2.46", +# "4.2.46", +# "4.2.46" +# ], +# "available_versions_full": [ +# "4.2.45-5.el7", +# "4.2.45-5.el7_0.2", +# "4.2.45-5.el7_0.4", +# "4.2.46-12.el7", +# "4.2.46-19.el7", +# "4.2.46-20.el7_2", +# "4.2.46-21.el7_3" +# ], +# "latest": "4.2.46", +# "latest_full": "4.2.46-21.el7_3" +# } +# }, +# "state": "present" +# } +# } + +# Example 3: Match a specific version + - name: matched versions repoquery test + repoquery: + name: atomic-openshift + show_duplicates: True + match_version: 3.3 + register: openshift_out + +# Result: + +# ok: [localhost] => { +# "openshift_out": { +# "changed": false, +# "results": { +# "cmd": "/usr/bin/repoquery --quiet --pkgnarrow=repos --queryformat=%{version}|%{release}|%{arch}|%{repo}|%{version}-%{release} --show-duplicates atomic-openshift", +# "package_found": true, +# "package_name": "atomic-openshift", +# "returncode": 0, +# "versions": { +# "available_versions": [ +# "3.2.0.43", +# "3.2.1.23", +# "3.3.0.32", +# "3.3.0.34", +# "3.3.0.35", +# "3.3.1.3", +# "3.3.1.4", +# "3.3.1.5", +# "3.3.1.7", +# "3.4.0.39" +# ], +# "available_versions_full": [ +# "3.2.0.43-1.git.0.672599f.el7", +# "3.2.1.23-1.git.0.88a7a1d.el7", +# "3.3.0.32-1.git.0.37bd7ea.el7", +# "3.3.0.34-1.git.0.83f306f.el7", +# "3.3.0.35-1.git.0.d7bd9b6.el7", +# "3.3.1.3-1.git.0.86dc49a.el7", +# "3.3.1.4-1.git.0.7c8657c.el7", +# "3.3.1.5-1.git.0.62700af.el7", +# "3.3.1.7-1.git.0.0988966.el7", +# "3.4.0.39-1.git.0.5f32f06.el7" +# ], +# "latest": "3.4.0.39", +# "latest_full": "3.4.0.39-1.git.0.5f32f06.el7", +# "matched_version_found": true, +# "matched_version_full_latest": "3.3.1.7-1.git.0.0988966.el7", +# "matched_version_latest": "3.3.1.7", +# "matched_versions": [ +# "3.3.0.32", +# "3.3.0.34", +# "3.3.0.35", +# "3.3.1.3", +# "3.3.1.4", +# "3.3.1.5", +# "3.3.1.7" +# ], +# "matched_versions_full": [ +# "3.3.0.32-1.git.0.37bd7ea.el7", +# "3.3.0.34-1.git.0.83f306f.el7", +# "3.3.0.35-1.git.0.d7bd9b6.el7", +# "3.3.1.3-1.git.0.86dc49a.el7", +# "3.3.1.4-1.git.0.7c8657c.el7", +# "3.3.1.5-1.git.0.62700af.el7", +# "3.3.1.7-1.git.0.0988966.el7" +# ], +# "requested_match_version": "3.3" +# } +# }, +# "state": "present" +# } +# } + +''' + +# -*- -*- -*- End included fragment: doc/repoquery -*- -*- -*- + +# -*- -*- -*- Begin included fragment: lib/repoquery.py -*- -*- -*- + +''' + class that wraps the repoquery commands in a subprocess +''' + +# pylint: disable=too-many-lines,wrong-import-position,wrong-import-order + +from collections import defaultdict # noqa: E402 + + +# pylint: disable=no-name-in-module,import-error +# Reason: pylint errors with "No name 'version' in module 'distutils'". +# This is a bug: https://github.com/PyCQA/pylint/issues/73 +from distutils.version import LooseVersion # noqa: E402 + +import subprocess # noqa: E402 + + +class RepoqueryCLIError(Exception): + '''Exception class for repoquerycli''' + pass + + +def _run(cmds): + ''' Actually executes the command. This makes mocking easier. ''' + proc = subprocess.Popen(cmds, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + + stdout, stderr = proc.communicate() + + return proc.returncode, stdout, stderr + + +# pylint: disable=too-few-public-methods +class RepoqueryCLI(object): + ''' Class to wrap the command line tools ''' + def __init__(self, + verbose=False): + ''' Constructor for RepoqueryCLI ''' + self.verbose = verbose + self.verbose = True + + def _repoquery_cmd(self, cmd, output=False, output_type='json'): + '''Base command for repoquery ''' + cmds = ['/usr/bin/repoquery', '--plugins', '--quiet'] + + cmds.extend(cmd) + + rval = {} + results = '' + err = None + + if self.verbose: + print(' '.join(cmds)) + + returncode, stdout, stderr = _run(cmds) + + rval = { + "returncode": returncode, + "results": results, + "cmd": ' '.join(cmds), + } + + if returncode == 0: + if output: + if output_type == 'raw': + rval['results'] = stdout + + if self.verbose: + print(stdout) + print(stderr) + + if err: + rval.update({ + "err": err, + "stderr": stderr, + "stdout": stdout, + "cmd": cmds + }) + + else: + rval.update({ + "stderr": stderr, + "stdout": stdout, + "results": {}, + }) + + return rval + +# -*- -*- -*- End included fragment: lib/repoquery.py -*- -*- -*- + +# -*- -*- -*- Begin included fragment: class/repoquery.py -*- -*- -*- + + +class Repoquery(RepoqueryCLI): + ''' Class to wrap the repoquery + ''' + # pylint: disable=too-many-arguments + def __init__(self, name, query_type, show_duplicates, + match_version, verbose): + ''' Constructor for YumList ''' + super(Repoquery, self).__init__(None) + self.name = name + self.query_type = query_type + self.show_duplicates = show_duplicates + self.match_version = match_version + self.verbose = verbose + + if self.match_version: + self.show_duplicates = True + + self.query_format = "%{version}|%{release}|%{arch}|%{repo}|%{version}-%{release}" + + def build_cmd(self): + ''' build the repoquery cmd options ''' + + repo_cmd = [] + + repo_cmd.append("--pkgnarrow=" + self.query_type) + repo_cmd.append("--queryformat=" + self.query_format) + + if self.show_duplicates: + repo_cmd.append('--show-duplicates') + + repo_cmd.append(self.name) + + return repo_cmd + + @staticmethod + def process_versions(query_output): + ''' format the package data into something that can be presented ''' + + version_dict = defaultdict(dict) + + for version in query_output.split('\n'): + pkg_info = version.split("|") + + pkg_version = {} + pkg_version['version'] = pkg_info[0] + pkg_version['release'] = pkg_info[1] + pkg_version['arch'] = pkg_info[2] + pkg_version['repo'] = pkg_info[3] + pkg_version['version_release'] = pkg_info[4] + + version_dict[pkg_info[4]] = pkg_version + + return version_dict + + def format_versions(self, formatted_versions): + ''' Gather and present the versions of each package ''' + + versions_dict = {} + versions_dict['available_versions_full'] = formatted_versions.keys() + + # set the match version, if called + if self.match_version: + versions_dict['matched_versions_full'] = [] + versions_dict['requested_match_version'] = self.match_version + versions_dict['matched_versions'] = [] + + # get the "full version (version - release) + versions_dict['available_versions_full'].sort(key=LooseVersion) + versions_dict['latest_full'] = versions_dict['available_versions_full'][-1] + + # get the "short version (version) + versions_dict['available_versions'] = [] + for version in versions_dict['available_versions_full']: + versions_dict['available_versions'].append(formatted_versions[version]['version']) + + if self.match_version: + if version.startswith(self.match_version): + versions_dict['matched_versions_full'].append(version) + versions_dict['matched_versions'].append(formatted_versions[version]['version']) + + versions_dict['available_versions'].sort(key=LooseVersion) + versions_dict['latest'] = versions_dict['available_versions'][-1] + + # finish up the matched version + if self.match_version: + if versions_dict['matched_versions_full']: + versions_dict['matched_version_found'] = True + versions_dict['matched_versions'].sort(key=LooseVersion) + versions_dict['matched_version_latest'] = versions_dict['matched_versions'][-1] + versions_dict['matched_version_full_latest'] = versions_dict['matched_versions_full'][-1] + else: + versions_dict['matched_version_found'] = False + versions_dict['matched_versions'] = [] + versions_dict['matched_version_latest'] = "" + versions_dict['matched_version_full_latest'] = "" + + return versions_dict + + def repoquery(self): + '''perform a repoquery ''' + + repoquery_cmd = self.build_cmd() + + rval = self._repoquery_cmd(repoquery_cmd, True, 'raw') + + # check to see if there are actual results + if rval['results']: + processed_versions = Repoquery.process_versions(rval['results'].strip()) + formatted_versions = self.format_versions(processed_versions) + + rval['package_found'] = True + rval['versions'] = formatted_versions + rval['package_name'] = self.name + + if self.verbose: + rval['raw_versions'] = processed_versions + else: + del rval['results'] + + # No packages found + else: + rval['package_found'] = False + + return rval + + @staticmethod + def run_ansible(params, check_mode): + '''run the ansible idempotent code''' + + repoquery = Repoquery( + params['name'], + params['query_type'], + params['show_duplicates'], + params['match_version'], + params['verbose'], + ) + + state = params['state'] + + if state == 'list': + results = repoquery.repoquery() + + if results['returncode'] != 0: + return {'failed': True, + 'msg': results} + + return {'changed': False, 'results': results, 'state': 'list', 'check_mode': check_mode} + + return {'failed': True, + 'changed': False, + 'msg': 'Unknown state passed. %s' % state, + 'state': 'unknown'} + +# -*- -*- -*- End included fragment: class/repoquery.py -*- -*- -*- + +# -*- -*- -*- Begin included fragment: ansible/repoquery.py -*- -*- -*- + + +def main(): + ''' + ansible repoquery module + ''' + module = AnsibleModule( + argument_spec=dict( + state=dict(default='list', type='str', choices=['list']), + name=dict(default=None, required=True, type='str'), + query_type=dict(default='repos', required=False, type='str', + choices=[ + 'installed', 'available', 'recent', + 'updates', 'extras', 'all', 'repos' + ]), + verbose=dict(default=False, required=False, type='bool'), + show_duplicates=dict(default=False, required=False, type='bool'), + match_version=dict(default=None, required=False, type='str'), + ), + supports_check_mode=False, + required_if=[('show_duplicates', True, ['name'])], + ) + + rval = Repoquery.run_ansible(module.params, module.check_mode) + + if 'failed' in rval: + module.fail_json(**rval) + + module.exit_json(**rval) + + +if __name__ == "__main__": + main() + +# -*- -*- -*- End included fragment: ansible/repoquery.py -*- -*- -*- diff --git a/roles/lib_utils/library/yedit.py b/roles/lib_utils/library/yedit.py index 8a2bd92f9..7ad2b7181 100644 --- a/roles/lib_utils/library/yedit.py +++ b/roles/lib_utils/library/yedit.py @@ -24,18 +24,21 @@ # limitations under the License. # -# -*- -*- -*- Begin included fragment: class/import.py -*- -*- -*- +# -*- -*- -*- Begin included fragment: lib/import.py -*- -*- -*- -# pylint: disable=wrong-import-order -import json -import os -import re +# pylint: disable=wrong-import-order,wrong-import-position,unused-import + +from __future__ import print_function # noqa: F401 +import json # noqa: F401 +import os # noqa: F401 +import re # noqa: F401 # pylint: disable=import-error -import ruamel.yaml as yaml -import shutil +import ruamel.yaml as yaml # noqa: F401 +import shutil # noqa: F401 + from ansible.module_utils.basic import AnsibleModule -# -*- -*- -*- End included fragment: class/import.py -*- -*- -*- +# -*- -*- -*- End included fragment: lib/import.py -*- -*- -*- # -*- -*- -*- Begin included fragment: doc/yedit -*- -*- -*- diff --git a/roles/lib_utils/src/ansible/repoquery.py b/roles/lib_utils/src/ansible/repoquery.py new file mode 100644 index 000000000..cb4efa6c1 --- /dev/null +++ b/roles/lib_utils/src/ansible/repoquery.py @@ -0,0 +1,35 @@ +# pylint: skip-file +# flake8: noqa + + +def main(): + ''' + ansible repoquery module + ''' + module = AnsibleModule( + argument_spec=dict( + state=dict(default='list', type='str', choices=['list']), + name=dict(default=None, required=True, type='str'), + query_type=dict(default='repos', required=False, type='str', + choices=[ + 'installed', 'available', 'recent', + 'updates', 'extras', 'all', 'repos' + ]), + verbose=dict(default=False, required=False, type='bool'), + show_duplicates=dict(default=False, required=False, type='bool'), + match_version=dict(default=None, required=False, type='str'), + ), + supports_check_mode=False, + required_if=[('show_duplicates', True, ['name'])], + ) + + rval = Repoquery.run_ansible(module.params, module.check_mode) + + if 'failed' in rval: + module.fail_json(**rval) + + module.exit_json(**rval) + + +if __name__ == "__main__": + main() diff --git a/roles/lib_utils/src/class/import.py b/roles/lib_utils/src/class/import.py deleted file mode 100644 index 249e07228..000000000 --- a/roles/lib_utils/src/class/import.py +++ /dev/null @@ -1,11 +0,0 @@ -# flake8: noqa -# pylint: skip-file - -# pylint: disable=wrong-import-order -import json -import os -import re -# pylint: disable=import-error -import ruamel.yaml as yaml -import shutil -from ansible.module_utils.basic import AnsibleModule diff --git a/roles/lib_utils/src/class/repoquery.py b/roles/lib_utils/src/class/repoquery.py new file mode 100644 index 000000000..2447719e2 --- /dev/null +++ b/roles/lib_utils/src/class/repoquery.py @@ -0,0 +1,156 @@ +# pylint: skip-file +# flake8: noqa + + +class Repoquery(RepoqueryCLI): + ''' Class to wrap the repoquery + ''' + # pylint: disable=too-many-arguments + def __init__(self, name, query_type, show_duplicates, + match_version, verbose): + ''' Constructor for YumList ''' + super(Repoquery, self).__init__(None) + self.name = name + self.query_type = query_type + self.show_duplicates = show_duplicates + self.match_version = match_version + self.verbose = verbose + + if self.match_version: + self.show_duplicates = True + + self.query_format = "%{version}|%{release}|%{arch}|%{repo}|%{version}-%{release}" + + def build_cmd(self): + ''' build the repoquery cmd options ''' + + repo_cmd = [] + + repo_cmd.append("--pkgnarrow=" + self.query_type) + repo_cmd.append("--queryformat=" + self.query_format) + + if self.show_duplicates: + repo_cmd.append('--show-duplicates') + + repo_cmd.append(self.name) + + return repo_cmd + + @staticmethod + def process_versions(query_output): + ''' format the package data into something that can be presented ''' + + version_dict = defaultdict(dict) + + for version in query_output.split('\n'): + pkg_info = version.split("|") + + pkg_version = {} + pkg_version['version'] = pkg_info[0] + pkg_version['release'] = pkg_info[1] + pkg_version['arch'] = pkg_info[2] + pkg_version['repo'] = pkg_info[3] + pkg_version['version_release'] = pkg_info[4] + + version_dict[pkg_info[4]] = pkg_version + + return version_dict + + def format_versions(self, formatted_versions): + ''' Gather and present the versions of each package ''' + + versions_dict = {} + versions_dict['available_versions_full'] = formatted_versions.keys() + + # set the match version, if called + if self.match_version: + versions_dict['matched_versions_full'] = [] + versions_dict['requested_match_version'] = self.match_version + versions_dict['matched_versions'] = [] + + # get the "full version (version - release) + versions_dict['available_versions_full'].sort(key=LooseVersion) + versions_dict['latest_full'] = versions_dict['available_versions_full'][-1] + + # get the "short version (version) + versions_dict['available_versions'] = [] + for version in versions_dict['available_versions_full']: + versions_dict['available_versions'].append(formatted_versions[version]['version']) + + if self.match_version: + if version.startswith(self.match_version): + versions_dict['matched_versions_full'].append(version) + versions_dict['matched_versions'].append(formatted_versions[version]['version']) + + versions_dict['available_versions'].sort(key=LooseVersion) + versions_dict['latest'] = versions_dict['available_versions'][-1] + + # finish up the matched version + if self.match_version: + if versions_dict['matched_versions_full']: + versions_dict['matched_version_found'] = True + versions_dict['matched_versions'].sort(key=LooseVersion) + versions_dict['matched_version_latest'] = versions_dict['matched_versions'][-1] + versions_dict['matched_version_full_latest'] = versions_dict['matched_versions_full'][-1] + else: + versions_dict['matched_version_found'] = False + versions_dict['matched_versions'] = [] + versions_dict['matched_version_latest'] = "" + versions_dict['matched_version_full_latest'] = "" + + return versions_dict + + def repoquery(self): + '''perform a repoquery ''' + + repoquery_cmd = self.build_cmd() + + rval = self._repoquery_cmd(repoquery_cmd, True, 'raw') + + # check to see if there are actual results + if rval['results']: + processed_versions = Repoquery.process_versions(rval['results'].strip()) + formatted_versions = self.format_versions(processed_versions) + + rval['package_found'] = True + rval['versions'] = formatted_versions + rval['package_name'] = self.name + + if self.verbose: + rval['raw_versions'] = processed_versions + else: + del rval['results'] + + # No packages found + else: + rval['package_found'] = False + + return rval + + @staticmethod + def run_ansible(params, check_mode): + '''run the ansible idempotent code''' + + repoquery = Repoquery( + params['name'], + params['query_type'], + params['show_duplicates'], + params['match_version'], + params['verbose'], + ) + + state = params['state'] + + if state == 'list': + results = repoquery.repoquery() + + if results['returncode'] != 0: + return {'failed': True, + 'msg': results} + + return {'changed': False, 'results': results, 'state': 'list', 'check_mode': check_mode} + + return {'failed': True, + 'changed': False, + 'msg': 'Unknown state passed. %s' % state, + 'state': 'unknown'} diff --git a/roles/lib_utils/src/doc/repoquery b/roles/lib_utils/src/doc/repoquery new file mode 100644 index 000000000..82e273a42 --- /dev/null +++ b/roles/lib_utils/src/doc/repoquery @@ -0,0 +1,275 @@ +# flake8: noqa +# pylint: skip-file + +DOCUMENTATION = ''' +--- +module: repoquery +short_description: Query package information from Yum repositories +description: + - Query package information from Yum repositories. +options: + state: + description: + - The expected state. Currently only supports list. + required: false + default: list + choices: ["list"] + aliases: [] + name: + description: + - The name of the package to query + required: true + default: None + aliases: [] + query_type: + description: + - Narrows the packages queried based off of this value. + - If repos, it narrows the query to repositories defined on the machine. + - If installed, it narrows the query to only packages installed on the machine. + - If available, it narrows the query to packages that are available to be installed. + - If recent, it narrows the query to only recently edited packages. + - If updates, it narrows the query to only packages that are updates to existing installed packages. + - If extras, it narrows the query to packages that are not present in any of the available repositories. + - If all, it queries all of the above. + required: false + default: repos + aliases: [] + verbose: + description: + - Shows more detail for the requested query. + required: false + default: false + aliases: [] + show_duplicates: + description: + - Shows multiple versions of a package. + required: false + default: false + aliases: [] + match_version: + description: + - Match the specific version given to the package. + required: false + default: None + aliases: [] +author: +- "Matt Woodson <mwoodson@redhat.com>" +extends_documentation_fragment: [] +''' + +EXAMPLES = ''' +# Example 1: Get bash versions + - name: Get bash version + repoquery: + name: bash + show_duplicates: True + register: bash_out + +# Results: +# ok: [localhost] => { +# "bash_out": { +# "changed": false, +# "results": { +# "cmd": "/usr/bin/repoquery --quiet --pkgnarrow=repos --queryformat=%{version}|%{release}|%{arch}|%{repo}|%{version}-%{release} --show-duplicates bash", +# "package_found": true, +# "package_name": "bash", +# "returncode": 0, +# "versions": { +# "available_versions": [ +# "4.2.45", +# "4.2.45", +# "4.2.45", +# "4.2.46", +# "4.2.46", +# "4.2.46", +# "4.2.46" +# ], +# "available_versions_full": [ +# "4.2.45-5.el7", +# "4.2.45-5.el7_0.2", +# "4.2.45-5.el7_0.4", +# "4.2.46-12.el7", +# "4.2.46-19.el7", +# "4.2.46-20.el7_2", +# "4.2.46-21.el7_3" +# ], +# "latest": "4.2.46", +# "latest_full": "4.2.46-21.el7_3" +# } +# }, +# "state": "present" +# } +# } + + + +# Example 2: Get bash versions verbosely + - name: Get bash versions verbosely + repoquery: + name: bash + show_duplicates: True + verbose: True + register: bash_out + +# Results: +# ok: [localhost] => { +# "bash_out": { +# "changed": false, +# "results": { +# "cmd": "/usr/bin/repoquery --quiet --pkgnarrow=repos --queryformat=%{version}|%{release}|%{arch}|%{repo}|%{version}-%{release} --show-duplicates bash", +# "package_found": true, +# "package_name": "bash", +# "raw_versions": { +# "4.2.45-5.el7": { +# "arch": "x86_64", +# "release": "5.el7", +# "repo": "rhel-7-server-rpms", +# "version": "4.2.45", +# "version_release": "4.2.45-5.el7" +# }, +# "4.2.45-5.el7_0.2": { +# "arch": "x86_64", +# "release": "5.el7_0.2", +# "repo": "rhel-7-server-rpms", +# "version": "4.2.45", +# "version_release": "4.2.45-5.el7_0.2" +# }, +# "4.2.45-5.el7_0.4": { +# "arch": "x86_64", +# "release": "5.el7_0.4", +# "repo": "rhel-7-server-rpms", +# "version": "4.2.45", +# "version_release": "4.2.45-5.el7_0.4" +# }, +# "4.2.46-12.el7": { +# "arch": "x86_64", +# "release": "12.el7", +# "repo": "rhel-7-server-rpms", +# "version": "4.2.46", +# "version_release": "4.2.46-12.el7" +# }, +# "4.2.46-19.el7": { +# "arch": "x86_64", +# "release": "19.el7", +# "repo": "rhel-7-server-rpms", +# "version": "4.2.46", +# "version_release": "4.2.46-19.el7" +# }, +# "4.2.46-20.el7_2": { +# "arch": "x86_64", +# "release": "20.el7_2", +# "repo": "rhel-7-server-rpms", +# "version": "4.2.46", +# "version_release": "4.2.46-20.el7_2" +# }, +# "4.2.46-21.el7_3": { +# "arch": "x86_64", +# "release": "21.el7_3", +# "repo": "rhel-7-server-rpms", +# "version": "4.2.46", +# "version_release": "4.2.46-21.el7_3" +# } +# }, +# "results": "4.2.45|5.el7|x86_64|rhel-7-server-rpms|4.2.45-5.el7\n4.2.45|5.el7_0.2|x86_64|rhel-7-server-rpms|4.2.45-5.el7_0.2\n4.2.45|5.el7_0.4|x86_64|rhel-7-server-rpms|4.2.45-5.el7_0.4\n4.2.46|12.el7|x86_64|rhel-7-server-rpms|4.2.46-12.el7\n4.2.46|19.el7|x86_64|rhel-7-server-rpms|4.2.46-19.el7\n4.2.46|20.el7_2|x86_64|rhel-7-server-rpms|4.2.46-20.el7_2\n4.2.46|21.el7_3|x86_64|rhel-7-server-rpms|4.2.46-21.el7_3\n", +# "returncode": 0, +# "versions": { +# "available_versions": [ +# "4.2.45", +# "4.2.45", +# "4.2.45", +# "4.2.46", +# "4.2.46", +# "4.2.46", +# "4.2.46" +# ], +# "available_versions_full": [ +# "4.2.45-5.el7", +# "4.2.45-5.el7_0.2", +# "4.2.45-5.el7_0.4", +# "4.2.46-12.el7", +# "4.2.46-19.el7", +# "4.2.46-20.el7_2", +# "4.2.46-21.el7_3" +# ], +# "latest": "4.2.46", +# "latest_full": "4.2.46-21.el7_3" +# } +# }, +# "state": "present" +# } +# } + +# Example 3: Match a specific version + - name: matched versions repoquery test + repoquery: + name: atomic-openshift + show_duplicates: True + match_version: 3.3 + register: openshift_out + +# Result: + +# ok: [localhost] => { +# "openshift_out": { +# "changed": false, +# "results": { +# "cmd": "/usr/bin/repoquery --quiet --pkgnarrow=repos --queryformat=%{version}|%{release}|%{arch}|%{repo}|%{version}-%{release} --show-duplicates atomic-openshift", +# "package_found": true, +# "package_name": "atomic-openshift", +# "returncode": 0, +# "versions": { +# "available_versions": [ +# "3.2.0.43", +# "3.2.1.23", +# "3.3.0.32", +# "3.3.0.34", +# "3.3.0.35", +# "3.3.1.3", +# "3.3.1.4", +# "3.3.1.5", +# "3.3.1.7", +# "3.4.0.39" +# ], +# "available_versions_full": [ +# "3.2.0.43-1.git.0.672599f.el7", +# "3.2.1.23-1.git.0.88a7a1d.el7", +# "3.3.0.32-1.git.0.37bd7ea.el7", +# "3.3.0.34-1.git.0.83f306f.el7", +# "3.3.0.35-1.git.0.d7bd9b6.el7", +# "3.3.1.3-1.git.0.86dc49a.el7", +# "3.3.1.4-1.git.0.7c8657c.el7", +# "3.3.1.5-1.git.0.62700af.el7", +# "3.3.1.7-1.git.0.0988966.el7", +# "3.4.0.39-1.git.0.5f32f06.el7" +# ], +# "latest": "3.4.0.39", +# "latest_full": "3.4.0.39-1.git.0.5f32f06.el7", +# "matched_version_found": true, +# "matched_version_full_latest": "3.3.1.7-1.git.0.0988966.el7", +# "matched_version_latest": "3.3.1.7", +# "matched_versions": [ +# "3.3.0.32", +# "3.3.0.34", +# "3.3.0.35", +# "3.3.1.3", +# "3.3.1.4", +# "3.3.1.5", +# "3.3.1.7" +# ], +# "matched_versions_full": [ +# "3.3.0.32-1.git.0.37bd7ea.el7", +# "3.3.0.34-1.git.0.83f306f.el7", +# "3.3.0.35-1.git.0.d7bd9b6.el7", +# "3.3.1.3-1.git.0.86dc49a.el7", +# "3.3.1.4-1.git.0.7c8657c.el7", +# "3.3.1.5-1.git.0.62700af.el7", +# "3.3.1.7-1.git.0.0988966.el7" +# ], +# "requested_match_version": "3.3" +# } +# }, +# "state": "present" +# } +# } + +''' diff --git a/roles/lib_utils/src/lib/import.py b/roles/lib_utils/src/lib/import.py new file mode 100644 index 000000000..d892353a1 --- /dev/null +++ b/roles/lib_utils/src/lib/import.py @@ -0,0 +1,14 @@ +# flake8: noqa +# pylint: skip-file + +# pylint: disable=wrong-import-order,wrong-import-position,unused-import + +from __future__ import print_function # noqa: F401 +import json # noqa: F401 +import os # noqa: F401 +import re # noqa: F401 +# pylint: disable=import-error +import ruamel.yaml as yaml # noqa: F401 +import shutil # noqa: F401 + +from ansible.module_utils.basic import AnsibleModule diff --git a/roles/lib_utils/src/lib/repoquery.py b/roles/lib_utils/src/lib/repoquery.py new file mode 100644 index 000000000..91ccd9815 --- /dev/null +++ b/roles/lib_utils/src/lib/repoquery.py @@ -0,0 +1,92 @@ +# pylint: skip-file +# flake8: noqa + +''' + class that wraps the repoquery commands in a subprocess +''' + +# pylint: disable=too-many-lines,wrong-import-position,wrong-import-order + +from collections import defaultdict # noqa: E402 + + +# pylint: disable=no-name-in-module,import-error +# Reason: pylint errors with "No name 'version' in module 'distutils'". +# This is a bug: https://github.com/PyCQA/pylint/issues/73 +from distutils.version import LooseVersion # noqa: E402 + +import subprocess # noqa: E402 + + +class RepoqueryCLIError(Exception): + '''Exception class for repoquerycli''' + pass + + +def _run(cmds): + ''' Actually executes the command. This makes mocking easier. ''' + proc = subprocess.Popen(cmds, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + + stdout, stderr = proc.communicate() + + return proc.returncode, stdout, stderr + + +# pylint: disable=too-few-public-methods +class RepoqueryCLI(object): + ''' Class to wrap the command line tools ''' + def __init__(self, + verbose=False): + ''' Constructor for RepoqueryCLI ''' + self.verbose = verbose + self.verbose = True + + def _repoquery_cmd(self, cmd, output=False, output_type='json'): + '''Base command for repoquery ''' + cmds = ['/usr/bin/repoquery', '--plugins', '--quiet'] + + cmds.extend(cmd) + + rval = {} + results = '' + err = None + + if self.verbose: + print(' '.join(cmds)) + + returncode, stdout, stderr = _run(cmds) + + rval = { + "returncode": returncode, + "results": results, + "cmd": ' '.join(cmds), + } + + if returncode == 0: + if output: + if output_type == 'raw': + rval['results'] = stdout + + if self.verbose: + print(stdout) + print(stderr) + + if err: + rval.update({ + "err": err, + "stderr": stderr, + "stdout": stdout, + "cmd": cmds + }) + + else: + rval.update({ + "stderr": stderr, + "stdout": stdout, + "results": {}, + }) + + return rval diff --git a/roles/lib_utils/src/sources.yml b/roles/lib_utils/src/sources.yml index 9cf3a0981..053b59f77 100644 --- a/roles/lib_utils/src/sources.yml +++ b/roles/lib_utils/src/sources.yml @@ -2,7 +2,16 @@ yedit.py: - doc/generated - doc/license -- class/import.py +- lib/import.py - doc/yedit - class/yedit.py - ansible/yedit.py + +repoquery.py: +- doc/generated +- doc/license +- lib/import.py +- doc/repoquery +- lib/repoquery.py +- class/repoquery.py +- ansible/repoquery.py diff --git a/roles/lib_utils/src/test/integration/repoquery.yml b/roles/lib_utils/src/test/integration/repoquery.yml new file mode 100755 index 000000000..425324387 --- /dev/null +++ b/roles/lib_utils/src/test/integration/repoquery.yml @@ -0,0 +1,136 @@ +#!/usr/bin/ansible-playbook --module-path=../../../library/ +--- +- hosts: localhost + gather_facts: no + + tasks: + - name: basic query test - Act + repoquery: + name: bash + register: rq_out + + - name: Set a real package version to be used later + set_fact: + latest_available_bash_version: "{{ rq_out.results.versions.latest }}" + latest_available_full_bash_version: "{{ rq_out.results.versions.latest_full }}" + + - name: basic query test - Assert + assert: + that: + - "rq_out.state == 'list'" + - "rq_out.changed == False" + - "rq_out.results.returncode == 0" + - "rq_out.results.package_found == True" + - "rq_out.results.package_name == 'bash'" + - "rq_out.results.versions.available_versions | length == 1" + - "rq_out.results.versions.available_versions_full | length == 1" + - "rq_out.results.versions.latest is defined" + - "rq_out.results.versions.latest in rq_out.results.versions.available_versions" + - "rq_out.results.versions.latest_full is defined" + - "rq_out.results.versions.latest_full in rq_out.results.versions.available_versions_full" + + - name: show_duplicates query test - Act + repoquery: + name: bash + show_duplicates: True + register: rq_out + + - name: show_duplicates query test - Assert + assert: + that: + - "rq_out.state == 'list'" + - "rq_out.changed == False" + - "rq_out.results.returncode == 0" + - "rq_out.results.package_found == True" + - "rq_out.results.package_name == 'bash'" + - "rq_out.results.versions.available_versions | length >= 1" + - "rq_out.results.versions.available_versions_full | length >= 1" + - "rq_out.results.versions.latest is defined" + - "rq_out.results.versions.latest in rq_out.results.versions.available_versions" + - "rq_out.results.versions.latest_full is defined" + - "rq_out.results.versions.latest_full in rq_out.results.versions.available_versions_full" + + - name: show_duplicates verbose query test - Act + repoquery: + name: bash + show_duplicates: True + verbose: True + register: rq_out + + - name: show_duplicates verbose query test - Assert + assert: + that: + - "rq_out.state == 'list'" + - "rq_out.changed == False" + - "rq_out.results.returncode == 0" + - "rq_out.results.package_found == True" + - "rq_out.results.package_name == 'bash'" + - "rq_out.results.raw_versions | length > 0" + - "rq_out.results.versions.available_versions | length > 0" + - "rq_out.results.versions.available_versions_full | length > 0" + - "rq_out.results.versions.latest is defined" + - "rq_out.results.versions.latest in rq_out.results.versions.available_versions" + - "rq_out.results.versions.latest_full is defined" + - "rq_out.results.versions.latest_full in rq_out.results.versions.available_versions_full" + + - name: query package does not exist query test - Act + repoquery: + name: somemadeuppackagenamethatwontmatch + show_duplicates: True + register: rq_out + + - name: query package does not exist query test - Assert + assert: + that: + - "rq_out.state == 'list'" + - "rq_out.changed == False" + - "rq_out.results.returncode == 0" + - "rq_out.results.package_found == False" + - "rq_out.results.results == ''" + + + - name: query match_version does not exist query test - Act + repoquery: + name: bash + show_duplicates: True + match_version: somemadeupversionnotexist + register: rq_out + + - name: query match_version does not exist query test - Assert + assert: + that: + - "rq_out.state == 'list'" + - "rq_out.changed == False" + - "rq_out.results.returncode == 0" + - "rq_out.results.package_found == True" + - "rq_out.results.package_name == 'bash'" + - "rq_out.results.versions.matched_version_found == False" + - "rq_out.results.versions.available_versions | length > 0" + - "rq_out.results.versions.available_versions_full | length > 0" + - "rq_out.results.versions.latest is defined" + - "rq_out.results.versions.latest in rq_out.results.versions.available_versions" + - "rq_out.results.versions.latest_full is defined" + - "rq_out.results.versions.latest_full in rq_out.results.versions.available_versions_full" + + - name: query match_version exists query test - Act + repoquery: + name: bash + show_duplicates: True + match_version: "{{ latest_available_bash_version }}" + register: rq_out + + - name: query match_version exists query test - Assert + assert: + that: + - "rq_out.state == 'list'" + - "rq_out.changed == False" + - "rq_out.results.returncode == 0" + - "rq_out.results.package_found == True" + - "rq_out.results.package_name == 'bash'" + - "rq_out.results.versions.matched_version_found == True" + - "rq_out.results.versions.available_versions | length > 0" + - "rq_out.results.versions.available_versions_full | length > 0" + - "rq_out.results.versions.latest is defined" + - "rq_out.results.versions.latest in rq_out.results.versions.available_versions" + - "rq_out.results.versions.latest_full is defined" + - "rq_out.results.versions.latest_full in rq_out.results.versions.available_versions_full" diff --git a/roles/lib_utils/src/test/unit/repoquery.py b/roles/lib_utils/src/test/unit/repoquery.py new file mode 100755 index 000000000..c487ab254 --- /dev/null +++ b/roles/lib_utils/src/test/unit/repoquery.py @@ -0,0 +1,87 @@ +#!/usr/bin/env python2 +''' + Unit tests for repoquery +''' +# To run: +# ./repoquery.py +# +# . +# Ran 1 test in 0.002s +# +# OK + +import os +import sys +import unittest +import mock + +# Removing invalid variable names for tests so that I can +# keep them brief +# pylint: disable=invalid-name,no-name-in-module +# Disable import-error b/c our libraries aren't loaded in jenkins +# pylint: disable=import-error,wrong-import-position +# place class in our python path +module_path = os.path.join('/'.join(os.path.realpath(__file__).split('/')[:-4]), 'library') # noqa: E501 +sys.path.insert(0, module_path) +from repoquery import Repoquery # noqa: E402 + + +class RepoQueryTest(unittest.TestCase): + ''' + Test class for RepoQuery + ''' + + def setUp(self): + ''' setup method for other tests ''' + pass + + @mock.patch('repoquery._run') + def test_querying_a_package(self, mock_cmd): + ''' Testing querying a package ''' + + # Arrange + + # run_ansible input parameters + params = { + 'state': 'list', + 'name': 'bash', + 'query_type': 'repos', + 'verbose': False, + 'show_duplicates': False, + 'match_version': None, + } + + valid_stderr = '''Repo rhel-7-server-extras-rpms forced skip_if_unavailable=True due to: /etc/pki/entitlement/3268107132875399464-key.pem + Repo rhel-7-server-rpms forced skip_if_unavailable=True due to: /etc/pki/entitlement/4128505182875899164-key.pem''' # not real + + # Return values of our mocked function call. These get returned once per call. + mock_cmd.side_effect = [ + (0, '4.2.46|21.el7_3|x86_64|rhel-7-server-rpms|4.2.46-21.el7_3', valid_stderr), # first call to the mock + ] + + # Act + results = Repoquery.run_ansible(params, False) + + # Assert + self.assertEqual(results['state'], 'list') + self.assertFalse(results['changed']) + self.assertTrue(results['results']['package_found']) + self.assertEqual(results['results']['returncode'], 0) + self.assertEqual(results['results']['package_name'], 'bash') + self.assertEqual(results['results']['versions'], {'latest_full': '4.2.46-21.el7_3', + 'available_versions': ['4.2.46'], + 'available_versions_full': ['4.2.46-21.el7_3'], + 'latest': '4.2.46'}) + + # Making sure our mock was called as we expected + mock_cmd.assert_has_calls([ + mock.call(['/usr/bin/repoquery', '--plugins', '--quiet', '--pkgnarrow=repos', '--queryformat=%{version}|%{release}|%{arch}|%{repo}|%{version}-%{release}', 'bash']), + ]) + + def tearDown(self): + '''TearDown method''' + pass + + +if __name__ == "__main__": + unittest.main() diff --git a/roles/openshift_facts/library/openshift_facts.py b/roles/openshift_facts/library/openshift_facts.py index 3c8e2ab9c..7c61da950 100755 --- a/roles/openshift_facts/library/openshift_facts.py +++ b/roles/openshift_facts/library/openshift_facts.py @@ -195,8 +195,7 @@ def hostname_valid(hostname): if (not hostname or hostname.startswith('localhost') or hostname.endswith('localdomain') or - hostname.endswith('novalocal') or - len(hostname.split('.')) < 2): + hostname.endswith('novalocal')): return False return True @@ -332,7 +331,8 @@ def normalize_gce_facts(metadata, facts): facts['network']['ip'] = facts['network']['interfaces'][0]['ips'][0] pub_ip = facts['network']['interfaces'][0]['public_ips'][0] facts['network']['public_ip'] = pub_ip - facts['network']['hostname'] = metadata['instance']['hostname'] + # Split instance hostname from GCE metadata to use the short instance name + facts['network']['hostname'] = metadata['instance']['hostname'].split('.')[0] # TODO: attempt to resolve public_hostname facts['network']['public_hostname'] = facts['network']['public_ip'] @@ -867,6 +867,7 @@ def set_deployment_facts_if_unset(facts): return facts +# pylint: disable=too-many-statements def set_version_facts_if_unset(facts): """ Set version facts. This currently includes common.version and common.version_gte_3_1_or_1_1. @@ -904,8 +905,8 @@ def set_version_facts_if_unset(facts): version_gte_3_1_1_or_1_1_1 = True version_gte_3_2_or_1_2 = True version_gte_3_3_or_1_3 = True - version_gte_3_4_or_1_4 = False - version_gte_3_5_or_1_5 = False + version_gte_3_4_or_1_4 = True + version_gte_3_5_or_1_5 = True version_gte_3_6_or_1_6 = False facts['common']['version_gte_3_1_or_1_1'] = version_gte_3_1_or_1_1 facts['common']['version_gte_3_1_1_or_1_1_1'] = version_gte_3_1_1_or_1_1_1 @@ -915,7 +916,9 @@ def set_version_facts_if_unset(facts): facts['common']['version_gte_3_5_or_1_5'] = version_gte_3_5_or_1_5 facts['common']['version_gte_3_6_or_1_6'] = version_gte_3_6_or_1_6 - if version_gte_3_4_or_1_4: + if version_gte_3_5_or_1_5: + examples_content_version = 'v1.5' + elif version_gte_3_4_or_1_4: examples_content_version = 'v1.4' elif version_gte_3_3_or_1_3: examples_content_version = 'v1.3' @@ -1019,7 +1022,7 @@ def set_nodename(facts): if 'cloudprovider' in facts and facts['cloudprovider']['kind'] == 'openstack': facts['node']['nodename'] = facts['provider']['metadata']['hostname'].replace('.novalocal', '') elif 'cloudprovider' in facts and facts['cloudprovider']['kind'] == 'gce': - facts['node']['nodename'] = '.'.split(facts['provider']['metadata']['hostname'])[0] + facts['node']['nodename'] = facts['provider']['metadata']['instance']['hostname'].split('.')[0] else: facts['node']['nodename'] = facts['common']['hostname'].lower() return facts diff --git a/roles/openshift_master_facts/lookup_plugins/openshift_master_facts_default_predicates.py b/roles/openshift_master_facts/lookup_plugins/openshift_master_facts_default_predicates.py index 29a59a0d3..0c94228c6 100644 --- a/roles/openshift_master_facts/lookup_plugins/openshift_master_facts_default_predicates.py +++ b/roles/openshift_master_facts/lookup_plugins/openshift_master_facts_default_predicates.py @@ -52,32 +52,64 @@ class LookupModule(LookupBase): # convert short_version to origin short_version short_version = re.sub('^3.', '1.', short_version) - if short_version in ['1.1', '1.2']: - predicates.append({'name': 'PodFitsHostPorts'}) - predicates.append({'name': 'PodFitsResources'}) - - # applies to all known versions - predicates.append({'name': 'NoDiskConflict'}) - - # only 1.1 didn't include NoVolumeZoneConflict - if short_version != '1.1': - predicates.append({'name': 'NoVolumeZoneConflict'}) - - if short_version in ['1.1', '1.2']: - predicates.append({'name': 'MatchNodeSelector'}) - - if short_version != '1.1': - predicates.append({'name': 'MaxEBSVolumeCount'}) - predicates.append({'name': 'MaxGCEPDVolumeCount'}) - - if short_version not in ['1.1', '1.2']: - predicates.append({'name': 'GeneralPredicates'}) - predicates.append({'name': 'PodToleratesNodeTaints'}) - predicates.append({'name': 'CheckNodeMemoryPressure'}) - - if short_version not in ['1.1', '1.2', '1.3']: - predicates.append({'name': 'CheckNodeDiskPressure'}) - predicates.append({'name': 'MatchInterPodAffinity'}) + # Predicates ordered according to OpenShift Origin source: + # origin/vendor/k8s.io/kubernetes/plugin/pkg/scheduler/algorithmprovider/defaults/defaults.go + + if short_version == '1.1': + predicates.extend([ + {'name': 'PodFitsHostPorts'}, + {'name': 'PodFitsResources'}, + {'name': 'NoDiskConflict'}, + {'name': 'MatchNodeSelector'}, + ]) + + if short_version == '1.2': + predicates.extend([ + {'name': 'PodFitsHostPorts'}, + {'name': 'PodFitsResources'}, + {'name': 'NoDiskConflict'}, + {'name': 'NoVolumeZoneConflict'}, + {'name': 'MatchNodeSelector'}, + {'name': 'MaxEBSVolumeCount'}, + {'name': 'MaxGCEPDVolumeCount'} + ]) + + if short_version == '1.3': + predicates.extend([ + {'name': 'NoDiskConflict'}, + {'name': 'NoVolumeZoneConflict'}, + {'name': 'MaxEBSVolumeCount'}, + {'name': 'MaxGCEPDVolumeCount'}, + {'name': 'GeneralPredicates'}, + {'name': 'PodToleratesNodeTaints'}, + {'name': 'CheckNodeMemoryPressure'} + ]) + + if short_version == '1.4': + predicates.extend([ + {'name': 'NoDiskConflict'}, + {'name': 'NoVolumeZoneConflict'}, + {'name': 'MaxEBSVolumeCount'}, + {'name': 'MaxGCEPDVolumeCount'}, + {'name': 'GeneralPredicates'}, + {'name': 'PodToleratesNodeTaints'}, + {'name': 'CheckNodeMemoryPressure'}, + {'name': 'CheckNodeDiskPressure'}, + {'name': 'MatchInterPodAffinity'} + ]) + + if short_version in ['1.5', '1.6']: + predicates.extend([ + {'name': 'NoVolumeZoneConflict'}, + {'name': 'MaxEBSVolumeCount'}, + {'name': 'MaxGCEPDVolumeCount'}, + {'name': 'MatchInterPodAffinity'}, + {'name': 'NoDiskConflict'}, + {'name': 'GeneralPredicates'}, + {'name': 'PodToleratesNodeTaints'}, + {'name': 'CheckNodeMemoryPressure'}, + {'name': 'CheckNodeDiskPressure'}, + ]) if regions_enabled: region_predicate = { diff --git a/roles/openshift_master_facts/lookup_plugins/openshift_master_facts_default_priorities.py b/roles/openshift_master_facts/lookup_plugins/openshift_master_facts_default_priorities.py index 36022597f..95ace7923 100644 --- a/roles/openshift_master_facts/lookup_plugins/openshift_master_facts_default_priorities.py +++ b/roles/openshift_master_facts/lookup_plugins/openshift_master_facts_default_priorities.py @@ -11,11 +11,7 @@ class LookupModule(LookupBase): def run(self, terms, variables=None, zones_enabled=True, short_version=None, deployment_type=None, **kwargs): - priorities = [ - {'name': 'LeastRequestedPriority', 'weight': 1}, - {'name': 'BalancedResourceAllocation', 'weight': 1}, - {'name': 'SelectorSpreadPriority', 'weight': 1} - ] + priorities = [] if short_version is None or deployment_type is None: if 'openshift' not in variables: @@ -57,18 +53,51 @@ class LookupModule(LookupBase): # convert short_version to origin short_version short_version = re.sub('^3.', '1.', short_version) - if short_version == '1.4': - priorities.append({'name': 'NodePreferAvoidPodsPriority', 'weight': 10000}) - - # only 1.1 didn't include NodeAffinityPriority - if short_version != '1.1': - priorities.append({'name': 'NodeAffinityPriority', 'weight': 1}) + if short_version == '1.1': + priorities.extend([ + {'name': 'LeastRequestedPriority', 'weight': 1}, + {'name': 'BalancedResourceAllocation', 'weight': 1}, + {'name': 'SelectorSpreadPriority', 'weight': 1} + ]) + + if short_version == '1.2': + priorities.extend([ + {'name': 'LeastRequestedPriority', 'weight': 1}, + {'name': 'BalancedResourceAllocation', 'weight': 1}, + {'name': 'SelectorSpreadPriority', 'weight': 1}, + {'name': 'NodeAffinityPriority', 'weight': 1} + ]) + + if short_version == '1.3': + priorities.extend([ + {'name': 'LeastRequestedPriority', 'weight': 1}, + {'name': 'BalancedResourceAllocation', 'weight': 1}, + {'name': 'SelectorSpreadPriority', 'weight': 1}, + {'name': 'NodeAffinityPriority', 'weight': 1}, + {'name': 'TaintTolerationPriority', 'weight': 1} + ]) - if short_version not in ['1.1', '1.2']: - priorities.append({'name': 'TaintTolerationPriority', 'weight': 1}) - - if short_version not in ['1.1', '1.2', '1.3']: - priorities.append({'name': 'InterPodAffinityPriority', 'weight': 1}) + if short_version == '1.4': + priorities.extend([ + {'name': 'LeastRequestedPriority', 'weight': 1}, + {'name': 'BalancedResourceAllocation', 'weight': 1}, + {'name': 'SelectorSpreadPriority', 'weight': 1}, + {'name': 'NodePreferAvoidPodsPriority', 'weight': 10000}, + {'name': 'NodeAffinityPriority', 'weight': 1}, + {'name': 'TaintTolerationPriority', 'weight': 1}, + {'name': 'InterPodAffinityPriority', 'weight': 1} + ]) + + if short_version in ['1.5', '1.6']: + priorities.extend([ + {'name': 'SelectorSpreadPriority', 'weight': 1}, + {'name': 'InterPodAffinityPriority', 'weight': 1}, + {'name': 'LeastRequestedPriority', 'weight': 1}, + {'name': 'BalancedResourceAllocation', 'weight': 1}, + {'name': 'NodePreferAvoidPodsPriority', 'weight': 10000}, + {'name': 'NodeAffinityPriority', 'weight': 1}, + {'name': 'TaintTolerationPriority', 'weight': 1} + ]) if zones_enabled: zone_priority = { diff --git a/roles/openshift_master_facts/test/openshift_master_facts_default_predicates_tests.py b/roles/openshift_master_facts/test/openshift_master_facts_default_predicates_tests.py index 07bac6826..68b6deb88 100644 --- a/roles/openshift_master_facts/test/openshift_master_facts_default_predicates_tests.py +++ b/roles/openshift_master_facts/test/openshift_master_facts_default_predicates_tests.py @@ -9,6 +9,9 @@ sys.path = [os.path.abspath(os.path.dirname(__file__) + "/../lookup_plugins/")] from openshift_master_facts_default_predicates import LookupModule # noqa: E402 +# Predicates ordered according to OpenShift Origin source: +# origin/vendor/k8s.io/kubernetes/plugin/pkg/scheduler/algorithmprovider/defaults/defaults.go + DEFAULT_PREDICATES_1_1 = [ {'name': 'PodFitsHostPorts'}, {'name': 'PodFitsResources'}, @@ -48,6 +51,18 @@ DEFAULT_PREDICATES_1_4 = [ {'name': 'MatchInterPodAffinity'} ] +DEFAULT_PREDICATES_1_5 = [ + {'name': 'NoVolumeZoneConflict'}, + {'name': 'MaxEBSVolumeCount'}, + {'name': 'MaxGCEPDVolumeCount'}, + {'name': 'MatchInterPodAffinity'}, + {'name': 'NoDiskConflict'}, + {'name': 'GeneralPredicates'}, + {'name': 'PodToleratesNodeTaints'}, + {'name': 'CheckNodeMemoryPressure'}, + {'name': 'CheckNodeDiskPressure'}, +] + REGION_PREDICATE = { 'name': 'Region', 'argument': { @@ -66,10 +81,10 @@ TEST_VARS = [ ('3.3', 'openshift-enterprise', DEFAULT_PREDICATES_1_3), ('1.4', 'origin', DEFAULT_PREDICATES_1_4), ('3.4', 'openshift-enterprise', DEFAULT_PREDICATES_1_4), - ('1.5', 'origin', DEFAULT_PREDICATES_1_4), - ('3.5', 'openshift-enterprise', DEFAULT_PREDICATES_1_4), - ('1.6', 'origin', DEFAULT_PREDICATES_1_4), - ('3.6', 'openshift-enterprise', DEFAULT_PREDICATES_1_4), + ('1.5', 'origin', DEFAULT_PREDICATES_1_5), + ('3.5', 'openshift-enterprise', DEFAULT_PREDICATES_1_5), + ('1.6', 'origin', DEFAULT_PREDICATES_1_5), + ('3.6', 'openshift-enterprise', DEFAULT_PREDICATES_1_5), ] diff --git a/roles/openshift_master_facts/test/openshift_master_facts_default_priorities_tests.py b/roles/openshift_master_facts/test/openshift_master_facts_default_priorities_tests.py index 5427a07a1..4e44a2b3d 100644 --- a/roles/openshift_master_facts/test/openshift_master_facts_default_priorities_tests.py +++ b/roles/openshift_master_facts/test/openshift_master_facts_default_priorities_tests.py @@ -40,6 +40,16 @@ DEFAULT_PRIORITIES_1_4 = [ {'name': 'InterPodAffinityPriority', 'weight': 1} ] +DEFAULT_PRIORITIES_1_5 = [ + {'name': 'SelectorSpreadPriority', 'weight': 1}, + {'name': 'InterPodAffinityPriority', 'weight': 1}, + {'name': 'LeastRequestedPriority', 'weight': 1}, + {'name': 'BalancedResourceAllocation', 'weight': 1}, + {'name': 'NodePreferAvoidPodsPriority', 'weight': 10000}, + {'name': 'NodeAffinityPriority', 'weight': 1}, + {'name': 'TaintTolerationPriority', 'weight': 1} +] + ZONE_PRIORITY = { 'name': 'Zone', 'argument': { @@ -58,7 +68,11 @@ TEST_VARS = [ ('1.3', 'origin', DEFAULT_PRIORITIES_1_3), ('3.3', 'openshift-enterprise', DEFAULT_PRIORITIES_1_3), ('1.4', 'origin', DEFAULT_PRIORITIES_1_4), - ('3.4', 'openshift-enterprise', DEFAULT_PRIORITIES_1_4) + ('3.4', 'openshift-enterprise', DEFAULT_PRIORITIES_1_4), + ('1.5', 'origin', DEFAULT_PRIORITIES_1_5), + ('3.5', 'openshift-enterprise', DEFAULT_PRIORITIES_1_5), + ('1.6', 'origin', DEFAULT_PRIORITIES_1_5), + ('3.6', 'openshift-enterprise', DEFAULT_PRIORITIES_1_5), ] |