Visitar URL original
Pagination fixes by mandre · Pull Request #4063 · gophercloud/gophercloud · GitHub
Skip to content

Pagination fixes - #4063

Open
mandre wants to merge 8 commits into
gophercloud:mainfrom
shiftstack:pagination-fixes
Open

mandre wants to merge 8 commits into
gophercloud:mainfrom
shiftstack:pagination-fixes

Conversation

@mandre

@mandre mandre commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

Fix list operations that silently stop after the first page despite the API supporting pagination. Both EachPage and AllPages can return incomplete collections without reporting an error.

The first commit successfully demonstrated the all the new tests failed as expected in live environments.

Fixes #4064.

@github-actions github-actions Bot added edit:orchestration This PR updates orchestration code edit:compute This PR updates compute code edit:sharedfilesystems This PR updates sharedfilesystems code semver:patch No API change backport-v2 This PR will be backported to v2 labels Oct 26, 2026
@coveralls

coveralls commented Oct 26, 2026 •

Copy link
Copy Markdown

Coverage Status

coverage: 64.462% (+0.5%) from 63.962% — shiftstack:pagination-fixes into gophercloud:main

@mandre

mandre commented Oct 26, 2026

Copy link
Copy Markdown
Contributor Author

All new tests failed as expected.

@github-actions github-actions Bot added edit:networking This PR updates networking code edit:db This PR updates db code edit:blockstorage This PR updates blockstorage code semver:major Breaking change and removed semver:patch No API change backport-v2 This PR will be backported to v2 labels Oct 26, 2026
}

// NextPageURL returns the URL for the next page of results.
func (r VolumeAttachmentPage) NextPageURL(endpointURL string) (string, error) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here looks to be a bit tricky. Nova applies the offset to the block device list[1], including block devices which has image as its source, then only after that it filters by volumes.

So moving the offset based on the returned items might lead to wrong results. One option is to remove duplicates[2].

[1] https://github.com/openstack/nova/blob/master/nova/api/openstack/compute/volume_attachments.py#L123-L135
[2] https://github.com/gophercloud/gophercloud/actions/runs/40345176521/job/121650072750?pr=4063#step:7:4925

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately that won't help: nova exposes neither the number of underlying block-device mappings nor a next-page marker. Empty pages can hide later volumes, so deduplication or a different offset increment cannot guarantee complete results.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this API doesn't accept pagination. It might be filtering out resources with the limit property instead of really filtering.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For securityservices, both summary and detail listing treat pagination parameters as filters for admins but remove unknown filters for non-admins before applying offset and limit.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mandre mandre added the hold Do not merge label Oct 27, 2026
@mandre

mandre commented Oct 27, 2026

Copy link
Copy Markdown
Contributor Author

Considering the risk of introducing regression (seeing that we found 2 upstream bugs already), we must have e2e tests for each of the pagination fixes.

@Sharpz7

Sharpz7 commented Nov 1, 2026

Copy link
Copy Markdown
Contributor

@mandre are you planning to add the remaining acceptance tests in this PR? Happy to help with those if useful.

Add acceptance coverage for server groups, keypairs, and stacks using
small pages. Assert that `EachPage` visits multiple pages and that both
`EachPage` and `AllPages` return each fixture exactly once, exposing
first-page truncation.

Compare server group traversal with direct API requests using explicit
offsets to distinguish SDK truncation from server-side behavior. Supply
missing page-size options through test-local query builders.

Verify single-page security service listing with two created services
and no pagination parameters, including `EachPage` and `AllPages`.

Use metadata and security-group-backed stack fixtures to avoid creating
VMs, volumes, or shares. Register cleanup as resources are created.
Leave production pagination unchanged so live reproduction can precede
the fixes.
Snapshot lists return collection-specific continuation links [1], while
attachment lists accept markers [2] but return no collection links [3].
The inherited page implementations therefore stop before all results
have been retrieved.

Follow `snapshots_links` and derive the next attachment marker from the
last attachment ID. Replace the snapshot `SinglePageBase` so `AllPages`
can iterate, and define `ResourceKey` for deterministic aggregation.

Add resource-local regression tests for `EachPage`, `AllPages`, empty
responses, malformed data, query preservation, and termination. Align
the attachment fixture with the upstream response format.

[1] https://github.com/openstack/cinder/blob/3bcb543305500c8f555c92b57b4ca4328ccdd078/cinder/api/views/snapshots.py#L64-L81
[2] https://github.com/openstack/cinder/blob/3bcb543305500c8f555c92b57b4ca4328ccdd078/cinder/api/v3/attachments.py#L82-L106
[3] https://github.com/openstack/cinder/blob/3bcb543305500c8f555c92b57b4ca4328ccdd078/cinder/api/v3/views/attachments.py#L52-L57
Nova exposes continuation links for instance actions [1], keypairs [2],
and migrations [3]. Security group [5] and server group [6] lists use
`common.limited` [4]. Inheriting `SinglePageBase` prevents these
collections from advancing.

