Feature/filestorage sharenetworks list (#124)
* sfs: Add list for share networks
* sfs: Add acceptance tests for share network List
* sfs: Add more fields for filtering List requests
* sfs: Add pagination for share network List
* sfs: Change pagination to use MarkerPage
* sfs: Add acceptance tests for share network pagination
diff --git a/openstack/sharedfilesystems/v2/sharenetworks/results.go b/openstack/sharedfilesystems/v2/sharenetworks/results.go
index 946ddd8..8086508 100644
--- a/openstack/sharedfilesystems/v2/sharenetworks/results.go
+++ b/openstack/sharedfilesystems/v2/sharenetworks/results.go
@@ -1,6 +1,12 @@
package sharenetworks
-import "github.com/gophercloud/gophercloud"
+import (
+ "net/url"
+ "strconv"
+
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
+)
// ShareNetwork contains all the information associated with an OpenStack
// ShareNetwork.
@@ -28,15 +34,91 @@
// The Share Network description
Description string `json:"description"`
// The date and time stamp when the Share Network was created
- CreatedAt string `json:"created_at"`
+ CreatedAt gophercloud.JSONRFC3339MilliNoZ `json:"created_at"`
// The date and time stamp when the Share Network was updated
- UpdatedAt string `json:"updated_at"`
+ UpdatedAt gophercloud.JSONRFC3339MilliNoZ `json:"updated_at"`
}
type commonResult struct {
gophercloud.Result
}
+// ShareNetworkPage is a pagination.pager that is returned from a call to the List function.
+type ShareNetworkPage struct {
+ pagination.MarkerPageBase
+}
+
+// NextPageURL generates the URL for the page of results after this one.
+func (r ShareNetworkPage) NextPageURL() (string, error) {
+ currentURL := r.URL
+ mark, err := r.Owner.LastMarker()
+ if err != nil {
+ return "", err
+ }
+
+ q := currentURL.Query()
+ q.Set("offset", mark)
+ currentURL.RawQuery = q.Encode()
+ return currentURL.String(), nil
+}
+
+// LastMarker returns the last offset in a ListResult.
+func (r ShareNetworkPage) LastMarker() (string, error) {
+ maxInt := strconv.Itoa(int(^uint(0) >> 1))
+ shareNetworks, err := ExtractShareNetworks(r)
+ if err != nil {
+ return maxInt, err
+ }
+ if len(shareNetworks) == 0 {
+ return maxInt, nil
+ }
+
+ u, err := url.Parse(r.URL.String())
+ if err != nil {
+ return maxInt, err
+ }
+ queryParams := u.Query()
+ offset := queryParams.Get("offset")
+ limit := queryParams.Get("limit")
+
+ // Limit is not present, only one page required
+ if limit == "" {
+ return maxInt, nil
+ }
+
+ iOffset := 0
+ if offset != "" {
+ iOffset, err = strconv.Atoi(offset)
+ if err != nil {
+ return maxInt, err
+ }
+ }
+ iLimit, err := strconv.Atoi(limit)
+ if err != nil {
+ return maxInt, err
+ }
+ iOffset = iOffset + iLimit
+ offset = strconv.Itoa(iOffset)
+
+ return offset, nil
+}
+
+// IsEmpty satisifies the IsEmpty method of the Page interface
+func (r ShareNetworkPage) IsEmpty() (bool, error) {
+ shareNetworks, err := ExtractShareNetworks(r)
+ return len(shareNetworks) == 0, err
+}
+
+// ExtractShareNetworks extracts and returns ShareNetworks. It is used while
+// iterating over a sharenetworks.List call.
+func ExtractShareNetworks(r pagination.Page) ([]ShareNetwork, error) {
+ var s struct {
+ ShareNetworks []ShareNetwork `json:"share_networks"`
+ }
+ err := (r.(ShareNetworkPage)).ExtractInto(&s)
+ return s.ShareNetworks, err
+}
+
// Extract will get the ShareNetwork object out of the commonResult object.
func (r commonResult) Extract() (*ShareNetwork, error) {
var s struct {