diff --git a/.gitignore b/.gitignore index a297ef3..9c56352 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,4 @@ dist designateclient/versioninfo .testrepository *.log +.idea/ \ No newline at end of file diff --git a/designateclient/v2/base.py b/designateclient/v2/base.py new file mode 100644 index 0000000..e03cfe6 --- /dev/null +++ b/designateclient/v2/base.py @@ -0,0 +1,43 @@ +# Copyright 2016 Hewlett Packard Enterprise Development Company LP +# +# Author: Graham Hayes +# +# 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. + +from designateclient import client +from designateclient.v2.utils import parse_query_from_url + + +class DesignateList(list): + + next_link_criterion = {} + next_page = False + + +class V2Controller(client.Controller): + + def _get(self, url, response_key=None): + resp, body = self.client.session.get(url) + + if response_key is not None: + data = DesignateList() + data.extend(body[response_key]) + + if 'next' in body.get('links', {}): + data.next_page = True + data.next_link_criterion = parse_query_from_url( + body['links']['next']) + + return data + + return body \ No newline at end of file diff --git a/designateclient/v2/cli/blacklists.py b/designateclient/v2/cli/blacklists.py index d52381d..9310841 100644 --- a/designateclient/v2/cli/blacklists.py +++ b/designateclient/v2/cli/blacklists.py @@ -22,6 +22,7 @@ from cliff import show import six from designateclient import utils +from designateclient.v2.utils import get_all LOG = logging.getLogger(__name__) @@ -40,7 +41,7 @@ class ListBlacklistsCommand(lister.Lister): client = self.app.client_manager.dns cols = self.columns - data = client.blacklists.list() + data = get_all(client.blacklists.list) return cols, (utils.get_item_properties(s, cols) for s in data) diff --git a/designateclient/v2/cli/recordsets.py b/designateclient/v2/cli/recordsets.py index df05dd9..6244d33 100644 --- a/designateclient/v2/cli/recordsets.py +++ b/designateclient/v2/cli/recordsets.py @@ -22,6 +22,7 @@ from cliff import show import six from designateclient import utils +from designateclient.v2.utils import get_all LOG = logging.getLogger(__name__) @@ -48,7 +49,8 @@ class ListRecordSetsCommand(lister.Lister): client = self.app.client_manager.dns cols = self.columns - data = client.recordsets.list(parsed_args.zone_id) + + data = get_all(client.recordsets.list, args=[parsed_args.zone_id]) six.moves.map(_format_recordset, data) return cols, (utils.get_item_properties(s, cols) for s in data) diff --git a/designateclient/v2/cli/reverse.py b/designateclient/v2/cli/reverse.py index f55e3b5..c8c2baf 100644 --- a/designateclient/v2/cli/reverse.py +++ b/designateclient/v2/cli/reverse.py @@ -22,6 +22,7 @@ from cliff import show import six from designateclient import utils +from designateclient.v2.utils import get_all LOG = logging.getLogger(__name__) @@ -40,7 +41,7 @@ class ListFloatingIPCommand(lister.Lister): client = self.app.client_manager.dns cols = self.columns - data = client.floatingips.list() + data = get_all(client.floatingips.list) return cols, (utils.get_item_properties(s, cols) for s in data) diff --git a/designateclient/v2/cli/tlds.py b/designateclient/v2/cli/tlds.py index 4aa543d..57f62bf 100644 --- a/designateclient/v2/cli/tlds.py +++ b/designateclient/v2/cli/tlds.py @@ -22,6 +22,7 @@ from cliff import show import six from designateclient import utils +from designateclient.v2.utils import get_all LOG = logging.getLogger(__name__) @@ -39,7 +40,7 @@ class ListTLDsCommand(lister.Lister): def take_action(self, parsed_args): client = self.app.client_manager.dns - data = client.tlds.list() + data = get_all(client.tlds.list) cols = self.columns return cols, (utils.get_item_properties(s, cols) for s in data) diff --git a/designateclient/v2/cli/zones.py b/designateclient/v2/cli/zones.py index ae35ec2..465c3ed 100644 --- a/designateclient/v2/cli/zones.py +++ b/designateclient/v2/cli/zones.py @@ -23,6 +23,7 @@ from openstackclient.common import exceptions as osc_exc import six from designateclient import utils +from designateclient.v2.utils import get_all LOG = logging.getLogger(__name__) @@ -73,7 +74,7 @@ class ListZonesCommand(lister.Lister): if parsed_args.status is not None: criterion["status"] = parsed_args.status - data = client.zones.list(criterion=criterion) + data = get_all(client.zones.list, criterion) cols = self.columns return cols, (utils.get_item_properties(s, cols) for s in data) diff --git a/designateclient/v2/recordsets.py b/designateclient/v2/recordsets.py index eab96ee..5096a69 100644 --- a/designateclient/v2/recordsets.py +++ b/designateclient/v2/recordsets.py @@ -16,11 +16,11 @@ from oslo_utils import uuidutils import six -from designateclient import client +from designateclient.v2.base import V2Controller from designateclient.v2 import utils as v2_utils -class RecordSetController(client.Controller): +class RecordSetController(V2Controller): def _canonicalize_record_name(self, zone, name): zone_info = None diff --git a/designateclient/v2/utils.py b/designateclient/v2/utils.py index 5fd6590..4a69a55 100644 --- a/designateclient/v2/utils.py +++ b/designateclient/v2/utils.py @@ -13,7 +13,12 @@ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. + from oslo_utils import uuidutils +from six import iteritems +from six import iterkeys +from six.moves.urllib.parse import parse_qs +from six.moves.urllib.parse import urlparse from designateclient import exceptions @@ -36,3 +41,40 @@ def resolve_by_name(func, name, *args): else: msg = "Multiple matches found for %s, please use ID instead." % name raise exceptions.NoUniqueMatch(msg) + + +def parse_query_from_url(url): + """ + Helper to get key bits of data from the "next" url returned + from the API on collections + :param url: + :return: dict + """ + values = parse_qs(urlparse(url)[4]) + return {k: values[k][0] for k in iterkeys(values)} + + +def get_all(function, criterion=None, args=None): + """ + + :param function: Function to be called to get data + :param criterion: dict of filters to be applied + :param args: arguments to be given to the function + :return: DesignateList() + """ + + criterion = criterion or {} + args = args or [] + + data = function(*args, criterion=criterion) + returned_data = data + while True: + if data.next_page: + for k, v in iteritems(data.next_link_criterion): + criterion[k] = v + data = function(*args, criterion=criterion) + returned_data.extend(data) + else: + break + + return returned_data \ No newline at end of file diff --git a/designateclient/v2/zones.py b/designateclient/v2/zones.py index a8ae74a..22631ab 100644 --- a/designateclient/v2/zones.py +++ b/designateclient/v2/zones.py @@ -13,11 +13,11 @@ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. -from designateclient import client +from designateclient.v2.base import V2Controller from designateclient.v2 import utils as v2_utils -class ZoneController(client.Controller): +class ZoneController(V2Controller): def create(self, name, type_=None, email=None, description=None, ttl=None, masters=None): type_ = type_ or "PRIMARY" @@ -81,7 +81,7 @@ class ZoneController(client.Controller): self.client.session.post(url) -class ZoneTransfersController(client.Controller): +class ZoneTransfersController(V2Controller): def create_request(self, zone, target_project_id, description=None): zone = v2_utils.resolve_by_name(self.client.zones.list, zone)