Replace single-page handling with the appropriate link or offset
protocol so `EachPage` and `AllPages` do not truncate results. Keep
server-specific security group associations single-page because their
controller does not paginate them [10]. Older microversions without
links [1][8][9] still terminate after their initial response.

Keep volume attachments single-page because Nova slices all block-device
mappings before excluding non-volume devices [7]. The returned
attachment count cannot determine the next offset. Document this
limitation and test mixed mappings, empty pages, and server-side caps.

Define `ResourceKey` for deterministic aggregation. Add resource-local
regressions for iteration, aggregation, query preservation, malformed
responses, empty results, and microversion behavior. Correct fixtures so
continuation requests stay on the local test server.

[1] https://github.com/openstack/nova/blob/0e701bfd411ec8d4c15419710c4968a582abedc7/nova/api/openstack/compute/instance_actions.py#L125-L139
[2] https://github.com/openstack/nova/blob/0e701bfd411ec8d4c15419710c4968a582abedc7/nova/api/openstack/compute/views/keypairs.py#L55-L69
[3] https://github.com/openstack/nova/blob/0e701bfd411ec8d4c15419710c4968a582abedc7/nova/api/openstack/compute/migrations.py#L173-L179
[4] https://github.com/openstack/nova/blob/0e701bfd411ec8d4c15419710c4968a582abedc7/nova/api/openstack/common.py#L215-L231
[5] https://github.com/openstack/nova/blob/0e701bfd411ec8d4c15419710c4968a582abedc7/nova/api/openstack/compute/security_groups.py#L182-L201
[6] https://github.com/openstack/nova/blob/0e701bfd411ec8d4c15419710c4968a582abedc7/nova/api/openstack/compute/server_groups.py#L195-L206
[7] https://github.com/openstack/nova/blob/0e701bfd411ec8d4c15419710c4968a582abedc7/nova/api/openstack/compute/volume_attachments.py#L113-L145
[8] https://github.com/openstack/nova/blob/0e701bfd411ec8d4c15419710c4968a582abedc7/nova/api/openstack/compute/keypairs.py#L196-L225
[9] https://github.com/openstack/nova/blob/0e701bfd411ec8d4c15419710c4968a582abedc7/nova/api/openstack/compute/migrations.py#L197-L210
[10] https://github.com/openstack/nova/blob/0e701bfd411ec8d4c15419710c4968a582abedc7/nova/api/openstack/compute/security_groups.py#L372-L398
Trove lists configuration groups through `SimplePaginatedDataView` [1],
which supplies a top-level `links` array when another page exists [2].
Inheriting `SinglePageBase` ignores this continuation and causes
`EachPage` and `AllPages` to return an incomplete collection.

Use `LinkedPageBase` and extract the next URL from the link array.
Define `ResourceKey` so aggregation selects `configurations` even when
other response fields contain arrays.

Add resource-local regression tests for iteration, aggregation,
termination, empty responses, malformed links, and query preservation.

[1] https://github.com/openstack/trove/blob/4d45feb3fe7568cc481c1d514560b6652e2d2e1a/trove/configuration/service.py#L50-L57
[2] https://github.com/openstack/trove/blob/4d45feb3fe7568cc481c1d514560b6652e2d2e1a/trove/common/pagination.py#L104-L120
Neutron emits extension continuation links in collection-specific arrays
[1], rather than the `links.next` object expected by `LinkedPageBase`.
Resource registration enables pagination for BGP [2], network IP
availability [3], QoS rules [4], segments [5], and trunks [6], including
registrations through the shared resource helper [7].

Read the corresponding link arrays in `NextPageURL` and replace
`SinglePageBase` where it prevents iteration. Define `ResourceKey` so
`AllPages` aggregates the intended resource list instead of selecting an
unrelated array from the response.

Add resource-local regression tests for `EachPage`, `AllPages`,
aggregation order, termination, empty responses, malformed links, and
query preservation.

