Team and project groups delete methods

Added delete methods for teams and project groups.
Now delete methods check project groups and teams for empty status.
DB api now raises exceptions if operation is no allowed.

Change-Id: Ic34d42d07c72683aa9624f45dcdf4c033af74e28
This commit is contained in:
Aleksey Ripinen
2014-12-23 17:37:09 +03:00
parent d6e5b0d91c
commit d8be665b37
7 changed files with 142 additions and 4 deletions

View File

@@ -14,6 +14,7 @@
# limitations under the License.
from oslo.config import cfg
from pecan import abort
from pecan import response
from pecan import rest
from pecan.secure import secure
@@ -22,6 +23,7 @@ import wsmeext.pecan as wsme_pecan
import storyboard.api.auth.authorization_checks as checks
from storyboard.api.v1 import wmodels
import storyboard.common.exception as exc
from storyboard.db.api import project_groups
from storyboard.db.api import projects
from storyboard.openstack.common.gettextutils import _ # noqa
@@ -165,13 +167,18 @@ class ProjectGroupsController(rest.RestController):
return wmodels.ProjectGroup.from_db_model(updated_group)
@secure(checks.superuser)
@wsme_pecan.wsexpose(wmodels.ProjectGroup, int)
@wsme_pecan.wsexpose(None, int)
def delete(self, project_group_id):
"""Delete this project group.
:param project_group_id: An ID of the project group.
"""
project_groups.project_group_delete(project_group_id)
try:
project_groups.project_group_delete(project_group_id)
except exc.NotFound as not_found_exc:
abort(404, not_found_exc.message)
except exc.NotEmpty as not_empty_exc:
abort(400, not_empty_exc.message)
response.status_code = 204

View File

@@ -14,6 +14,7 @@
# limitations under the License.
from oslo.config import cfg
from pecan import abort
from pecan.decorators import expose
from pecan import response
from pecan import rest
@@ -23,6 +24,7 @@ import wsmeext.pecan as wsme_pecan
from storyboard.api.auth import authorization_checks as checks
from storyboard.api.v1 import wmodels
from storyboard.common import exception as exc
from storyboard.db.api import teams as teams_api
from storyboard.db.api import users as users_api
from storyboard.openstack.common.gettextutils import _ # noqa
@@ -197,3 +199,19 @@ class TeamsController(rest.RestController):
# Use default routing for all other requests
return super(TeamsController, self)._route(args, request)
@secure(checks.superuser)
@wsme_pecan.wsexpose(None, int)
def delete(self, team_id):
"""Delete this team.
:param team_id: An ID of the team.
"""
try:
teams_api.team_delete(team_id)
except exc.NotFound as not_found_exc:
abort(404, not_found_exc.message)
except exc.NotEmpty as not_empty_exc:
abort(400, not_empty_exc.message)
response.status_code = 204

View File

@@ -46,3 +46,11 @@ class DuplicateEntry(StoryboardException):
def __init__(self, message=None):
if message:
self.message = message
class NotEmpty(StoryboardException):
message = _("Database object must be empty")
def __init__(self, message=None):
if message:
self.message = message

View File

@@ -120,5 +120,10 @@ def project_group_delete_project(project_group_id, project_id):
def project_group_delete(project_group_id):
project_group = project_group_get(project_group_id)
if project_group:
api_base.entity_hard_delete(models.ProjectGroup, project_group_id)
if not project_group:
raise exc.NotFound(_('Project group not found.'))
if len(project_group.projects) > 0:
raise exc.NotEmpty(_('Project group must be empty.'))
api_base.entity_hard_delete(models.ProjectGroup, project_group_id)

View File

@@ -105,3 +105,15 @@ def team_delete_user(team_id, user_id):
session.add(team)
return team
def team_delete(team_id):
team = team_get(team_id)
if not team:
raise exc.NotFound(_('Team not found.'))
if len(team.users) > 0:
raise exc.NotEmpty(_('Team must be empty.'))
api_base.entity_hard_delete(models.Team, team_id)

View File

@@ -99,6 +99,36 @@ class TestProjectGroups(base.FunctionalTest):
# check for a too short name
self.assertRaises(AppError, self.put_json, url, delta)
def test_delete_invalid(self):
# try to delete project group with projects
# she can't be deleted, because
# only empty project groups can be deleted
response = self.delete(self.resource + '/2', expect_errors=True)
self.assertEqual(400, response.status_code)
def test_delete(self):
# create new empty project group with name 'testProjectGroup'
response = self.post_json(self.resource,
{'name': 'testProjectGroup',
'title': 'testProjectGroupTitle'})
body = json.loads(response.body)
self.assertEqual('testProjectGroup', body['name'])
self.assertEqual('testProjectGroupTitle', body['title'])
# delete project group with name 'testProjectGroup'
# project group with name 'testProjectGroup' can be deleted, because
# she is empty
# only empty project groups can be deleted
resource = (self.resource + '/%d') % body['id']
response = self.delete(resource)
self.assertEqual(204, response.status_code)
# check that project group with name 'testProjectGroup'
# doesn't exist now
response = self.get_json(resource, expect_errors=True)
self.assertEqual(404, response.status_code)
class TestProjectGroupSearch(base.FunctionalTest):
def setUp(self):

View File

@@ -0,0 +1,58 @@
# Copyright (c) 2014 Mirantis Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import json
from storyboard.tests import base
class TestTeams(base.FunctionalTest):
def setUp(self):
super(TestTeams, self).setUp()
self.resource = '/teams'
self.default_headers['Authorization'] = 'Bearer valid_superuser_token'
def test_delete_invalid(self):
# create new empty team with name 'testTeam'
response = self.post_json(self.resource, {'name': 'testTeam'})
body = json.loads(response.body)
self.assertEqual('testTeam', body['name'])
# add user with id = 2 to team with name 'testTeam'
resource = (self.resource + '/%d') % body['id']
response = self.put_json(resource + '/users', {'user_id': '2'})
self.assertEqual(200, response.status_code)
# try to delete team with name 'testTeam'
# team with name 'testTeam' can't be deleted, because she isn't empty
# only empty teams can be deleted
response = self.delete(resource, expect_errors=True)
self.assertEqual(400, response.status_code)
def test_delete(self):
# create new team with name 'testTeam'
response = self.post_json(self.resource, {'name': 'testTeam'})
body = json.loads(response.body)
self.assertEqual('testTeam', body['name'])
resource = (self.resource + '/%d') % body['id']
# delete team with name 'testTeam'
# team with name 'testTeam' can be deleted, because she is empty
# only empty teams can be deleted
response = self.delete(resource)
self.assertEqual(204, response.status_code)
# check that team with name 'testTeam' doesn't exist now
response = self.get_json(resource, expect_errors=True)
self.assertEqual(404, response.status_code)