Skip to content

Commit 97c0a32

Browse files
committed
[nova] fix pagination of hypervisors.List()
This is a mildly backwards-incompatible change, but since most people only use this API on the level of pagination.Pager, it ought not be a big deal in practice. Closes gophercloud#3222.
1 parent b50fc2b commit 97c0a32

File tree

4 files changed

+49
-12
lines changed

4 files changed

+49
-12
lines changed

openstack/compute/v2/hypervisors/requests.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ func List(client *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pa
5353
}
5454

5555
return pagination.NewPager(client, url, func(r pagination.PageResult) pagination.Page {
56-
return HypervisorPage{pagination.SinglePageBase(r)}
56+
return HypervisorPage{pagination.LinkedPageBase{PageResult: r}}
5757
})
5858
}
5959

openstack/compute/v2/hypervisors/results.go

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ func (r *Hypervisor) UnmarshalJSON(b []byte) error {
240240
// HypervisorPage represents a single page of all Hypervisors from a List
241241
// request.
242242
type HypervisorPage struct {
243-
pagination.SinglePageBase
243+
pagination.LinkedPageBase
244244
}
245245

246246
// IsEmpty determines whether or not a HypervisorPage is empty.
@@ -253,6 +253,19 @@ func (page HypervisorPage) IsEmpty() (bool, error) {
253253
return len(va) == 0, err
254254
}
255255

256+
// NextPageURL uses the response's embedded link reference to navigate to the
257+
// next page of results.
258+
func (page HypervisorPage) NextPageURL() (string, error) {
259+
var s struct {
260+
Links []gophercloud.Link `json:"hypervisors_links"`
261+
}
262+
err := page.ExtractInto(&s)
263+
if err != nil {
264+
return "", err
265+
}
266+
return gophercloud.ExtractNextURL(s.Links)
267+
}
268+
256269
// ExtractHypervisors interprets a page of results as a slice of Hypervisors.
257270
func ExtractHypervisors(p pagination.Page) ([]Hypervisor, error) {
258271
var h struct {

openstack/compute/v2/hypervisors/testing/fixtures_test.go

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"testing"
77

88
"github.com/gophercloud/gophercloud/v2/openstack/compute/v2/hypervisors"
9+
"github.com/gophercloud/gophercloud/v2/testhelper"
910
th "github.com/gophercloud/gophercloud/v2/testhelper"
1011
"github.com/gophercloud/gophercloud/v2/testhelper/client"
1112
)
@@ -85,8 +86,8 @@ const HypervisorListBodyPre253 = `
8586
]
8687
}`
8788

88-
// HypervisorListBody represents a raw hypervisor list result with Pike+ release.
89-
const HypervisorListBody = `
89+
// HypervisorListBodyPage1 represents page 1 of a raw hypervisor list result with Pike+ release.
90+
const HypervisorListBodyPage1 = `
9091
{
9192
"hypervisors": [
9293
{
@@ -127,7 +128,20 @@ const HypervisorListBody = `
127128
},
128129
"vcpus": 1,
129130
"vcpus_used": 0
130-
},
131+
}
132+
],
133+
"hypervisors_links": [
134+
{
135+
"href": "%s/os-hypervisors/detail?marker=c48f6247-abe4-4a24-824e-ea39e108874f",
136+
"rel": "next"
137+
}
138+
]
139+
}`
140+
141+
// HypervisorListBodyPage2 represents page 2 of a raw hypervisor list result with Pike+ release.
142+
const HypervisorListBodyPage2 = `
143+
{
144+
"hypervisors": [
131145
{
132146
"cpu_info": "{\"arch\": \"x86_64\", \"model\": \"Nehalem\", \"vendor\": \"Intel\", \"features\": [\"pge\", \"clflush\"], \"topology\": {\"cores\": 1, \"threads\": 1, \"sockets\": 4}}",
133147
"current_workload": 0,
@@ -157,6 +171,9 @@ const HypervisorListBody = `
157171
]
158172
}`
159173

174+
// HypervisorListBodyEmpty represents an empty raw hypervisor list result, marking the end of pagination.
175+
const HypervisorListBodyEmpty = `{ "hypervisors": [] }`
176+
160177
// HypervisorListWithParametersBody represents a raw hypervisor list result with Pike+ release.
161178
const HypervisorListWithParametersBody = `
162179
{
@@ -624,8 +641,16 @@ func HandleHypervisorListSuccessfully(t *testing.T) {
624641
th.TestMethod(t, r, "GET")
625642
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
626643

627-
w.Header().Add("Content-Type", "application/json")
628-
fmt.Fprint(w, HypervisorListBody)
644+
switch r.URL.Query().Get("marker") {
645+
case "":
646+
w.Header().Add("Content-Type", "application/json")
647+
fmt.Fprintf(w, HypervisorListBodyPage1, testhelper.Server.URL)
648+
case "c48f6247-abe4-4a24-824e-ea39e108874f":
649+
w.Header().Add("Content-Type", "application/json")
650+
fmt.Fprint(w, HypervisorListBodyPage2)
651+
default:
652+
http.Error(w, "unexpected marker value", http.StatusInternalServerError)
653+
}
629654
})
630655
}
631656

openstack/compute/v2/hypervisors/testing/requests_test.go

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -69,19 +69,18 @@ func TestListHypervisors(t *testing.T) {
6969
return false, err
7070
}
7171

72-
if len(actual) != 2 {
73-
t.Fatalf("Expected 2 hypervisors, got %d", len(actual))
72+
if len(actual) != 1 {
73+
t.Fatalf("Expected 1 hypervisors on page %d, got %d", pages, len(actual))
7474
}
7575
th.CheckDeepEquals(t, HypervisorFake, actual[0])
76-
th.CheckDeepEquals(t, HypervisorFake, actual[1])
7776

7877
return true, nil
7978
})
8079

8180
th.AssertNoErr(t, err)
8281

83-
if pages != 1 {
84-
t.Errorf("Expected 1 page, saw %d", pages)
82+
if pages != 2 {
83+
t.Errorf("Expected 2 pages, saw %d", pages)
8584
}
8685
}
8786

0 commit comments

Comments
 (0)