[1] https://github.com/openstack/neutron/blob/7a3841bb4f5a47c3694767c3440f6f417a3ae15b/neutron/api/v2/base.py#L339-L345
[2] https://github.com/openstack/neutron-dynamic-routing/blob/bd960e7bfbf2ca536d1aa2ad4c8e4a8d5d8a9405/neutron_dynamic_routing/extensions/bgp.py#L76-L85
[3] https://github.com/openstack/neutron/blob/7a3841bb4f5a47c3694767c3440f6f417a3ae15b/neutron/extensions/network_ip_availability.py#L28-L43
[4] https://github.com/openstack/neutron/blob/7a3841bb4f5a47c3694767c3440f6f417a3ae15b/neutron/extensions/qos.py#L57-L76
[5] https://github.com/openstack/neutron/blob/7a3841bb4f5a47c3694767c3440f6f417a3ae15b/neutron/extensions/segment.py#L30-L43
[6] https://github.com/openstack/neutron/blob/7a3841bb4f5a47c3694767c3440f6f417a3ae15b/neutron/extensions/trunk.py#L26-L36
[7] https://github.com/openstack/neutron/blob/7a3841bb4f5a47c3694767c3440f6f417a3ae15b/neutron/api/v2/resource_helper.py#L93-L107
Heat includes a collection-level `links` array in stack list responses
[1]. Its pagination helper creates the next URL from the last stack ID
when the requested page is full [2]. Inheriting `SinglePageBase` ignores
these links and silently truncates `EachPage` and `AllPages` results.

Use `LinkedPageBase` and extract the next URL from the collection links.
Define `ResourceKey` so `AllPages` consistently aggregates `stacks`.

Add resource-local regression tests for iteration, aggregation,
termination, empty responses, malformed links, and query preservation.

[1] https://github.com/openstack/heat/blob/741d092fd101927ede252d676fd0372457ad418b/heat/api/openstack/v1/views/stacks_view.py#L66-L78
[2] https://github.com/openstack/heat/blob/741d092fd101927ede252d676fd0372457ad418b/heat/api/openstack/v1/views/views_common.py#L17-L40
Manila message lists use offset pagination [1]. Their inherited
`SinglePageBase` prevents iteration beyond the initial response.

Advance offsets by the number of returned messages while retaining
filters and page sizes, and stop when the collection is empty. Do not
follow the message view's continuation links [2]: its helper uses
markers [3][4], but the controller passes offsets, not markers, to the
message API [1][5].

Replace `SinglePageBase` so `AllPages` can iterate and define
`ResourceKey` for deterministic aggregation. Add resource-local
regression tests for iteration, aggregation, termination, empty
responses, malformed data, offset validation, and query preservation.
Update fixtures to return an empty collection after their initial page.

Keep security service lists single-page. The controller treats
pagination parameters as resource filters for admin requests [6][7].
Document the limitation and cover admin filtering and server-side caps.

[1] https://github.com/openstack/manila/blob/e969e4473db963e80c733e20cbeaf2d5740bbaa0/manila/api/v2/messages.py#L91-L122
[2] https://github.com/openstack/manila/blob/e969e4473db963e80c733e20cbeaf2d5740bbaa0/manila/api/views/messages.py#L58-L68
[3] https://github.com/openstack/manila/blob/e969e4473db963e80c733e20cbeaf2d5740bbaa0/manila/api/common.py#L387-L401
[4] https://github.com/openstack/manila/blob/e969e4473db963e80c733e20cbeaf2d5740bbaa0/manila/api/common.py#L343-L346
[5] https://github.com/openstack/manila/blob/e969e4473db963e80c733e20cbeaf2d5740bbaa0/manila/message/api.py#L75-L86
[6] https://github.com/openstack/manila/blob/e969e4473db963e80c733e20cbeaf2d5740bbaa0/manila/api/v2/security_service.py#L93-L150
[7] https://github.com/openstack/manila/blob/e969e4473db963e80c733e20cbeaf2d5740bbaa0/manila/api/common.py#L450-L462
@mandre

mandre commented Nov 2, 2026

Copy link
Copy Markdown
Contributor Author

@mandre are you planning to add the remaining acceptance tests in this PR? Happy to help with those if useful.

Yes. I planed to work on it soon. Happy to hand over to you if I don't get a chance to get back at this quicly.

@Sharpz7

Sharpz7 commented Nov 2, 2026

Copy link
Copy Markdown
Contributor

sounds good

Add shared helpers for `EachPage`, `AllPages`, and retained single-page
collections, with scoped page-size controls and continuation checks.

Add Compute, Trove, and Neutron acceptance fixtures, including QoS rule
capability checks. Strengthen Manila security-service termination checks.

Validate the unit suite, helper race tests, and acceptance compilation.
Live prerequisites, CI execution, and regression-reversion runs remain
unverified.
@mandre

mandre commented Nov 10, 2026

Copy link
Copy Markdown
Contributor Author

New tests found another pagination issue, this time in trove that I'm trying to fix with https://review.opendev.org/c/openstack/trove/+/1014860

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

edit:blockstorage This PR updates blockstorage code edit:compute This PR updates compute code edit:db This PR updates db code edit:networking This PR updates networking code edit:orchestration This PR updates orchestration code edit:sharedfilesystems This PR updates sharedfilesystems code hold Do not merge semver:major Breaking change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

List pagination silently truncates results across multiple services

4 participants