Esempio n. 1
0
def main():
    """ The main function. It creates VmaaS application, servers, run everything."""

    vmaas_app = Application()

    server = tornado.httpserver.HTTPServer(vmaas_app)
    server.bind(PUBLIC_API_PORT)
    num_servers = int(os.getenv("MAX_VMAAS_SERVERS", MAX_SERVERS))
    server.start(num_servers)  # start forking here
    init_logging(num_servers)
    LOGGER.info("Starting (version %s).", VMAAS_VERSION)

    # The rest stuff must be done only after forking
    BaseHandler.db_cache = Cache()
    BaseHandler.updates_api = UpdatesAPI(BaseHandler.db_cache)
    BaseHandler.repo_api = RepoAPI(BaseHandler.db_cache)
    BaseHandler.cve_api = CveAPI(BaseHandler.db_cache)
    BaseHandler.errata_api = ErrataAPI(BaseHandler.db_cache)
    BaseHandler.dbchange_api = DBChange(BaseHandler.db_cache)

    vmaas_app.websocket_reconnect()
    vmaas_app.reconnect_callback = PeriodicCallback(
        vmaas_app.websocket_reconnect, WEBSOCKET_RECONNECT_INTERVAL * 1000)
    vmaas_app.reconnect_callback.start()

    IOLoop.instance().start()
Esempio n. 2
0
def load_cache_to_apis():
    """Reload cache in APIs."""
    BaseHandler.updates_api = UpdatesAPI(BaseHandler.db_cache)
    BaseHandler.repo_api = RepoAPI(BaseHandler.db_cache)
    BaseHandler.cve_api = CveAPI(BaseHandler.db_cache)
    BaseHandler.errata_api = ErrataAPI(BaseHandler.db_cache)
    BaseHandler.packages_api = PackagesAPI(BaseHandler.db_cache)
    BaseHandler.vulnerabilities_api = VulnerabilitiesAPI(BaseHandler.db_cache, BaseHandler.updates_api)
    BaseHandler.dbchange_api = DBChange(BaseHandler.db_cache)
Esempio n. 3
0
 def __init__(self):
     handlers = [
         (r"/api/internal/refresh/?", RefreshHandler),  # GET request
         (r"/api/v1/updates/?", UpdatesHandler),  # POST request
         (r"/api/v1/updates/[a-zA-Z0-9-._:]+",
          UpdatesHandler),  # GET request with package name
         (r"/api/v1/cves/?", CVEHandler),
         (r"/api/v1/cves/[a-zA-Z0-9*-]+", CVEHandler),
         (r"/api/v1/repos/?", ReposHandler),
         (r"/api/v1/repos/[a-zA-Z0-9*-_]+", ReposHandler),
         (r"/api/v1/errata/?", ErrataHandler),  # POST request
         (r"/api/v1/errata/[a-zA-Z0-9*-:]+", ErrataHandler)  # GET request
     ]
     cursor = Database().cursor()
     self.updatesapi = UpdatesAPI(cursor)
     self.cveapi = CveAPI(cursor)
     self.repoapi = RepoAPI(cursor)
     self.errataapi = ErrataAPI(cursor)
     tornado.web.Application.__init__(self, handlers)
Esempio n. 4
0
 def setup_api(self, load_cache):
     """Setup UpdatesAPI object."""
     self.updates_api = UpdatesAPI(self.cache)
