Skip to content

Commit

Permalink
Add utility to simplify pagination
Browse files Browse the repository at this point in the history
  • Loading branch information
cjgajard committed May 22, 2024
1 parent 801c565 commit 99eb75a
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 37 deletions.
60 changes: 23 additions & 37 deletions pagerdutyplugin/data_source_pagerduty_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,15 @@ import (
"context"
"fmt"
"log"
"time"

"github.com/PagerDuty/go-pagerduty"
"github.com/PagerDuty/terraform-provider-pagerduty/util"
"github.com/PagerDuty/terraform-provider-pagerduty/util/apiutil"
"github.com/hashicorp/terraform-plugin-framework/attr"
"github.com/hashicorp/terraform-plugin-framework/datasource"
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
"github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry"
)

type dataSourceService struct{ client *pagerduty.Client }
Expand Down Expand Up @@ -64,43 +62,31 @@ func (d *dataSourceService) Read(ctx context.Context, req datasource.ReadRequest
}

var found *pagerduty.Service
var offset uint = 0
more := true

for more {
err := retry.RetryContext(ctx, 2*time.Minute, func() *retry.RetryError {
resp, err := d.client.ListServicesWithContext(ctx, pagerduty.ListServiceOptions{
Query: searchName.ValueString(),
Limit: 10,
Offset: offset,
})
if err != nil {
if util.IsBadRequestError(err) {
return retry.NonRetryableError(err)
}
return retry.RetryableError(err)
}

more = resp.More
offset += uint(len(resp.Services))

for _, service := range resp.Services {
if service.Name == searchName.ValueString() {
found = &service
more = false
break
}
}

return nil
err := apiutil.All(ctx, func(offset int) (bool, error) {
resp, err := d.client.ListServicesWithContext(ctx, pagerduty.ListServiceOptions{
Query: searchName.ValueString(),
Limit: apiutil.Limit,
Offset: uint(offset),
})
if err != nil {
resp.Diagnostics.AddError(
fmt.Sprintf("Error searching Service %s", searchName),
err.Error(),
)
return
return false, err
}

for _, service := range resp.Services {
if service.Name == searchName.ValueString() {
found = &service
return false, nil
}
}

return resp.More, nil
})
if err != nil {
resp.Diagnostics.AddError(
fmt.Sprintf("Error searching Service %s", searchName),
err.Error(),
)
return
}

if found == nil {
Expand Down
48 changes: 48 additions & 0 deletions util/apiutil/search.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package apiutil

import (
"context"
"time"

"github.com/PagerDuty/terraform-provider-pagerduty/util"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry"
)

// AllFunc is a signature to use with function `All`, it receives the current
// number of items already listed, it returns a boolean signaling whether the
// system should keep requesting more items, and an error if any occured.
type AllFunc = func(offset int) (bool, error)

// Limit is the maximum amount of items a single request to PagerDuty's API
// should response
const Limit = 100

// All provides a boilerplate to request all pages from a list of a resource
// from PagerDuty's API
func All(ctx context.Context, requestFn AllFunc) error {
offset := 0
keepSearching := true

for keepSearching {
err := retry.RetryContext(ctx, 2*time.Minute, func() *retry.RetryError {
more, err := requestFn(offset)

if err != nil {
if util.IsBadRequestError(err) {
return retry.NonRetryableError(err)
}
return retry.RetryableError(err)
}

offset += Limit
keepSearching = more
return nil
})

if err != nil {
return err
}
}

return nil
}

0 comments on commit 99eb75a

Please sign in to comment.