Merge "Support getting project groups by name"
This commit is contained in:
commit
343d51ebe0
@ -15,9 +15,11 @@
|
||||
|
||||
from oslo_config import cfg
|
||||
from pecan import abort
|
||||
from pecan.decorators import expose
|
||||
from pecan import response
|
||||
from pecan import rest
|
||||
from pecan.secure import secure
|
||||
from six.moves.urllib.parse import unquote
|
||||
|
||||
import wsme.types as wtypes
|
||||
import wsmeext.pecan as wsme_pecan
|
||||
@ -35,6 +37,12 @@ from storyboard.db.api import projects
|
||||
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):
|
||||
"""This controller should be used to list, add or remove projects from a
|
||||
Project Group.
|
||||
@ -42,7 +50,7 @@ class ProjectsSubcontroller(rest.RestController):
|
||||
|
||||
@decorators.db_exceptions
|
||||
@secure(checks.guest)
|
||||
@wsme_pecan.wsexpose([wmodels.Project], int)
|
||||
@wsme_pecan.wsexpose([wmodels.Project], wtypes.text)
|
||||
def get(self, project_group_id):
|
||||
"""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
|
||||
|
||||
: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")
|
||||
% project_group_id)
|
||||
|
||||
return [wmodels.Project.from_db_model(project)
|
||||
for project in project_group.projects]
|
||||
for project in group.projects]
|
||||
|
||||
@decorators.db_exceptions
|
||||
@secure(checks.superuser)
|
||||
@ -118,7 +129,7 @@ class ProjectGroupsController(rest.RestController):
|
||||
@decorators.db_exceptions
|
||||
@secure(checks.guest)
|
||||
@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.
|
||||
|
||||
Example::
|
||||
@ -135,6 +146,23 @@ class ProjectGroupsController(rest.RestController):
|
||||
|
||||
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
|
||||
@secure(checks.guest)
|
||||
@wsme_pecan.wsexpose([wmodels.ProjectGroup], int, int, int, wtypes.text,
|
||||
@ -258,3 +286,21 @@ class ProjectGroupsController(rest.RestController):
|
||||
abort(400, not_empty_exc.message)
|
||||
|
||||
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)
|
||||
|
@ -23,13 +23,17 @@ from storyboard.db.api import projects
|
||||
from storyboard.db import models
|
||||
|
||||
|
||||
def _entity_get(id, session=None):
|
||||
def _entity_get_query(session=None):
|
||||
if not session:
|
||||
session = api_base.get_session()
|
||||
query = session.query(models.ProjectGroup)\
|
||||
.options(subqueryload(models.ProjectGroup.projects))\
|
||||
.filter_by(id=id)
|
||||
.options(subqueryload(models.ProjectGroup.projects))
|
||||
|
||||
return query
|
||||
|
||||
|
||||
def _entity_get(id, session=None):
|
||||
query = _entity_get_query(session).filter_by(id=id)
|
||||
return query.first()
|
||||
|
||||
|
||||
@ -37,6 +41,11 @@ def project_group_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,
|
||||
subscriber_id=None, sort_field=None, sort_dir=None,
|
||||
**kwargs):
|
||||
|
@ -40,6 +40,12 @@ class TestProjectGroups(base.FunctionalTest):
|
||||
self.assertEqual("projectgroup1", response['name'])
|
||||
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):
|
||||
response = self.get_json(path=self.resource + "/999",
|
||||
expect_errors=True)
|
||||
|
Loading…
Reference in New Issue
Block a user