Esempio n. 5
0
class TestUpdatesAPI(TestBase):
    """Test updates api class."""

    updates_api = None

    @pytest.fixture(autouse=True)
    def setup_api(self, load_cache):
        """Setup UpdatesAPI object."""
        self.updates_api = UpdatesAPI(self.cache)

    def test_process_repos(self):
        """Test repos processing."""
        response = {}
        repo_ids = self.updates_api._process_repositories(
            UPDATES_JSON, response)
        assert len(repo_ids) == 1

    def test_process_repos_repo(self):
        """Test repos processing - filter out repository_list."""
        response = {}
        repo_ids = self.updates_api._process_repositories(
            UPDATES_JSON_REPO, response)
        assert repo_ids == set()

    def test_process_repos_release(self):
        """Test repos processing - filter out releasever."""
        response = {}
        repo_ids = self.updates_api._process_repositories(
            UPDATES_JSON_RELEASE, response)
        assert repo_ids == set()

    def test_process_repos_arch(self):
        """Test repos processing - filter out basearch."""
        response = {}
        repo_ids = self.updates_api._process_repositories(
            UPDATES_JSON_ARCH, response)
        assert repo_ids == set()

    def test_process_input_pkg(self):
        """Test filtering out unknown (or without updates) package names."""
        response = {}
        response["update_list"] = {}
        response["update_list"][PKG] = {}
        pkgs = self.updates_api._process_input_packages(UPDATES_JSON, response)
        assert pkgs

    def test_process_input_non_exist(self):
        """Test filtering out unknown non existing package."""
        response = {}
        response["update_list"] = {}
        response["update_list"][PKG] = {}
        pkgs = self.updates_api._process_input_packages(
            UPDATES_JSON_NON_EXIST, response)
        assert pkgs == {}

    def test_schema_v1(self):
        """Test schema of updates api v1."""
        # NOTE: use copy of dict with json input, because process_list changes this dict
        updates = self.updates_api.process_list(1, UPDATES_JSON.copy())
        assert schemas.updates_top_all_schema.validate(updates)
        assert schemas.updates_package_schema.validate(
            updates["update_list"][PKG])

    def test_schema_v2(self):
        """Test schema of updates api v2."""
        # NOTE: use copy of dict with json input, because process_list changes this dict
        updates = self.updates_api.process_list(2, UPDATES_JSON.copy())
        assert schemas.updates_top_all_schema.validate(updates)
        assert schemas.updates_package_schema_v2.validate(
            updates["update_list"][PKG])

    def test_schema_repolist(self):
        """Test repolist schema of updates api v2."""
        # NOTE: use copy of dict with json input, because process_list changes this dict
        updates = self.updates_api.process_list(2, UPDATES_JSON_REPO.copy())
        assert schemas.updates_top_repolist_schema.validate(updates)

    def test_schema_releasever(self):
        """Test releasever schema of updates api v2."""
        # NOTE: use copy of dict with json input, because process_list changes this dict
        updates = self.updates_api.process_list(2, UPDATES_JSON_RELEASE.copy())
        assert schemas.updates_top_releasever_schema.validate(updates)

    def test_schema_basearch(self):
        """Test basearch schema of updates api v2."""
        # NOTE: use copy of dict with json input, because process_list changes this dict
        updates = self.updates_api.process_list(2, UPDATES_JSON_ARCH.copy())
        assert schemas.updates_top_basearch_schema.validate(updates)

    def test_process_list_v1(self):
        """Test looking for package updates api v1."""
        # NOTE: use copy of dict with json input, because process_list changes this dict
        updates = self.updates_api.process_list(1, UPDATES_JSON.copy())
        assert updates

    def test_process_list_v2(self):
        """Test looking for package updates api v2."""
        # NOTE: use copy of dict with json input, because process_list changes this dict
        updates = self.updates_api.process_list(2, UPDATES_JSON.copy())
        assert updates

    def test_process_empty_pkg_list_v1(self):
        """Test empty package_list updates api v1."""
        # NOTE: use copy of dict with json input, because process_list changes this dict
        updates = self.updates_api.process_list(1,
                                                UPDATES_JSON_EMPTY_LIST.copy())
        assert updates == EMPTY_RESPONSE

    def test_process_empty_pkg_list_v2(self):
        """Test empty package_list updates api v2."""
        # NOTE: use copy of dict with json input, because process_list changes this dict
        updates = self.updates_api.process_list(2,
                                                UPDATES_JSON_EMPTY_LIST.copy())
        assert updates == EMPTY_RESPONSE

    def test_process_non_exist_v1(self):
        """Test non-existing package updates api v1."""
        # NOTE: use copy of dict with json input, because process_list changes this dict
        updates = self.updates_api.process_list(1,
                                                UPDATES_JSON_NON_EXIST.copy())
        assert updates == NON_EXIST_RESPONSE

    def test_process_non_exist_v2(self):
        """Test non-existing package updates api v2."""
        # NOTE: use copy of dict with json input, because process_list changes this dict
        updates = self.updates_api.process_list(2,
                                                UPDATES_JSON_NON_EXIST.copy())
        assert updates == NON_EXIST_RESPONSE
