Merge "Adding pagination support for backups"
This commit is contained in:
@@ -27,9 +27,10 @@ import os
|
||||
|
||||
import six
|
||||
|
||||
from troveclient.openstack.common.apiclient import exceptions
|
||||
from troveclient import utils
|
||||
|
||||
from troveclient import common
|
||||
from troveclient.openstack.common.apiclient import exceptions
|
||||
from troveclient.openstack.common.py3kcompat import urlutils
|
||||
|
||||
# Python 2.4 compat
|
||||
try:
|
||||
@@ -60,6 +61,21 @@ class Manager(utils.HookableMixin):
|
||||
def __init__(self, api):
|
||||
self.api = api
|
||||
|
||||
def _paginated(self, url, response_key, limit=None, marker=None):
|
||||
resp, body = self.api.client.get(common.limit_url(url, limit, marker))
|
||||
if not body:
|
||||
raise Exception("Call to " + url + " did not return a body.")
|
||||
links = body.get('links', [])
|
||||
next_links = [link['href'] for link in links if link['rel'] == 'next']
|
||||
next_marker = None
|
||||
for link in next_links:
|
||||
# Extract the marker from the url.
|
||||
parsed_url = urlutils.urlparse(link)
|
||||
query_dict = dict(urlutils.parse_qsl(parsed_url.query))
|
||||
next_marker = query_dict.get('marker')
|
||||
data = [self.resource_class(self, res) for res in body[response_key]]
|
||||
return common.Paginated(data, next_marker=next_marker, links=links)
|
||||
|
||||
def _list(self, url, response_key, obj_class=None, body=None):
|
||||
resp = None
|
||||
if body:
|
||||
|
||||
101
troveclient/tests/test_backups.py
Normal file
101
troveclient/tests/test_backups.py
Normal file
@@ -0,0 +1,101 @@
|
||||
# Copyright 2013 OpenStack Foundation
|
||||
# Copyright 2013 Rackspace Hosting
|
||||
#
|
||||
# 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 testtools
|
||||
import mock
|
||||
import uuid
|
||||
|
||||
from troveclient.v1 import backups
|
||||
|
||||
"""
|
||||
Unit tests for backups.py
|
||||
"""
|
||||
|
||||
|
||||
class BackupTest(testtools.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(BackupTest, self).setUp()
|
||||
self.backup_id = str(uuid.uuid4())
|
||||
self.info = {'name': 'my backup', 'id': self.backup_id}
|
||||
self.api = mock.Mock()
|
||||
self.manager = backups.Backups(self.api)
|
||||
self.backup = backups.Backup(self.manager, self.info)
|
||||
|
||||
def tearDown(self):
|
||||
super(BackupTest, self).tearDown()
|
||||
|
||||
def test___repr__(self):
|
||||
self.assertEqual(repr(self.backup), '<Backup: my backup>')
|
||||
|
||||
|
||||
class BackupManagerTest(testtools.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(BackupManagerTest, self).setUp()
|
||||
self.backups = backups.Backups(mock.Mock())
|
||||
|
||||
def tearDown(self):
|
||||
super(BackupManagerTest, self).tearDown()
|
||||
|
||||
def test_create(self):
|
||||
create_mock = mock.Mock()
|
||||
self.backups._create = create_mock
|
||||
args = {'name': 'test_backup', 'instance': '1'}
|
||||
body = {'backup': args}
|
||||
self.backups.create(**args)
|
||||
create_mock.assert_called_with('/backups', body, 'backup')
|
||||
|
||||
def test_create_description(self):
|
||||
create_mock = mock.Mock()
|
||||
self.backups._create = create_mock
|
||||
args = {'name': 'test_backup', 'instance': '1', 'description': 'foo'}
|
||||
body = {'backup': args}
|
||||
self.backups.create(**args)
|
||||
create_mock.assert_called_with('/backups', body, 'backup')
|
||||
|
||||
def test_list(self):
|
||||
page_mock = mock.Mock()
|
||||
self.backups._paginated = page_mock
|
||||
limit = "test-limit"
|
||||
marker = "test-marker"
|
||||
self.backups.list(limit, marker)
|
||||
page_mock.assert_called_with("/backups", "backups", limit, marker)
|
||||
|
||||
def test_get(self):
|
||||
get_mock = mock.Mock()
|
||||
self.backups._get = get_mock
|
||||
self.backups.get(1)
|
||||
get_mock.assert_called_with('/backups/1', 'backup')
|
||||
|
||||
def test_delete(self):
|
||||
resp = mock.Mock()
|
||||
resp.status_code = 200
|
||||
delete_mock = mock.Mock(return_value=(resp, None))
|
||||
self.backups.api.client.delete = delete_mock
|
||||
self.backups.delete('backup1')
|
||||
delete_mock.assert_called_with('/backups/backup1')
|
||||
|
||||
def test_delete_500(self):
|
||||
resp = mock.Mock()
|
||||
resp.status_code = 500
|
||||
self.backups.api.client.delete = mock.Mock(return_value=(resp, None))
|
||||
self.assertRaises(Exception, self.backups.delete, 'backup1')
|
||||
|
||||
def test_delete_422(self):
|
||||
resp = mock.Mock()
|
||||
resp.status_code = 422
|
||||
self.backups.api.client.delete = mock.Mock(return_value=(resp, None))
|
||||
self.assertRaises(Exception, self.backups.delete, 'backup1')
|
||||
@@ -25,6 +25,7 @@ import mock
|
||||
|
||||
from troveclient import base
|
||||
from troveclient.openstack.common.apiclient import exceptions
|
||||
from troveclient import common
|
||||
from troveclient import utils
|
||||
|
||||
"""
|
||||
@@ -254,6 +255,66 @@ class ManagerListTest(ManagerTest):
|
||||
self.assertEqual(len(data_), len(l))
|
||||
|
||||
|
||||
class MangerPaginationTests(ManagerTest):
|
||||
|
||||
def setUp(self):
|
||||
super(MangerPaginationTests, self).setUp()
|
||||
self.manager = base.Manager()
|
||||
self.manager.api = mock.Mock()
|
||||
self.manager.api.client = mock.Mock()
|
||||
self.manager.resource_class = base.Resource
|
||||
|
||||
self.response_key = "response_key"
|
||||
self.data = [{"foo": "p1"}, {"foo": "p2"}]
|
||||
self.next_data = [{"foo": "p3"}, {"foo": "p4"}]
|
||||
self.marker = 'test-marker'
|
||||
self.limit = '20'
|
||||
self.url = "http://test_url"
|
||||
self.next_url = '%s?marker=%s&limit=%s' % (self.url, self.marker,
|
||||
self.limit)
|
||||
self.links = [{'href': self.next_url, 'rel': 'next'}]
|
||||
self.body = {
|
||||
self.response_key: self.data,
|
||||
'links': self.links
|
||||
}
|
||||
self.next_body = {self.response_key: self.next_data}
|
||||
|
||||
def side_effect(url):
|
||||
if url == self.url:
|
||||
return (None, self.body)
|
||||
if url == self.next_url:
|
||||
return (None, self.next_body)
|
||||
|
||||
self.manager.api.client.get = mock.Mock(side_effect=side_effect)
|
||||
|
||||
def tearDown(self):
|
||||
super(MangerPaginationTests, self).tearDown()
|
||||
|
||||
def test_pagination(self):
|
||||
resp = self.manager._paginated(self.url, self.response_key)
|
||||
self.manager.api.client.get.assert_called_with(self.url)
|
||||
self.assertEqual(resp.items[0].foo, 'p1')
|
||||
self.assertEqual(resp.items[1].foo, 'p2')
|
||||
self.assertEqual(resp.next, self.marker)
|
||||
self.assertEqual(resp.links, self.links)
|
||||
self.assertTrue(isinstance(resp, common.Paginated))
|
||||
|
||||
def test_pagination_next(self):
|
||||
resp = self.manager._paginated(self.url, self.response_key,
|
||||
limit=self.limit, marker=self.marker)
|
||||
self.manager.api.client.get.assert_called_with(self.next_url)
|
||||
self.assertEqual(resp.items[0].foo, 'p3')
|
||||
self.assertEqual(resp.items[1].foo, 'p4')
|
||||
self.assertEqual(resp.next, None)
|
||||
self.assertEqual(resp.links, [])
|
||||
self.assertTrue(isinstance(resp, common.Paginated))
|
||||
|
||||
def test_pagination_error(self):
|
||||
self.manager.api.client.get = mock.Mock(return_value=(None, None))
|
||||
self.assertRaises(Exception, self.manager._paginated,
|
||||
self.url, self.response_key)
|
||||
|
||||
|
||||
class FakeResource(object):
|
||||
def __init__(self, _id, properties):
|
||||
self.id = _id
|
||||
|
||||
@@ -35,9 +35,7 @@ class CommonTest(testtools.TestCase):
|
||||
|
||||
def test_limit_url(self):
|
||||
url = "test-url"
|
||||
limit = None
|
||||
marker = None
|
||||
self.assertEqual(url, common.limit_url(url))
|
||||
self.assertEqual(url, common.limit_url(url, limit=None, marker=None))
|
||||
|
||||
limit = "test-limit"
|
||||
marker = "test-marker"
|
||||
|
||||
@@ -68,14 +68,15 @@ class DatastoresTest(testtools.TestCase):
|
||||
base.getid = self.orig_base_getid
|
||||
|
||||
def test_list(self):
|
||||
def side_effect_func(path, inst, limit, marker):
|
||||
return path, inst, limit, marker
|
||||
|
||||
self.datastores._list = mock.Mock(side_effect=side_effect_func)
|
||||
page_mock = mock.Mock()
|
||||
self.datastores._paginated = page_mock
|
||||
limit = "test-limit"
|
||||
marker = "test-marker"
|
||||
expected = ("/datastores", "datastores", limit, marker)
|
||||
self.assertEqual(expected, self.datastores.list(limit, marker))
|
||||
self.datastores.list(limit, marker)
|
||||
page_mock.assert_called_with("/datastores", "datastores",
|
||||
limit, marker)
|
||||
self.datastores.list()
|
||||
page_mock.assert_called_with("/datastores", "datastores", None, None)
|
||||
|
||||
def test_get(self):
|
||||
def side_effect_func(path, inst):
|
||||
@@ -108,16 +109,13 @@ class DatastoreVersionsTest(testtools.TestCase):
|
||||
base.getid = self.orig_base_getid
|
||||
|
||||
def test_list(self):
|
||||
def side_effect_func(path, inst, limit, marker):
|
||||
return path, inst, limit, marker
|
||||
|
||||
self.datastore_versions._list = mock.Mock(side_effect=side_effect_func)
|
||||
page_mock = mock.Mock()
|
||||
self.datastore_versions._paginated = page_mock
|
||||
limit = "test-limit"
|
||||
marker = "test-marker"
|
||||
expected = ("/datastores/datastore1/versions",
|
||||
"versions", limit, marker)
|
||||
self.assertEqual(expected, self.datastore_versions.list(
|
||||
"datastore1", limit, marker))
|
||||
self.datastore_versions.list("datastore1", limit, marker)
|
||||
page_mock.assert_called_with("/datastores/datastore1/versions",
|
||||
"versions", limit, marker)
|
||||
|
||||
def test_get(self):
|
||||
def side_effect_func(path, inst):
|
||||
|
||||
@@ -104,30 +104,13 @@ class InstancesTest(testtools.TestCase):
|
||||
b["instance"]["datastore"]["version"])
|
||||
self.assertEqual(103, b["instance"]["flavorRef"])
|
||||
|
||||
def test__list(self):
|
||||
self.instances.api.client.get = mock.Mock(return_value=('resp', None))
|
||||
self.assertRaises(Exception, self.instances._list, "url", None)
|
||||
|
||||
body = mock.Mock()
|
||||
body.get = mock.Mock(
|
||||
return_value=[{'href': 'http://test.net/test_file',
|
||||
'rel': 'next'}]
|
||||
)
|
||||
body.__getitem__ = mock.Mock(return_value='instance1')
|
||||
#self.instances.resource_class = mock.Mock(return_value="instance-1")
|
||||
self.instances.api.client.get = mock.Mock(return_value=('resp', body))
|
||||
_expected = [{'href': 'http://test.net/test_file', 'rel': 'next'}]
|
||||
self.assertEqual(_expected, self.instances._list("url", None).links)
|
||||
|
||||
def test_list(self):
|
||||
def side_effect_func(path, inst, limit, marker):
|
||||
return path, inst, limit, marker
|
||||
|
||||
self.instances._list = mock.Mock(side_effect=side_effect_func)
|
||||
page_mock = mock.Mock()
|
||||
self.instances._paginated = page_mock
|
||||
limit = "test-limit"
|
||||
marker = "test-marker"
|
||||
expected = ("/instances", "instances", limit, marker)
|
||||
self.assertEqual(expected, self.instances.list(limit, marker))
|
||||
self.instances.list(limit, marker)
|
||||
page_mock.assert_called_with("/instances", "instances", limit, marker)
|
||||
|
||||
def test_get(self):
|
||||
def side_effect_func(path, inst):
|
||||
|
||||
@@ -68,21 +68,6 @@ class ManagementTest(testtools.TestCase):
|
||||
management.RootHistory.__init__ = self.orig_hist__init
|
||||
base.getid = self.orig_base_getid
|
||||
|
||||
def test__list(self):
|
||||
self.management.api.client.get = mock.Mock(return_value=('resp', None))
|
||||
self.assertRaises(Exception, self.management._list, "url", None)
|
||||
|
||||
body = mock.Mock()
|
||||
body.get = mock.Mock(
|
||||
return_value=[{'href': 'http://test.net/test_file',
|
||||
'rel': 'next'}]
|
||||
)
|
||||
body.__getitem__ = mock.Mock(return_value='instance1')
|
||||
self.management.resource_class = mock.Mock(return_value="instance-1")
|
||||
self.management.api.client.get = mock.Mock(return_value=('resp', body))
|
||||
_expected = [{'href': 'http://test.net/test_file', 'rel': 'next'}]
|
||||
self.assertEqual(_expected, self.management._list("url", None).links)
|
||||
|
||||
def test_show(self):
|
||||
def side_effect_func(path, instance):
|
||||
return path, instance
|
||||
@@ -91,14 +76,17 @@ class ManagementTest(testtools.TestCase):
|
||||
self.assertEqual(('/mgmt/instances/instance1', 'instance'), (p, i))
|
||||
|
||||
def test_index(self):
|
||||
def side_effect_func(url, name, limit, marker):
|
||||
return url
|
||||
|
||||
self.management._list = mock.Mock(side_effect=side_effect_func)
|
||||
self.assertEqual('/mgmt/instances?deleted=true',
|
||||
self.management.index(deleted=True))
|
||||
self.assertEqual('/mgmt/instances?deleted=false',
|
||||
self.management.index(deleted=False))
|
||||
page_mock = mock.Mock()
|
||||
self.management._paginated = page_mock
|
||||
self.management.index(deleted=True)
|
||||
page_mock.assert_called_with('/mgmt/instances?deleted=true',
|
||||
'instances', None, None)
|
||||
self.management.index(deleted=False)
|
||||
page_mock.assert_called_with('/mgmt/instances?deleted=false',
|
||||
'instances', None, None)
|
||||
self.management.index(deleted=True, limit=10, marker="foo")
|
||||
page_mock.assert_called_with('/mgmt/instances?deleted=true',
|
||||
'instances', 10, "foo")
|
||||
|
||||
def test_root_enabled_history(self):
|
||||
self.management.api.client.get = mock.Mock(return_value=('resp', None))
|
||||
|
||||
@@ -117,30 +117,14 @@ class UsersTest(testtools.TestCase):
|
||||
self._resp.status_code = 400
|
||||
self.assertRaises(Exception, self.users.delete, 34, 'user1')
|
||||
|
||||
def test__list(self):
|
||||
def side_effect_func(self, val):
|
||||
return val
|
||||
|
||||
key = 'key'
|
||||
body = mock.Mock()
|
||||
body.get = mock.Mock(
|
||||
return_value=[{'href': 'http://test.net/test_file',
|
||||
'rel': 'next'}]
|
||||
)
|
||||
body.__getitem__ = mock.Mock(return_value=["test-value"])
|
||||
|
||||
resp = mock.Mock()
|
||||
resp.status_code = 200
|
||||
self.users.resource_class = mock.Mock(side_effect=side_effect_func)
|
||||
self.users.api.client.get = mock.Mock(return_value=(resp, body))
|
||||
self.assertEqual(["test-value"], self.users._list('url', key).items)
|
||||
|
||||
self.users.api.client.get = mock.Mock(return_value=(resp, None))
|
||||
self.assertRaises(Exception, self.users._list, 'url', None)
|
||||
|
||||
def test_list(self):
|
||||
def side_effect_func(path, user, limit, marker):
|
||||
return path
|
||||
|
||||
self.users._list = mock.Mock(side_effect=side_effect_func)
|
||||
self.assertEqual('/instances/instance1/users', self.users.list(1))
|
||||
page_mock = mock.Mock()
|
||||
self.users._paginated = page_mock
|
||||
self.users.list(1)
|
||||
page_mock.assert_called_with('/instances/instance1/users',
|
||||
'users', None, None)
|
||||
limit = 'test-limit'
|
||||
marker = 'test-marker'
|
||||
self.users.list(1, limit, marker)
|
||||
page_mock.assert_called_with('/instances/instance1/users',
|
||||
'users', limit, marker)
|
||||
|
||||
@@ -51,7 +51,7 @@ class Backups(base.ManagerWithFind):
|
||||
|
||||
:rtype: list of :class:`Backups`.
|
||||
"""
|
||||
return self._list("/backups", "backups", limit, marker)
|
||||
return self._paginated("/backups", "backups", limit, marker)
|
||||
|
||||
def create(self, name, instance, description=None):
|
||||
"""
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
|
||||
from troveclient import base
|
||||
from troveclient import common
|
||||
from troveclient.openstack.common.py3kcompat import urlutils
|
||||
|
||||
|
||||
class Database(base.Resource):
|
||||
@@ -52,34 +51,14 @@ class Databases(base.ManagerWithFind):
|
||||
resp, body = self.api.client.delete(url)
|
||||
common.check_for_exceptions(resp, body)
|
||||
|
||||
def _list(self, url, response_key, limit=None, marker=None):
|
||||
resp, body = self.api.client.get(common.limit_url(url, limit, marker))
|
||||
common.check_for_exceptions(resp, body)
|
||||
if not body:
|
||||
raise Exception("Call to " + url +
|
||||
" did not return a body.")
|
||||
links = body.get('links', [])
|
||||
next_links = [link['href'] for link in links if link['rel'] == 'next']
|
||||
next_marker = None
|
||||
for link in next_links:
|
||||
# Extract the marker from the url.
|
||||
parsed_url = urlutils.urlparse(link)
|
||||
query_dict = dict(urlutils.parse_qsl(parsed_url.query))
|
||||
next_marker = query_dict.get('marker', None)
|
||||
databases = body[response_key]
|
||||
databases = [self.resource_class(self, res) for res in databases]
|
||||
return common.Paginated(
|
||||
databases, next_marker=next_marker, links=links
|
||||
)
|
||||
|
||||
def list(self, instance, limit=None, marker=None):
|
||||
"""
|
||||
Get a list of all Databases from the instance.
|
||||
|
||||
:rtype: list of :class:`Database`.
|
||||
"""
|
||||
return self._list("/instances/%s/databases" % base.getid(instance),
|
||||
"databases", limit, marker)
|
||||
url = "/instances/%s/databases" % base.getid(instance)
|
||||
return self._paginated(url, "databases", limit, marker)
|
||||
|
||||
# def get(self, instance, database):
|
||||
# """
|
||||
|
||||
@@ -46,7 +46,7 @@ class Datastores(base.ManagerWithFind):
|
||||
|
||||
:rtype: list of :class:`Datastore`.
|
||||
"""
|
||||
return self._list("/datastores", "datastores", limit, marker)
|
||||
return self._paginated("/datastores", "datastores", limit, marker)
|
||||
|
||||
def get(self, datastore):
|
||||
"""
|
||||
@@ -73,8 +73,8 @@ class DatastoreVersions(base.ManagerWithFind):
|
||||
|
||||
:rtype: list of :class:`DatastoreVersion`.
|
||||
"""
|
||||
return self._list("/datastores/%s/versions" % datastore,
|
||||
"versions", limit, marker)
|
||||
return self._paginated("/datastores/%s/versions" % datastore,
|
||||
"versions", limit, marker)
|
||||
|
||||
def get(self, datastore, datastore_version):
|
||||
"""
|
||||
|
||||
@@ -19,11 +19,9 @@
|
||||
|
||||
from troveclient import base
|
||||
from troveclient import common
|
||||
from troveclient.openstack.common.apiclient import exceptions
|
||||
from troveclient.openstack.common.py3kcompat import urlutils
|
||||
|
||||
|
||||
REBOOT_SOFT, REBOOT_HARD = 'SOFT', 'HARD'
|
||||
REBOOT_SOFT = 'SOFT'
|
||||
REBOOT_HARD = 'HARD'
|
||||
|
||||
|
||||
class Instance(base.Resource):
|
||||
@@ -85,31 +83,13 @@ class Instances(base.ManagerWithFind):
|
||||
|
||||
return self._create("/instances", body, "instance")
|
||||
|
||||
def _list(self, url, response_key, limit=None, marker=None):
|
||||
resp, body = self.api.client.get(common.limit_url(url, limit, marker))
|
||||
if not body:
|
||||
raise Exception("Call to " + url + " did not return a body.")
|
||||
links = body.get('links', [])
|
||||
next_links = [link['href'] for link in links if link['rel'] == 'next']
|
||||
next_marker = None
|
||||
for link in next_links:
|
||||
# Extract the marker from the url.
|
||||
parsed_url = urlutils.urlparse(link)
|
||||
query_dict = dict(urlutils.parse_qsl(parsed_url.query))
|
||||
next_marker = query_dict.get('marker', None)
|
||||
instances = body[response_key]
|
||||
instances = [self.resource_class(self, res) for res in instances]
|
||||
return common.Paginated(
|
||||
instances, next_marker=next_marker, links=links
|
||||
)
|
||||
|
||||
def list(self, limit=None, marker=None):
|
||||
"""
|
||||
Get a list of all instances.
|
||||
|
||||
:rtype: list of :class:`Instance`.
|
||||
"""
|
||||
return self._list("/instances", "instances", limit, marker)
|
||||
return self._paginated("/instances", "instances", limit, marker)
|
||||
|
||||
def get(self, instance):
|
||||
"""
|
||||
@@ -120,14 +100,14 @@ class Instances(base.ManagerWithFind):
|
||||
return self._get("/instances/%s" % base.getid(instance),
|
||||
"instance")
|
||||
|
||||
def backups(self, instance):
|
||||
def backups(self, instance, limit=None, marker=None):
|
||||
"""
|
||||
Get the list of backups for a specific instance.
|
||||
|
||||
:rtype: list of :class:`Backups`.
|
||||
"""
|
||||
return self._list("/instances/%s/backups" % base.getid(instance),
|
||||
"backups")
|
||||
url = "/instances/%s/backups" % base.getid(instance)
|
||||
return self._paginated(url, "backups", limit, marker)
|
||||
|
||||
def delete(self, instance):
|
||||
"""
|
||||
@@ -137,8 +117,7 @@ class Instances(base.ManagerWithFind):
|
||||
"""
|
||||
resp, body = self.api.client.delete("/instances/%s" %
|
||||
base.getid(instance))
|
||||
if resp.status_code in (422, 500):
|
||||
raise exceptions.from_response(resp, body)
|
||||
common.check_for_exceptions(resp, body)
|
||||
|
||||
def _action(self, instance_id, body):
|
||||
"""
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
|
||||
from troveclient import base
|
||||
from troveclient import common
|
||||
from troveclient.openstack.common.py3kcompat import urlutils
|
||||
from troveclient.v1 import instances
|
||||
from troveclient.v1 import flavors
|
||||
|
||||
@@ -39,24 +38,6 @@ class Management(base.ManagerWithFind):
|
||||
def list(self):
|
||||
pass
|
||||
|
||||
def _list(self, url, response_key, limit=None, marker=None):
|
||||
resp, body = self.api.client.get(common.limit_url(url, limit, marker))
|
||||
if not body:
|
||||
raise Exception("Call to " + url + " did not return a body.")
|
||||
links = body.get('links', [])
|
||||
next_links = [link['href'] for link in links if link['rel'] == 'next']
|
||||
next_marker = None
|
||||
for link in next_links:
|
||||
# Extract the marker from the url.
|
||||
parsed_url = urlutils.urlparse(link)
|
||||
query_dict = dict(urlutils.parse_qsl(parsed_url.query))
|
||||
next_marker = query_dict.get('marker', None)
|
||||
instances = body[response_key]
|
||||
instances = [self.resource_class(self, res) for res in instances]
|
||||
return common.Paginated(
|
||||
instances, next_marker=next_marker, links=links
|
||||
)
|
||||
|
||||
def show(self, instance):
|
||||
"""
|
||||
Get details of one instance.
|
||||
@@ -82,7 +63,7 @@ class Management(base.ManagerWithFind):
|
||||
form = "?deleted=false"
|
||||
|
||||
url = "/mgmt/instances%s" % form
|
||||
return self._list(url, "instances", limit, marker)
|
||||
return self._paginated(url, "instances", limit, marker)
|
||||
|
||||
def root_enabled_history(self, instance):
|
||||
"""
|
||||
|
||||
@@ -19,8 +19,6 @@
|
||||
|
||||
from troveclient import base
|
||||
from troveclient import common
|
||||
from troveclient.openstack.common.apiclient import exceptions
|
||||
from troveclient.openstack.common.py3kcompat import urlutils
|
||||
|
||||
|
||||
class SecurityGroup(base.Resource):
|
||||
@@ -37,32 +35,14 @@ class SecurityGroups(base.ManagerWithFind):
|
||||
"""
|
||||
resource_class = SecurityGroup
|
||||
|
||||
def _list(self, url, response_key, limit=None, marker=None):
|
||||
resp, body = self.api.client.get(common.limit_url(url, limit, marker))
|
||||
if not body:
|
||||
raise Exception("Call to " + url + " did not return a body.")
|
||||
links = body.get('links', [])
|
||||
next_links = [link['href'] for link in links if link['rel'] == 'next']
|
||||
next_marker = None
|
||||
for link in next_links:
|
||||
# Extract the marker from the url.
|
||||
parsed_url = urlutils.urlparse(link)
|
||||
query_dict = dict(urlutils.parse_qsl(parsed_url.query))
|
||||
next_marker = query_dict.get('marker', None)
|
||||
instances = body[response_key]
|
||||
instances = [self.resource_class(self, res) for res in instances]
|
||||
return common.Paginated(
|
||||
instances, next_marker=next_marker, links=links
|
||||
)
|
||||
|
||||
def list(self, limit=None, marker=None):
|
||||
"""
|
||||
Get a list of all security groups.
|
||||
|
||||
:rtype: list of :class:`SecurityGroup`.
|
||||
"""
|
||||
return self._list("/security-groups", "security_groups", limit,
|
||||
marker)
|
||||
return self._paginated("/security-groups", "security_groups",
|
||||
limit, marker)
|
||||
|
||||
def get(self, security_group):
|
||||
"""
|
||||
@@ -118,8 +98,7 @@ class SecurityGroupRules(base.ManagerWithFind):
|
||||
"""
|
||||
resp, body = self.api.client.delete("/security-group-rules/%s" %
|
||||
base.getid(security_group_rule))
|
||||
if resp.status_code in (422, 500):
|
||||
raise exceptions.from_response(resp, body)
|
||||
common.check_for_exceptions(resp, body)
|
||||
|
||||
# Appease the abc gods
|
||||
def list(self):
|
||||
|
||||
@@ -240,21 +240,36 @@ def do_backup_show(cs, args):
|
||||
_print_instance(backup)
|
||||
|
||||
|
||||
@utils.arg('--limit', metavar='<limit>',
|
||||
default=None,
|
||||
help='Return up to N number of the most recent backups.')
|
||||
@utils.arg('instance', metavar='<instance>', help='ID of the instance.')
|
||||
@utils.service_type('database')
|
||||
def do_backup_list_instance(cs, args):
|
||||
"""List available backups for an instance."""
|
||||
backups = cs.instances.backups(args.instance)
|
||||
utils.print_list(backups, ['id', 'instance_id',
|
||||
'name', 'description', 'status'])
|
||||
wrapper = cs.instances.backups(args.instance, limit=args.limit)
|
||||
backups = wrapper.items
|
||||
while wrapper.next and not args.limit:
|
||||
wrapper = cs.instances.backups(args.instance, marker=wrapper.next)
|
||||
backups += wrapper.items
|
||||
utils.print_list(backups, ['id', 'name', 'status', 'updated'],
|
||||
order_by='updated')
|
||||
|
||||
|
||||
@utils.arg('--limit', metavar='<limit>',
|
||||
default=None,
|
||||
help='Return up to N number of the most recent backups.')
|
||||
@utils.service_type('database')
|
||||
def do_backup_list(cs, args):
|
||||
"""List available backups."""
|
||||
backups = cs.backups.list()
|
||||
utils.print_list(backups, ['id', 'instance_id',
|
||||
'name', 'description', 'status'])
|
||||
wrapper = cs.backups.list(limit=args.limit)
|
||||
backups = wrapper.items
|
||||
while wrapper.next and not args.limit:
|
||||
wrapper = cs.backups.list(marker=wrapper.next)
|
||||
backups += wrapper.items
|
||||
utils.print_list(backups, ['id', 'instance_id', 'name',
|
||||
'status', 'updated'],
|
||||
order_by='updated')
|
||||
|
||||
|
||||
@utils.arg('backup', metavar='<backup>', help='ID of the backup.')
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
from troveclient import base
|
||||
from troveclient.v1 import databases
|
||||
from troveclient import common
|
||||
from troveclient.openstack.common.py3kcompat import urlutils
|
||||
|
||||
|
||||
class User(base.Resource):
|
||||
@@ -52,33 +51,14 @@ class Users(base.ManagerWithFind):
|
||||
resp, body = self.api.client.delete(url)
|
||||
common.check_for_exceptions(resp, body)
|
||||
|
||||
def _list(self, url, response_key, limit=None, marker=None):
|
||||
resp, body = self.api.client.get(common.limit_url(url, limit, marker))
|
||||
common.check_for_exceptions(resp, body)
|
||||
if not body:
|
||||
raise Exception("Call to " + url +
|
||||
" did not return a body.")
|
||||
links = body.get('links', [])
|
||||
next_links = [link['href'] for link in links if link['rel'] == 'next']
|
||||
next_marker = None
|
||||
for link in next_links:
|
||||
# Extract the marker from the url.
|
||||
parsed_url = urlutils.urlparse(link)
|
||||
query_dict = dict(urlutils.parse_qsl(parsed_url.query))
|
||||
next_marker = query_dict.get('marker', None)
|
||||
users = [self.resource_class(self, res) for res in body[response_key]]
|
||||
return common.Paginated(
|
||||
users, next_marker=next_marker, links=links
|
||||
)
|
||||
|
||||
def list(self, instance, limit=None, marker=None):
|
||||
"""
|
||||
Get a list of all Users from the instance's Database.
|
||||
|
||||
:rtype: list of :class:`User`.
|
||||
"""
|
||||
return self._list("/instances/%s/users" % base.getid(instance),
|
||||
"users", limit, marker)
|
||||
url = "/instances/%s/users" % base.getid(instance)
|
||||
return self._paginated(url, "users", limit, marker)
|
||||
|
||||
def get(self, instance_id, username, hostname=None):
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user