Merge "Support getting backups of a specific project"

This commit is contained in:
Zuul 2020-09-13 22:32:16 +00:00 committed by Gerrit Code Review
commit 2cd5bb6f83
5 changed files with 78 additions and 4 deletions

View File

@ -20,6 +20,8 @@ using query string parameters. The following filters are supported:
- ``all_projects=True/False`` - Return the list of backups for all the - ``all_projects=True/False`` - Return the list of backups for all the
projects, this is an admin only param by default. projects, this is an admin only param by default.
- ``datastore={datastore}`` - Return a list of backups of the same datastore. - ``datastore={datastore}`` - Return a list of backups of the same datastore.
- ``project_id={project_id}`` - Get backups of a specific project. Admin
required.
Normal response codes: 200 Normal response codes: 200

View File

@ -0,0 +1,3 @@
---
features:
- The admin user is able to get backups of a specific project.

View File

@ -186,13 +186,16 @@ class Backup(object):
return query.all(), marker return query.all(), marker
@classmethod @classmethod
def list(cls, context, datastore=None, instance_id=None, def list(cls, context, datastore=None, instance_id=None, project_id=None,
all_projects=False): all_projects=False):
query = DBBackup.query() query = DBBackup.query()
filters = [DBBackup.deleted == 0] filters = [DBBackup.deleted == 0]
if not all_projects: if project_id:
filters.append(DBBackup.tenant_id == project_id)
elif not all_projects:
filters.append(DBBackup.tenant_id == context.project_id) filters.append(DBBackup.tenant_id == context.project_id)
if instance_id: if instance_id:
filters.append(DBBackup.instance_id == instance_id) filters.append(DBBackup.instance_id == instance_id)

View File

@ -44,10 +44,11 @@ class BackupController(wsgi.Controller):
LOG.debug("Listing backups for tenant %s", tenant_id) LOG.debug("Listing backups for tenant %s", tenant_id)
datastore = req.GET.get('datastore') datastore = req.GET.get('datastore')
instance_id = req.GET.get('instance_id') instance_id = req.GET.get('instance_id')
project_id = req.GET.get('project_id')
all_projects = strutils.bool_from_string(req.GET.get('all_projects')) all_projects = strutils.bool_from_string(req.GET.get('all_projects'))
context = req.environ[wsgi.CONTEXT_KEY] context = req.environ[wsgi.CONTEXT_KEY]
if all_projects: if project_id or all_projects:
policy.authorize_on_tenant(context, 'backup:index:all_projects') policy.authorize_on_tenant(context, 'backup:index:all_projects')
else: else:
policy.authorize_on_tenant(context, 'backup:index') policy.authorize_on_tenant(context, 'backup:index')
@ -56,6 +57,7 @@ class BackupController(wsgi.Controller):
context, context,
datastore=datastore, datastore=datastore,
instance_id=instance_id, instance_id=instance_id,
project_id=project_id,
all_projects=all_projects all_projects=all_projects
) )
view = views.BackupViews(backups) view = views.BackupViews(backups)

View File

@ -13,20 +13,36 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
# #
from unittest import mock
import uuid
import jsonschema import jsonschema
from testtools.matchers import Equals from testtools.matchers import Equals
from trove.backup import models
from trove.backup import state
from trove.backup.service import BackupController from trove.backup.service import BackupController
from trove.common import apischema from trove.common import apischema
from trove.common import context
from trove.common import wsgi
from trove.tests.unittests import trove_testtools from trove.tests.unittests import trove_testtools
from trove.tests.unittests.util import util
class TestBackupController(trove_testtools.TestCase): class TestBackupController(trove_testtools.TestCase):
def setUp(self): def setUp(self):
super(TestBackupController, self).setUp() super(TestBackupController, self).setUp()
self.uuid = "d6338c9c-3cc8-4313-b98f-13cc0684cf15" self.uuid = "d6338c9c-3cc8-4313-b98f-13cc0684cf15"
self.invalid_uuid = "ead-edsa-e23-sdf-23" self.invalid_uuid = "ead-edsa-e23-sdf-23"
self.controller = BackupController() self.controller = BackupController()
self.context = context.TroveContext(project_id=str(uuid.uuid4()))
util.init_db()
def tearDown(self):
super(TestBackupController, self).tearDown()
backups = models.DBBackup.find_all(tenant_id=self.context.project_id)
for backup in backups:
backup.delete()
def test_validate_create_complete(self): def test_validate_create_complete(self):
body = {"backup": {"instance": self.uuid, body = {"backup": {"instance": self.uuid,
@ -87,3 +103,51 @@ class TestBackupController(trove_testtools.TestCase):
self.assertThat(errors[0].message, self.assertThat(errors[0].message,
Equals("'%s' does not match '%s'" % Equals("'%s' does not match '%s'" %
(self.invalid_uuid, apischema.uuid['pattern']))) (self.invalid_uuid, apischema.uuid['pattern'])))
def test_list_by_project(self):
req = mock.MagicMock(GET={'project_id': self.context.project_id},
environ={wsgi.CONTEXT_KEY: self.context},
url='http://localhost')
instance_id = str(uuid.uuid4())
backup_name = str(uuid.uuid4())
location = 'https://object-storage.com/tenant/database_backups/backup'
models.DBBackup.create(tenant_id=self.context.project_id,
name=backup_name,
state=state.BackupState.NEW,
instance_id=instance_id,
deleted=False,
size=2.0,
location=location)
res = self.controller.index(req, 'fake_tenant_id')
self.assertEqual(200, res.status)
backups = res.data(None)['backups']
self.assertGreaterEqual(len(backups), 1)
our_backup = None
for backup in backups:
if backup['name'] == backup_name:
our_backup = backup
break
self.assertIsNotNone(our_backup)
expected = {
'name': backup_name,
'locationRef': location,
'instance_id': instance_id,
'size': 2.0,
'status': 'NEW',
}
self.assertTrue(
set(expected.items()).issubset(set(our_backup.items()))
)
# Get backups of unknown project
req = mock.MagicMock(GET={'project_id': str(uuid.uuid4())},
environ={wsgi.CONTEXT_KEY: self.context},
url='http://localhost')
res = self.controller.index(req, 'fake_tenant_id')
self.assertEqual(200, res.status)
backups = res.data(None)['backups']
self.assertEqual(0, len(backups))