Esempio n. 6
0
class TestModularity(TestBase):
    """Test /updates modularity"""

    updates_api = None

    @staticmethod
    def gen_pkg_json(nevra, modules=None):
        """Prepares a request to VMaaS"""
        retval = {'package_list': [nevra]}
        if modules is not None:
            retval['modules_list'] = modules
        return retval

    @pytest.fixture(autouse=True)
    def setup_api(self, load_cache):
        """Setup UpdatesAPI object."""
        self.updates_api = UpdatesAPI(self.cache)

    @pytest.mark.parametrize('test_data', OLD_OLD, ids=[x[0] for x in OLD_OLD])
    def test_old_pkg_old_module(self, test_data):
        """
        Test with my-pkg-1.1.0-1.el8.i686
        Test without modularity info provided, should find 3 updates:
          my-pkg-1.2.0-1.el8.i686
          my-pkg-2.0.0-1.el8.i686
          my-pkg-2.1.0-1.el8.i686
        Test with modularity info provided, should find one update:
          my-pkg-1.2.0-1.el8.i686
        """
        pkg = PKG_NEVRAS[0]
        mode, modules, expected_update_pkgs = test_data  # pylint:disable=unused-variable
        updates = self.updates_api.process_list(
            2, self.gen_pkg_json(pkg, modules))
        assert updates
        available_updates = updates['update_list'][pkg]['available_updates']
        assert len(available_updates) == len(expected_update_pkgs)
        assert expected_update_pkgs == {
            rec['package']
            for rec in available_updates
        }

    @pytest.mark.parametrize('test_data', NEW_OLD, ids=[x[0] for x in NEW_OLD])
    def test_new_pkg_old_module(self, test_data):
        """Test with my-pkg-1.2.0-1.el8.i686
        Test without modularity info enabled, should find two updates
          my-pkg-2.0.0-1.el8.i686
          my-pkg-2.1.0-1.el8.i686
        With correct modularity stream enabled there should be no upates
        Test with incorrect modularity information, should find two (incorrect) update:
          my-pkg-2.0.0-1.el8.i686
          my-pkg-2.1.0-1.el8.i686
          DNF on the client should never let this happen
        """
        pkg = PKG_NEVRAS[1]
        mode, modules, expected_update_pkgs = test_data  # pylint:disable=unused-variable
        updates = self.updates_api.process_list(
            2, self.gen_pkg_json(pkg, modules))
        assert updates
        available_updates = updates['update_list'][pkg]['available_updates']
        if mode == 'correct_stream_enabled':  # with correct stream enabled there should be no updates
            assert not available_updates
            return
        assert len(available_updates) == len(expected_update_pkgs)
        assert expected_update_pkgs == {
            rec['package']
            for rec in available_updates
        }

    @pytest.mark.parametrize('test_data',
                             NEW_MODULE,
                             ids=[x[0] for x in NEW_MODULE])
    def test_old_pkg_new_module(self, test_data):
        """
        Test with my-pkg-2.0.0-1.el8.i686
        Both tests with, or without modularity should find one update
          my-pkg-2.1.0-1.el8.i686
        """
        pkg = PKG_NEVRAS[2]
        mode, modules, expected_update_pkgs = test_data  # pylint:disable=unused-variable
        updates = self.updates_api.process_list(
            2, self.gen_pkg_json(pkg, modules))
        assert updates
        available_updates = updates['update_list'][pkg]['available_updates']
        assert len(available_updates) == len(expected_update_pkgs)
        assert expected_update_pkgs == {
            rec['package']
            for rec in available_updates
        }

    @pytest.mark.parametrize('test_data',
                             NEW_MODULE,
                             ids=[x[0] for x in NEW_MODULE])
    def test_new_pkg_new_module(self, test_data):
        """
        Test with my-pkg-2.1.0-1.el8.i686 which is the latest package and has no updates
        There should be zero updates with or without modularity
        """

        pkg = PKG_NEVRAS[3]
        mode, modules, expected_update_pkgs = test_data  # pylint:disable=unused-variable
        updates = self.updates_api.process_list(
            2, self.gen_pkg_json(pkg, modules))
        assert updates
        assert not updates['update_list'][pkg]['available_updates']

    @pytest.mark.parametrize('test_data',
                             NO_MODULES,
                             ids=[x[0] for x in NO_MODULES])
    def test_no_enabled_modules(self, test_data):
        """
        Tests with modularity functionaility enabled witout needed module (my-pkg 1) enabled
        Scenarios: no modules enabled at all, only rhn-tools module enabled, module not present in the database enabled
        All of these should result in no updates found
        """
        pkg = PKG_NEVRAS[0]
        mode, modules = test_data  # pylint:disable=unused-variable
        updates = self.updates_api.process_list(
            2, self.gen_pkg_json(pkg, modules))
        assert updates
        assert not updates['update_list'][pkg]['available_updates']
