From 6e7fade815b8cdf7a64ec884301d543667dd0243 Mon Sep 17 00:00:00 2001 From: mprahl Date: Jan 17 2019 16:55:34 +0000 Subject: Add support for `excluded_packages` in a policy and deprecate `blacklist` This is the first part of #216 --- diff --git a/conf/policies/fedora.yaml b/conf/policies/fedora.yaml index 9a795f2..c038d3d 100644 --- a/conf/policies/fedora.yaml +++ b/conf/policies/fedora.yaml @@ -21,6 +21,8 @@ blacklist: - qt - mariadb - java-1.8.0-openjdk-libreoffice +excluded_packages: + - module-build* rules: - !PassingTestCaseRule {test_case_name: dist.abicheck} --- !Policy diff --git a/conf/policies/redhat.yaml b/conf/policies/redhat.yaml index db3dfb5..fb8bdd2 100644 --- a/conf/policies/redhat.yaml +++ b/conf/policies/redhat.yaml @@ -6,6 +6,8 @@ product_versions: decision_context: osci_compose_gate subject_type: koji_build blacklist: [] +excluded_packages: +- module-build* rules: - !PackageSpecificBuild { test_case_name: osci.brew-build.tier0.functional, diff --git a/docs/policies.rst b/docs/policies.rst index bb5943e..1602899 100644 --- a/docs/policies.rst +++ b/docs/policies.rst @@ -29,9 +29,8 @@ Here is an example policy: rules: - !PassingTestCaseRule {test_case_name: dist.rpmdeplint} - !PassingTestCaseRule {test_case_name: dist.upgradepath} - blacklist: - - qt - - mariadb + excluded_packages: + - python2-* On line 1, the ``---`` YAML document header marks the beginning of a new document. @@ -102,12 +101,19 @@ The document is a map (dictionary) with the following keys: Currently there are a few rule types, ``PassingTestCaseRule`` being one of them. See the :ref:`rule-types` section below for a full list. -``blacklist`` (optional) +``blacklist`` (**deprecated**) (optional) A list of binary RPM package names which are exempted from this policy. The blacklist only takes effect when Greenwave is making a decision about subjects with ``"item": "koji_build"``. +``excluded_packages`` (optional) + A list of binary RPM package names which are exempted from this policy. + This supports Unix shell-style wildcards (e.g. ``python2-*``). + + ``excluded_packages`` only takes effect when Greenwave is making a decision + about subjects with ``"item": "koji_build"``. + .. _Koji: https://pagure.io/koji .. _Bodhi: https://github.com/fedora-infra/bodhi .. _Product Definition Center: https://github.com/product-definition-center/product-definition-center @@ -247,7 +253,7 @@ Here's an example of a RemoteRule: - fedora-29 decision_context: osci_compose_gate subject_type: koji_build - blacklist: [] + excluded_packages: [] rules: - !RemoteRule {} diff --git a/functional-tests/test_api_v1.py b/functional-tests/test_api_v1.py index de7c080..06cc3f2 100644 --- a/functional-tests/test_api_v1.py +++ b/functional-tests/test_api_v1.py @@ -906,6 +906,29 @@ def test_blacklist(requests_session, greenwave_server, testdatabuilder): assert res_data['policies_satisfied'] is True +def test_excluded_packages(requests_session, greenwave_server, testdatabuilder): + """ + Test that packages in the excluded_packages list will be excluded when applying the policy. + """ + nvr = testdatabuilder.unique_nvr(name='module-build-service') + testdatabuilder.create_koji_build_result( + nvr=nvr, testcase_name='osci.brew-build.tier0.functional', + outcome='FAILED', type_='brew-build') + data = { + 'decision_context': 'osci_compose_gate', + 'product_version': 'rhel-something', + 'subject': [{'type': 'brew-build', 'item': nvr}], + } + r = requests_session.post(greenwave_server + 'api/v1.0/decision', + headers={'Content-Type': 'application/json'}, + data=json.dumps(data)) + assert r.status_code == 200 + res_data = r.json() + # the failed test result of sci.brew-build.tier0.functiona should be ignored and thus the + # policy is satisfied. + assert res_data['policies_satisfied'] is True + + def test_make_a_decision_about_brew_build(requests_session, greenwave_server, testdatabuilder): # The 'brew-build' type is used internally within Red Hat. We treat it as # the 'koji_build' subject type. diff --git a/greenwave/policies.py b/greenwave/policies.py index 1ca9253..3718500 100644 --- a/greenwave/policies.py +++ b/greenwave/policies.py @@ -215,6 +215,20 @@ class BlacklistedInPolicy(RuleSatisfied): } +class ExcludedInPolicy(RuleSatisfied): + """ + Package was excluded in policy. + """ + def __init__(self, subject_identifier): + self.subject_identifier = subject_identifier + + def to_json(self): + return { + 'type': 'excluded', + 'subject_identifier': self.subject_identifier, + } + + def summarize_answers(answers): """ Produces a one-sentence human-readable summary of the result of evaluating a policy. @@ -550,6 +564,7 @@ class Policy(SafeYAMLObject): 'subject_type': SafeYAMLString(), 'rules': SafeYAMLList(Rule), 'blacklist': SafeYAMLList(str, optional=True), + 'excluded_packages': SafeYAMLList(str, optional=True), 'relevance_key': SafeYAMLString(optional=True), 'relevance_value': SafeYAMLString(optional=True), } @@ -584,6 +599,9 @@ class Policy(SafeYAMLObject): name = subject_identifier.rsplit('-', 2)[0] if name in self.blacklist: return [BlacklistedInPolicy(subject_identifier) for rule in self.rules] + for exclude in self.excluded_packages: + if fnmatch(name, exclude): + return [ExcludedInPolicy(subject_identifier) for rule in self.rules] answers = [] for rule in self.rules: response = rule.check( @@ -612,6 +630,7 @@ class RemotePolicy(Policy): 'decision_context': SafeYAMLString(), 'rules': SafeYAMLList(Rule), 'blacklist': SafeYAMLList(str, optional=True), + 'excluded_packages': SafeYAMLList(str, optional=True), } def validate(self): diff --git a/greenwave/tests/test_policies.py b/greenwave/tests/test_policies.py index 659145c..26ca419 100644 --- a/greenwave/tests/test_policies.py +++ b/greenwave/tests/test_policies.py @@ -855,6 +855,7 @@ def test_policies_to_json(): decision_context: test subject_type: compose blacklist: [] + excluded_packages: [] rules: [] """)) assert len(policies) == 1 @@ -864,6 +865,7 @@ def test_policies_to_json(): 'decision_context': 'test', 'subject_type': 'compose', 'blacklist': [], + 'excluded_packages': [], 'rules': [], 'relevance_key': None, 'relevance_value': None,