1// Code generated by smithy-go-codegen DO NOT EDIT.
2
3package docdb
4
5import (
6	"context"
7	"fmt"
8	awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware"
9	"github.com/aws/aws-sdk-go-v2/aws/signer/v4"
10	"github.com/aws/aws-sdk-go-v2/service/docdb/types"
11	"github.com/aws/smithy-go/middleware"
12	smithytime "github.com/aws/smithy-go/time"
13	smithyhttp "github.com/aws/smithy-go/transport/http"
14	smithywaiter "github.com/aws/smithy-go/waiter"
15	"github.com/jmespath/go-jmespath"
16	"time"
17)
18
19// Returns information about provisioned Amazon DocumentDB instances. This API
20// supports pagination.
21func (c *Client) DescribeDBInstances(ctx context.Context, params *DescribeDBInstancesInput, optFns ...func(*Options)) (*DescribeDBInstancesOutput, error) {
22	if params == nil {
23		params = &DescribeDBInstancesInput{}
24	}
25
26	result, metadata, err := c.invokeOperation(ctx, "DescribeDBInstances", params, optFns, addOperationDescribeDBInstancesMiddlewares)
27	if err != nil {
28		return nil, err
29	}
30
31	out := result.(*DescribeDBInstancesOutput)
32	out.ResultMetadata = metadata
33	return out, nil
34}
35
36// Represents the input to DescribeDBInstances.
37type DescribeDBInstancesInput struct {
38
39	// The user-provided instance identifier. If this parameter is specified,
40	// information from only the specific instance is returned. This parameter isn't
41	// case sensitive. Constraints:
42	//
43	// * If provided, must match the identifier of an
44	// existing DBInstance.
45	DBInstanceIdentifier *string
46
47	// A filter that specifies one or more instances to describe. Supported filters:
48	//
49	// *
50	// db-cluster-id - Accepts cluster identifiers and cluster Amazon Resource Names
51	// (ARNs). The results list includes only the information about the instances that
52	// are associated with the clusters that are identified by these ARNs.
53	//
54	// *
55	// db-instance-id - Accepts instance identifiers and instance ARNs. The results
56	// list includes only the information about the instances that are identified by
57	// these ARNs.
58	Filters []types.Filter
59
60	// An optional pagination token provided by a previous request. If this parameter
61	// is specified, the response includes only records beyond the marker, up to the
62	// value specified by MaxRecords.
63	Marker *string
64
65	// The maximum number of records to include in the response. If more records exist
66	// than the specified MaxRecords value, a pagination token (marker) is included in
67	// the response so that the remaining results can be retrieved. Default: 100
68	// Constraints: Minimum 20, maximum 100.
69	MaxRecords *int32
70}
71
72// Represents the output of DescribeDBInstances.
73type DescribeDBInstancesOutput struct {
74
75	// Detailed information about one or more instances.
76	DBInstances []types.DBInstance
77
78	// An optional pagination token provided by a previous request. If this parameter
79	// is specified, the response includes only records beyond the marker, up to the
80	// value specified by MaxRecords.
81	Marker *string
82
83	// Metadata pertaining to the operation's result.
84	ResultMetadata middleware.Metadata
85}
86
87func addOperationDescribeDBInstancesMiddlewares(stack *middleware.Stack, options Options) (err error) {
88	err = stack.Serialize.Add(&awsAwsquery_serializeOpDescribeDBInstances{}, middleware.After)
89	if err != nil {
90		return err
91	}
92	err = stack.Deserialize.Add(&awsAwsquery_deserializeOpDescribeDBInstances{}, middleware.After)
93	if err != nil {
94		return err
95	}
96	if err = addSetLoggerMiddleware(stack, options); err != nil {
97		return err
98	}
99	if err = awsmiddleware.AddClientRequestIDMiddleware(stack); err != nil {
100		return err
101	}
102	if err = smithyhttp.AddComputeContentLengthMiddleware(stack); err != nil {
103		return err
104	}
105	if err = addResolveEndpointMiddleware(stack, options); err != nil {
106		return err
107	}
108	if err = v4.AddComputePayloadSHA256Middleware(stack); err != nil {
109		return err
110	}
111	if err = addRetryMiddlewares(stack, options); err != nil {
112		return err
113	}
114	if err = addHTTPSignerV4Middleware(stack, options); err != nil {
115		return err
116	}
117	if err = awsmiddleware.AddRawResponseToMetadata(stack); err != nil {
118		return err
119	}
120	if err = awsmiddleware.AddRecordResponseTiming(stack); err != nil {
121		return err
122	}
123	if err = addClientUserAgent(stack); err != nil {
124		return err
125	}
126	if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil {
127		return err
128	}
129	if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil {
130		return err
131	}
132	if err = addOpDescribeDBInstancesValidationMiddleware(stack); err != nil {
133		return err
134	}
135	if err = stack.Initialize.Add(newServiceMetadataMiddleware_opDescribeDBInstances(options.Region), middleware.Before); err != nil {
136		return err
137	}
138	if err = addRequestIDRetrieverMiddleware(stack); err != nil {
139		return err
140	}
141	if err = addResponseErrorMiddleware(stack); err != nil {
142		return err
143	}
144	if err = addRequestResponseLogging(stack, options); err != nil {
145		return err
146	}
147	return nil
148}
149
150// DescribeDBInstancesAPIClient is a client that implements the DescribeDBInstances
151// operation.
152type DescribeDBInstancesAPIClient interface {
153	DescribeDBInstances(context.Context, *DescribeDBInstancesInput, ...func(*Options)) (*DescribeDBInstancesOutput, error)
154}
155
156var _ DescribeDBInstancesAPIClient = (*Client)(nil)
157
158// DescribeDBInstancesPaginatorOptions is the paginator options for
159// DescribeDBInstances
160type DescribeDBInstancesPaginatorOptions struct {
161	// The maximum number of records to include in the response. If more records exist
162	// than the specified MaxRecords value, a pagination token (marker) is included in
163	// the response so that the remaining results can be retrieved. Default: 100
164	// Constraints: Minimum 20, maximum 100.
165	Limit int32
166
167	// Set to true if pagination should stop if the service returns a pagination token
168	// that matches the most recent token provided to the service.
169	StopOnDuplicateToken bool
170}
171
172// DescribeDBInstancesPaginator is a paginator for DescribeDBInstances
173type DescribeDBInstancesPaginator struct {
174	options   DescribeDBInstancesPaginatorOptions
175	client    DescribeDBInstancesAPIClient
176	params    *DescribeDBInstancesInput
177	nextToken *string
178	firstPage bool
179}
180
181// NewDescribeDBInstancesPaginator returns a new DescribeDBInstancesPaginator
182func NewDescribeDBInstancesPaginator(client DescribeDBInstancesAPIClient, params *DescribeDBInstancesInput, optFns ...func(*DescribeDBInstancesPaginatorOptions)) *DescribeDBInstancesPaginator {
183	if params == nil {
184		params = &DescribeDBInstancesInput{}
185	}
186
187	options := DescribeDBInstancesPaginatorOptions{}
188	if params.MaxRecords != nil {
189		options.Limit = *params.MaxRecords
190	}
191
192	for _, fn := range optFns {
193		fn(&options)
194	}
195
196	return &DescribeDBInstancesPaginator{
197		options:   options,
198		client:    client,
199		params:    params,
200		firstPage: true,
201	}
202}
203
204// HasMorePages returns a boolean indicating whether more pages are available
205func (p *DescribeDBInstancesPaginator) HasMorePages() bool {
206	return p.firstPage || p.nextToken != nil
207}
208
209// NextPage retrieves the next DescribeDBInstances page.
210func (p *DescribeDBInstancesPaginator) NextPage(ctx context.Context, optFns ...func(*Options)) (*DescribeDBInstancesOutput, error) {
211	if !p.HasMorePages() {
212		return nil, fmt.Errorf("no more pages available")
213	}
214
215	params := *p.params
216	params.Marker = p.nextToken
217
218	var limit *int32
219	if p.options.Limit > 0 {
220		limit = &p.options.Limit
221	}
222	params.MaxRecords = limit
223
224	result, err := p.client.DescribeDBInstances(ctx, &params, optFns...)
225	if err != nil {
226		return nil, err
227	}
228	p.firstPage = false
229
230	prevToken := p.nextToken
231	p.nextToken = result.Marker
232
233	if p.options.StopOnDuplicateToken && prevToken != nil && p.nextToken != nil && *prevToken == *p.nextToken {
234		p.nextToken = nil
235	}
236
237	return result, nil
238}
239
240// DBInstanceAvailableWaiterOptions are waiter options for
241// DBInstanceAvailableWaiter
242type DBInstanceAvailableWaiterOptions struct {
243
244	// Set of options to modify how an operation is invoked. These apply to all
245	// operations invoked for this client. Use functional options on operation call to
246	// modify this list for per operation behavior.
247	APIOptions []func(*middleware.Stack) error
248
249	// MinDelay is the minimum amount of time to delay between retries. If unset,
250	// DBInstanceAvailableWaiter will use default minimum delay of 30 seconds. Note
251	// that MinDelay must resolve to a value lesser than or equal to the MaxDelay.
252	MinDelay time.Duration
253
254	// MaxDelay is the maximum amount of time to delay between retries. If unset or set
255	// to zero, DBInstanceAvailableWaiter will use default max delay of 120 seconds.
256	// Note that MaxDelay must resolve to value greater than or equal to the MinDelay.
257	MaxDelay time.Duration
258
259	// LogWaitAttempts is used to enable logging for waiter retry attempts
260	LogWaitAttempts bool
261
262	// Retryable is function that can be used to override the service defined
263	// waiter-behavior based on operation output, or returned error. This function is
264	// used by the waiter to decide if a state is retryable or a terminal state. By
265	// default service-modeled logic will populate this option. This option can thus be
266	// used to define a custom waiter state with fall-back to service-modeled waiter
267	// state mutators.The function returns an error in case of a failure state. In case
268	// of retry state, this function returns a bool value of true and nil error, while
269	// in case of success it returns a bool value of false and nil error.
270	Retryable func(context.Context, *DescribeDBInstancesInput, *DescribeDBInstancesOutput, error) (bool, error)
271}
272
273// DBInstanceAvailableWaiter defines the waiters for DBInstanceAvailable
274type DBInstanceAvailableWaiter struct {
275	client DescribeDBInstancesAPIClient
276
277	options DBInstanceAvailableWaiterOptions
278}
279
280// NewDBInstanceAvailableWaiter constructs a DBInstanceAvailableWaiter.
281func NewDBInstanceAvailableWaiter(client DescribeDBInstancesAPIClient, optFns ...func(*DBInstanceAvailableWaiterOptions)) *DBInstanceAvailableWaiter {
282	options := DBInstanceAvailableWaiterOptions{}
283	options.MinDelay = 30 * time.Second
284	options.MaxDelay = 120 * time.Second
285	options.Retryable = dBInstanceAvailableStateRetryable
286
287	for _, fn := range optFns {
288		fn(&options)
289	}
290	return &DBInstanceAvailableWaiter{
291		client:  client,
292		options: options,
293	}
294}
295
296// Wait calls the waiter function for DBInstanceAvailable waiter. The maxWaitDur is
297// the maximum wait duration the waiter will wait. The maxWaitDur is required and
298// must be greater than zero.
299func (w *DBInstanceAvailableWaiter) Wait(ctx context.Context, params *DescribeDBInstancesInput, maxWaitDur time.Duration, optFns ...func(*DBInstanceAvailableWaiterOptions)) error {
300	if maxWaitDur <= 0 {
301		return fmt.Errorf("maximum wait time for waiter must be greater than zero")
302	}
303
304	options := w.options
305	for _, fn := range optFns {
306		fn(&options)
307	}
308
309	if options.MaxDelay <= 0 {
310		options.MaxDelay = 120 * time.Second
311	}
312
313	if options.MinDelay > options.MaxDelay {
314		return fmt.Errorf("minimum waiter delay %v must be lesser than or equal to maximum waiter delay of %v.", options.MinDelay, options.MaxDelay)
315	}
316
317	ctx, cancelFn := context.WithTimeout(ctx, maxWaitDur)
318	defer cancelFn()
319
320	logger := smithywaiter.Logger{}
321	remainingTime := maxWaitDur
322
323	var attempt int64
324	for {
325
326		attempt++
327		apiOptions := options.APIOptions
328		start := time.Now()
329
330		if options.LogWaitAttempts {
331			logger.Attempt = attempt
332			apiOptions = append([]func(*middleware.Stack) error{}, options.APIOptions...)
333			apiOptions = append(apiOptions, logger.AddLogger)
334		}
335
336		out, err := w.client.DescribeDBInstances(ctx, params, func(o *Options) {
337			o.APIOptions = append(o.APIOptions, apiOptions...)
338		})
339
340		retryable, err := options.Retryable(ctx, params, out, err)
341		if err != nil {
342			return err
343		}
344		if !retryable {
345			return nil
346		}
347
348		remainingTime -= time.Since(start)
349		if remainingTime < options.MinDelay || remainingTime <= 0 {
350			break
351		}
352
353		// compute exponential backoff between waiter retries
354		delay, err := smithywaiter.ComputeDelay(
355			attempt, options.MinDelay, options.MaxDelay, remainingTime,
356		)
357		if err != nil {
358			return fmt.Errorf("error computing waiter delay, %w", err)
359		}
360
361		remainingTime -= delay
362		// sleep for the delay amount before invoking a request
363		if err := smithytime.SleepWithContext(ctx, delay); err != nil {
364			return fmt.Errorf("request cancelled while waiting, %w", err)
365		}
366	}
367	return fmt.Errorf("exceeded max wait time for DBInstanceAvailable waiter")
368}
369
370func dBInstanceAvailableStateRetryable(ctx context.Context, input *DescribeDBInstancesInput, output *DescribeDBInstancesOutput, err error) (bool, error) {
371
372	if err == nil {
373		pathValue, err := jmespath.Search("DBInstances[].DBInstanceStatus", output)
374		if err != nil {
375			return false, fmt.Errorf("error evaluating waiter state: %w", err)
376		}
377
378		expectedValue := "available"
379		var match = true
380		listOfValues, ok := pathValue.([]interface{})
381		if !ok {
382			return false, fmt.Errorf("waiter comparator expected list got %T", pathValue)
383		}
384
385		if len(listOfValues) == 0 {
386			match = false
387		}
388		for _, v := range listOfValues {
389			value, ok := v.(*string)
390			if !ok {
391				return false, fmt.Errorf("waiter comparator expected *string value, got %T", pathValue)
392			}
393
394			if string(*value) != expectedValue {
395				match = false
396			}
397		}
398
399		if match {
400			return false, nil
401		}
402	}
403
404	if err == nil {
405		pathValue, err := jmespath.Search("DBInstances[].DBInstanceStatus", output)
406		if err != nil {
407			return false, fmt.Errorf("error evaluating waiter state: %w", err)
408		}
409
410		expectedValue := "deleted"
411		listOfValues, ok := pathValue.([]interface{})
412		if !ok {
413			return false, fmt.Errorf("waiter comparator expected list got %T", pathValue)
414		}
415
416		for _, v := range listOfValues {
417			value, ok := v.(*string)
418			if !ok {
419				return false, fmt.Errorf("waiter comparator expected *string value, got %T", pathValue)
420			}
421
422			if string(*value) == expectedValue {
423				return false, fmt.Errorf("waiter state transitioned to Failure")
424			}
425		}
426	}
427
428	if err == nil {
429		pathValue, err := jmespath.Search("DBInstances[].DBInstanceStatus", output)
430		if err != nil {
431			return false, fmt.Errorf("error evaluating waiter state: %w", err)
432		}
433
434		expectedValue := "deleting"
435		listOfValues, ok := pathValue.([]interface{})
436		if !ok {
437			return false, fmt.Errorf("waiter comparator expected list got %T", pathValue)
438		}
439
440		for _, v := range listOfValues {
441			value, ok := v.(*string)
442			if !ok {
443				return false, fmt.Errorf("waiter comparator expected *string value, got %T", pathValue)
444			}
445
446			if string(*value) == expectedValue {
447				return false, fmt.Errorf("waiter state transitioned to Failure")
448			}
449		}
450	}
451
452	if err == nil {
453		pathValue, err := jmespath.Search("DBInstances[].DBInstanceStatus", output)
454		if err != nil {
455			return false, fmt.Errorf("error evaluating waiter state: %w", err)
456		}
457
458		expectedValue := "failed"
459		listOfValues, ok := pathValue.([]interface{})
460		if !ok {
461			return false, fmt.Errorf("waiter comparator expected list got %T", pathValue)
462		}
463
464		for _, v := range listOfValues {
465			value, ok := v.(*string)
466			if !ok {
467				return false, fmt.Errorf("waiter comparator expected *string value, got %T", pathValue)
468			}
469
470			if string(*value) == expectedValue {
471				return false, fmt.Errorf("waiter state transitioned to Failure")
472			}
473		}
474	}
475
476	if err == nil {
477		pathValue, err := jmespath.Search("DBInstances[].DBInstanceStatus", output)
478		if err != nil {
479			return false, fmt.Errorf("error evaluating waiter state: %w", err)
480		}
481
482		expectedValue := "incompatible-restore"
483		listOfValues, ok := pathValue.([]interface{})
484		if !ok {
485			return false, fmt.Errorf("waiter comparator expected list got %T", pathValue)
486		}
487
488		for _, v := range listOfValues {
489			value, ok := v.(*string)
490			if !ok {
491				return false, fmt.Errorf("waiter comparator expected *string value, got %T", pathValue)
492			}
493
494			if string(*value) == expectedValue {
495				return false, fmt.Errorf("waiter state transitioned to Failure")
496			}
497		}
498	}
499
500	if err == nil {
501		pathValue, err := jmespath.Search("DBInstances[].DBInstanceStatus", output)
502		if err != nil {
503			return false, fmt.Errorf("error evaluating waiter state: %w", err)
504		}
505
506		expectedValue := "incompatible-parameters"
507		listOfValues, ok := pathValue.([]interface{})
508		if !ok {
509			return false, fmt.Errorf("waiter comparator expected list got %T", pathValue)
510		}
511
512		for _, v := range listOfValues {
513			value, ok := v.(*string)
514			if !ok {
515				return false, fmt.Errorf("waiter comparator expected *string value, got %T", pathValue)
516			}
517
518			if string(*value) == expectedValue {
519				return false, fmt.Errorf("waiter state transitioned to Failure")
520			}
521		}
522	}
523
524	return true, nil
525}
526
527func newServiceMetadataMiddleware_opDescribeDBInstances(region string) *awsmiddleware.RegisterServiceMetadata {
528	return &awsmiddleware.RegisterServiceMetadata{
529		Region:        region,
530		ServiceID:     ServiceID,
531		SigningName:   "rds",
532		OperationName: "DescribeDBInstances",
533	}
534}
535