Support getting backups of a specific project

Change-Id: I6a6778ddbb1ee92da28a709be91b04873fe749fe
This commit is contained in:
Lingxian Kong 2020-09-13 22:57:05 +12:00
parent df4f74769e
commit f79bb53a39
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))