Merge "Support getting project groups by name"

This commit is contained in:
Zuul 2018-09-09 16:57:22 +00:00 committed by Gerrit Code Review
commit 343d51ebe0
3 changed files with 70 additions and 9 deletions

View File

@ -15,9 +15,11 @@
from oslo_config import cfg from oslo_config import cfg
from pecan import abort from pecan import abort
from pecan.decorators import expose
from pecan import response from pecan import response
from pecan import rest from pecan import rest
from pecan.secure import secure from pecan.secure import secure
from six.moves.urllib.parse import unquote
import wsme.types as wtypes import wsme.types as wtypes
import wsmeext.pecan as wsme_pecan import wsmeext.pecan as wsme_pecan
@ -35,6 +37,12 @@ from storyboard.db.api import projects
CONF = cfg.CONF CONF = cfg.CONF
def _is_int(s):
# 20 is the number of digits in a 64-bit integer, which is realistically
# way more than the number of Project Groups likely to be created.
return len(s) < 20 and s.isdigit()
class ProjectsSubcontroller(rest.RestController): class ProjectsSubcontroller(rest.RestController):
"""This controller should be used to list, add or remove projects from a """This controller should be used to list, add or remove projects from a
Project Group. Project Group.
@ -42,7 +50,7 @@ class ProjectsSubcontroller(rest.RestController):
@decorators.db_exceptions @decorators.db_exceptions
@secure(checks.guest) @secure(checks.guest)
@wsme_pecan.wsexpose([wmodels.Project], int) @wsme_pecan.wsexpose([wmodels.Project], wtypes.text)
def get(self, project_group_id): def get(self, project_group_id):
"""Get projects inside a project group. """Get projects inside a project group.
@ -50,17 +58,20 @@ class ProjectsSubcontroller(rest.RestController):
curl https://my.example.org/api/v1/project_groups/55/projects curl https://my.example.org/api/v1/project_groups/55/projects
:param project_group_id: An ID of the project group. :param project_group_id: An ID or name of the project group.
""" """
project_group = project_groups.project_group_get(project_group_id) if _is_int(project_group_id):
group = project_groups.project_group_get(int(project_group_id))
else:
group = project_groups.project_group_get_by_name(project_group_id)
if not project_group: if not group:
raise exc.NotFound(_("Project Group %s not found") raise exc.NotFound(_("Project Group %s not found")
% project_group_id) % project_group_id)
return [wmodels.Project.from_db_model(project) return [wmodels.Project.from_db_model(project)
for project in project_group.projects] for project in group.projects]
@decorators.db_exceptions @decorators.db_exceptions
@secure(checks.superuser) @secure(checks.superuser)
@ -118,7 +129,7 @@ class ProjectGroupsController(rest.RestController):
@decorators.db_exceptions @decorators.db_exceptions
@secure(checks.guest) @secure(checks.guest)
@wsme_pecan.wsexpose(wmodels.ProjectGroup, int) @wsme_pecan.wsexpose(wmodels.ProjectGroup, int)
def get_one(self, project_group_id): def get_one_by_id(self, project_group_id):
"""Retrieve information about the given project group. """Retrieve information about the given project group.
Example:: Example::
@ -135,6 +146,23 @@ class ProjectGroupsController(rest.RestController):
return wmodels.ProjectGroup.from_db_model(group) return wmodels.ProjectGroup.from_db_model(group)
@decorators.db_exceptions
@secure(checks.guest)
@wsme_pecan.wsexpose(wmodels.ProjectGroup, wtypes.text)
def get_one_by_name(self, project_group_name):
"""Retrieve information about the given project group.
:param project_group_name: Project group name.
"""
group = project_groups.project_group_get_by_name(project_group_name)
if group:
return wmodels.ProjectGroup.from_db_model(group)
else:
raise exc.NotFound(_("Project Group %s not found") %
project_group_name)
@decorators.db_exceptions @decorators.db_exceptions
@secure(checks.guest) @secure(checks.guest)
@wsme_pecan.wsexpose([wmodels.ProjectGroup], int, int, int, wtypes.text, @wsme_pecan.wsexpose([wmodels.ProjectGroup], int, int, int, wtypes.text,
@ -258,3 +286,21 @@ class ProjectGroupsController(rest.RestController):
abort(400, not_empty_exc.message) abort(400, not_empty_exc.message)
projects = ProjectsSubcontroller() projects = ProjectsSubcontroller()
@expose()
def _route(self, args, request):
if request.method == 'GET' and len(args) > 0:
something = unquote(args[0])
if _is_int(something):
if len(args) == 1:
return self.get_one_by_id, args
elif args[-1] != 'projects':
return self.get_one_by_name, ["/".join(args)]
else:
# If a getting a groups' projects by name, handle the case
# where the project group has slashes in the name by joining
# all but the last arg with slashes.
args = ["/".join(args[:-1]), args[-1]]
return super(ProjectGroupsController, self)._route(args, request)

View File

@ -23,13 +23,17 @@ from storyboard.db.api import projects
from storyboard.db import models from storyboard.db import models
def _entity_get(id, session=None): def _entity_get_query(session=None):
if not session: if not session:
session = api_base.get_session() session = api_base.get_session()
query = session.query(models.ProjectGroup)\ query = session.query(models.ProjectGroup)\
.options(subqueryload(models.ProjectGroup.projects))\ .options(subqueryload(models.ProjectGroup.projects))
.filter_by(id=id)
return query
def _entity_get(id, session=None):
query = _entity_get_query(session).filter_by(id=id)
return query.first() return query.first()
@ -37,6 +41,11 @@ def project_group_get(project_group_id):
return _entity_get(project_group_id) return _entity_get(project_group_id)
def project_group_get_by_name(name):
query = _entity_get_query().filter_by(name=name)
return query.first()
def project_group_get_all(marker=None, limit=None, offset=None, def project_group_get_all(marker=None, limit=None, offset=None,
subscriber_id=None, sort_field=None, sort_dir=None, subscriber_id=None, sort_field=None, sort_dir=None,
**kwargs): **kwargs):

View File

@ -40,6 +40,12 @@ class TestProjectGroups(base.FunctionalTest):
self.assertEqual("projectgroup1", response['name']) self.assertEqual("projectgroup1", response['name'])
self.assertEqual("C Sort - foo", response['title']) self.assertEqual("C Sort - foo", response['title'])
def test_get_by_name(self):
response = self.get_json(path=self.resource + '/1')
self.assertEqual(1, response['id'])
self.assertEqual("projectgroup1", response['name'])
self.assertEqual("C Sort - foo", response['title'])
def test_get_empty(self): def test_get_empty(self):
response = self.get_json(path=self.resource + "/999", response = self.get_json(path=self.resource + "/999",
expect_errors=True) expect_errors=True)