def test_package_search_search(self): pkg1 = api.package_upload( self._stub_package( fully_qualified_name=str(uuid.uuid4())), self.tenant_id) pkg2 = api.package_upload( self._stub_package( tags=[], fully_qualified_name=str(uuid.uuid4())), self.tenant_id) res = api.package_search( {'search': 'tag1'}, self.context) self.assertEqual(1, len(res)) res = api.package_search( {'search': pkg1.fully_qualified_name}, self.context) self.assertEqual(1, len(res)) res = api.package_search( {'search': pkg2.fully_qualified_name}, self.context) self.assertEqual(1, len(res)) res = api.package_search( {'search': 'not_a_valid_uuid'}, self.context) self.assertEqual(0, len(res)) res = api.package_search( {'search': 'some text'}, self.context) self.assertEqual(2, len(res))
def test_pagination_loops_through_names(self): """Tests that packages with same display name are not skipped Creates 10 packages with the same display name and iterates through them, checking that package are not skipped. """ for dummy in range(10): api.package_upload( self._stub_package(name='test', fully_qualified_name=str(uuid.uuid4())), self.tenant_id) res = api.package_search({}, self.context, limit=4) self.assertEqual(4, len(res)) marker = res[-1].id res = api.package_search({'marker': marker}, self.context, limit=4) self.assertEqual(4, len(res)) marker = res[-1].id res = api.package_search({'marker': marker}, self.context, limit=4) self.assertEqual(2, len(res)) marker = res[-1].id res = api.package_search({'marker': marker}, self.context, limit=4) self.assertEqual(0, len(res))
def test_pagination(self): """Creates 10 packages with unique names and iterates through them, checking that package order is correct. """ pkgs = [] for dummy in range(10): package = api.package_upload(self._stub_package( name=str(uuid.uuid4()), fully_qualified_name=str(uuid.uuid4())), self.tenant_id) pkgs.append(package) # sort pkg ids by pkg name pkg_ids = [pkg.id for pkg in sorted(pkgs, key=lambda _pkg: _pkg.name)] res = api.package_search({}, self.context, limit=4) self.assertEqual(4, len(res)) self.assertEqual(pkg_ids[0:4], [r.id for r in res]) marker = res[-1].id res = api.package_search({'marker': marker}, self.context, limit=4) self.assertEqual(4, len(res)) self.assertEqual(pkg_ids[4:8], [r.id for r in res]) marker = res[-1].id res = api.package_search({'marker': marker}, self.context, limit=4) self.assertEqual(2, len(res)) self.assertEqual(pkg_ids[8:10], [r.id for r in res]) marker = res[-1].id res = api.package_search({'marker': marker}, self.context, limit=4) self.assertEqual(0, len(res))
def test_package_search_no_filters_catalog(self): res = api.package_search({}, self.context, catalog=True) self.assertEqual(0, len(res)) api.package_upload( self._stub_package( is_public=True, fully_qualified_name=str(uuid.uuid4())), self.tenant_id) api.package_upload( self._stub_package( is_public=False, fully_qualified_name=str(uuid.uuid4())), self.tenant_id) api.package_upload( self._stub_package( is_public=True, fully_qualified_name=str(uuid.uuid4())), self.tenant_id_2) api.package_upload( self._stub_package( is_public=False, fully_qualified_name=str(uuid.uuid4())), self.tenant_id_2) # catalog=True should show public + mine res = api.package_search({}, self.context, catalog=True) self.assertEqual(3, len(res)) res = api.package_search({}, self.context_admin, catalog=True) self.assertEqual(3, len(res))
def test_package_search_no_filters(self): res = api.package_search({}, self.context) self.assertEqual(0, len(res)) api.package_upload( self._stub_package( is_public=True, fully_qualified_name=str(uuid.uuid4())), self.tenant_id) api.package_upload( self._stub_package( is_public=False, fully_qualified_name=str(uuid.uuid4())), self.tenant_id) api.package_upload( self._stub_package( is_public=True, fully_qualified_name=str(uuid.uuid4())), self.tenant_id_2) api.package_upload( self._stub_package( is_public=False, fully_qualified_name=str(uuid.uuid4())), self.tenant_id_2) # I can only edit mine pkgs res = api.package_search({}, self.context) self.assertEqual(2, len(res)) for pkg in res: self.assertEqual(self.tenant_id, pkg.owner_id) # Admin can see everything res = api.package_search({}, self.context_admin) self.assertEqual(4, len(res))
def test_pagination_backwards(self): """Creates 10 packages with unique names and iterates backwards, checking that package order is correct. """ pkgs = [] for dummy in range(10): package = api.package_upload( self._stub_package(name=str(uuid.uuid4()), fully_qualified_name=str(uuid.uuid4())), self.tenant_id ) pkgs.append(package) # sort pkg ids by pkg name pkg_ids = [pkg.id for pkg in sorted(pkgs, key=lambda _pkg: _pkg.name)] res = api.package_search({}, self.context, limit=10) self.assertEqual(10, len(res)) self.assertEqual(pkg_ids, [r.id for r in res]) marker = res[-1].id res = api.package_search({"marker": marker, "sort_dir": "desc"}, self.context, limit=5) self.assertEqual(5, len(res)) self.assertEqual(list(reversed(pkg_ids[4:9])), [r.id for r in res]) marker = res[-1].id res = api.package_search({"marker": marker, "sort_dir": "desc"}, self.context, limit=5) self.assertEqual(4, len(res)) self.assertEqual(list(reversed(pkg_ids[0:4])), [r.id for r in res]) marker = res[-1].id res = api.package_search({"marker": marker, "sort_dir": "desc"}, self.context, limit=5) self.assertEqual(0, len(res))
def test_package_search_owned(self): api.package_upload(self._stub_package(is_public=True, fully_qualified_name=str(uuid.uuid4())), self.tenant_id) api.package_upload(self._stub_package(is_public=True, fully_qualified_name=str(uuid.uuid4())), self.tenant_id_2) res = api.package_search({"owned": "true"}, self.context_admin) self.assertEqual(1, len(res)) res = api.package_search({"owned": "false"}, self.context_admin) self.assertEqual(2, len(res))
def test_package_search_type(self): api.package_upload( self._stub_package(type="Application", fully_qualified_name=str(uuid.uuid4())), self.tenant_id ) api.package_upload(self._stub_package(type="Library", fully_qualified_name=str(uuid.uuid4())), self.tenant_id) res = api.package_search({"type": "Library"}, self.context) self.assertEqual(1, len(res)) res = api.package_search({"type": "Application"}, self.context) self.assertEqual(1, len(res))
def test_package_search_tags(self): api.package_upload(self._stub_package(fully_qualified_name=str(uuid.uuid4())), self.tenant_id) api.package_upload(self._stub_package(tags=[], fully_qualified_name=str(uuid.uuid4())), self.tenant_id) res = api.package_search({"tag": ["tag1"]}, self.context) self.assertEqual(1, len(res)) res = api.package_search({"tag": ["tag2"]}, self.context) self.assertEqual(1, len(res)) res = api.package_search({"tag": ["tag3"]}, self.context) self.assertEqual(0, len(res))
def test_package_search_disabled(self): api.package_upload( self._stub_package(is_public=True, enabled=True, fully_qualified_name=str(uuid.uuid4())), self.tenant_id ) api.package_upload( self._stub_package(is_public=True, enabled=False, fully_qualified_name=str(uuid.uuid4())), self.tenant_id ) res = api.package_search({"include_disabled": "false"}, self.context) self.assertEqual(1, len(res)) res = api.package_search({"include_disabled": "true"}, self.context) self.assertEqual(2, len(res))
def test_package_search_owned(self): api.package_upload( self._stub_package( is_public=True, fully_qualified_name=str(uuid.uuid4())), self.tenant_id) api.package_upload( self._stub_package( is_public=True, fully_qualified_name=str(uuid.uuid4())), self.tenant_id_2) res = api.package_search({'owned': 'true'}, self.context_admin) self.assertEqual(len(res), 1) res = api.package_search({'owned': 'false'}, self.context_admin) self.assertEqual(len(res), 2)
def test_package_search_search(self): pkg1 = api.package_upload(self._stub_package(fully_qualified_name=str(uuid.uuid4())), self.tenant_id) pkg2 = api.package_upload(self._stub_package(tags=[], fully_qualified_name=str(uuid.uuid4())), self.tenant_id) res = api.package_search({"search": "tag1"}, self.context) self.assertEqual(len(res), 1) res = api.package_search({"search": pkg1.fully_qualified_name}, self.context) self.assertEqual(len(res), 1) res = api.package_search({"search": pkg2.fully_qualified_name}, self.context) self.assertEqual(len(res), 1) res = api.package_search({"search": "not_a_valid_uuid"}, self.context) self.assertEqual(len(res), 0) res = api.package_search({"search": "some text"}, self.context) self.assertEqual(len(res), 2)
def test_package_search_tags(self): api.package_upload( self._stub_package(fully_qualified_name=str(uuid.uuid4())), self.tenant_id) api.package_upload( self._stub_package(tags=[], fully_qualified_name=str(uuid.uuid4())), self.tenant_id) res = api.package_search({'tag': ['tag1']}, self.context) self.assertEqual(1, len(res)) res = api.package_search({'tag': ['tag2']}, self.context) self.assertEqual(1, len(res)) res = api.package_search({'tag': ['tag3']}, self.context) self.assertEqual(0, len(res))
def search(self, req): policy.check("get_package", req.context) manage_public = True try: policy.check("manage_public_package", req.context) except exc.HTTPForbidden: manage_public = False filters = _get_filters(req.GET.items()) limit = self._validate_limit(filters.get('limit')) if limit is None: limit = CONF.murano.limit_param_default limit = min(CONF.murano.api_limit_max, limit) result = {} catalog = req.GET.pop('catalog', '').lower() == 'true' packages = db_api.package_search(filters, req.context, manage_public, limit, catalog=catalog) if len(packages) == limit: result['next_marker'] = packages[-1].id result['packages'] = [package.to_dict() for package in packages] return result
def test_package_search_type(self): api.package_upload( self._stub_package( type="Application", fully_qualified_name=str(uuid.uuid4())), self.tenant_id) api.package_upload( self._stub_package( type="Library", fully_qualified_name=str(uuid.uuid4())), self.tenant_id) res = api.package_search( {'type': 'Library'}, self.context) self.assertEqual(1, len(res)) res = api.package_search( {'type': 'Application'}, self.context) self.assertEqual(1, len(res))
def test_package_search_disabled(self): api.package_upload( self._stub_package(is_public=True, enabled=True, fully_qualified_name=str(uuid.uuid4())), self.tenant_id) api.package_upload( self._stub_package(is_public=True, enabled=False, fully_qualified_name=str(uuid.uuid4())), self.tenant_id) res = api.package_search({'include_disabled': 'false'}, self.context) self.assertEqual(1, len(res)) res = api.package_search({'include_disabled': 'true'}, self.context) self.assertEqual(2, len(res))
def test_order_by(self): pkgs = [] for dummy in range(10): package = api.package_upload( self._stub_package(name=str(uuid.uuid4()), fully_qualified_name=str(uuid.uuid4())), self.tenant_id) pkgs.append(package) pkg_created = [ pkg.id for pkg in sorted(pkgs, key=lambda _pkg: _pkg.created) ] pkg_name = [pkg.id for pkg in sorted(pkgs, key=lambda _pkg: _pkg.name)] pkg_fqn = [ pkg.id for pkg in sorted(pkgs, key=lambda _pkg: _pkg.fully_qualified_name) ] for order, pkg_ids in zip(['created', 'name', 'fqn'], [pkg_created, pkg_name, pkg_fqn]): res = api.package_search({'order_by': [order]}, self.context, limit=10) self.assertEqual(10, len(res)) self.assertEqual(pkg_ids, [r.id for r in res])
def test_order_by_compound(self): pkgs_a, pkgs_z = [], [] for _ in range(5): package = api.package_upload( self._stub_package(name='z', fully_qualified_name=str(uuid.uuid4())), self.tenant_id) pkgs_z.append(package) for _ in range(5): package = api.package_upload( self._stub_package(name='a', fully_qualified_name=str(uuid.uuid4())), self.tenant_id) pkgs_a.append(package) # sort pkg ids by pkg created pkg_a_id = [ pkg.id for pkg in sorted(pkgs_a, key=lambda _pkg: _pkg.created) ] pkg_z_id = [ pkg.id for pkg in sorted(pkgs_z, key=lambda _pkg: _pkg.created) ] res = api.package_search({'order_by': ['name', 'created']}, self.context, limit=10) self.assertEqual(10, len(res)) self.assertEqual(pkg_a_id + pkg_z_id, [r.id for r in res])
def search(self, req): def _validate_limit(value): if value is None: return try: value = int(value) except ValueError: msg = _("limit param must be an integer") LOG.error(msg) raise exc.HTTPBadRequest(explanation=msg) if value <= 0: msg = _("limit param must be positive") LOG.error(msg) raise exc.HTTPBadRequest(explanation=msg) return value policy.check("search_packages", req.context) filters = _get_filters(req.GET.items()) limit = _validate_limit(filters.get('limit')) if limit is None: limit = CONF.packages_opts.limit_param_default limit = min(CONF.packages_opts.api_limit_max, limit) result = {} packages = db_api.package_search(filters, req.context, limit) if len(packages) == limit: result['next_marker'] = packages[-1].id result['packages'] = [package.to_dict() for package in packages] return result
def test_pagination_backwards(self): """Creates 10 packages with unique names and iterates backwards, checking that package order is correct. """ pkgs = [] for dummy in range(10): package = api.package_upload( self._stub_package(name=str(uuid.uuid4()), fully_qualified_name=str(uuid.uuid4())), self.tenant_id) pkgs.append(package) # sort pkg ids by pkg name pkg_ids = [pkg.id for pkg in sorted(pkgs, key=lambda _pkg: _pkg.name)] res = api.package_search({}, self.context, limit=10) self.assertEqual(len(res), 10) self.assertEqual(pkg_ids, [r.id for r in res]) marker = res[-1].id res = api.package_search({ 'marker': marker, 'sort_dir': 'desc' }, self.context, limit=5) self.assertEqual(len(res), 5) self.assertEqual(list(reversed(pkg_ids[4:9])), [r.id for r in res]) marker = res[-1].id res = api.package_search({ 'marker': marker, 'sort_dir': 'desc' }, self.context, limit=5) self.assertEqual(len(res), 4) self.assertEqual(list(reversed(pkg_ids[0:4])), [r.id for r in res]) marker = res[-1].id res = api.package_search({ 'marker': marker, 'sort_dir': 'desc' }, self.context, limit=5) self.assertEqual(len(res), 0)
def test_package_search_disabled(self): api.package_upload( self._stub_package( is_public=True, enabled=True, fully_qualified_name=str(uuid.uuid4())), self.tenant_id) api.package_upload( self._stub_package( is_public=True, enabled=False, fully_qualified_name=str(uuid.uuid4())), self.tenant_id) res = api.package_search( {'include_disabled': 'false'}, self.context) self.assertEqual(len(res), 1) res = api.package_search( {'include_disabled': 'true'}, self.context) self.assertEqual(len(res), 2)
def test_package_search_tags(self): api.package_upload( self._stub_package( fully_qualified_name=str(uuid.uuid4())), self.tenant_id) api.package_upload( self._stub_package( tags=[], fully_qualified_name=str(uuid.uuid4())), self.tenant_id) res = api.package_search( {'tag': ['tag1']}, self.context) self.assertEqual(len(res), 1) res = api.package_search( {'tag': ['tag2']}, self.context) self.assertEqual(len(res), 1) res = api.package_search( {'tag': ['tag3']}, self.context) self.assertEqual(len(res), 0)
def list(self, req): packages = db_api.package_search({'type': 'application'}, req.context, catalog=True) services = [] for package in packages: services.append(self._package_to_service(package)) resp = {'services': services} return resp
def test_package_search_search(self): pkg1 = api.package_upload( self._stub_package(fully_qualified_name=str(uuid.uuid4())), self.tenant_id) pkg2 = api.package_upload( self._stub_package(tags=[], fully_qualified_name=str(uuid.uuid4())), self.tenant_id) res = api.package_search({'search': 'tag1'}, self.context) self.assertEqual(1, len(res)) res = api.package_search({'search': pkg1.fully_qualified_name}, self.context) self.assertEqual(1, len(res)) res = api.package_search({'search': pkg2.fully_qualified_name}, self.context) self.assertEqual(1, len(res)) res = api.package_search({'search': 'not_a_valid_uuid'}, self.context) self.assertEqual(0, len(res)) res = api.package_search({'search': 'some text'}, self.context) self.assertEqual(2, len(res))
def test_pagination_loops_through_names(self): """Creates 10 packages with the same name and iterates through them, checking that package are not skipped. """ # TODO(kzaitsev): fix https://bugs.launchpad.net/murano/+bug/1448782 for i in range(10): api.package_upload(self._stub_package(fully_qualified_name=str(uuid.uuid4())), self.tenant_id) res = api.package_search({}, self.context, limit=4) self.assertEqual(len(res), 4) marker = res[-1].id res = api.package_search({"marker": marker}, self.context, limit=4) self.assertEqual(len(res), 4) marker = res[-1].id res = api.package_search({"marker": marker}, self.context, limit=4) self.assertEqual(len(res), 2) marker = res[-1].id res = api.package_search({"marker": marker}, self.context, limit=4) self.assertEqual(len(res), 0)
def test_pagination_loops_through_names(self): """Creates 10 packages with the same name and iterates through them, checking that package are not skipped. """ # TODO(kzaitsev): fix https://bugs.launchpad.net/murano/+bug/1448782 for i in range(10): api.package_upload( self._stub_package(fully_qualified_name=str(uuid.uuid4())), self.tenant_id) res = api.package_search({}, self.context, limit=4) self.assertEqual(len(res), 4) marker = res[-1].id res = api.package_search({'marker': marker}, self.context, limit=4) self.assertEqual(len(res), 4) marker = res[-1].id res = api.package_search({'marker': marker}, self.context, limit=4) self.assertEqual(len(res), 2) marker = res[-1].id res = api.package_search({'marker': marker}, self.context, limit=4) self.assertEqual(len(res), 0)
def test_pagination_loops_through_names(self): """Creates 10 packages with the same display name and iterates through them, checking that package are not skipped. """ for dummy in range(10): api.package_upload( self._stub_package(name='test', fully_qualified_name=str(uuid.uuid4())), self.tenant_id) res = api.package_search({}, self.context, limit=4) self.assertEqual(len(res), 4) marker = res[-1].id res = api.package_search({'marker': marker}, self.context, limit=4) self.assertEqual(len(res), 4) marker = res[-1].id res = api.package_search({'marker': marker}, self.context, limit=4) self.assertEqual(len(res), 2) marker = res[-1].id res = api.package_search({'marker': marker}, self.context, limit=4) self.assertEqual(len(res), 0)
def list(self, req): user, _, keystone = self._check_auth(req) # Once we get here we were authorized by keystone token = keystone.auth_token ctx = context.RequestContext(user=user, tenant='', auth_token=token) packages = db_api.package_search({'type': 'application'}, ctx, catalog=True) services = [] for package in packages: services.append(self._package_to_service(package)) resp = {'services': services} return resp
def test_order_by(self): pkgs = [] for dummy in range(10): package = api.package_upload( self._stub_package(name=str(uuid.uuid4()), fully_qualified_name=str(uuid.uuid4())), self.tenant_id ) pkgs.append(package) pkg_created = [pkg.id for pkg in sorted(pkgs, key=lambda _pkg: _pkg.created)] pkg_name = [pkg.id for pkg in sorted(pkgs, key=lambda _pkg: _pkg.name)] pkg_fqn = [pkg.id for pkg in sorted(pkgs, key=lambda _pkg: _pkg.fully_qualified_name)] for order, pkg_ids in zip(["created", "name", "fqn"], [pkg_created, pkg_name, pkg_fqn]): res = api.package_search({"order_by": [order]}, self.context, limit=10) self.assertEqual(10, len(res)) self.assertEqual(pkg_ids, [r.id for r in res])
def _do_import_package(_dir, categories, update=False): LOG.debug( "Going to import Murano package from {source}".format(source=_dir)) pkg = load_utils.load_from_dir(_dir) LOG.debug("Checking for existing packages") existing = db_catalog_api.package_search({'fqn': pkg.full_name}, AdminContext()) if existing: existing_pkg = existing[0] if update: LOG.debug('Deleting existing package {exst_pkg_id}').format( exst_pkg_id=existing_pkg.id) db_catalog_api.package_delete(existing_pkg.id, AdminContext()) else: LOG.error( _LE("Package '{name}' exists ({pkg_id}). Use --update."). format(name=pkg.full_name, pkg_id=existing_pkg.id)) return package = { 'fully_qualified_name': pkg.full_name, 'type': pkg.package_type, 'author': pkg.author, 'supplier': pkg.supplier, 'name': pkg.display_name, 'description': pkg.description, # note: we explicitly mark all the imported packages as public, # until a parameter added to control visibility scope of a package 'is_public': True, 'tags': pkg.tags, 'logo': pkg.logo, 'supplier_logo': pkg.supplier_logo, 'ui_definition': pkg.ui, 'class_definitions': pkg.classes, 'archive': pkg.blob, 'categories': categories or [] } # note(ruhe): the second parameter is tenant_id # it is a required field in the DB, that's why we pass an empty string result = db_catalog_api.package_upload(package, '') LOG.info( _LI("Finished import of package {res_id}").format(res_id=result.id))
def _do_import_package(_dir, categories, update=False): LOG.debug("Going to import Murano package from {source}".format( source=_dir)) pkg = load_utils.load_from_dir(_dir) LOG.debug("Checking for existing packages") existing = db_catalog_api.package_search( {'fqn': pkg.full_name}, AdminContext()) if existing: existing_pkg = existing[0] if update: LOG.debug('Deleting existing package {exst_pkg_id}').format( exst_pkg_id=existing_pkg.id) db_catalog_api.package_delete(existing_pkg.id, AdminContext()) else: LOG.error(_LE("Package '{name}' exists ({pkg_id}). Use --update.") .format(name=pkg.full_name, pkg_id=existing_pkg.id)) return package = { 'fully_qualified_name': pkg.full_name, 'type': pkg.package_type, 'author': pkg.author, 'supplier': pkg.supplier, 'name': pkg.display_name, 'description': pkg.description, # note: we explicitly mark all the imported packages as public, # until a parameter added to control visibility scope of a package 'is_public': True, 'tags': pkg.tags, 'logo': pkg.logo, 'supplier_logo': pkg.supplier_logo, 'ui_definition': pkg.ui, 'class_definitions': pkg.classes, 'archive': pkg.blob, 'categories': categories or [] } # note(ruhe): the second parameter is tenant_id # it is a required field in the DB, that's why we pass an empty string result = db_catalog_api.package_upload(package, '') LOG.info(_LI("Finished import of package {res_id}").format( res_id=result.id))
def test_package_search_search_order(self): pkg1 = api.package_upload( self._stub_package(fully_qualified_name=str(uuid.uuid4()), name='mysql', description='awcloud'), self.tenant_id) pkg2 = api.package_upload( self._stub_package(fully_qualified_name=str(uuid.uuid4()), name='awcloud', description='mysql'), self.tenant_id) api.package_upload( self._stub_package(tags=[], fully_qualified_name=str(uuid.uuid4())), self.tenant_id) res = api.package_search({'search': 'mysql'}, self.context) self.assertEqual(2, len(res)) self.assertEqual(pkg1.name, res[0].name) self.assertEqual(pkg2.description, res[1].description)
def search(self, req): policy.check("get_package", req.context) filters = _get_filters(req.GET.items()) limit = self._validate_limit(filters.get('limit')) if limit is None: limit = CONF.packages_opts.limit_param_default limit = min(CONF.packages_opts.api_limit_max, limit) result = {} catalog = req.GET.pop('catalog', '').lower() == 'true' packages = db_api.package_search( filters, req.context, limit, catalog=catalog) if len(packages) == limit: result['next_marker'] = packages[-1].id result['packages'] = [package.to_dict() for package in packages] return result
def test_order_by_compound(self): pkgs_a, pkgs_z = [], [] for _ in range(5): package = api.package_upload( self._stub_package(name="z", fully_qualified_name=str(uuid.uuid4())), self.tenant_id ) pkgs_z.append(package) for _ in range(5): package = api.package_upload( self._stub_package(name="a", fully_qualified_name=str(uuid.uuid4())), self.tenant_id ) pkgs_a.append(package) # sort pkg ids by pkg created pkg_a_id = [pkg.id for pkg in sorted(pkgs_a, key=lambda _pkg: _pkg.created)] pkg_z_id = [pkg.id for pkg in sorted(pkgs_z, key=lambda _pkg: _pkg.created)] res = api.package_search({"order_by": ["name", "created"]}, self.context, limit=10) self.assertEqual(10, len(res)) self.assertEqual(pkg_a_id + pkg_z_id, [r.id for r in res])
def search(self, req): policy.check("get_package", req.context) manage_public = True try: policy.check("manage_public_package", req.context) except exc.HTTPForbidden: manage_public = False filters = _get_filters(req.GET.items()) limit = self._validate_limit(filters.get('limit')) if limit is None: limit = CONF.murano.limit_param_default limit = min(CONF.murano.api_limit_max, limit) result = {} catalog = req.GET.pop('catalog', '').lower() == 'true' packages = db_api.package_search( filters, req.context, manage_public, limit, catalog=catalog) if len(packages) == limit: result['next_marker'] = packages[-1].id result['packages'] = [package.to_dict() for package in packages] return result