1// Code generated by smithy-go-codegen DO NOT EDIT.
2
3package redshift
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/redshift/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 one or more snapshot objects, which contain metadata about your cluster
20// snapshots. By default, this operation returns information about all snapshots of
21// all clusters that are owned by you AWS customer account. No information is
22// returned for snapshots owned by inactive AWS customer accounts. If you specify
23// both tag keys and tag values in the same request, Amazon Redshift returns all
24// snapshots that match any combination of the specified keys and values. For
25// example, if you have owner and environment for tag keys, and admin and test for
26// tag values, all snapshots that have any combination of those values are
27// returned. Only snapshots that you own are returned in the response; shared
28// snapshots are not returned with the tag key and tag value request parameters. If
29// both tag keys and values are omitted from the request, snapshots are returned
30// regardless of whether they have tag keys or values associated with them.
31func (c *Client) DescribeClusterSnapshots(ctx context.Context, params *DescribeClusterSnapshotsInput, optFns ...func(*Options)) (*DescribeClusterSnapshotsOutput, error) {
32	if params == nil {
33		params = &DescribeClusterSnapshotsInput{}
34	}
35
36	result, metadata, err := c.invokeOperation(ctx, "DescribeClusterSnapshots", params, optFns, addOperationDescribeClusterSnapshotsMiddlewares)
37	if err != nil {
38		return nil, err
39	}
40
41	out := result.(*DescribeClusterSnapshotsOutput)
42	out.ResultMetadata = metadata
43	return out, nil
44}
45
46//
47type DescribeClusterSnapshotsInput struct {
48
49	// A value that indicates whether to return snapshots only for an existing cluster.
50	// You can perform table-level restore only by using a snapshot of an existing
51	// cluster, that is, a cluster that has not been deleted. Values for this parameter
52	// work as follows:
53	//
54	// * If ClusterExists is set to true, ClusterIdentifier is
55	// required.
56	//
57	// * If ClusterExists is set to false and ClusterIdentifier isn't
58	// specified, all snapshots associated with deleted clusters (orphaned snapshots)
59	// are returned.
60	//
61	// * If ClusterExists is set to false and ClusterIdentifier is
62	// specified for a deleted cluster, snapshots associated with that cluster are
63	// returned.
64	//
65	// * If ClusterExists is set to false and ClusterIdentifier is specified
66	// for an existing cluster, no snapshots are returned.
67	ClusterExists *bool
68
69	// The identifier of the cluster which generated the requested snapshots.
70	ClusterIdentifier *string
71
72	// A time value that requests only snapshots created at or before the specified
73	// time. The time value is specified in ISO 8601 format. For more information about
74	// ISO 8601, go to the ISO8601 Wikipedia page.
75	// (http://en.wikipedia.org/wiki/ISO_8601) Example: 2012-07-16T18:00:00Z
76	EndTime *time.Time
77
78	// An optional parameter that specifies the starting point to return a set of
79	// response records. When the results of a DescribeClusterSnapshots request exceed
80	// the value specified in MaxRecords, AWS returns a value in the Marker field of
81	// the response. You can retrieve the next set of response records by providing the
82	// returned marker value in the Marker parameter and retrying the request.
83	Marker *string
84
85	// The maximum number of response records to return in each call. If the number of
86	// remaining response records exceeds the specified MaxRecords value, a value is
87	// returned in a marker field of the response. You can retrieve the next set of
88	// records by retrying the command with the returned marker value. Default: 100
89	// Constraints: minimum 20, maximum 100.
90	MaxRecords *int32
91
92	// The AWS customer account used to create or copy the snapshot. Use this field to
93	// filter the results to snapshots owned by a particular account. To describe
94	// snapshots you own, either specify your AWS customer account, or do not specify
95	// the parameter.
96	OwnerAccount *string
97
98	// The snapshot identifier of the snapshot about which to return information.
99	SnapshotIdentifier *string
100
101	// The type of snapshots for which you are requesting information. By default,
102	// snapshots of all types are returned. Valid Values: automated | manual
103	SnapshotType *string
104
105	//
106	SortingEntities []types.SnapshotSortingEntity
107
108	// A value that requests only snapshots created at or after the specified time. The
109	// time value is specified in ISO 8601 format. For more information about ISO 8601,
110	// go to the ISO8601 Wikipedia page. (http://en.wikipedia.org/wiki/ISO_8601)
111	// Example: 2012-07-16T18:00:00Z
112	StartTime *time.Time
113
114	// A tag key or keys for which you want to return all matching cluster snapshots
115	// that are associated with the specified key or keys. For example, suppose that
116	// you have snapshots that are tagged with keys called owner and environment. If
117	// you specify both of these tag keys in the request, Amazon Redshift returns a
118	// response with the snapshots that have either or both of these tag keys
119	// associated with them.
120	TagKeys []string
121
122	// A tag value or values for which you want to return all matching cluster
123	// snapshots that are associated with the specified tag value or values. For
124	// example, suppose that you have snapshots that are tagged with values called
125	// admin and test. If you specify both of these tag values in the request, Amazon
126	// Redshift returns a response with the snapshots that have either or both of these
127	// tag values associated with them.
128	TagValues []string
129}
130
131// Contains the output from the DescribeClusterSnapshots action.
132type DescribeClusterSnapshotsOutput struct {
133
134	// A value that indicates the starting point for the next set of response records
135	// in a subsequent request. If a value is returned in a response, you can retrieve
136	// the next set of records by providing this returned marker value in the Marker
137	// parameter and retrying the command. If the Marker field is empty, all response
138	// records have been retrieved for the request.
139	Marker *string
140
141	// A list of Snapshot instances.
142	Snapshots []types.Snapshot
143
144	// Metadata pertaining to the operation's result.
145	ResultMetadata middleware.Metadata
146}
147
148func addOperationDescribeClusterSnapshotsMiddlewares(stack *middleware.Stack, options Options) (err error) {
149	err = stack.Serialize.Add(&awsAwsquery_serializeOpDescribeClusterSnapshots{}, middleware.After)
150	if err != nil {
151		return err
152	}
153	err = stack.Deserialize.Add(&awsAwsquery_deserializeOpDescribeClusterSnapshots{}, middleware.After)
154	if err != nil {
155		return err
156	}
157	if err = addSetLoggerMiddleware(stack, options); err != nil {
158		return err
159	}
160	if err = awsmiddleware.AddClientRequestIDMiddleware(stack); err != nil {
161		return err
162	}
163	if err = smithyhttp.AddComputeContentLengthMiddleware(stack); err != nil {
164		return err
165	}
166	if err = addResolveEndpointMiddleware(stack, options); err != nil {
167		return err
168	}
169	if err = v4.AddComputePayloadSHA256Middleware(stack); err != nil {
170		return err
171	}
172	if err = addRetryMiddlewares(stack, options); err != nil {
173		return err
174	}
175	if err = addHTTPSignerV4Middleware(stack, options); err != nil {
176		return err
177	}
178	if err = awsmiddleware.AddRawResponseToMetadata(stack); err != nil {
179		return err
180	}
181	if err = awsmiddleware.AddRecordResponseTiming(stack); err != nil {
182		return err
183	}
184	if err = addClientUserAgent(stack); err != nil {
185		return err
186	}
187	if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil {
188		return err
189	}
190	if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil {
191		return err
192	}
193	if err = addOpDescribeClusterSnapshotsValidationMiddleware(stack); err != nil {
194		return err
195	}
196	if err = stack.Initialize.Add(newServiceMetadataMiddleware_opDescribeClusterSnapshots(options.Region), middleware.Before); err != nil {
197		return err
198	}
199	if err = addRequestIDRetrieverMiddleware(stack); err != nil {
200		return err
201	}
202	if err = addResponseErrorMiddleware(stack); err != nil {
203		return err
204	}
205	if err = addRequestResponseLogging(stack, options); err != nil {
206		return err
207	}
208	return nil
209}
210
211// DescribeClusterSnapshotsAPIClient is a client that implements the
212// DescribeClusterSnapshots operation.
213type DescribeClusterSnapshotsAPIClient interface {
214	DescribeClusterSnapshots(context.Context, *DescribeClusterSnapshotsInput, ...func(*Options)) (*DescribeClusterSnapshotsOutput, error)
215}
216
217var _ DescribeClusterSnapshotsAPIClient = (*Client)(nil)
218
219// DescribeClusterSnapshotsPaginatorOptions is the paginator options for
220// DescribeClusterSnapshots
221type DescribeClusterSnapshotsPaginatorOptions struct {
222	// The maximum number of response records to return in each call. If the number of
223	// remaining response records exceeds the specified MaxRecords value, a value is
224	// returned in a marker field of the response. You can retrieve the next set of
225	// records by retrying the command with the returned marker value. Default: 100
226	// Constraints: minimum 20, maximum 100.
227	Limit int32
228
229	// Set to true if pagination should stop if the service returns a pagination token
230	// that matches the most recent token provided to the service.
231	StopOnDuplicateToken bool
232}
233
234// DescribeClusterSnapshotsPaginator is a paginator for DescribeClusterSnapshots
235type DescribeClusterSnapshotsPaginator struct {
236	options   DescribeClusterSnapshotsPaginatorOptions
237	client    DescribeClusterSnapshotsAPIClient
238	params    *DescribeClusterSnapshotsInput
239	nextToken *string
240	firstPage bool
241}
242
243// NewDescribeClusterSnapshotsPaginator returns a new
244// DescribeClusterSnapshotsPaginator
245func NewDescribeClusterSnapshotsPaginator(client DescribeClusterSnapshotsAPIClient, params *DescribeClusterSnapshotsInput, optFns ...func(*DescribeClusterSnapshotsPaginatorOptions)) *DescribeClusterSnapshotsPaginator {
246	if params == nil {
247		params = &DescribeClusterSnapshotsInput{}
248	}
249
250	options := DescribeClusterSnapshotsPaginatorOptions{}
251	if params.MaxRecords != nil {
252		options.Limit = *params.MaxRecords
253	}
254
255	for _, fn := range optFns {
256		fn(&options)
257	}
258
259	return &DescribeClusterSnapshotsPaginator{
260		options:   options,
261		client:    client,
262		params:    params,
263		firstPage: true,
264	}
265}
266
267// HasMorePages returns a boolean indicating whether more pages are available
268func (p *DescribeClusterSnapshotsPaginator) HasMorePages() bool {
269	return p.firstPage || p.nextToken != nil
270}
271
272// NextPage retrieves the next DescribeClusterSnapshots page.
273func (p *DescribeClusterSnapshotsPaginator) NextPage(ctx context.Context, optFns ...func(*Options)) (*DescribeClusterSnapshotsOutput, error) {
274	if !p.HasMorePages() {
275		return nil, fmt.Errorf("no more pages available")
276	}
277
278	params := *p.params
279	params.Marker = p.nextToken
280
281	var limit *int32
282	if p.options.Limit > 0 {
283		limit = &p.options.Limit
284	}
285	params.MaxRecords = limit
286
287	result, err := p.client.DescribeClusterSnapshots(ctx, &params, optFns...)
288	if err != nil {
289		return nil, err
290	}
291	p.firstPage = false
292
293	prevToken := p.nextToken
294	p.nextToken = result.Marker
295
296	if p.options.StopOnDuplicateToken && prevToken != nil && p.nextToken != nil && *prevToken == *p.nextToken {
297		p.nextToken = nil
298	}
299
300	return result, nil
301}
302
303// SnapshotAvailableWaiterOptions are waiter options for SnapshotAvailableWaiter
304type SnapshotAvailableWaiterOptions struct {
305
306	// Set of options to modify how an operation is invoked. These apply to all
307	// operations invoked for this client. Use functional options on operation call to
308	// modify this list for per operation behavior.
309	APIOptions []func(*middleware.Stack) error
310
311	// MinDelay is the minimum amount of time to delay between retries. If unset,
312	// SnapshotAvailableWaiter will use default minimum delay of 15 seconds. Note that
313	// MinDelay must resolve to a value lesser than or equal to the MaxDelay.
314	MinDelay time.Duration
315
316	// MaxDelay is the maximum amount of time to delay between retries. If unset or set
317	// to zero, SnapshotAvailableWaiter will use default max delay of 120 seconds. Note
318	// that MaxDelay must resolve to value greater than or equal to the MinDelay.
319	MaxDelay time.Duration
320
321	// LogWaitAttempts is used to enable logging for waiter retry attempts
322	LogWaitAttempts bool
323
324	// Retryable is function that can be used to override the service defined
325	// waiter-behavior based on operation output, or returned error. This function is
326	// used by the waiter to decide if a state is retryable or a terminal state. By
327	// default service-modeled logic will populate this option. This option can thus be
328	// used to define a custom waiter state with fall-back to service-modeled waiter
329	// state mutators.The function returns an error in case of a failure state. In case
330	// of retry state, this function returns a bool value of true and nil error, while
331	// in case of success it returns a bool value of false and nil error.
332	Retryable func(context.Context, *DescribeClusterSnapshotsInput, *DescribeClusterSnapshotsOutput, error) (bool, error)
333}
334
335// SnapshotAvailableWaiter defines the waiters for SnapshotAvailable
336type SnapshotAvailableWaiter struct {
337	client DescribeClusterSnapshotsAPIClient
338
339	options SnapshotAvailableWaiterOptions
340}
341
342// NewSnapshotAvailableWaiter constructs a SnapshotAvailableWaiter.
343func NewSnapshotAvailableWaiter(client DescribeClusterSnapshotsAPIClient, optFns ...func(*SnapshotAvailableWaiterOptions)) *SnapshotAvailableWaiter {
344	options := SnapshotAvailableWaiterOptions{}
345	options.MinDelay = 15 * time.Second
346	options.MaxDelay = 120 * time.Second
347	options.Retryable = snapshotAvailableStateRetryable
348
349	for _, fn := range optFns {
350		fn(&options)
351	}
352	return &SnapshotAvailableWaiter{
353		client:  client,
354		options: options,
355	}
356}
357
358// Wait calls the waiter function for SnapshotAvailable waiter. The maxWaitDur is
359// the maximum wait duration the waiter will wait. The maxWaitDur is required and
360// must be greater than zero.
361func (w *SnapshotAvailableWaiter) Wait(ctx context.Context, params *DescribeClusterSnapshotsInput, maxWaitDur time.Duration, optFns ...func(*SnapshotAvailableWaiterOptions)) error {
362	if maxWaitDur <= 0 {
363		return fmt.Errorf("maximum wait time for waiter must be greater than zero")
364	}
365
366	options := w.options
367	for _, fn := range optFns {
368		fn(&options)
369	}
370
371	if options.MaxDelay <= 0 {
372		options.MaxDelay = 120 * time.Second
373	}
374
375	if options.MinDelay > options.MaxDelay {
376		return fmt.Errorf("minimum waiter delay %v must be lesser than or equal to maximum waiter delay of %v.", options.MinDelay, options.MaxDelay)
377	}
378
379	ctx, cancelFn := context.WithTimeout(ctx, maxWaitDur)
380	defer cancelFn()
381
382	logger := smithywaiter.Logger{}
383	remainingTime := maxWaitDur
384
385	var attempt int64
386	for {
387
388		attempt++
389		apiOptions := options.APIOptions
390		start := time.Now()
391
392		if options.LogWaitAttempts {
393			logger.Attempt = attempt
394			apiOptions = append([]func(*middleware.Stack) error{}, options.APIOptions...)
395			apiOptions = append(apiOptions, logger.AddLogger)
396		}
397
398		out, err := w.client.DescribeClusterSnapshots(ctx, params, func(o *Options) {
399			o.APIOptions = append(o.APIOptions, apiOptions...)
400		})
401
402		retryable, err := options.Retryable(ctx, params, out, err)
403		if err != nil {
404			return err
405		}
406		if !retryable {
407			return nil
408		}
409
410		remainingTime -= time.Since(start)
411		if remainingTime < options.MinDelay || remainingTime <= 0 {
412			break
413		}
414
415		// compute exponential backoff between waiter retries
416		delay, err := smithywaiter.ComputeDelay(
417			attempt, options.MinDelay, options.MaxDelay, remainingTime,
418		)
419		if err != nil {
420			return fmt.Errorf("error computing waiter delay, %w", err)
421		}
422
423		remainingTime -= delay
424		// sleep for the delay amount before invoking a request
425		if err := smithytime.SleepWithContext(ctx, delay); err != nil {
426			return fmt.Errorf("request cancelled while waiting, %w", err)
427		}
428	}
429	return fmt.Errorf("exceeded max wait time for SnapshotAvailable waiter")
430}
431
432func snapshotAvailableStateRetryable(ctx context.Context, input *DescribeClusterSnapshotsInput, output *DescribeClusterSnapshotsOutput, err error) (bool, error) {
433
434	if err == nil {
435		pathValue, err := jmespath.Search("Snapshots[].Status", output)
436		if err != nil {
437			return false, fmt.Errorf("error evaluating waiter state: %w", err)
438		}
439
440		expectedValue := "available"
441		var match = true
442		listOfValues, ok := pathValue.([]interface{})
443		if !ok {
444			return false, fmt.Errorf("waiter comparator expected list got %T", pathValue)
445		}
446
447		if len(listOfValues) == 0 {
448			match = false
449		}
450		for _, v := range listOfValues {
451			value, ok := v.(*string)
452			if !ok {
453				return false, fmt.Errorf("waiter comparator expected *string value, got %T", pathValue)
454			}
455
456			if string(*value) != expectedValue {
457				match = false
458			}
459		}
460
461		if match {
462			return false, nil
463		}
464	}
465
466	if err == nil {
467		pathValue, err := jmespath.Search("Snapshots[].Status", output)
468		if err != nil {
469			return false, fmt.Errorf("error evaluating waiter state: %w", err)
470		}
471
472		expectedValue := "failed"
473		listOfValues, ok := pathValue.([]interface{})
474		if !ok {
475			return false, fmt.Errorf("waiter comparator expected list got %T", pathValue)
476		}
477
478		for _, v := range listOfValues {
479			value, ok := v.(*string)
480			if !ok {
481				return false, fmt.Errorf("waiter comparator expected *string value, got %T", pathValue)
482			}
483
484			if string(*value) == expectedValue {
485				return false, fmt.Errorf("waiter state transitioned to Failure")
486			}
487		}
488	}
489
490	if err == nil {
491		pathValue, err := jmespath.Search("Snapshots[].Status", output)
492		if err != nil {
493			return false, fmt.Errorf("error evaluating waiter state: %w", err)
494		}
495
496		expectedValue := "deleted"
497		listOfValues, ok := pathValue.([]interface{})
498		if !ok {
499			return false, fmt.Errorf("waiter comparator expected list got %T", pathValue)
500		}
501
502		for _, v := range listOfValues {
503			value, ok := v.(*string)
504			if !ok {
505				return false, fmt.Errorf("waiter comparator expected *string value, got %T", pathValue)
506			}
507
508			if string(*value) == expectedValue {
509				return false, fmt.Errorf("waiter state transitioned to Failure")
510			}
511		}
512	}
513
514	return true, nil
515}
516
517func newServiceMetadataMiddleware_opDescribeClusterSnapshots(region string) *awsmiddleware.RegisterServiceMetadata {
518	return &awsmiddleware.RegisterServiceMetadata{
519		Region:        region,
520		ServiceID:     ServiceID,
521		SigningName:   "redshift",
522		OperationName: "DescribeClusterSnapshots",
523	}
524}
525