diff --git a/service/ec2/handwritten_paginators.go b/service/ec2/handwritten_paginators.go new file mode 100644 index 000000000000..51e2c000ca00 --- /dev/null +++ b/service/ec2/handwritten_paginators.go @@ -0,0 +1,206 @@ +package ec2 + +import ( + "context" + "fmt" +) + +// DescribeVpcEncryptionControlsAPIClient is a client that implements the +// DescribeVpcEncryptionControls operation. +type DescribeVpcEncryptionControlsAPIClient interface { + DescribeVpcEncryptionControls(context.Context, *DescribeVpcEncryptionControlsInput, ...func(*Options)) (*DescribeVpcEncryptionControlsOutput, error) +} + +var _ DescribeVpcEncryptionControlsAPIClient = (*Client)(nil) + +// DescribeVpcEncryptionControlsPaginatorOptions is the paginator options for +// DescribeVpcEncryptionControls +type DescribeVpcEncryptionControlsPaginatorOptions struct { + // The maximum number of items to return for this request. To get the next page of + // items, make another request with the token returned in the output. For more + // information, see [Pagination]. + // + // [Pagination]: https://docs.aws.amazon.com/AWSEC2/latest/APIReference/Query-Requests.html#api-pagination + 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 +} + +// DescribeVpcEncryptionControlsPaginator is a paginator for +// DescribeVpcEncryptionControls +type DescribeVpcEncryptionControlsPaginator struct { + options DescribeVpcEncryptionControlsPaginatorOptions + client DescribeVpcEncryptionControlsAPIClient + params *DescribeVpcEncryptionControlsInput + nextToken *string + firstPage bool +} + +// NewDescribeVpcEncryptionControlsPaginator returns a new +// DescribeVpcEncryptionControlsPaginator +func NewDescribeVpcEncryptionControlsPaginator(client DescribeVpcEncryptionControlsAPIClient, params *DescribeVpcEncryptionControlsInput, optFns ...func(*DescribeVpcEncryptionControlsPaginatorOptions)) *DescribeVpcEncryptionControlsPaginator { + if params == nil { + params = &DescribeVpcEncryptionControlsInput{} + } + + options := DescribeVpcEncryptionControlsPaginatorOptions{} + if params.MaxResults != nil { + options.Limit = *params.MaxResults + } + + for _, fn := range optFns { + fn(&options) + } + + return &DescribeVpcEncryptionControlsPaginator{ + options: options, + client: client, + params: params, + firstPage: true, + nextToken: params.NextToken, + } +} + +// HasMorePages returns a boolean indicating whether more pages are available +func (p *DescribeVpcEncryptionControlsPaginator) HasMorePages() bool { + return p.firstPage || (p.nextToken != nil && len(*p.nextToken) != 0) +} + +// NextPage retrieves the next DescribeVpcEncryptionControls page. +func (p *DescribeVpcEncryptionControlsPaginator) NextPage(ctx context.Context, optFns ...func(*Options)) (*DescribeVpcEncryptionControlsOutput, error) { + if !p.HasMorePages() { + return nil, fmt.Errorf("no more pages available") + } + + params := *p.params + params.NextToken = p.nextToken + + var limit *int32 + if p.options.Limit > 0 { + limit = &p.options.Limit + } + params.MaxResults = limit + + optFns = append([]func(*Options){ + addIsPaginatorUserAgent, + }, optFns...) + result, err := p.client.DescribeVpcEncryptionControls(ctx, ¶ms, optFns...) + if err != nil { + return nil, err + } + p.firstPage = false + + prevToken := p.nextToken + p.nextToken = result.NextToken + + if p.options.StopOnDuplicateToken && + prevToken != nil && + p.nextToken != nil && + *prevToken == *p.nextToken { + p.nextToken = nil + } + + return result, nil +} + +// GetVpcResourcesBlockingEncryptionEnforcementAPIClient is a client that +// implements the GetVpcResourcesBlockingEncryptionEnforcement operation. +type GetVpcResourcesBlockingEncryptionEnforcementAPIClient interface { + GetVpcResourcesBlockingEncryptionEnforcement(context.Context, *GetVpcResourcesBlockingEncryptionEnforcementInput, ...func(*Options)) (*GetVpcResourcesBlockingEncryptionEnforcementOutput, error) +} + +var _ GetVpcResourcesBlockingEncryptionEnforcementAPIClient = (*Client)(nil) + +// GetVpcResourcesBlockingEncryptionEnforcementPaginatorOptions is the paginator +// options for GetVpcResourcesBlockingEncryptionEnforcement +type GetVpcResourcesBlockingEncryptionEnforcementPaginatorOptions struct { + // The maximum number of items to return for this request. To get the next page of + // items, make another request with the token returned in the output. For more + // information, see [Pagination]. + // + // [Pagination]: https://docs.aws.amazon.com/AWSEC2/latest/APIReference/Query-Requests.html#api-pagination + 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 +} + +// GetVpcResourcesBlockingEncryptionEnforcementPaginator is a paginator for +// GetVpcResourcesBlockingEncryptionEnforcement +type GetVpcResourcesBlockingEncryptionEnforcementPaginator struct { + options GetVpcResourcesBlockingEncryptionEnforcementPaginatorOptions + client GetVpcResourcesBlockingEncryptionEnforcementAPIClient + params *GetVpcResourcesBlockingEncryptionEnforcementInput + nextToken *string + firstPage bool +} + +// NewGetVpcResourcesBlockingEncryptionEnforcementPaginator returns a new +// GetVpcResourcesBlockingEncryptionEnforcementPaginator +func NewGetVpcResourcesBlockingEncryptionEnforcementPaginator(client GetVpcResourcesBlockingEncryptionEnforcementAPIClient, params *GetVpcResourcesBlockingEncryptionEnforcementInput, optFns ...func(*GetVpcResourcesBlockingEncryptionEnforcementPaginatorOptions)) *GetVpcResourcesBlockingEncryptionEnforcementPaginator { + if params == nil { + params = &GetVpcResourcesBlockingEncryptionEnforcementInput{} + } + + options := GetVpcResourcesBlockingEncryptionEnforcementPaginatorOptions{} + if params.MaxResults != nil { + options.Limit = *params.MaxResults + } + + for _, fn := range optFns { + fn(&options) + } + + return &GetVpcResourcesBlockingEncryptionEnforcementPaginator{ + options: options, + client: client, + params: params, + firstPage: true, + nextToken: params.NextToken, + } +} + +// HasMorePages returns a boolean indicating whether more pages are available +func (p *GetVpcResourcesBlockingEncryptionEnforcementPaginator) HasMorePages() bool { + return p.firstPage || (p.nextToken != nil && len(*p.nextToken) != 0) +} + +// NextPage retrieves the next GetVpcResourcesBlockingEncryptionEnforcement page. +func (p *GetVpcResourcesBlockingEncryptionEnforcementPaginator) NextPage(ctx context.Context, optFns ...func(*Options)) (*GetVpcResourcesBlockingEncryptionEnforcementOutput, error) { + if !p.HasMorePages() { + return nil, fmt.Errorf("no more pages available") + } + + params := *p.params + params.NextToken = p.nextToken + + var limit *int32 + if p.options.Limit > 0 { + limit = &p.options.Limit + } + params.MaxResults = limit + + optFns = append([]func(*Options){ + addIsPaginatorUserAgent, + }, optFns...) + result, err := p.client.GetVpcResourcesBlockingEncryptionEnforcement(ctx, ¶ms, optFns...) + if err != nil { + return nil, err + } + p.firstPage = false + + prevToken := p.nextToken + p.nextToken = result.NextToken + + if p.options.StopOnDuplicateToken && + prevToken != nil && + p.nextToken != nil && + *prevToken == *p.nextToken { + p.nextToken = nil + } + + return result, nil +} diff --git a/service/ec2/handwritten_paginators_test.go b/service/ec2/handwritten_paginators_test.go new file mode 100644 index 000000000000..c93809481641 --- /dev/null +++ b/service/ec2/handwritten_paginators_test.go @@ -0,0 +1,200 @@ +package ec2 + +import ( + "context" + "testing" + + "github.com/aws/aws-sdk-go-v2/aws" +) + +// --- DescribeVpcEncryptionControls --- + +type mockDescribeVpcEncryptionControlsClient struct { + outputs []*DescribeVpcEncryptionControlsOutput + inputs []*DescribeVpcEncryptionControlsInput + t *testing.T +} + +func (c *mockDescribeVpcEncryptionControlsClient) DescribeVpcEncryptionControls(_ context.Context, input *DescribeVpcEncryptionControlsInput, _ ...func(*Options)) (*DescribeVpcEncryptionControlsOutput, error) { + c.inputs = append(c.inputs, input) + requestCnt := len(c.inputs) + if requestCnt > len(c.outputs) { + c.t.Fatalf("paginator called client more times than expected (%d)", len(c.outputs)) + } + return c.outputs[requestCnt-1], nil +} + +func TestDescribeVpcEncryptionControlsPaginator(t *testing.T) { + cases := map[string]struct { + limit int32 + requestCnt int + stopOnDuplicateToken bool + outputs []*DescribeVpcEncryptionControlsOutput + }{ + "multi-page": { + limit: 5, + requestCnt: 3, + outputs: []*DescribeVpcEncryptionControlsOutput{ + {NextToken: aws.String("token1")}, + {NextToken: aws.String("token2")}, + {NextToken: nil}, + }, + }, + "single page": { + limit: 10, + requestCnt: 1, + outputs: []*DescribeVpcEncryptionControlsOutput{ + {NextToken: nil}, + }, + }, + "stop on duplicate token": { + limit: 10, + requestCnt: 2, + stopOnDuplicateToken: true, + outputs: []*DescribeVpcEncryptionControlsOutput{ + {NextToken: aws.String("token1")}, + {NextToken: aws.String("token1")}, + }, + }, + } + + for name, c := range cases { + t.Run(name, func(t *testing.T) { + client := &mockDescribeVpcEncryptionControlsClient{ + t: t, + outputs: c.outputs, + inputs: []*DescribeVpcEncryptionControlsInput{}, + } + paginator := NewDescribeVpcEncryptionControlsPaginator(client, &DescribeVpcEncryptionControlsInput{}, func(o *DescribeVpcEncryptionControlsPaginatorOptions) { + o.Limit = c.limit + o.StopOnDuplicateToken = c.stopOnDuplicateToken + }) + + for paginator.HasMorePages() { + _, err := paginator.NextPage(context.TODO()) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + } + + inputLen := len(client.inputs) + testTotalRequestsEC2(c.requestCnt, inputLen, t) + + for i := 1; i < inputLen; i++ { + if aws.ToInt32(client.inputs[i].MaxResults) != c.limit { + t.Errorf("page %d: expected MaxResults %d, got %d", i, c.limit, aws.ToInt32(client.inputs[i].MaxResults)) + } + expectedToken := aws.ToString(c.outputs[i-1].NextToken) + actualToken := aws.ToString(client.inputs[i].NextToken) + if expectedToken != actualToken { + t.Errorf("page %d: expected NextToken %q, got %q", i, expectedToken, actualToken) + } + } + }) + } +} + +// --- GetVpcResourcesBlockingEncryptionEnforcement --- + +type mockGetVpcResourcesBlockingEncryptionEnforcementClient struct { + outputs []*GetVpcResourcesBlockingEncryptionEnforcementOutput + inputs []*GetVpcResourcesBlockingEncryptionEnforcementInput + t *testing.T +} + +func (c *mockGetVpcResourcesBlockingEncryptionEnforcementClient) GetVpcResourcesBlockingEncryptionEnforcement(_ context.Context, input *GetVpcResourcesBlockingEncryptionEnforcementInput, _ ...func(*Options)) (*GetVpcResourcesBlockingEncryptionEnforcementOutput, error) { + c.inputs = append(c.inputs, input) + requestCnt := len(c.inputs) + if requestCnt > len(c.outputs) { + c.t.Fatalf("paginator called client more times than expected (%d)", len(c.outputs)) + } + return c.outputs[requestCnt-1], nil +} + +func TestGetVpcResourcesBlockingEncryptionEnforcementPaginator(t *testing.T) { + cases := map[string]struct { + vpcID string + limit int32 + requestCnt int + stopOnDuplicateToken bool + outputs []*GetVpcResourcesBlockingEncryptionEnforcementOutput + }{ + "multi-page": { + vpcID: "vpc-12345", + limit: 5, + requestCnt: 3, + outputs: []*GetVpcResourcesBlockingEncryptionEnforcementOutput{ + {NextToken: aws.String("token1")}, + {NextToken: aws.String("token2")}, + {NextToken: nil}, + }, + }, + "single page": { + vpcID: "vpc-67890", + limit: 10, + requestCnt: 1, + outputs: []*GetVpcResourcesBlockingEncryptionEnforcementOutput{ + {NextToken: nil}, + }, + }, + "stop on duplicate token": { + vpcID: "vpc-abcde", + limit: 10, + requestCnt: 2, + stopOnDuplicateToken: true, + outputs: []*GetVpcResourcesBlockingEncryptionEnforcementOutput{ + {NextToken: aws.String("token1")}, + {NextToken: aws.String("token1")}, + }, + }, + } + + for name, c := range cases { + t.Run(name, func(t *testing.T) { + client := &mockGetVpcResourcesBlockingEncryptionEnforcementClient{ + t: t, + outputs: c.outputs, + inputs: []*GetVpcResourcesBlockingEncryptionEnforcementInput{}, + } + paginator := NewGetVpcResourcesBlockingEncryptionEnforcementPaginator(client, &GetVpcResourcesBlockingEncryptionEnforcementInput{ + VpcId: aws.String(c.vpcID), + }, func(o *GetVpcResourcesBlockingEncryptionEnforcementPaginatorOptions) { + o.Limit = c.limit + o.StopOnDuplicateToken = c.stopOnDuplicateToken + }) + + for paginator.HasMorePages() { + _, err := paginator.NextPage(context.TODO()) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + } + + inputLen := len(client.inputs) + testTotalRequestsEC2(c.requestCnt, inputLen, t) + + for i := 0; i < inputLen; i++ { + if aws.ToString(client.inputs[i].VpcId) != c.vpcID { + t.Errorf("page %d: expected VpcId %q, got %q", i, c.vpcID, aws.ToString(client.inputs[i].VpcId)) + } + } + for i := 1; i < inputLen; i++ { + if aws.ToInt32(client.inputs[i].MaxResults) != c.limit { + t.Errorf("page %d: expected MaxResults %d, got %d", i, c.limit, aws.ToInt32(client.inputs[i].MaxResults)) + } + expectedToken := aws.ToString(c.outputs[i-1].NextToken) + actualToken := aws.ToString(client.inputs[i].NextToken) + if expectedToken != actualToken { + t.Errorf("page %d: expected NextToken %q, got %q", i, expectedToken, actualToken) + } + } + }) + } +} + +func testTotalRequestsEC2(expect, actual int, t *testing.T) { + t.Helper() + if actual != expect { + t.Errorf("expected %d total requests, got %d", expect, actual) + } +} \ No newline at end of file