Use a Concat method to aggregate Collection pages.
diff --git a/collections.go b/collections.go
index 82e6c7a..0a800a0 100644
--- a/collections.go
+++ b/collections.go
@@ -21,6 +21,10 @@
// Pager returns one of the concrete Pager implementations from this package, or a custom one.
// The style of Pager returned determines how the collection is paged.
Pager() Pager
+
+ // Concat the contents of another collection on to the end of this one.
+ // Return a new collection that contains elements from both.
+ Concat(Collection) Collection
}
// EachPage iterates through a Collection one page at a time.
@@ -50,7 +54,19 @@
// AllPages consolidates all pages reachable from a provided starting point into a single mega-Page.
// Use this only when you know that the full set will always fit within memory.
func AllPages(first Collection) (Collection, error) {
- return first, nil
+ megaPage := first
+ isFirst := true
+
+ err := EachPage(first, func(page Collection) bool {
+ if isFirst {
+ isFirst = false
+ } else {
+ megaPage = megaPage.Concat(page)
+ }
+ return true
+ })
+
+ return megaPage, err
}
// Pager describes a specific paging idiom for a Page resource.
diff --git a/collections_test.go b/collections_test.go
index 4c8674d..4b0fdc5 100644
--- a/collections_test.go
+++ b/collections_test.go
@@ -20,6 +20,10 @@
return SinglePager{}
}
+func (c SinglePageCollection) Concat(other Collection) Collection {
+ panic("Concat should never be called on a single-paged collection.")
+}
+
func AsSingleInts(c Collection) []int {
return c.(SinglePageCollection).results
}
@@ -68,6 +72,17 @@
results []int
}
+func (c LinkedCollection) Pager() Pager {
+ return NewLinkPager(c)
+}
+
+func (c LinkedCollection) Concat(other Collection) Collection {
+ return LinkedCollection{
+ service: c.service,
+ results: append(c.results, AsLinkedInts(other)...),
+ }
+}
+
func (c LinkedCollection) Links() PaginationLinks {
return c.PaginationLinks
}
@@ -77,7 +92,6 @@
}
func (c LinkedCollection) Interpret(response interface{}) (LinkCollection, error) {
- fmt.Printf("Interpreting result: %#v\n", response)
casted, ok := response.([]interface{})
if ok {
asInts := make([]int, len(casted))
@@ -102,20 +116,11 @@
service: c.service,
results: asInts,
}
- if nextURL != nil {
- fmt.Printf("Returning result: %s\n", *nextURL)
- } else {
- fmt.Printf("No next link")
- }
return result, nil
}
return nil, errors.New("Wat")
}
-func (c LinkedCollection) Pager() Pager {
- return NewLinkPager(c)
-}
-
func AsLinkedInts(results Collection) []int {
return results.(LinkedCollection).results
}
@@ -196,3 +201,28 @@
t.Errorf("Expected 3 calls, but was %d", callCount)
}
}
+
+func TestAllLinked(t *testing.T) {
+ testhelper.SetupHTTP()
+ defer testhelper.TeardownHTTP()
+
+ setupLinkedResponses(t)
+ lc := createLinked()
+
+ all, err := AllPages(lc)
+ if err != nil {
+ t.Fatalf("Unexpected error collection all linked pages: %v", err)
+ }
+
+ actual := AsLinkedInts(all)
+ expected := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
+
+ if !reflect.DeepEqual(expected, actual) {
+ t.Errorf("Expected %v, but was %v", expected, actual)
+ }
+
+ original := []int{1, 2, 3}
+ if !reflect.DeepEqual(AsLinkedInts(lc), original) {
+ t.Errorf("AllPages modified the original page, and now it contains: %v", lc)
+ }
+}
diff --git a/openstack/identity/v3/endpoints/results.go b/openstack/identity/v3/endpoints/results.go
index d3068df..e972404 100644
--- a/openstack/identity/v3/endpoints/results.go
+++ b/openstack/identity/v3/endpoints/results.go
@@ -30,6 +30,14 @@
return gophercloud.NewLinkPager(list)
}
+// Concat adds the contents of another Collection to this one.
+func (list EndpointList) Concat(other gophercloud.Collection) gophercloud.Collection {
+ return EndpointList{
+ client: list.client,
+ Endpoints: append(list.Endpoints, AsEndpoints(other)...),
+ }
+}
+
// Service returns the ServiceClient used to acquire this list.
func (list EndpointList) Service() *gophercloud.ServiceClient {
return list.client
diff --git a/openstack/identity/v3/services/results.go b/openstack/identity/v3/services/results.go
index c6ce1b9..88510b4 100644
--- a/openstack/identity/v3/services/results.go
+++ b/openstack/identity/v3/services/results.go
@@ -19,8 +19,8 @@
type ServiceList struct {
gophercloud.PaginationLinks `json:"links"`
- client *gophercloud.ServiceClient
- Page []Service `json:"services"`
+ client *gophercloud.ServiceClient
+ Services []Service `json:"services"`
}
// Pager indicates that the ServiceList is paginated by next and previous links.
@@ -28,6 +28,14 @@
return gophercloud.NewLinkPager(list)
}
+// Concat returns a new collection that's the result of appending a new collection at the end of this one.
+func (list ServiceList) Concat(other gophercloud.Collection) gophercloud.Collection {
+ return ServiceList{
+ client: list.client,
+ Services: append(list.Services, AsServices(other)...),
+ }
+}
+
// Service returns the ServiceClient used to acquire this list.
func (list ServiceList) Service() *gophercloud.ServiceClient {
return list.client
@@ -56,5 +64,5 @@
// AsServices extracts a slice of Services from a Collection acquired from List.
// It panics if the Collection does not actually contain Services.
func AsServices(results gophercloud.Collection) []Service {
- return results.(*ServiceList).Page
+ return results.(*ServiceList).Services
}