From 0cdc39f9dd575e8002a9173af04c6c5fac491c37 Mon Sep 17 00:00:00 2001
From: Valerij Maljulin <vmaljuli@redhat.com>
Date: Sep 11 2020 09:40:51 +0000
Subject: [PATCH 1/3] redhat-container-image subject now queries both itself and koji_build

JIRA: RHELWF-1569

---

diff --git a/conf/subject_types/redhat-container-image.yaml b/conf/subject_types/redhat-container-image.yaml
index e509ef2..6a75c0e 100644
--- a/conf/subject_types/redhat-container-image.yaml
+++ b/conf/subject_types/redhat-container-image.yaml
@@ -1,4 +1,14 @@
 --- !SubjectType
 id: redhat-container-image
 product_version: rhel-8
+is_koji_build: true
+is_nvr: true
 supports_remote_rule: true
+item_key: "nvr"
+result_queries:
+  - item_key: "nvr"
+    keys:
+      type: "redhat-container-image"
+  - item_key: "item"
+    keys:
+      type: "koji_build"
diff --git a/functional-tests/conftest.py b/functional-tests/conftest.py
index d030b0b..637f1f0 100644
--- a/functional-tests/conftest.py
+++ b/functional-tests/conftest.py
@@ -294,7 +294,7 @@ class TestDataBuilder(object):
         return self._create_result(data)
 
     def create_result(self, item, testcase_name, outcome,
-                      scenario=None, key=None, _type='koji_build'):
+                      scenario=None, key=None, _type='koji_build', **custom_data):
         data = {
             'testcase': {'name': testcase_name},
             'outcome': outcome,
@@ -305,6 +305,7 @@ class TestDataBuilder(object):
             data['data'] = {key: item}
         if scenario:
             data['data']['scenario'] = scenario
+        data['data'].update(custom_data)
         return self._create_result(data)
 
     def create_waiver(self, nvr, testcase_name, product_version, comment, waived=True,
diff --git a/functional-tests/consumers/test_resultsdb.py b/functional-tests/consumers/test_resultsdb.py
index ffd0804..b15697b 100644
--- a/functional-tests/consumers/test_resultsdb.py
+++ b/functional-tests/consumers/test_resultsdb.py
@@ -516,7 +516,7 @@ def test_consume_new_result_container_image(
                         "fedora"
                     ],
                     "item": [
-                        "fedora@sha256:{}".format(sha256)
+                        nvr
                     ],
                     "system_provider": [
                         "openstack"
diff --git a/functional-tests/test_api_v1.py b/functional-tests/test_api_v1.py
index 0513656..7e8f967 100644
--- a/functional-tests/test_api_v1.py
+++ b/functional-tests/test_api_v1.py
@@ -508,6 +508,56 @@ def test_make_a_decision_on_no_results(requests_session, greenwave_server, testd
     assert res_data['unsatisfied_requirements'] == expected_unsatisfied_requirements
 
 
+def test_make_a_decision_on_redhat_cont_image(requests_session, greenwave_server, testdatabuilder):
+    item1_nvr = testdatabuilder.unique_nvr()
+    # _type='koji-build'
+    result1 = testdatabuilder.create_result(item=item1_nvr,
+                                            testcase_name='test.testcase1',
+                                            outcome='FAILED')
+    result2 = testdatabuilder.create_result(item=item1_nvr,
+                                            testcase_name='test.testcase2',
+                                            outcome='FAILED', _type='redhat-container-image',
+                                            nvr=item1_nvr)
+    data = {
+        'product_version': 'fedora-26',
+        'subject_type': 'redhat-container-image',
+        'subject_identifier': item1_nvr,
+        "rules": [
+            {
+                "type": "PassingTestCaseRule",
+                "test_case_name": "test.testcase1"
+            },
+            {
+                "type": "PassingTestCaseRule",
+                "test_case_name": "test.testcase2"
+            }
+        ]
+    }
+    r = requests_session.post(greenwave_server + 'api/v1.0/decision', json=data)
+    assert r.status_code == 200
+    res_data = r.json()
+    assert res_data['policies_satisfied'] is False
+    expected_summary = '2 of 2 required tests failed'
+    assert res_data['summary'] == expected_summary
+    expected_unsatisfied_requirements = [
+        {
+            'item': {'item': item1_nvr, 'type': 'redhat-container-image'},
+            'result_id': result1['id'],
+            'testcase': 'test.testcase1',
+            'scenario': None,
+            'type': 'test-result-failed'
+        },
+        {
+            'item': {'item': item1_nvr, 'type': 'redhat-container-image'},
+            'result_id': result2['id'],
+            'testcase': 'test.testcase2',
+            'type': 'test-result-failed',
+            'scenario': None,
+        }
+    ]
+    assert res_data['unsatisfied_requirements'] == expected_unsatisfied_requirements
+
+
 def test_subject_type_group(requests_session, greenwave_server, testdatabuilder):
     results_item = 'sha256:' + sha256(os.urandom(50)).hexdigest()
 
diff --git a/greenwave/subjects/factory.py b/greenwave/subjects/factory.py
index df25fea..8e5d2ee 100644
--- a/greenwave/subjects/factory.py
+++ b/greenwave/subjects/factory.py
@@ -25,7 +25,12 @@ def create_subject_from_data(data):
             from data (in case data are invalid or subject configuration is
             missing)
     """
+    type_id = data.get("type")
+
     for type_ in subject_types():
+        if type_id and type_ != type_id:
+            continue
+
         if not type_.item_key:
             continue
 
@@ -35,7 +40,6 @@ def create_subject_from_data(data):
 
         return Subject(type_, item)
 
-    type_id = data.get("type")
     item = data.get("item")
     if type_id and item:
         return create_subject(type_id, item)
diff --git a/greenwave/tests/test_policies.py b/greenwave/tests/test_policies.py
index 643c913..c928f43 100644
--- a/greenwave/tests/test_policies.py
+++ b/greenwave/tests/test_policies.py
@@ -3,6 +3,7 @@
 
 import pytest
 import mock
+import time
 
 from textwrap import dedent
 
@@ -45,7 +46,8 @@ class DummyResultsRetriever(ResultsRetriever):
         self.outcome = outcome
 
     def _retrieve_data(self, params):
-        if (self.subject and params.get('item') == self.subject.identifier and
+        if (self.subject and (params.get('item') == self.subject.identifier or
+                              params.get('nvr') == self.subject.identifier) and
                 ('type' not in params or self.subject.type in params['type'].split(',')) and
                 params.get('testcases') == self.testcase):
             return [{
@@ -650,6 +652,37 @@ def test_remote_rule_policy_redhat_container_image(tmpdir):
                 assert isinstance(decision[0], TestResultFailed)
 
 
+def test_redhat_container_image_subject_type():
+    nvr = '389-ds-1.4-820181127205924.9edba152'
+    rdb_url = 'http://results.db'
+    cur_time = time.strftime('%Y-%m-%dT%H:%M:%S.00')
+    testcase_name = 'testcase1'
+    app = create_app('greenwave.config.TestingConfig')
+    with app.app_context():
+        rh_img_subject = create_subject('redhat-container-image', nvr)
+        retriever = ResultsRetriever(ignore_ids=list(), when=cur_time, url=rdb_url)
+        with mock.patch('requests.Session.get') as req_get:
+            req_get.json.return_value = {'data': {'item': [nvr]}}
+            retriever._retrieve_all(rh_img_subject, testcase_name)
+            assert req_get.call_count == 2
+            assert req_get.call_args_list[0] == mock.call(
+                f'{rdb_url}/results/latest',
+                params={'nvr': nvr,
+                        'type': 'redhat-container-image',
+                        '_distinct_on': 'scenario,system_architecture,system_variant',
+                        'since': f'1900-01-01T00:00:00.000000,{cur_time}',
+                        'testcases': testcase_name}
+            )
+            assert req_get.call_args_list[1] == mock.call(
+                f'{rdb_url}/results/latest',
+                params={'item': nvr,
+                        'type': 'koji_build',
+                        '_distinct_on': 'scenario,system_architecture,system_variant',
+                        'since': f'1900-01-01T00:00:00.000000,{cur_time}',
+                        'testcases': testcase_name}
+            )
+
+
 def test_remote_rule_policy_optional_id(tmpdir):
     subject = create_test_subject('koji_build', 'nethack-1.2.3-1.el9000')
 

From 9ed8f4fd2943a4ee88620fa748380fdddc7207e8 Mon Sep 17 00:00:00 2001
From: Valerij Maljulin <vmaljuli@redhat.com>
Date: Sep 11 2020 14:14:28 +0000
Subject: [PATCH 2/3] Rename the confusing variable in test_consume_new_result_container_image


---

diff --git a/functional-tests/consumers/test_resultsdb.py b/functional-tests/consumers/test_resultsdb.py
index b15697b..3ad2c32 100644
--- a/functional-tests/consumers/test_resultsdb.py
+++ b/functional-tests/consumers/test_resultsdb.py
@@ -441,8 +441,8 @@ def test_consume_new_result_container_image(
         testdatabuilder):
     unique_id = str(time.time()).encode('utf-8')
     sha256 = hashlib.sha256(unique_id).hexdigest()
-    nvr = 'fedora@sha256:{}'.format(sha256)
-    result = testdatabuilder.create_result(item=nvr,
+    item_hash = 'fedora@sha256:{}'.format(sha256)
+    result = testdatabuilder.create_result(item=item_hash,
                                            testcase_name='baseos-qe.baseos-ci.tier1.functional',
                                            outcome='PASSED', _type='container-image')
     message = {
@@ -516,7 +516,7 @@ def test_consume_new_result_container_image(
                         "fedora"
                     ],
                     "item": [
-                        nvr
+                        item_hash
                     ],
                     "system_provider": [
                         "openstack"
@@ -561,7 +561,7 @@ def test_consume_new_result_container_image(
     data = {
         'decision_context': 'container-image-test',
         'product_version': 'c3i',
-        'subject': [{'item': nvr, 'type': 'container-image'}],
+        'subject': [{'item': item_hash, 'type': 'container-image'}],
         'when': right_before_this_time(result['submit_time']),
     }
     r = requests_session.post(greenwave_server + 'api/v1.0/decision', json=data)
@@ -573,14 +573,14 @@ def test_consume_new_result_container_image(
         'decision_context': 'container-image-test',
         'policies_satisfied': True,
         'product_version': 'c3i',
-        'subject': [{'item': nvr, 'type': 'container-image'}],
+        'subject': [{'item': item_hash, 'type': 'container-image'}],
         'subject_type': 'container-image',
-        'subject_identifier': nvr,
+        'subject_identifier': item_hash,
         'summary': 'All required tests passed',
         'previous': old_decision,
         'satisfied_requirements': [{
             'subject_type': 'container-image',
-            'subject_identifier': nvr,
+            'subject_identifier': item_hash,
             'result_id': result['id'],
             'testcase': 'baseos-qe.baseos-ci.tier1.functional',
             'type': 'test-result-passed'

From f059e7905fcdaf349ceee1ef396c8b93b897d5a9 Mon Sep 17 00:00:00 2001
From: Valerij Maljulin <vmaljuli@redhat.com>
Date: Sep 11 2020 15:05:35 +0000
Subject: [PATCH 3/3] Suppress pylint warning for test


---

diff --git a/greenwave/tests/test_policies.py b/greenwave/tests/test_policies.py
index c928f43..560d969 100644
--- a/greenwave/tests/test_policies.py
+++ b/greenwave/tests/test_policies.py
@@ -663,7 +663,7 @@ def test_redhat_container_image_subject_type():
         retriever = ResultsRetriever(ignore_ids=list(), when=cur_time, url=rdb_url)
         with mock.patch('requests.Session.get') as req_get:
             req_get.json.return_value = {'data': {'item': [nvr]}}
-            retriever._retrieve_all(rh_img_subject, testcase_name)
+            retriever._retrieve_all(rh_img_subject, testcase_name)  # pylint: disable=W0212
             assert req_get.call_count == 2
             assert req_get.call_args_list[0] == mock.call(
                 f'{rdb_url}/results/latest',

