From e0bb30755dea99c4cf7e35977e6c0f1e90a823bf Mon Sep 17 00:00:00 2001
From: Lukas Holecek <hluk@email.cz>
Date: Aug 03 2018 12:32:00 +0000
Subject: Fix retrieving old decisions


---

diff --git a/conf/policies/fedora.yaml b/conf/policies/fedora.yaml
index 98cf691..698723b 100644
--- a/conf/policies/fedora.yaml
+++ b/conf/policies/fedora.yaml
@@ -62,6 +62,16 @@ blacklist: []
 rules:
   - !RemoteRule {}
 
+--- !Policy
+id: "bodhi_update_with_a_package_test"
+product_versions:
+  - fedora-26
+decision_context: bodhi_update_with_a_package_test
+subject_type: bodhi_update
+blacklist: []
+rules:
+  - !PassingTestCaseRule {test_case_name: a_package_test}
+
 # No Fedora product has *actually* used an empty policy like this,
 # but we cover it in our tests for completeness.
 --- !Policy
diff --git a/functional-tests/consumers/test_resultsdb.py b/functional-tests/consumers/test_resultsdb.py
index 1396942..8c7dcd6 100644
--- a/functional-tests/consumers/test_resultsdb.py
+++ b/functional-tests/consumers/test_resultsdb.py
@@ -643,3 +643,48 @@ def test_consume_legacy_result(
         'previous': old_decision,
     }
     mock_fedmsg.assert_any_call(topic='decision.update', msg=second_msg)
+
+
+@mock.patch('greenwave.consumers.resultsdb.fedmsg.config.load_config')
+@mock.patch('greenwave.consumers.resultsdb.fedmsg.publish')
+def test_no_message_for_nonapplicable_policies(
+        mock_fedmsg, load_config, requests_session, greenwave_server,
+        testdatabuilder):
+    load_config.return_value = {'greenwave_api_url': greenwave_server + 'api/v1.0'}
+    nvr = testdatabuilder.unique_nvr()
+    # One result gets the decision in a certain state.
+    testdatabuilder.create_result(item=nvr,
+                                  testcase_name='a_package_test',
+                                  outcome='FAILED')
+    # Recording a new version of the same result shouldn't change our decision at all.
+    new_result = testdatabuilder.create_result(
+        item=nvr,
+        testcase_name='a_package_test',
+        outcome='PASSED')
+    message = {
+        'body': {
+            'topic': 'resultsdb.result.new',
+            'msg': {
+                'id': new_result['id'],
+                'outcome': 'PASSED',
+                'testcase': {
+                    'name': 'a_package_test',
+                },
+                'data': {
+                    'item': [nvr],
+                    'type': ['koji_build'],
+                }
+            }
+        }
+    }
+    hub = mock.MagicMock()
+    hub.config = {
+        'environment': 'environment',
+        'topic_prefix': 'topic_prefix',
+    }
+    handler = resultsdb.ResultsDBHandler(hub)
+    assert handler.topic == ['topic_prefix.environment.taskotron.result.new']
+    handler.consume(message)
+    # No message should be published as the decision is unchanged since we
+    # are still missing the required tests.
+    mock_fedmsg.assert_not_called()
diff --git a/functional-tests/test_api_v1.py b/functional-tests/test_api_v1.py
index cf5307b..ea04fde 100644
--- a/functional-tests/test_api_v1.py
+++ b/functional-tests/test_api_v1.py
@@ -36,7 +36,7 @@ def test_inspect_policies(requests_session, greenwave_server):
     assert r.status_code == 200
     body = r.json()
     policies = body['policies']
-    assert len(policies) == 8
+    assert len(policies) == 9
     assert any(p['id'] == 'taskotron_release_critical_tasks' for p in policies)
     assert any(p['decision_context'] == 'bodhi_update_push_stable' for p in policies)
     assert any(p['product_versions'] == ['fedora-26'] for p in policies)
diff --git a/greenwave/consumers/resultsdb.py b/greenwave/consumers/resultsdb.py
index ee27d63..ff1d8d1 100644
--- a/greenwave/consumers/resultsdb.py
+++ b/greenwave/consumers/resultsdb.py
@@ -138,13 +138,23 @@ class ResultsDBHandler(fedmsg.consumers.FedmsgConsumer):
             result_id (int): A result ID to ignore for comparison.
             testcase (munch.Munch): The name of a testcase to consider.
         """
+        # Also need to apply policies for each build in the update.
+        if subject_type == 'bodhi_update':
+            subject_types = set([subject_type, 'koji_build'])
+        else:
+            subject_types = set([subject_type])
 
         # Build a set of all policies which might apply to this new results
         applicable_policies = set()
         for policy in current_app.config['policies']:
-            for rule in policy.rules:
-                if getattr(rule, 'test_case_name', None) == testcase:
+            if policy.subject_type in subject_types:
+                testcases = (
+                    getattr(rule, 'test_case_name', None)
+                    for rule in policy.rules)
+
+                if testcase in testcases:
                     applicable_policies.add(policy)
+
         log.debug("messaging: found %i applicable policies of %i for testcase %r",
                   len(applicable_policies), len(current_app.config['policies']), testcase)
 
@@ -169,13 +179,18 @@ class ResultsDBHandler(fedmsg.consumers.FedmsgConsumer):
                     'subject_type': subject_type,
                     'subject_identifier': subject_identifier,
                 }
-                decision = greenwave.resources.retrieve_decision(greenwave_url, data)
 
-                # get old decision
-                data.update({
-                    'ignore_result': [result_id],
-                })
-                old_decision = greenwave.resources.retrieve_decision(greenwave_url, data)
+                try:
+                    decision = greenwave.resources.retrieve_decision(greenwave_url, data)
+
+                    # get old decision
+                    data.update({
+                        'ignore_result': [result_id],
+                    })
+                    old_decision = greenwave.resources.retrieve_decision(greenwave_url, data)
+                except requests.exceptions.HTTPError as e:
+                    log.exception('Failed to retrieve decision for data=%s, error: %s', data, e)
+                    continue
 
                 if decision == old_decision:
                     log.debug('Skipped emitting fedmsg, decision did not change: %s', decision)