Esempio n. 7
0
 def setup_api(self, load_cache):
     """Setup UpdatesAPI object."""
     self.vulnerabilities_api = VulnerabilitiesAPI(self.cache,
                                                   UpdatesAPI(self.cache))
Esempio n. 8
0
class TestUpdatesAPI(TestBase):
    """Test updates api class."""

    updates_api = None

    @pytest.fixture(autouse=True)
    def setup_api(self, load_cache):
        """Setup UpdatesAPI object."""
        self.updates_api = UpdatesAPI(self.cache)

    def test_process_input_pkg(self):
        """Test filtering out unknown (or without updates) package names."""
        pkgs, update_list = self.updates_api._process_input_packages(UPDATES_JSON)
        assert pkgs == {'my-pkg-1.1.0-1.el8.i686': {'parsed_nevra': ('my-pkg', '0', '1.1.0', '1.el8', 'i686')}}
        assert update_list == {'my-pkg-1.1.0-1.el8.i686': {}}

    def test_process_input_non_exist(self):
        """Test filtering out unknown non existing package."""
        pkgs, update_list = self.updates_api._process_input_packages(UPDATES_JSON_NON_EXIST)
        assert pkgs == {}
        assert update_list == {'non-exist': {}}

    def test_schema_v1(self):
        """Test schema of updates api v1."""
        # NOTE: use copy of dict with json input, because process_list changes this dict
        updates = self.updates_api.process_list(1, UPDATES_JSON.copy())
        assert schemas.updates_top_all_schema.validate(updates)
        assert schemas.updates_package_schema.validate(updates["update_list"][PKG])

    def test_schema_v2(self):
        """Test schema of updates api v2."""
        # NOTE: use copy of dict with json input, because process_list changes this dict
        updates = self.updates_api.process_list(2, UPDATES_JSON.copy())
        assert schemas.updates_top_all_schema.validate(updates)
        assert schemas.updates_package_schema_v2.validate(updates["update_list"][PKG])

    def test_schema_repolist(self):
        """Test repolist schema of updates api v2."""
        # NOTE: use copy of dict with json input, because process_list changes this dict
        updates = self.updates_api.process_list(2, UPDATES_JSON_REPO.copy())
        assert schemas.updates_top_repolist_schema.validate(updates)

    def test_schema_releasever(self):
        """Test releasever schema of updates api v2."""
        # NOTE: use copy of dict with json input, because process_list changes this dict
        updates = self.updates_api.process_list(2, UPDATES_JSON_RELEASE.copy())
        assert schemas.updates_top_releasever_schema.validate(updates)

    def test_schema_basearch(self):
        """Test basearch schema of updates api v2."""
        # NOTE: use copy of dict with json input, because process_list changes this dict
        updates = self.updates_api.process_list(2, UPDATES_JSON_ARCH.copy())
        assert schemas.updates_top_basearch_schema.validate(updates)

    def test_process_list_v1(self):
        """Test looking for package updates api v1."""
        # NOTE: use copy of dict with json input, because process_list changes this dict
        updates = self.updates_api.process_list(1, UPDATES_JSON.copy())
        assert updates == UPDATES_RESPONSE_1

    def test_process_list_v2(self):
        """Test looking for package updates api v2."""
        # NOTE: use copy of dict with json input, because process_list changes this dict
        updates = self.updates_api.process_list(2, UPDATES_JSON.copy())
        assert updates == UPDATES_RESPONSE_2

    def test_process_list_v2_unknown(self):
        """Test looking for unknown EVRA updates, disabled optimistic_updates."""
        # NOTE: use copy of dict with json input, because process_list changes this dict
        updates = self.updates_api.process_list(2, UPDATES_JSON_UNKNOWN.copy())
        assert updates == UPDATES_RESPONSE_2_UNKNOWN_NONE

    def test_optimistic_updates_1(self):
        """Test looking for unknown EVRA updates (module_stream: 1)."""
        # NOTE: use copy of dict with json input, because process_list changes this dict
        updates = self.updates_api.process_list(2, UPDATES_JSON_UNKNOWN_OPT_UPD.copy())
        assert updates == UPDATES_RESPONSE_2_UNKNOWN

    def test_optimistic_updates_2(self):
        """Test looking for unknown EVRA updates (module_stream: 2)."""
        # NOTE: use copy of dict with json input, because process_list changes this dict
        updates = self.updates_api.process_list(2, UPDATES_JSON_UNKNOWN_OPT_UPD_2.copy())
        assert updates == UPDATES_RESPONSE_2_UNKNOWN_2

    def test_process_empty_pkg_list_v1(self):
        """Test empty package_list updates api v1."""
        # NOTE: use copy of dict with json input, because process_list changes this dict
        updates = self.updates_api.process_list(1, UPDATES_JSON_EMPTY_LIST.copy())
        assert updates == EMPTY_RESPONSE

    def test_process_empty_pkg_list_v2(self):
        """Test empty package_list updates api v2."""
        # NOTE: use copy of dict with json input, because process_list changes this dict
        updates = self.updates_api.process_list(2, UPDATES_JSON_EMPTY_LIST.copy())
        assert updates == EMPTY_RESPONSE

    def test_process_non_exist_v1(self):
        """Test non-existing package updates api v1."""
        # NOTE: use copy of dict with json input, because process_list changes this dict
        updates = self.updates_api.process_list(1, UPDATES_JSON_NON_EXIST.copy())
        assert updates == NON_EXIST_RESPONSE

    def test_process_non_exist_v2(self):
        """Test non-existing package updates api v2."""
        # NOTE: use copy of dict with json input, because process_list changes this dict
        updates = self.updates_api.process_list(2, UPDATES_JSON_NON_EXIST.copy())
        assert updates == NON_EXIST_RESPONSE
