From c7e3529dea48d010f1fd5a6631638ea754b130dd Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Tue, 27 Jul 2021 11:00:06 +0100 Subject: [PATCH] Add pagination helpers Add some pagination helpers to configure pagination parameters for various commands. Two pagination schemes are supported, based on what we currently support across OSC commands: marker-based pagination and offset-based pagination. Change-Id: I551bb4c3ff0568c6df5244a1d0f0669497bee58f Signed-off-by: Stephen Finucane --- openstackclient/common/pagination.py | 82 +++++++++++++++++++ openstackclient/compute/v2/flavor.py | 18 +--- openstackclient/compute/v2/hypervisor.py | 23 +----- openstackclient/compute/v2/keypair.py | 11 +-- openstackclient/compute/v2/server.py | 25 +----- openstackclient/compute/v2/server_event.py | 17 +--- openstackclient/compute/v2/server_group.py | 25 +----- .../compute/v2/server_migration.py | 24 +----- openstackclient/image/v2/image.py | 20 +---- openstackclient/object/v1/container.py | 14 +--- openstackclient/object/v1/object.py | 13 +-- openstackclient/volume/v1/volume.py | 16 +--- openstackclient/volume/v2/volume.py | 14 +--- openstackclient/volume/v2/volume_backup.py | 15 +--- openstackclient/volume/v2/volume_snapshot.py | 14 +--- .../volume/v3/volume_attachment.py | 16 +--- openstackclient/volume/v3/volume_message.py | 15 +--- 17 files changed, 115 insertions(+), 247 deletions(-) create mode 100644 openstackclient/common/pagination.py diff --git a/openstackclient/common/pagination.py b/openstackclient/common/pagination.py new file mode 100644 index 0000000000..b6a11c5f5f --- /dev/null +++ b/openstackclient/common/pagination.py @@ -0,0 +1,82 @@ +# 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 osc_lib.cli import parseractions + +from openstackclient.i18n import _ + + +# TODO(stephenfin): Consider moving these to osc-lib since they're broadly +# useful + + +def add_marker_pagination_option_to_parser(parser): + """Add marker-based pagination options to the parser. + + APIs that use marker-based paging use the marker and limit query parameters + to paginate through items in a collection. + + Marker-based pagination is often used in cases where the length of the + total set of items is either changing frequently, or where the total length + might not be known upfront. + """ + parser.add_argument( + '--limit', + metavar='', + type=int, + action=parseractions.NonNegativeAction, + help=_( + 'The maximum number of entries to return. If the value exceeds ' + 'the server-defined maximum, then the maximum value will be used.' + ), + ) + parser.add_argument( + '--marker', + metavar='', + default=None, + help=_( + 'The first position in the collection to return results from. ' + 'This should be a value that was returned in a previous request.' + ), + ) + + +def add_offset_pagination_option_to_parser(parser): + """Add offset-based pagination options to the parser. + + APIs that use offset-based paging use the offset and limit query parameters + to paginate through items in a collection. + + Offset-based pagination is often used where the list of items is of a fixed + and predetermined length. + """ + parser.add_argument( + '--limit', + metavar='', + type=int, + action=parseractions.NonNegativeAction, + help=_( + 'The maximum number of entries to return. If the value exceeds ' + 'the server-defined maximum, then the maximum value will be used.' + ), + ) + parser.add_argument( + '--offset', + metavar='', + type=int, + action=parseractions.NonNegativeAction, + default=None, + help=_( + 'The (zero-based) offset of the first item in the collection to ' + 'return.' + ), + ) diff --git a/openstackclient/compute/v2/flavor.py b/openstackclient/compute/v2/flavor.py index d670720ca1..aa8c010f13 100644 --- a/openstackclient/compute/v2/flavor.py +++ b/openstackclient/compute/v2/flavor.py @@ -25,6 +25,7 @@ from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils +from openstackclient.common import pagination from openstackclient.i18n import _ from openstackclient.identity import common as identity_common @@ -292,22 +293,7 @@ class ListFlavor(command.Lister): default=False, help=_("List additional fields in output"), ) - parser.add_argument( - '--marker', - metavar="", - help=_("The last flavor ID of the previous page"), - ) - parser.add_argument( - '--limit', - type=int, - metavar='', - help=_( - 'Maximum number of flavors to display. This is also ' - 'configurable on the server. The actual limit used will be ' - 'the lower of the user-supplied value and the server ' - 'configuration-derived value' - ), - ) + pagination.add_marker_pagination_option_to_parser(parser) return parser def take_action(self, parsed_args): diff --git a/openstackclient/compute/v2/hypervisor.py b/openstackclient/compute/v2/hypervisor.py index ddfd3e8d9f..a118913b62 100644 --- a/openstackclient/compute/v2/hypervisor.py +++ b/openstackclient/compute/v2/hypervisor.py @@ -25,6 +25,7 @@ from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils +from openstackclient.common import pagination from openstackclient.i18n import _ @@ -80,27 +81,7 @@ class ListHypervisor(command.Lister): "when using microversion 2.52 or lower" ), ) - parser.add_argument( - '--marker', - metavar='', - help=_( - "The UUID of the last hypervisor of the previous page; " - "displays list of hypervisors after 'marker'. " - "(supported with --os-compute-api-version 2.33 or above)" - ), - ) - parser.add_argument( - '--limit', - metavar='', - type=int, - help=_( - "Maximum number of hypervisors to display. Note that there " - "is a configurable max limit on the server, and the limit " - "that is used will be the minimum of what is requested " - "here and what is configured in the server. " - "(supported with --os-compute-api-version 2.33 or above)" - ), - ) + pagination.add_marker_pagination_option_to_parser(parser) parser.add_argument( '--long', action='store_true', diff --git a/openstackclient/compute/v2/keypair.py b/openstackclient/compute/v2/keypair.py index 3e16feabcd..5d7815b269 100644 --- a/openstackclient/compute/v2/keypair.py +++ b/openstackclient/compute/v2/keypair.py @@ -27,6 +27,7 @@ from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils +from openstackclient.common import pagination from openstackclient.i18n import _ from openstackclient.identity import common as identity_common @@ -296,15 +297,7 @@ class ListKeypair(command.Lister): ), ) identity_common.add_project_domain_option_to_parser(parser) - parser.add_argument( - '--marker', - help=_('The last keypair ID of the previous page'), - ) - parser.add_argument( - '--limit', - type=int, - help=_('Maximum number of keypairs to display'), - ) + pagination.add_marker_pagination_option_to_parser(parser) return parser def take_action(self, parsed_args): diff --git a/openstackclient/compute/v2/server.py b/openstackclient/compute/v2/server.py index 5b563a4839..4854e91f8c 100644 --- a/openstackclient/compute/v2/server.py +++ b/openstackclient/compute/v2/server.py @@ -33,6 +33,7 @@ from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils +from openstackclient.common import pagination from openstackclient.i18n import _ from openstackclient.identity import common as identity_common from openstackclient.network import common as network_common @@ -2370,29 +2371,7 @@ class ListServer(command.Lister): 'Mutually exclusive with "--no-name-lookup|-n" option.' ), ) - parser.add_argument( - '--marker', - metavar='', - default=None, - help=_( - 'The last server of the previous page. Display ' - 'list of servers after marker. Display all servers if not ' - 'specified. When used with ``--deleted``, the marker must ' - 'be an ID, otherwise a name or ID can be used.' - ), - ) - parser.add_argument( - '--limit', - metavar='', - type=int, - default=None, - help=_( - "Maximum number of servers to display. If limit equals -1, " - "all servers will be displayed. If limit is greater than " - "'osapi_max_limit' option of Nova API, " - "'osapi_max_limit' will be used instead." - ), - ) + pagination.add_marker_pagination_option_to_parser(parser) parser.add_argument( '--changes-before', metavar='', diff --git a/openstackclient/compute/v2/server_event.py b/openstackclient/compute/v2/server_event.py index 683179524c..1fc4672103 100644 --- a/openstackclient/compute/v2/server_event.py +++ b/openstackclient/compute/v2/server_event.py @@ -26,6 +26,7 @@ from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils +from openstackclient.common import pagination from openstackclient.i18n import _ LOG = logging.getLogger(__name__) @@ -143,21 +144,7 @@ class ListServerEvent(command.Lister): "(supported with --os-compute-api-version 2.66 or above)" ), ) - parser.add_argument( - '--marker', - help=_( - 'The last server event ID of the previous page ' - '(supported by --os-compute-api-version 2.58 or above)' - ), - ) - parser.add_argument( - '--limit', - type=int, - help=_( - 'Maximum number of server events to display ' - '(supported by --os-compute-api-version 2.58 or above)' - ), - ) + pagination.add_marker_pagination_option_to_parser(parser) return parser def take_action(self, parsed_args): diff --git a/openstackclient/compute/v2/server_group.py b/openstackclient/compute/v2/server_group.py index d1c0bf976c..e5a1a4cead 100644 --- a/openstackclient/compute/v2/server_group.py +++ b/openstackclient/compute/v2/server_group.py @@ -24,9 +24,9 @@ from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils +from openstackclient.common import pagination from openstackclient.i18n import _ - LOG = logging.getLogger(__name__) @@ -191,28 +191,7 @@ class ListServerGroup(command.Lister): ) # TODO(stephenfin): This should really be a --marker option, but alas # the API doesn't support that for some reason - parser.add_argument( - '--offset', - metavar='', - type=int, - default=None, - help=_( - 'Index from which to start listing servers. This should ' - 'typically be a factor of --limit. Display all servers groups ' - 'if not specified.' - ), - ) - parser.add_argument( - '--limit', - metavar='', - type=int, - default=None, - help=_( - "Maximum number of server groups to display. " - "If limit is greater than 'osapi_max_limit' option of Nova " - "API, 'osapi_max_limit' will be used instead." - ), - ) + pagination.add_offset_pagination_option_to_parser(parser) return parser def take_action(self, parsed_args): diff --git a/openstackclient/compute/v2/server_migration.py b/openstackclient/compute/v2/server_migration.py index 6235ae6974..8a4440d6ab 100644 --- a/openstackclient/compute/v2/server_migration.py +++ b/openstackclient/compute/v2/server_migration.py @@ -19,6 +19,7 @@ from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils +from openstackclient.common import pagination from openstackclient.i18n import _ from openstackclient.identity import common as identity_common @@ -54,28 +55,7 @@ class ListMigration(command.Lister): ], help=_('Filter migrations by type'), ) - parser.add_argument( - '--marker', - metavar='', - help=_( - "The last migration of the previous page; displays list " - "of migrations after 'marker'. Note that the marker is " - "the migration UUID. " - "(supported with --os-compute-api-version 2.59 or above)" - ), - ) - parser.add_argument( - '--limit', - metavar='', - type=int, - help=_( - "Maximum number of migrations to display. Note that there " - "is a configurable max limit on the server, and the limit " - "that is used will be the minimum of what is requested " - "here and what is configured in the server. " - "(supported with --os-compute-api-version 2.59 or above)" - ), - ) + pagination.add_marker_pagination_option_to_parser(parser) parser.add_argument( '--changes-since', dest='changes_since', diff --git a/openstackclient/image/v2/image.py b/openstackclient/image/v2/image.py index 48b2639265..725a4d3efd 100644 --- a/openstackclient/image/v2/image.py +++ b/openstackclient/image/v2/image.py @@ -31,6 +31,7 @@ from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils +from openstackclient.common import pagination from openstackclient.common import progressbar from openstackclient.i18n import _ from openstackclient.identity import common as identity_common @@ -805,9 +806,9 @@ class ListImage(command.Lister): default=False, help=_('List additional fields in output'), ) - # --page-size has never worked, leave here for silent compatibility # We'll implement limit/marker differently later + # TODO(stephenfin): Remove this in the next major version bump parser.add_argument( "--page-size", metavar="", @@ -823,22 +824,7 @@ class ListImage(command.Lister): "specified separated by comma" ), ) - parser.add_argument( - "--limit", - metavar="", - type=int, - help=_("Maximum number of images to display."), - ) - parser.add_argument( - '--marker', - metavar='', - default=None, - help=_( - "The last image of the previous page. Display " - "list of images after marker. Display all images if not " - "specified. (name or ID)" - ), - ) + pagination.add_marker_pagination_option_to_parser(parser) return parser def take_action(self, parsed_args): diff --git a/openstackclient/object/v1/container.py b/openstackclient/object/v1/container.py index 4f01c1d925..25108e2c62 100644 --- a/openstackclient/object/v1/container.py +++ b/openstackclient/object/v1/container.py @@ -22,9 +22,9 @@ from osc_lib.cli import parseractions from osc_lib.command import command from osc_lib import utils +from openstackclient.common import pagination from openstackclient.i18n import _ - LOG = logging.getLogger(__name__) @@ -127,22 +127,12 @@ class ListContainer(command.Lister): metavar="", help=_("Filter list using "), ) - parser.add_argument( - "--marker", - metavar="", - help=_("Anchor for paging"), - ) + pagination.add_marker_pagination_option_to_parser(parser) parser.add_argument( "--end-marker", metavar="", help=_("End anchor for paging"), ) - parser.add_argument( - "--limit", - metavar="", - type=int, - help=_("Limit the number of containers returned"), - ) parser.add_argument( '--long', action='store_true', diff --git a/openstackclient/object/v1/object.py b/openstackclient/object/v1/object.py index e88be16268..24cebb3b8b 100644 --- a/openstackclient/object/v1/object.py +++ b/openstackclient/object/v1/object.py @@ -23,6 +23,7 @@ from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils +from openstackclient.common import pagination from openstackclient.i18n import _ @@ -140,22 +141,12 @@ class ListObject(command.Lister): metavar="", help=_("Roll up items with "), ) - parser.add_argument( - "--marker", - metavar="", - help=_("Anchor for paging"), - ) + pagination.add_marker_pagination_option_to_parser(parser) parser.add_argument( "--end-marker", metavar="", help=_("End anchor for paging"), ) - parser.add_argument( - "--limit", - metavar="", - type=int, - help=_("Limit the number of objects returned"), - ) parser.add_argument( '--long', action='store_true', diff --git a/openstackclient/volume/v1/volume.py b/openstackclient/volume/v1/volume.py index 7c60d6c784..168fed4ab8 100644 --- a/openstackclient/volume/v1/volume.py +++ b/openstackclient/volume/v1/volume.py @@ -26,6 +26,7 @@ from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils +from openstackclient.common import pagination from openstackclient.i18n import _ @@ -372,20 +373,7 @@ class ListVolume(command.Lister): default=False, help=_('List additional fields in output'), ) - parser.add_argument( - '--offset', - type=int, - action=parseractions.NonNegativeAction, - metavar='', - help=_('Index from which to start listing volumes'), - ) - parser.add_argument( - '--limit', - type=int, - action=parseractions.NonNegativeAction, - metavar='', - help=_('Maximum number of volumes to display'), - ) + pagination.add_offset_pagination_option_to_parser(parser) return parser def take_action(self, parsed_args): diff --git a/openstackclient/volume/v2/volume.py b/openstackclient/volume/v2/volume.py index 096305543c..4127e23d49 100644 --- a/openstackclient/volume/v2/volume.py +++ b/openstackclient/volume/v2/volume.py @@ -26,6 +26,7 @@ from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils +from openstackclient.common import pagination from openstackclient.i18n import _ from openstackclient.identity import common as identity_common @@ -456,18 +457,7 @@ class ListVolume(command.Lister): default=False, help=_('List additional fields in output'), ) - parser.add_argument( - '--marker', - metavar='', - help=_('The last volume ID of the previous page'), - ) - parser.add_argument( - '--limit', - type=int, - action=parseractions.NonNegativeAction, - metavar='', - help=_('Maximum number of volumes to display'), - ) + pagination.add_marker_pagination_option_to_parser(parser) return parser def take_action(self, parsed_args): diff --git a/openstackclient/volume/v2/volume_backup.py b/openstackclient/volume/v2/volume_backup.py index 6cacc7fa59..72e8871565 100644 --- a/openstackclient/volume/v2/volume_backup.py +++ b/openstackclient/volume/v2/volume_backup.py @@ -26,9 +26,9 @@ from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils +from openstackclient.common import pagination from openstackclient.i18n import _ - LOG = logging.getLogger(__name__) @@ -272,18 +272,7 @@ class ListVolumeBackup(command.Lister): "Filters results by the volume which they backup (name or ID)" ), ) - parser.add_argument( - '--marker', - metavar='', - help=_('The last backup of the previous page (name or ID)'), - ) - parser.add_argument( - '--limit', - type=int, - action=parseractions.NonNegativeAction, - metavar='', - help=_('Maximum number of backups to display'), - ) + pagination.add_marker_pagination_option_to_parser(parser) parser.add_argument( '--all-projects', action='store_true', diff --git a/openstackclient/volume/v2/volume_snapshot.py b/openstackclient/volume/v2/volume_snapshot.py index 376c2b5e13..0ca87144bc 100644 --- a/openstackclient/volume/v2/volume_snapshot.py +++ b/openstackclient/volume/v2/volume_snapshot.py @@ -25,6 +25,7 @@ from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils +from openstackclient.common import pagination from openstackclient.i18n import _ from openstackclient.identity import common as identity_common @@ -228,18 +229,6 @@ class ListVolumeSnapshot(command.Lister): default=False, help=_('List additional fields in output'), ) - parser.add_argument( - '--marker', - metavar='', - help=_('The last snapshot ID of the previous page'), - ) - parser.add_argument( - '--limit', - type=int, - action=parseractions.NonNegativeAction, - metavar='', - help=_('Maximum number of snapshots to display'), - ) parser.add_argument( '--name', metavar='', @@ -268,6 +257,7 @@ class ListVolumeSnapshot(command.Lister): default=None, help=_('Filters results by a volume (name or ID).'), ) + pagination.add_marker_pagination_option_to_parser(parser) return parser def take_action(self, parsed_args): diff --git a/openstackclient/volume/v3/volume_attachment.py b/openstackclient/volume/v3/volume_attachment.py index 652fdf63c8..8adbac46a5 100644 --- a/openstackclient/volume/v3/volume_attachment.py +++ b/openstackclient/volume/v3/volume_attachment.py @@ -18,6 +18,7 @@ from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils +from openstackclient.common import pagination from openstackclient.i18n import _ from openstackclient.identity import common as identity_common @@ -410,20 +411,7 @@ class ListVolumeAttachment(command.Lister): metavar='', help=_('Filters results by a status. ') + _FILTER_DEPRECATED, ) - parser.add_argument( - '--marker', - metavar='', - help=_( - 'Begin returning volume attachments that appear later in ' - 'volume attachment list than that represented by this ID.' - ), - ) - parser.add_argument( - '--limit', - type=int, - metavar='', - help=_('Maximum number of volume attachments to return.'), - ) + pagination.add_marker_pagination_option_to_parser(parser) # TODO(stephenfin): Add once we have an equivalent command for # 'cinder list-filters' # parser.add_argument( diff --git a/openstackclient/volume/v3/volume_message.py b/openstackclient/volume/v3/volume_message.py index b76ebe326b..071a10d456 100644 --- a/openstackclient/volume/v3/volume_message.py +++ b/openstackclient/volume/v3/volume_message.py @@ -21,6 +21,7 @@ from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils +from openstackclient.common import pagination from openstackclient.i18n import _ from openstackclient.identity import common as identity_common @@ -78,19 +79,7 @@ class ListMessages(command.Lister): help=_('Filter results by project (name or ID) (admin only)'), ) identity_common.add_project_domain_option_to_parser(parser) - parser.add_argument( - '--marker', - metavar='', - help=_('The last message ID of the previous page'), - default=None, - ) - parser.add_argument( - '--limit', - type=int, - metavar='', - help=_('Maximum number of messages to display'), - default=None, - ) + pagination.add_marker_pagination_option_to_parser(parser) return parser