From 9a399b2c6a8cf773dc62efd0e61388b3ba158005 Mon Sep 17 00:00:00 2001
From: Chenxiong Qi <cqi@redhat.com>
Date: Jun 05 2017 02:25:28 +0000
Subject: [PATCH 1/2] Avoid repeating api/v1/ in Errata


Signed-off-by: Chenxiong Qi <cqi@redhat.com>

---

diff --git a/freshmaker/errata.py b/freshmaker/errata.py
index 5c8df7f..08b7dfd 100644
--- a/freshmaker/errata.py
+++ b/freshmaker/errata.py
@@ -50,10 +50,12 @@ class Errata(object):
 
         :param str server_url: Base URL of Errata server.
         """
+        self._api_ver = 'api/v1'
         self.server_url = server_url.rstrip('/')
 
     def _errata_get(self, endpoint):
-        r = requests.get("%s/%s" % (self.server_url, endpoint),
+        r = requests.get("%s/%s/%s" % (self.server_url, self._api_ver,
+                                       endpoint.lstrip('/')),
                          auth=HTTPKerberosAuth())
         r.raise_for_status()
         return r.json()
@@ -71,7 +73,7 @@ class Errata(object):
         :rtype: list
         """
         if isinstance(event, BrewRPMSignEvent):
-            build = self._errata_get("api/v1/build/%s" % str(event.nvr))
+            build = self._errata_get("/build/%s" % str(event.nvr))
             if "all_errata" not in build:
                 return []
             return [
@@ -98,7 +100,7 @@ class Errata(object):
 
         # For each NVR, check that all the rpms are signed.
         for nvr in nvrs:
-            build = self._errata_get("api/v1/build/%s" % str(nvr))
+            build = self._errata_get("build/%s" % str(nvr))
             if "rpms_signed" not in build or not build["rpms_signed"]:
                 return False
 
diff --git a/tests/test_errata.py b/tests/test_errata.py
index 0f7aeaf..94cc29e 100644
--- a/tests/test_errata.py
+++ b/tests/test_errata.py
@@ -69,7 +69,7 @@ class MockedErrataAPI(object):
     def errata_get(self, endpoint):
         if endpoint.endswith("builds.json"):
             return self.builds_json
-        elif endpoint.find("api/v1/build/") != -1:
+        elif endpoint.find("build/") != -1:
             nvr = endpoint.split("/")[-1]
             return self.builds[nvr]
 

From 4a8529d539358080b83812aa39de12a6b09fae10 Mon Sep 17 00:00:00 2001
From: Chenxiong Qi <cqi@redhat.com>
Date: Jun 05 2017 08:30:47 +0000
Subject: [PATCH 2/2] Query errata repo IDs


Besides the new method get_pulp_repository_ids, also refactor
_errata_get, because Errata has to deal with two kinds of Errata APIs, a
REST-style API and legacy HTTP API. The former one must have version
information api/v1 as prefix, whereas legacy HTTP API does not need it.

Signed-off-by: Chenxiong Qi <cqi@redhat.com>

---

diff --git a/freshmaker/errata.py b/freshmaker/errata.py
index 08b7dfd..d60cc73 100644
--- a/freshmaker/errata.py
+++ b/freshmaker/errata.py
@@ -50,16 +50,31 @@ class Errata(object):
 
         :param str server_url: Base URL of Errata server.
         """
-        self._api_ver = 'api/v1'
+        self._rest_api_ver = 'api/v1'
         self.server_url = server_url.rstrip('/')
 
-    def _errata_get(self, endpoint):
-        r = requests.get("%s/%s/%s" % (self.server_url, self._api_ver,
+    def _errata_rest_get(self, endpoint):
+        """Request REST-style API
+
+        Document: /developer-guide/api-http-api.html
+        """
+        r = requests.get("%s/%s/%s" % (self.server_url,
+                                       self._rest_api_ver,
                                        endpoint.lstrip('/')),
                          auth=HTTPKerberosAuth())
         r.raise_for_status()
         return r.json()
 
+    def _errata_http_get(self, endpoint):
+        """Request Errata legacy HTTP API
+
+        See also Legacy section in /developer-guide/api-http-api.html
+        """
+        r = requests.get('{}/{}'.format(self.server_url, endpoint),
+                         auth=HTTPKerberosAuth())
+        r.raise_for_status()
+        return r.json()
+
     def advisories_from_event(self, event):
         """
         Returns list of ErrataAdvisory instances associated with
@@ -73,7 +88,7 @@ class Errata(object):
         :rtype: list
         """
         if isinstance(event, BrewRPMSignEvent):
-            build = self._errata_get("/build/%s" % str(event.nvr))
+            build = self._errata_rest_get("/build/%s" % str(event.nvr))
             if "all_errata" not in build:
                 return []
             return [
@@ -89,7 +104,7 @@ class Errata(object):
         :return: True if all builds in advisory are signed.
         :rtype: bool
         """
-        builds_per_product = self._errata_get(
+        builds_per_product = self._errata_rest_get(
             "advisory/%s/builds.json" % str(errata_id))
 
         # Store NVRs of all builds in advisory to nvrs set.
@@ -100,8 +115,20 @@ class Errata(object):
 
         # For each NVR, check that all the rpms are signed.
         for nvr in nvrs:
-            build = self._errata_get("build/%s" % str(nvr))
+            build = self._errata_rest_get("build/%s" % str(nvr))
             if "rpms_signed" not in build or not build["rpms_signed"]:
                 return False
 
         return True
+
+    def get_pulp_repository_ids(self, errata_id):
+        """Get Pulp repository IDs where packages included in errata will end up
+
+        :param errata_id: Errata advisory ID, e.g. 25713.
+        :type errata_id: str or int
+        :return: a list of strings each of them represents a pulp repository ID
+        :rtype: list
+        """
+        data = self._errata_http_get(
+            '/errata/get_pulp_packages/{}.json'.format(errata_id))
+        return data.keys()
diff --git a/tests/test_errata.py b/tests/test_errata.py
index 94cc29e..2d1a5dd 100644
--- a/tests/test_errata.py
+++ b/tests/test_errata.py
@@ -28,12 +28,12 @@ from freshmaker.errata import Errata
 from freshmaker.events import BrewRPMSignEvent, GitRPMSpecChangeEvent
 
 
-class MockedErrataAPI(object):
+class MockedErrataRESTAPI(object):
     """
     Class mocking methods accessing Errata API in Errata class.
     """
-    def __init__(self, errata_get):
-        errata_get.side_effect = (self.errata_get)
+    def __init__(self, errata_rest_get):
+        errata_rest_get.side_effect = (self.errata_rest_get)
 
         self.builds_json = {
             "PRODUCT1": [
@@ -66,7 +66,7 @@ class MockedErrataAPI(object):
             "all_errata": [{"id": 28484, "name": "RHSA-2017:28484", "status": "QE"}],
             "rpms_signed": True}
 
-    def errata_get(self, endpoint):
+    def errata_rest_get(self, endpoint):
         if endpoint.endswith("builds.json"):
             return self.builds_json
         elif endpoint.find("build/") != -1:
@@ -78,17 +78,17 @@ class TestErrata(unittest.TestCase):
     def setUp(self):
         self.errata = Errata("https://localhost/")
 
-    @patch.object(Errata, "_errata_get")
-    def test_advisories_from_event(self, errata_get):
-        MockedErrataAPI(errata_get)
+    @patch.object(Errata, "_errata_rest_get")
+    def test_advisories_from_event(self, errata_rest_get):
+        MockedErrataRESTAPI(errata_rest_get)
         event = BrewRPMSignEvent("msgid", "libntirpc-1.4.3-4.el7rhgs")
         advisories = self.errata.advisories_from_event(event)
         self.assertEqual(len(advisories), 1)
         self.assertEqual(advisories[0].errata_id, 28484)
 
-    @patch.object(Errata, "_errata_get")
-    def test_advisories_from_event_missing_all_errata(self, errata_get):
-        mocked_errata = MockedErrataAPI(errata_get)
+    @patch.object(Errata, "_errata_rest_get")
+    def test_advisories_from_event_missing_all_errata(self, errata_rest_get):
+        mocked_errata = MockedErrataRESTAPI(errata_rest_get)
         del mocked_errata.builds["libntirpc-1.4.3-4.el7rhgs"]["all_errata"]
 
         event = BrewRPMSignEvent("msgid", "libntirpc-1.4.3-4.el7rhgs")
@@ -100,19 +100,40 @@ class TestErrata(unittest.TestCase):
         with self.assertRaises(ValueError):
             self.errata.advisories_from_event(event)
 
-    @patch.object(Errata, "_errata_get")
-    def test_builds_signed_all_signed(self, errata_get):
-        MockedErrataAPI(errata_get)
+    @patch.object(Errata, "_errata_rest_get")
+    def test_builds_signed_all_signed(self, errata_rest_get):
+        MockedErrataRESTAPI(errata_rest_get)
         self.assertTrue(self.errata.builds_signed(28484))
 
-    @patch.object(Errata, "_errata_get")
-    def test_builds_signed_some_unsigned(self, errata_get):
-        mocked_errata = MockedErrataAPI(errata_get)
+    @patch.object(Errata, "_errata_rest_get")
+    def test_builds_signed_some_unsigned(self, errata_rest_get):
+        mocked_errata = MockedErrataRESTAPI(errata_rest_get)
         mocked_errata.builds["libntirpc-1.4.3-4.el7rhgs"]["rpms_signed"] = False
         self.assertFalse(self.errata.builds_signed(28484))
 
-    @patch.object(Errata, "_errata_get")
-    def test_builds_signed_missing_data(self, errata_get):
-        mocked_errata = MockedErrataAPI(errata_get)
+    @patch.object(Errata, "_errata_rest_get")
+    def test_builds_signed_missing_data(self, errata_rest_get):
+        mocked_errata = MockedErrataRESTAPI(errata_rest_get)
         mocked_errata.builds["libntirpc-1.4.3-4.el7rhgs"] = {}
         self.assertFalse(self.errata.builds_signed(28484))
+
+    @patch('freshmaker.errata.requests.get')
+    def test_get_errata_repo_ids(self, get):
+        get.return_value.json.return_value = {
+            'rhel-6-server-eus-source-rpms__6_DOT_7__x86_64': [
+            ],
+            'rhel-6-server-eus-optional-debug-rpms__6_DOT_7__i386': [
+                '/path/to/package.rpm',
+                '/path/to/package1.rpm',
+                '/path/to/package2.rpm',
+            ],
+            'rhel-6-server-eus-rpms__6_DOT_7__x86_64': [
+            ],
+        }
+
+        repo_ids = self.errata.get_pulp_repository_ids(25718)
+
+        self.assertEqual(set(['rhel-6-server-eus-source-rpms__6_DOT_7__x86_64',
+                              'rhel-6-server-eus-optional-debug-rpms__6_DOT_7__i386',
+                              'rhel-6-server-eus-rpms__6_DOT_7__x86_64']),
+                         set(repo_ids))

