class TestErrata(helpers.FreshmakerTestCase): def setUp(self): super(TestErrata, self).setUp() self.errata = Errata("https://localhost/") def tearDown(self): super(TestErrata, self).tearDown() @patch.object(Errata, "_errata_rest_get") @patch.object(Errata, "_errata_http_get") def test_advisories_from_event(self, errata_http_get, errata_rest_get): MockedErrataAPI(errata_rest_get, errata_http_get) event = BrewSignRPMEvent("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) self.assertEqual(advisories[0].name, "RHSA-2017:28484") self.assertEqual(advisories[0].state, "QE") self.assertEqual(advisories[0].content_types, ["rpm"]) self.assertEqual(advisories[0].security_impact, "important") self.assertEqual(advisories[0].product_short_name, "product") self.assertEqual(advisories[0].cve_list, ["CVE-2015-3253", "CVE-2016-6814"]) self.assertEqual(advisories[0].has_hightouch_bug, True) @patch.object(Errata, "_errata_rest_get") @patch.object(Errata, "_errata_http_get") def test_advisories_from_event_empty_cve(self, errata_http_get, errata_rest_get): mocked_errata = MockedErrataAPI(errata_rest_get, errata_http_get) mocked_errata.advisory_rest_json["content"]["content"]["cve"] = "" event = BrewSignRPMEvent("msgid", "libntirpc-1.4.3-4.el7rhgs") advisories = self.errata.advisories_from_event(event) self.assertEqual(len(advisories), 1) self.assertEqual(advisories[0].cve_list, []) @patch.object(Errata, "_errata_rest_get") @patch.object(Errata, "_errata_http_get") def test_advisories_from_event_no_bugs(self, errata_http_get, errata_rest_get): mocked_errata = MockedErrataAPI(errata_rest_get, errata_http_get) mocked_errata.bugs = [] event = BrewSignRPMEvent("msgid", "libntirpc-1.4.3-4.el7rhgs") advisories = self.errata.advisories_from_event(event) self.assertEqual(len(advisories), 1) self.assertEqual(advisories[0].has_hightouch_bug, False) @patch.object(Errata, "_errata_rest_get") @patch.object(Errata, "_errata_http_get") def test_advisories_from_event_empty_bug_flags(self, errata_http_get, errata_rest_get): mocked_errata = MockedErrataAPI(errata_rest_get, errata_http_get) for bug in mocked_errata.bugs: bug["flags"] = "" event = BrewSignRPMEvent("msgid", "libntirpc-1.4.3-4.el7rhgs") advisories = self.errata.advisories_from_event(event) self.assertEqual(len(advisories), 1) self.assertEqual(advisories[0].has_hightouch_bug, False) @patch.object(Errata, "_errata_rest_get") @patch.object(Errata, "_errata_http_get") def test_advisories_from_event_missing_all_errata(self, errata_http_get, errata_rest_get): mocked_errata = MockedErrataAPI(errata_rest_get, errata_http_get) del mocked_errata.builds["libntirpc-1.4.3-4.el7rhgs"]["all_errata"] event = BrewSignRPMEvent("msgid", "libntirpc-1.4.3-4.el7rhgs") advisories = self.errata.advisories_from_event(event) self.assertEqual(len(advisories), 0) def test_advisories_from_event_unsupported_event(self): event = GitRPMSpecChangeEvent("msgid", "libntirpc", "master", "foo") with self.assertRaises(ValueError): self.errata.advisories_from_event(event) @patch.object(Errata, "_errata_rest_get") @patch.object(Errata, "_errata_http_get") def test_advisories_from_event_errata_state_change_event( self, errata_http_get, errata_rest_get): MockedErrataAPI(errata_rest_get, errata_http_get) event = ErrataAdvisoryStateChangedEvent( "msgid", ErrataAdvisory(28484, "name", "SHIPPED_LIVE", ['rpm'])) advisories = self.errata.advisories_from_event(event) self.assertEqual(len(advisories), 1) self.assertEqual(advisories[0].errata_id, 28484) @patch.object(Errata, "_errata_rest_get") @patch.object(Errata, "_errata_http_get") def test_builds_signed_all_signed(self, errata_http_get, errata_rest_get): MockedErrataAPI(errata_rest_get, errata_http_get) self.assertTrue(self.errata.builds_signed(28484)) @patch.object(Errata, "_errata_rest_get") @patch.object(Errata, "_errata_http_get") def test_builds_signed_some_unsigned(self, errata_http_get, errata_rest_get): mocked_errata = MockedErrataAPI(errata_rest_get, errata_http_get) mocked_errata.builds["libntirpc-1.4.3-4.el7rhgs"][ "rpms_signed"] = False self.assertFalse(self.errata.builds_signed(28484)) @patch.object(Errata, "_errata_rest_get") @patch.object(Errata, "_errata_http_get") def test_builds_signed_missing_data(self, errata_http_get, errata_rest_get): mocked_errata = MockedErrataAPI(errata_rest_get, errata_http_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)) @patch.object(Errata, "_errata_rest_get") @patch.object(Errata, "_errata_http_get") def test_rhel_release_from_product_version(self, errata_http_get, errata_rest_get): MockedErrataAPI(errata_rest_get, errata_http_get) ret = self.errata._rhel_release_from_product_version( 28484, "PRODUCT1-3.2-NFS") self.assertEqual(ret, "RHEL-6-foobar") @patch.object(Errata, "_errata_rest_get") @patch.object(Errata, "_errata_http_get") def test_rhel_release_from_product_version_unknown_product_ver( self, errata_http_get, errata_rest_get): MockedErrataAPI(errata_rest_get, errata_http_get) with self.assertRaises(ValueError): self.errata._rhel_release_from_product_version( 28484, "PRODUCT1-2.9-NFS") @patch.object(Errata, "_errata_rest_get") @patch.object(Errata, "_errata_http_get") def test_get_nvrs(self, errata_http_get, errata_rest_get): MockedErrataAPI(errata_rest_get, errata_http_get) srpms = self.errata.get_srpm_nvrs(28484, "") binary_rpms = self.errata.get_binary_rpm_nvrs(28484) self.assertEqual( set(srpms), set(['libntirpc-1.4.3-4.el7rhgs', 'libntirpc-1.4.3-4.el6rhs'])) self.assertEqual( set(binary_rpms), set([ 'libntirpc-devel-1.4.3-4.el6rhs', 'libntirpc-devel-1.4.3-4.el7rhgs' ])) @patch.object(Errata, "_errata_rest_get") @patch.object(Errata, "_errata_http_get") def test_get_binary_rpms_rhel_7(self, errata_http_get, errata_rest_get): MockedErrataAPI(errata_rest_get, errata_http_get) ret = self.errata.get_binary_rpm_nvrs(28484, "RHEL-7") self.assertEqual(ret, ['libntirpc-devel-1.4.3-4.el7rhgs']) @patch.object(Errata, "_errata_rest_get") @patch.object(Errata, "_errata_http_get") def test_get_srpm_nvrs_empty(self, errata_http_get, errata_rest_get): api = MockedErrataAPI(errata_rest_get, errata_http_get) api.builds_json = { "PRODUCT1": [{ "libntirpc-1.4.3-4.el7rhgs": { "PRODUCT2-3.2-NFS": { "x86_64": ["libntirpc-devel-1.4.3-4.el7rhgs.x86_64.rpm"] } } }] } ret = self.errata.get_srpm_nvrs(28484, "") self.assertEqual(ret, []) @patch.object(Errata, "_errata_rest_get") @patch.object(Errata, "_errata_http_get") def test_get_binary_nvrs_empty(self, errata_http_get, errata_rest_get): api = MockedErrataAPI(errata_rest_get, errata_http_get) api.builds_json = { "PRODUCT1": [{ "libntirpc-1.4.3-4.el7rhgs": { "PRODUCT2-3.2-NFS": { "SRPMS": ["libntirpc-devel-1.4.3-4.el7rhgs.x86_64.rpm"] } } }] } ret = self.errata.get_binary_rpm_nvrs(28484, "") self.assertEqual(ret, []) @patch.object(Errata, "_errata_rest_get") @patch.object(Errata, "_errata_http_get") def test_errata_get_cve_affected_rpm_nvrs(self, errata_http_get, errata_rest_get): MockedErrataAPI(errata_rest_get, errata_http_get) ret = self.errata.get_cve_affected_rpm_nvrs(28484) self.assertEqual(ret, ['libntirpc-1.4.3-4.el6rhs']) def test_get_docker_repo_tags(self): with patch.object(self.errata, "xmlrpc") as xmlrpc: xmlrpc.get_advisory_cdn_docker_file_list.return_value = { 'foo-container-1-1': { 'docker': { 'target': { 'repos': { 'foo-526': { 'tags': ['5.26', 'latest'] } } } } } } repo_tags = self.errata.get_docker_repo_tags(28484) expected = {'foo-container-1-1': {'foo-526': ['5.26', 'latest']}} self.assertEqual(repo_tags, expected) def test_get_docker_repo_tags_xmlrpc_exception(self): with patch.object(self.errata, "xmlrpc") as xmlrpc: xmlrpc.get_advisory_cdn_docker_file_list.side_effect = ValueError( "Expected XMLRPC test exception") repo_tags = self.errata.get_docker_repo_tags(28484) self.assertEqual(repo_tags, None) def test_get_docker_repo_tags_xmlrpc_non_returned(self): with patch.object(self.errata, "xmlrpc") as xmlrpc: xmlrpc.get_advisory_cdn_docker_file_list.return_value = None repo_tags = self.errata.get_docker_repo_tags(28484) self.assertEqual(repo_tags, None)
def rebuild_images_depending_on_advisory(self, db_event, errata_id): """ Submits requests to Bob to rebuild the images depending on the images updated in the advisory with ID `errata_id`. """ # Get the list of CDN repository names for each build in the advisory # as well as the name of tags used for the images. errata = Errata() repo_tags = errata.get_docker_repo_tags(errata_id) if not repo_tags: msg = "No CDN repo found for advisory %r" % errata_id self.log_info(msg) db_event.transition(EventState.FAILED, msg) db.session.commit() return # Use the Pulp to get the Docker repository name from the CDN repository # name and store it into `docker_repos` dict. pulp = Pulp(conf.pulp_docker_server_url, conf.pulp_docker_username, conf.pulp_docker_password) # {docker_repository_name: [list, of, docker, tags], ...} docker_repos = {} for per_build_repo_tags in repo_tags.values(): for cdn_repo, docker_repo_tags in per_build_repo_tags.items(): docker_repo = pulp.get_docker_repository_name(cdn_repo) if not docker_repo: self.log_error("No Docker repo found for CDN repo %r", cdn_repo) continue docker_repos[docker_repo] = docker_repo_tags self.log_info( "Found following Docker repositories updated by the advisory: %r", docker_repos.keys()) # Count the number of impacted builds to show them in state reason # when moving the Event to COMPLETE. num_impacted = None # Submit rebuild request to Bob :). for repo_name in docker_repos.keys(): self.log_info("Requesting Bob rebuild of %s", repo_name) parent_build = self.record_build( db_event, repo_name, ArtifactType.IMAGE_REPOSITORY, state=ArtifactBuildState.DONE.value) bob_url = "%s/update_children/%s" % ( conf.bob_server_url.rstrip('/'), repo_name) headers = {"Authorization": "Bearer %s" % conf.bob_auth_token} if self.dry_run: self.log_info("DRY RUN: Skipping request to Bob.") continue r = requests.get(bob_url, headers=headers) r.raise_for_status() resp = r.json() self.log_info("Response: %r", resp) if "impacted" in resp: if num_impacted is None: num_impacted = 0 num_impacted += len(resp["impacted"]) for external_repo_name in resp["impacted"]: self.record_build(db_event, external_repo_name, ArtifactType.IMAGE_REPOSITORY, state=ArtifactBuildState.DONE.value, dep_on=parent_build) msg = "Advisory %s: Informed Bob about update of %d image repositories." % ( db_event.search_key, len(docker_repos)) if num_impacted is not None: msg += " Bob is rebuilding %d impacted external image repositories." % ( num_impacted) db_event.transition(EventState.COMPLETE, msg) db.session.commit()