Esempio n. 9
0
class TestInternalUpdatesAPI(TestBase):
    """Test internal methods of updates api class."""

    updates_api = None

    @pytest.fixture(autouse=True)
    def setup_api(self, load_cache):
        """Setup UpdatesAPI object."""
        self.updates_api = UpdatesAPI(self.cache)

    def test_get_repository_list_1(self):
        """Test with complete request."""
        repositories_list, repo_ids = self.updates_api._get_repository_list(UPDATES_JSON)
        assert repositories_list == ['rhel-7-server-rpms']
        assert repo_ids == [1]

    def test_get_repository_list_3(self):
        """Test with 'repository_list' only request."""
        repositories_list, repo_ids = self.updates_api._get_repository_list(UPDATES_JSON_REPO)
        assert repositories_list == ['rhel-6-server-rpms']
        assert repo_ids == []

    def test_get_repository_list_4(self):
        """Test with 'releasever' only request."""
        repositories_list, repo_ids = self.updates_api._get_repository_list(UPDATES_JSON_RELEASE)
        assert repositories_list is None
        assert list(repo_ids) == [1, 2, 3, 4, 5, 6]

    def test_get_repository_list_5(self):
        """Test with 'basearch' only request."""
        repositories_list, repo_ids = self.updates_api._get_repository_list(UPDATES_JSON_ARCH)
        assert repositories_list is None
        assert list(repo_ids) == [1, 2, 3, 4, 5, 6]

    def test_get_releasever_1(self):
        """Test with complete request"""
        repo_ids_in = [1]
        releasever, repo_ids = self.updates_api._get_releasever(UPDATES_JSON, repo_ids_in)
        assert releasever == '7Server'
        assert repo_ids == [1]

    def test_get_releasever_2(self):
        """Test with 'releasever' only request."""
        repo_ids_in = [1, 2, 3, 4, 5]
        releasever, repo_ids = self.updates_api._get_releasever(UPDATES_JSON_RELEASE, repo_ids_in)
        assert releasever == '6Server'
        assert repo_ids == []

    def test_get_releasever_3(self):
        """Test with 'basearch' only request."""
        repo_ids_in = [1, 2, 3, 4, 5]
        releasever, repo_ids = self.updates_api._get_releasever(UPDATES_JSON_ARCH, repo_ids_in)
        assert releasever is None
        assert repo_ids == repo_ids_in

    def test_get_basearch_1(self):
        """Test with complete request."""
        repo_ids_in = [1]
        basearch, repo_ids = self.updates_api._get_basearch(UPDATES_JSON, repo_ids_in)
        assert basearch == 'x86_64'
        assert repo_ids == {1}

    def test_get_basearch_2(self):
        """Test with 'repository_list' only request."""
        repo_ids_in = []
        basearch, repo_ids = self.updates_api._get_basearch(UPDATES_JSON_REPO, repo_ids_in)
        assert basearch is None
        assert repo_ids == set()

    def test_get_basearch_3(self):
        """Test with 'releasever' only request."""
        repo_ids_in = []
        basearch, repo_ids = self.updates_api._get_basearch(UPDATES_JSON_RELEASE, repo_ids_in)
        assert basearch is None
        assert repo_ids == set()

    def test_get_basearch_4(self):
        """Test with 'basearch' only request."""
        repo_ids_in = [1, 2, 3, 4, 5]
        basearch, repo_ids = self.updates_api._get_basearch(UPDATES_JSON_ARCH, repo_ids_in)
        assert basearch == 'i386'
        assert repo_ids == set()
