open-nomad/vendor/github.com/linode/linodego/pagination.go
Seth Hoenig 435c0d9fc8 deps: Switch to Go modules for dependency management
This PR switches the Nomad repository from using govendor to Go modules
for managing dependencies. Aspects of the Nomad workflow remain pretty
much the same. The usual Makefile targets should continue to work as
they always did. The API submodule simply defers to the parent Nomad
version on the repository, keeping the semantics of API versioning that
currently exists.
2020-06-02 14:30:36 -05:00

431 lines
15 KiB
Go

package linodego
/**
* Pagination and Filtering types and helpers
*/
import (
"context"
"fmt"
"log"
"strconv"
"gopkg.in/resty.v1"
)
// PageOptions are the pagination parameters for List endpoints
type PageOptions struct {
Page int `url:"page,omitempty" json:"page"`
Pages int `url:"pages,omitempty" json:"pages"`
Results int `url:"results,omitempty" json:"results"`
}
// ListOptions are the pagination and filtering (TODO) parameters for endpoints
type ListOptions struct {
*PageOptions
Filter string
}
// NewListOptions simplified construction of ListOptions using only
// the two writable properties, Page and Filter
func NewListOptions(Page int, Filter string) *ListOptions {
return &ListOptions{PageOptions: &PageOptions{Page: Page}, Filter: Filter}
}
// listHelper abstracts fetching and pagination for GET endpoints that
// do not require any Ids (top level endpoints).
// When opts (or opts.Page) is nil, all pages will be fetched and
// returned in a single (endpoint-specific)PagedResponse
// opts.results and opts.pages will be updated from the API response
func (c *Client) listHelper(ctx context.Context, i interface{}, opts *ListOptions) error {
req := c.R(ctx)
if opts != nil && opts.PageOptions != nil && opts.Page > 0 {
req.SetQueryParam("page", strconv.Itoa(opts.Page))
}
var (
err error
pages int
results int
r *resty.Response
)
if opts != nil && len(opts.Filter) > 0 {
req.SetHeader("X-Filter", opts.Filter)
}
switch v := i.(type) {
case *LinodeKernelsPagedResponse:
if r, err = coupleAPIErrors(req.SetResult(LinodeKernelsPagedResponse{}).Get(v.endpoint(c))); err == nil {
pages = r.Result().(*LinodeKernelsPagedResponse).Pages
results = r.Result().(*LinodeKernelsPagedResponse).Results
v.appendData(r.Result().(*LinodeKernelsPagedResponse))
}
case *LinodeTypesPagedResponse:
if r, err = coupleAPIErrors(req.SetResult(LinodeTypesPagedResponse{}).Get(v.endpoint(c))); err == nil {
pages = r.Result().(*LinodeTypesPagedResponse).Pages
results = r.Result().(*LinodeTypesPagedResponse).Results
v.appendData(r.Result().(*LinodeTypesPagedResponse))
}
case *ImagesPagedResponse:
if r, err = coupleAPIErrors(req.SetResult(ImagesPagedResponse{}).Get(v.endpoint(c))); err == nil {
pages = r.Result().(*ImagesPagedResponse).Pages
results = r.Result().(*ImagesPagedResponse).Results
v.appendData(r.Result().(*ImagesPagedResponse))
}
case *StackscriptsPagedResponse:
if r, err = coupleAPIErrors(req.SetResult(StackscriptsPagedResponse{}).Get(v.endpoint(c))); err == nil {
pages = r.Result().(*StackscriptsPagedResponse).Pages
results = r.Result().(*StackscriptsPagedResponse).Results
v.appendData(r.Result().(*StackscriptsPagedResponse))
}
case *InstancesPagedResponse:
if r, err = coupleAPIErrors(req.SetResult(InstancesPagedResponse{}).Get(v.endpoint(c))); err == nil {
pages = r.Result().(*InstancesPagedResponse).Pages
results = r.Result().(*InstancesPagedResponse).Results
v.appendData(r.Result().(*InstancesPagedResponse))
}
case *RegionsPagedResponse:
if r, err = coupleAPIErrors(req.SetResult(RegionsPagedResponse{}).Get(v.endpoint(c))); err == nil {
pages = r.Result().(*RegionsPagedResponse).Pages
results = r.Result().(*RegionsPagedResponse).Results
v.appendData(r.Result().(*RegionsPagedResponse))
}
case *VolumesPagedResponse:
if r, err = coupleAPIErrors(req.SetResult(VolumesPagedResponse{}).Get(v.endpoint(c))); err == nil {
pages = r.Result().(*VolumesPagedResponse).Pages
results = r.Result().(*VolumesPagedResponse).Results
v.appendData(r.Result().(*VolumesPagedResponse))
}
case *DomainsPagedResponse:
if r, err = coupleAPIErrors(req.SetResult(DomainsPagedResponse{}).Get(v.endpoint(c))); err == nil {
response, ok := r.Result().(*DomainsPagedResponse)
if !ok {
return fmt.Errorf("Response is not a *DomainsPagedResponse")
}
pages = response.Pages
results = response.Results
v.appendData(response)
}
case *EventsPagedResponse:
if r, err = coupleAPIErrors(req.SetResult(EventsPagedResponse{}).Get(v.endpoint(c))); err == nil {
pages = r.Result().(*EventsPagedResponse).Pages
results = r.Result().(*EventsPagedResponse).Results
v.appendData(r.Result().(*EventsPagedResponse))
}
case *LongviewSubscriptionsPagedResponse:
if r, err = coupleAPIErrors(req.SetResult(LongviewSubscriptionsPagedResponse{}).Get(v.endpoint(c))); err == nil {
pages = r.Result().(*LongviewSubscriptionsPagedResponse).Pages
results = r.Result().(*LongviewSubscriptionsPagedResponse).Results
v.appendData(r.Result().(*LongviewSubscriptionsPagedResponse))
}
case *LongviewClientsPagedResponse:
if r, err = coupleAPIErrors(req.SetResult(LongviewClientsPagedResponse{}).Get(v.endpoint(c))); err == nil {
pages = r.Result().(*LongviewClientsPagedResponse).Pages
results = r.Result().(*LongviewClientsPagedResponse).Results
v.appendData(r.Result().(*LongviewClientsPagedResponse))
}
case *IPAddressesPagedResponse:
if r, err = coupleAPIErrors(req.SetResult(IPAddressesPagedResponse{}).Get(v.endpoint(c))); err == nil {
pages = r.Result().(*IPAddressesPagedResponse).Pages
results = r.Result().(*IPAddressesPagedResponse).Results
v.appendData(r.Result().(*IPAddressesPagedResponse))
}
case *IPv6PoolsPagedResponse:
if r, err = coupleAPIErrors(req.SetResult(IPv6PoolsPagedResponse{}).Get(v.endpoint(c))); err == nil {
pages = r.Result().(*IPv6PoolsPagedResponse).Pages
results = r.Result().(*IPv6PoolsPagedResponse).Results
v.appendData(r.Result().(*IPv6PoolsPagedResponse))
}
case *IPv6RangesPagedResponse:
if r, err = coupleAPIErrors(req.SetResult(IPv6RangesPagedResponse{}).Get(v.endpoint(c))); err == nil {
pages = r.Result().(*IPv6RangesPagedResponse).Pages
results = r.Result().(*IPv6RangesPagedResponse).Results
v.appendData(r.Result().(*IPv6RangesPagedResponse))
// @TODO consolidate this type with IPv6PoolsPagedResponse?
}
case *SSHKeysPagedResponse:
if r, err = coupleAPIErrors(req.SetResult(SSHKeysPagedResponse{}).Get(v.endpoint(c))); err == nil {
response, ok := r.Result().(*SSHKeysPagedResponse)
if !ok {
return fmt.Errorf("Response is not a *SSHKeysPagedResponse")
}
pages = response.Pages
results = response.Results
v.appendData(response)
}
case *TicketsPagedResponse:
if r, err = coupleAPIErrors(req.SetResult(TicketsPagedResponse{}).Get(v.endpoint(c))); err == nil {
pages = r.Result().(*TicketsPagedResponse).Pages
results = r.Result().(*TicketsPagedResponse).Results
v.appendData(r.Result().(*TicketsPagedResponse))
}
case *InvoicesPagedResponse:
if r, err = coupleAPIErrors(req.SetResult(InvoicesPagedResponse{}).Get(v.endpoint(c))); err == nil {
pages = r.Result().(*InvoicesPagedResponse).Pages
results = r.Result().(*InvoicesPagedResponse).Results
v.appendData(r.Result().(*InvoicesPagedResponse))
}
case *NotificationsPagedResponse:
if r, err = coupleAPIErrors(req.SetResult(NotificationsPagedResponse{}).Get(v.endpoint(c))); err == nil {
pages = r.Result().(*NotificationsPagedResponse).Pages
results = r.Result().(*NotificationsPagedResponse).Results
v.appendData(r.Result().(*NotificationsPagedResponse))
}
case *NodeBalancersPagedResponse:
if r, err = coupleAPIErrors(req.SetResult(NodeBalancersPagedResponse{}).Get(v.endpoint(c))); err == nil {
pages = r.Result().(*NodeBalancersPagedResponse).Pages
results = r.Result().(*NodeBalancersPagedResponse).Results
v.appendData(r.Result().(*NodeBalancersPagedResponse))
}
case *TagsPagedResponse:
if r, err = coupleAPIErrors(req.SetResult(TagsPagedResponse{}).Get(v.endpoint(c))); err == nil {
pages = r.Result().(*TagsPagedResponse).Pages
results = r.Result().(*TagsPagedResponse).Results
v.appendData(r.Result().(*TagsPagedResponse))
}
case *TokensPagedResponse:
if r, err = coupleAPIErrors(req.SetResult(TokensPagedResponse{}).Get(v.endpoint(c))); err == nil {
pages = r.Result().(*TokensPagedResponse).Pages
results = r.Result().(*TokensPagedResponse).Results
v.appendData(r.Result().(*TokensPagedResponse))
}
case *UsersPagedResponse:
if r, err = coupleAPIErrors(req.SetResult(UsersPagedResponse{}).Get(v.endpoint(c))); err == nil {
pages = r.Result().(*UsersPagedResponse).Pages
results = r.Result().(*UsersPagedResponse).Results
v.appendData(r.Result().(*UsersPagedResponse))
}
/**
case AccountOauthClientsPagedResponse:
case AccountPaymentsPagedResponse:
case ProfileAppsPagedResponse:
case ProfileWhitelistPagedResponse:
case ManagedContactsPagedResponse:
case ManagedCredentialsPagedResponse:
case ManagedIssuesPagedResponse:
case ManagedLinodeSettingsPagedResponse:
case ManagedServicesPagedResponse:
**/
default:
log.Fatalf("listHelper interface{} %+v used", i)
}
if err != nil {
return err
}
if opts == nil {
for page := 2; page <= pages; page = page + 1 {
if err := c.listHelper(ctx, i, &ListOptions{PageOptions: &PageOptions{Page: page}}); err != nil {
return err
}
}
} else {
if opts.PageOptions == nil {
opts.PageOptions = &PageOptions{}
}
if opts.Page == 0 {
for page := 2; page <= pages; page = page + 1 {
opts.Page = page
if err := c.listHelper(ctx, i, opts); err != nil {
return err
}
}
}
opts.Results = results
opts.Pages = pages
}
return nil
}
// listHelperWithID abstracts fetching and pagination for GET endpoints that
// require an Id (second level endpoints).
// When opts (or opts.Page) is nil, all pages will be fetched and
// returned in a single (endpoint-specific)PagedResponse
// opts.results and opts.pages will be updated from the API response
func (c *Client) listHelperWithID(ctx context.Context, i interface{}, idRaw interface{}, opts *ListOptions) error {
req := c.R(ctx)
if opts != nil && opts.Page > 0 {
req.SetQueryParam("page", strconv.Itoa(opts.Page))
}
var (
err error
pages int
results int
r *resty.Response
)
id, _ := idRaw.(int)
if opts != nil && len(opts.Filter) > 0 {
req.SetHeader("X-Filter", opts.Filter)
}
switch v := i.(type) {
case *InvoiceItemsPagedResponse:
if r, err = coupleAPIErrors(req.SetResult(InvoiceItemsPagedResponse{}).Get(v.endpointWithID(c, id))); err == nil {
pages = r.Result().(*InvoiceItemsPagedResponse).Pages
results = r.Result().(*InvoiceItemsPagedResponse).Results
v.appendData(r.Result().(*InvoiceItemsPagedResponse))
}
case *DomainRecordsPagedResponse:
if r, err = coupleAPIErrors(req.SetResult(DomainRecordsPagedResponse{}).Get(v.endpointWithID(c, id))); err == nil {
response, ok := r.Result().(*DomainRecordsPagedResponse)
if !ok {
return fmt.Errorf("Response is not a *DomainRecordsPagedResponse")
}
pages = response.Pages
results = response.Results
v.appendData(response)
}
case *InstanceConfigsPagedResponse:
if r, err = coupleAPIErrors(req.SetResult(InstanceConfigsPagedResponse{}).Get(v.endpointWithID(c, id))); err == nil {
pages = r.Result().(*InstanceConfigsPagedResponse).Pages
results = r.Result().(*InstanceConfigsPagedResponse).Results
v.appendData(r.Result().(*InstanceConfigsPagedResponse))
}
case *InstanceDisksPagedResponse:
if r, err = coupleAPIErrors(req.SetResult(InstanceDisksPagedResponse{}).Get(v.endpointWithID(c, id))); err == nil {
pages = r.Result().(*InstanceDisksPagedResponse).Pages
results = r.Result().(*InstanceDisksPagedResponse).Results
v.appendData(r.Result().(*InstanceDisksPagedResponse))
}
case *NodeBalancerConfigsPagedResponse:
if r, err = coupleAPIErrors(req.SetResult(NodeBalancerConfigsPagedResponse{}).Get(v.endpointWithID(c, id))); err == nil {
pages = r.Result().(*NodeBalancerConfigsPagedResponse).Pages
results = r.Result().(*NodeBalancerConfigsPagedResponse).Results
v.appendData(r.Result().(*NodeBalancerConfigsPagedResponse))
}
case *InstanceVolumesPagedResponse:
if r, err = coupleAPIErrors(req.SetResult(InstanceVolumesPagedResponse{}).Get(v.endpointWithID(c, id))); err == nil {
pages = r.Result().(*InstanceVolumesPagedResponse).Pages
results = r.Result().(*InstanceVolumesPagedResponse).Results
v.appendData(r.Result().(*InstanceVolumesPagedResponse))
}
case *TaggedObjectsPagedResponse:
idStr := idRaw.(string)
if r, err = coupleAPIErrors(req.SetResult(TaggedObjectsPagedResponse{}).Get(v.endpointWithID(c, idStr))); err == nil {
pages = r.Result().(*TaggedObjectsPagedResponse).Pages
results = r.Result().(*TaggedObjectsPagedResponse).Results
v.appendData(r.Result().(*TaggedObjectsPagedResponse))
}
/**
case TicketAttachmentsPagedResponse:
if r, err = req.SetResult(v).Get(v.endpoint(c)); r.Error() != nil {
return NewError(r)
} else if err == nil {
pages = r.Result().(*TicketAttachmentsPagedResponse).Pages
results = r.Result().(*TicketAttachmentsPagedResponse).Results
v.appendData(r.Result().(*TicketAttachmentsPagedResponse))
}
case TicketRepliesPagedResponse:
if r, err = req.SetResult(v).Get(v.endpoint(c)); r.Error() != nil {
return NewError(r)
} else if err == nil {
pages = r.Result().(*TicketRepliesPagedResponse).Pages
results = r.Result().(*TicketRepliesPagedResponse).Results
v.appendData(r.Result().(*TicketRepliesPagedResponse))
}
**/
default:
log.Fatalf("Unknown listHelperWithID interface{} %T used", i)
}
if err != nil {
return err
}
if opts == nil {
for page := 2; page <= pages; page = page + 1 {
if err := c.listHelperWithID(ctx, i, id, &ListOptions{PageOptions: &PageOptions{Page: page}}); err != nil {
return err
}
}
} else {
if opts.PageOptions == nil {
opts.PageOptions = &PageOptions{}
}
if opts.Page == 0 {
for page := 2; page <= pages; page = page + 1 {
opts.Page = page
if err := c.listHelperWithID(ctx, i, id, opts); err != nil {
return err
}
}
}
opts.Results = results
opts.Pages = pages
}
return nil
}
// listHelperWithTwoIDs abstracts fetching and pagination for GET endpoints that
// require twos IDs (third level endpoints).
// When opts (or opts.Page) is nil, all pages will be fetched and
// returned in a single (endpoint-specific)PagedResponse
// opts.results and opts.pages will be updated from the API response
func (c *Client) listHelperWithTwoIDs(ctx context.Context, i interface{}, firstID, secondID int, opts *ListOptions) error {
req := c.R(ctx)
if opts != nil && opts.Page > 0 {
req.SetQueryParam("page", strconv.Itoa(opts.Page))
}
var (
err error
pages int
results int
r *resty.Response
)
if opts != nil && len(opts.Filter) > 0 {
req.SetHeader("X-Filter", opts.Filter)
}
switch v := i.(type) {
case *NodeBalancerNodesPagedResponse:
if r, err = coupleAPIErrors(req.SetResult(NodeBalancerNodesPagedResponse{}).Get(v.endpointWithTwoIDs(c, firstID, secondID))); err == nil {
pages = r.Result().(*NodeBalancerNodesPagedResponse).Pages
results = r.Result().(*NodeBalancerNodesPagedResponse).Results
v.appendData(r.Result().(*NodeBalancerNodesPagedResponse))
}
default:
log.Fatalf("Unknown listHelperWithTwoIDs interface{} %T used", i)
}
if err != nil {
return err
}
if opts == nil {
for page := 2; page <= pages; page = page + 1 {
if err := c.listHelper(ctx, i, &ListOptions{PageOptions: &PageOptions{Page: page}}); err != nil {
return err
}
}
} else {
if opts.PageOptions == nil {
opts.PageOptions = &PageOptions{}
}
if opts.Page == 0 {
for page := 2; page <= pages; page = page + 1 {
opts.Page = page
if err := c.listHelperWithTwoIDs(ctx, i, firstID, secondID, opts); err != nil {
return err
}
}
}
opts.Results = results
opts.Pages = pages
}
return nil
}