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
projects, this is an admin only param by default.
- ``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

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
@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):
query = DBBackup.query()
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)
if 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)
datastore = req.GET.get('datastore')
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'))
context = req.environ[wsgi.CONTEXT_KEY]
if all_projects:
if project_id or all_projects:
policy.authorize_on_tenant(context, 'backup:index:all_projects')
else:
policy.authorize_on_tenant(context, 'backup:index')
@ -56,6 +57,7 @@ class BackupController(wsgi.Controller):
context,
datastore=datastore,
instance_id=instance_id,
project_id=project_id,
all_projects=all_projects
)
view = views.BackupViews(backups)

View File

@ -13,20 +13,36 @@
# License for the specific language governing permissions and limitations
# under the License.
#
from unittest import mock
import uuid
import jsonschema
from testtools.matchers import Equals
from trove.backup import models
from trove.backup import state
from trove.backup.service import BackupController
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.util import util
class TestBackupController(trove_testtools.TestCase):
def setUp(self):
super(TestBackupController, self).setUp()
self.uuid = "d6338c9c-3cc8-4313-b98f-13cc0684cf15"
self.invalid_uuid = "ead-edsa-e23-sdf-23"
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):
body = {"backup": {"instance": self.uuid,
@ -87,3 +103,51 @@ class TestBackupController(trove_testtools.TestCase):
self.assertThat(errors[0].message,
Equals("'%s' does not match '%s'" %
(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))