Esempio n. 10
0
class TestModularity(TestBase):
    """Test /updates modularity"""

    updates_api = None

    @staticmethod
    def gen_pkg_json(nevra, modules=None):
        """Prepares a request to VMaaS"""
        retval = {'package_list': [nevra]}
        if modules is not None:
            retval['modules_list'] = modules
        return retval

    @pytest.fixture(autouse=True)
    def setup_api(self, load_cache):
        """Setup UpdatesAPI object."""
        self.updates_api = UpdatesAPI(self.cache)

    @pytest.mark.parametrize('test_data', OLD_OLD, ids=[x[0] for x in OLD_OLD])
    def test_old_pkg_old_module(self, test_data):
        """
        Test with postgresql-9.6.10-1.el8+1547+210b7007.x86_64
        Test without modularity info provided, should find 2 updates:
          postgresql-9.6.10-1.module+el8+2470+d1bafa0e.x86_64.rpm
          postgresql-10.6-1.module+el8+2469+5ecd5aae.x86_64.rpm
        Test with modularity info provided, should find one update:
          postgresql-9.6.10-1.module+el8+2470+d1bafa0e.x86_64.rpm
        """
        updates = self.updates_api.process_list(2, self.gen_pkg_json(PKG_NEVRAS[0], test_data[1]))
        assert updates
        available_updates = updates['update_list'][PKG_NEVRAS[0]]['available_updates']
        assert len(available_updates) == len(test_data[2])
        assert test_data[2] == {rec['package'] for rec in available_updates}

    @pytest.mark.parametrize('test_data', NEW_OLD, ids=[x[0] for x in NEW_OLD])
    def test_new_pkg_old_module(self, test_data):
        """Test with postgresql-9.6.10-1.module+el8+2470+d1bafa0e.x86_64
        Test without modularity info enabled, should find one update
          postgresql-10.6-1.module+el8+2469+5ecd5aae.x86_64.rpm
        With correct modularity stream enabled there should be no upates
        Test with incorrect modularity information, should find one (incorrect) update:
          postgresql-10.6-1.module+el8+2469+5ecd5aae.x86_64
          DNF on the client should never let this happen
        """
        updates = self.updates_api.process_list(2, self.gen_pkg_json(PKG_NEVRAS[1], test_data[1]))
        assert updates
        available_updates = updates['update_list'][PKG_NEVRAS[1]]['available_updates']
        if test_data[0] == 'correct_stream_enabled':  # with correct stream enabled there should be no updates
            assert not available_updates
            return
        assert len(available_updates) == len(test_data[2])
        assert test_data[2] == {rec['package'] for rec in available_updates}

    @pytest.mark.parametrize('test_data', NEW_MODULE, ids=[x[0] for x in NEW_MODULE])
    def test_old_pkg_new_module(self, test_data):
        """
        Test with postgresql-10.5-1.el8+1546+27ad5f8e.x86_64
        Both tests with, or without modularity should find one update
          postgresql-10.6-1.module+el8+2469+5ecd5aae.x86_64
        """
        updates = self.updates_api.process_list(2, self.gen_pkg_json(PKG_NEVRAS[2], test_data[1]))
        assert updates
        available_updates = updates['update_list'][PKG_NEVRAS[2]]['available_updates']
        assert len(available_updates) == len(test_data[2])
        assert test_data[2] == {rec['package'] for rec in available_updates}

    @pytest.mark.parametrize('test_data', NEW_MODULE, ids=[x[0] for x in NEW_MODULE])
    def test_new_pkg_new_module(self, test_data):
        """
        Test with postgresql-10.6-1.module+el8+2469+5ecd5aae.x86_64 which is the latest package and has no updates
        There should be zero updates with or without modularity
        """
        updates = self.updates_api.process_list(2, self.gen_pkg_json(PKG_NEVRAS[3], test_data[1]))
        assert updates
        assert not updates['update_list'][PKG_NEVRAS[3]]['available_updates']

    @pytest.mark.parametrize('test_data', NO_MODULES, ids=[x[0] for x in NO_MODULES])
    def test_no_enabled_modules(self, test_data):
        """
        Tests with modularity functionaility enabled witout needed module (postgresql 9.6) enabled
        Scenarios: no modules enabled at all, only rhn-tools module enabled, module not present in the database enabled
        All of these should result in no updates found
        """
        updates = self.updates_api.process_list(2, self.gen_pkg_json(PKG_NEVRAS[0], test_data[1]))
        assert updates
        assert not updates['update_list'][PKG_NEVRAS[0]]['available_updates']