-
Notifications
You must be signed in to change notification settings - Fork 619
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1984 from RanVaknin/r53-paginators-a
R53 paginators a
- Loading branch information
Showing
3 changed files
with
268 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
{ | ||
"id": "85820b40-8582-47f8-a975-883ac9ae7fb3", | ||
"type": "feature", | ||
"description": "added paginator for listResourceRecordSets", | ||
"modules": [ | ||
"service/route53" | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
package route53 | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"github.com/aws/aws-sdk-go-v2/service/route53/types" | ||
) | ||
|
||
// ListResourceRecordSetsAPIClient is a client that implements the ListResourceRecordSets | ||
// operation | ||
type ListResourceRecordSetsAPIClient interface { | ||
ListResourceRecordSets(context.Context, *ListResourceRecordSetsInput, ...func(*Options)) (*ListResourceRecordSetsOutput, error) | ||
} | ||
|
||
var _ ListResourceRecordSetsAPIClient = (*Client)(nil) | ||
|
||
// ListResourceRecordSetsPaginatorOptions is the paginator options for ListResourceRecordSets | ||
type ListResourceRecordSetsPaginatorOptions struct { | ||
// (Optional) The maximum number of ResourceRecordSets that you want Amazon Route 53 to | ||
// return. | ||
Limit int32 | ||
|
||
// Set to true if pagination should stop if the service returns a pagination token | ||
// that matches the most recent token provided to the service. | ||
StopOnDuplicateToken bool | ||
} | ||
|
||
// ListResourceRecordSetsPaginator is a paginator for ListResourceRecordSets | ||
type ListResourceRecordSetsPaginator struct { | ||
options ListResourceRecordSetsPaginatorOptions | ||
client ListResourceRecordSetsAPIClient | ||
params *ListResourceRecordSetsInput | ||
firstPage bool | ||
startRecordName *string | ||
startRecordType types.RRType | ||
startRecordIdentifier *string | ||
isTruncated bool | ||
} | ||
|
||
// NewListResourceRecordSetsPaginator returns a new ListResourceRecordSetsPaginator | ||
func NewListResourceRecordSetsPaginator(client ListResourceRecordSetsAPIClient, params *ListResourceRecordSetsInput, optFns ...func(*ListResourceRecordSetsPaginatorOptions)) *ListResourceRecordSetsPaginator { | ||
if params == nil { | ||
params = &ListResourceRecordSetsInput{} | ||
} | ||
|
||
options := ListResourceRecordSetsPaginatorOptions{} | ||
if params.MaxItems != nil { | ||
options.Limit = *params.MaxItems | ||
} | ||
|
||
for _, fn := range optFns { | ||
fn(&options) | ||
} | ||
|
||
return &ListResourceRecordSetsPaginator{ | ||
options: options, | ||
client: client, | ||
params: params, | ||
firstPage: true, | ||
startRecordName: params.StartRecordName, | ||
startRecordType: params.StartRecordType, | ||
startRecordIdentifier: params.StartRecordIdentifier, | ||
} | ||
} | ||
|
||
// HasMorePages returns a boolean indicating whether more pages are available | ||
func (p *ListResourceRecordSetsPaginator) HasMorePages() bool { | ||
return p.firstPage || p.isTruncated | ||
} | ||
|
||
// NextPage retrieves the next ListResourceRecordSets page. | ||
func (p *ListResourceRecordSetsPaginator) NextPage(ctx context.Context, optFns ...func(*Options)) (*ListResourceRecordSetsOutput, error) { | ||
if !p.HasMorePages() { | ||
return nil, fmt.Errorf("no more pages available") | ||
} | ||
|
||
params := *p.params | ||
params.StartRecordName = p.startRecordName | ||
params.StartRecordIdentifier = p.startRecordIdentifier | ||
params.StartRecordType = p.startRecordType | ||
|
||
var limit *int32 | ||
if p.options.Limit > 0 { | ||
limit = &p.options.Limit | ||
} | ||
params.MaxItems = limit | ||
|
||
result, err := p.client.ListResourceRecordSets(ctx, ¶ms, optFns...) | ||
if err != nil { | ||
return nil, err | ||
} | ||
p.firstPage = false | ||
|
||
prevToken := p.startRecordName | ||
p.isTruncated = result.IsTruncated | ||
p.startRecordName = nil | ||
p.startRecordIdentifier = nil | ||
p.startRecordType = "" | ||
if result.IsTruncated { | ||
p.startRecordName = result.NextRecordName | ||
p.startRecordIdentifier = result.NextRecordIdentifier | ||
p.startRecordType = result.NextRecordType | ||
} | ||
|
||
if p.options.StopOnDuplicateToken && | ||
prevToken != nil && | ||
p.startRecordName != nil && | ||
*prevToken == *p.startRecordName { | ||
p.isTruncated = false | ||
} | ||
|
||
return result, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
package route53 | ||
|
||
import ( | ||
"context" | ||
"github.com/aws/aws-sdk-go-v2/aws" | ||
"github.com/aws/aws-sdk-go-v2/service/route53/types" | ||
"testing" | ||
) | ||
|
||
type mockListResourceRecordSetsClient struct { | ||
outputs []*ListResourceRecordSetsOutput | ||
inputs []*ListResourceRecordSetsInput | ||
t *testing.T | ||
} | ||
|
||
func (c *mockListResourceRecordSetsClient) ListResourceRecordSets(ctx context.Context, input *ListResourceRecordSetsInput, optFns ...func(*Options)) (*ListResourceRecordSetsOutput, error) { | ||
c.inputs = append(c.inputs, input) | ||
requestCnt := len(c.inputs) | ||
if *input.MaxItems != *c.outputs[requestCnt-1].MaxItems { | ||
c.t.Errorf("Expect page limit to be %d, got %d", *c.outputs[requestCnt-1].MaxItems, *input.MaxItems) | ||
} | ||
if outputLen := len(c.outputs); requestCnt > outputLen { | ||
c.t.Errorf("Paginator calls client more than expected %d times", outputLen) | ||
} | ||
return c.outputs[requestCnt-1], nil | ||
} | ||
|
||
type listRRSTestCase struct { | ||
limit int32 | ||
requestCnt int | ||
stopOnDuplicationToken bool | ||
outputs []*ListResourceRecordSetsOutput | ||
} | ||
|
||
func TestListResourceRecordSetsPaginator(t *testing.T) { | ||
cases := map[string]listRRSTestCase{ | ||
"page limit 5": { | ||
limit: 5, | ||
requestCnt: 3, | ||
outputs: []*ListResourceRecordSetsOutput{ | ||
&ListResourceRecordSetsOutput{ | ||
MaxItems: aws.Int32(5), | ||
NextRecordName: aws.String("testRecord1"), | ||
NextRecordIdentifier: aws.String("testID1"), | ||
NextRecordType: types.RRTypeA, | ||
IsTruncated: true, | ||
}, | ||
&ListResourceRecordSetsOutput{ | ||
MaxItems: aws.Int32(5), | ||
NextRecordName: aws.String("testRecord2"), | ||
NextRecordIdentifier: aws.String("testID2"), | ||
NextRecordType: types.RRTypeA, | ||
IsTruncated: true, | ||
}, | ||
&ListResourceRecordSetsOutput{ | ||
MaxItems: aws.Int32(5), | ||
NextRecordName: aws.String("testRecord3"), | ||
NextRecordIdentifier: aws.String("testID3"), | ||
NextRecordType: types.RRTypeA, | ||
IsTruncated: false, | ||
}, | ||
}, | ||
}, | ||
"page limit 10 with duplicate record": { | ||
limit: 10, | ||
requestCnt: 4, | ||
stopOnDuplicationToken: true, | ||
outputs: []*ListResourceRecordSetsOutput{ | ||
&ListResourceRecordSetsOutput{ | ||
MaxItems: aws.Int32(10), | ||
NextRecordName: aws.String("testRecord1"), | ||
NextRecordIdentifier: aws.String("testID1"), | ||
NextRecordType: types.RRTypeA, | ||
IsTruncated: true, | ||
}, | ||
&ListResourceRecordSetsOutput{ | ||
MaxItems: aws.Int32(10), | ||
NextRecordName: aws.String("testRecord2"), | ||
NextRecordIdentifier: aws.String("testID2"), | ||
NextRecordType: types.RRTypeA, | ||
IsTruncated: true, | ||
}, | ||
&ListResourceRecordSetsOutput{ | ||
MaxItems: aws.Int32(10), | ||
NextRecordName: aws.String("testRecord3"), | ||
NextRecordIdentifier: aws.String("testID3"), | ||
NextRecordType: types.RRTypeA, | ||
IsTruncated: true, | ||
}, | ||
&ListResourceRecordSetsOutput{ | ||
MaxItems: aws.Int32(10), | ||
NextRecordName: aws.String("testRecord3"), | ||
NextRecordIdentifier: aws.String("testID3"), | ||
NextRecordType: types.RRTypeA, | ||
IsTruncated: true, | ||
}, | ||
&ListResourceRecordSetsOutput{ | ||
MaxItems: aws.Int32(10), | ||
NextRecordName: aws.String("testRecord5"), | ||
NextRecordIdentifier: aws.String("testID5"), | ||
NextRecordType: types.RRTypeA, | ||
IsTruncated: false, | ||
}, | ||
}, | ||
}, | ||
} | ||
|
||
for name, c := range cases { | ||
t.Run(name, func(t *testing.T) { | ||
client := mockListResourceRecordSetsClient{ | ||
inputs: []*ListResourceRecordSetsInput{}, | ||
outputs: c.outputs, | ||
t: t, | ||
} | ||
|
||
paginator := NewListResourceRecordSetsPaginator(&client, &ListResourceRecordSetsInput{}, func(options *ListResourceRecordSetsPaginatorOptions) { | ||
options.Limit = c.limit | ||
options.StopOnDuplicateToken = c.stopOnDuplicationToken | ||
}) | ||
for paginator.HasMorePages() { | ||
_, err := paginator.NextPage(context.TODO()) | ||
if err != nil { | ||
t.Errorf("error: %v", err) | ||
} | ||
} | ||
|
||
inputLen := len(client.inputs) | ||
if inputLen != c.requestCnt { | ||
t.Errorf("Expect total request number to be %d, got %d", c.requestCnt, inputLen) | ||
} | ||
for i := 1; i < inputLen; i++ { | ||
if *client.inputs[i].StartRecordName != *c.outputs[i-1].NextRecordName { | ||
t.Errorf("Expect next input's RecordName to be eaqul to %s, got %s", | ||
*c.outputs[i-1].NextRecordName, *client.inputs[i].StartRecordName) | ||
} | ||
if *client.inputs[i].StartRecordIdentifier != *c.outputs[i-1].NextRecordIdentifier { | ||
t.Errorf("Expect next input's RecordIdentifier to be eaqul to %s, got %s", | ||
*c.outputs[i-1].NextRecordIdentifier, *client.inputs[i].StartRecordIdentifier) | ||
} | ||
if client.inputs[i].StartRecordType != c.outputs[i-1].NextRecordType { | ||
t.Errorf("Expect next input's RecordType to be eaqul to %s, got %s", | ||
c.outputs[i-1].NextRecordType, client.inputs[i].StartRecordType) | ||
} | ||
} | ||
}) | ||
} | ||
} |