1// Code generated by smithy-go-codegen DO NOT EDIT.
2
3package ec2
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/ec2/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// Describes the specified EBS snapshots available to you or all of the EBS
20// snapshots available to you. The snapshots available to you include public
21// snapshots, private snapshots that you own, and private snapshots owned by other
22// AWS accounts for which you have explicit create volume permissions. The create
23// volume permissions fall into the following categories:
24//
25// * public: The owner of
26// the snapshot granted create volume permissions for the snapshot to the all
27// group. All AWS accounts have create volume permissions for these snapshots.
28//
29// *
30// explicit: The owner of the snapshot granted create volume permissions to a
31// specific AWS account.
32//
33// * implicit: An AWS account has implicit create volume
34// permissions for all snapshots it owns.
35//
36// The list of snapshots returned can be
37// filtered by specifying snapshot IDs, snapshot owners, or AWS accounts with
38// create volume permissions. If no options are specified, Amazon EC2 returns all
39// snapshots for which you have create volume permissions. If you specify one or
40// more snapshot IDs, only snapshots that have the specified IDs are returned. If
41// you specify an invalid snapshot ID, an error is returned. If you specify a
42// snapshot ID for which you do not have access, it is not included in the returned
43// results. If you specify one or more snapshot owners using the OwnerIds option,
44// only snapshots from the specified owners and for which you have access are
45// returned. The results can include the AWS account IDs of the specified owners,
46// amazon for snapshots owned by Amazon, or self for snapshots that you own. If you
47// specify a list of restorable users, only snapshots with create snapshot
48// permissions for those users are returned. You can specify AWS account IDs (if
49// you own the snapshots), self for snapshots for which you own or have explicit
50// permissions, or all for public snapshots. If you are describing a long list of
51// snapshots, we recommend that you paginate the output to make the list more
52// manageable. The MaxResults parameter sets the maximum number of results returned
53// in a single page. If the list of results exceeds your MaxResults value, then
54// that number of results is returned along with a NextToken value that can be
55// passed to a subsequent DescribeSnapshots request to retrieve the remaining
56// results. To get the state of fast snapshot restores for a snapshot, use
57// DescribeFastSnapshotRestores. For more information about EBS snapshots, see
58// Amazon EBS snapshots
59// (https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EBSSnapshots.html) in the
60// Amazon Elastic Compute Cloud User Guide.
61func (c *Client) DescribeSnapshots(ctx context.Context, params *DescribeSnapshotsInput, optFns ...func(*Options)) (*DescribeSnapshotsOutput, error) {
62	if params == nil {
63		params = &DescribeSnapshotsInput{}
64	}
65
66	result, metadata, err := c.invokeOperation(ctx, "DescribeSnapshots", params, optFns, addOperationDescribeSnapshotsMiddlewares)
67	if err != nil {
68		return nil, err
69	}
70
71	out := result.(*DescribeSnapshotsOutput)
72	out.ResultMetadata = metadata
73	return out, nil
74}
75
76type DescribeSnapshotsInput struct {
77
78	// Checks whether you have the required permissions for the action, without
79	// actually making the request, and provides an error response. If you have the
80	// required permissions, the error response is DryRunOperation. Otherwise, it is
81	// UnauthorizedOperation.
82	DryRun bool
83
84	// The filters.
85	//
86	// * description - A description of the snapshot.
87	//
88	// * encrypted -
89	// Indicates whether the snapshot is encrypted (true | false)
90	//
91	// * owner-alias - The
92	// owner alias, from an Amazon-maintained list (amazon). This is not the
93	// user-configured AWS account alias set using the IAM console. We recommend that
94	// you use the related parameter instead of this filter.
95	//
96	// * owner-id - The AWS
97	// account ID of the owner. We recommend that you use the related parameter instead
98	// of this filter.
99	//
100	// * progress - The progress of the snapshot, as a percentage (for
101	// example, 80%).
102	//
103	// * snapshot-id - The snapshot ID.
104	//
105	// * start-time - The time stamp
106	// when the snapshot was initiated.
107	//
108	// * status - The status of the snapshot (pending
109	// | completed | error).
110	//
111	// * tag: - The key/value combination of a tag assigned to
112	// the resource. Use the tag key in the filter name and the tag value as the filter
113	// value. For example, to find all resources that have a tag with the key Owner and
114	// the value TeamA, specify tag:Owner for the filter name and TeamA for the filter
115	// value.
116	//
117	// * tag-key - The key of a tag assigned to the resource. Use this filter
118	// to find all resources assigned a tag with a specific key, regardless of the tag
119	// value.
120	//
121	// * volume-id - The ID of the volume the snapshot is for.
122	//
123	// * volume-size -
124	// The size of the volume, in GiB.
125	Filters []types.Filter
126
127	// The maximum number of snapshot results returned by DescribeSnapshots in
128	// paginated output. When this parameter is used, DescribeSnapshots only returns
129	// MaxResults results in a single page along with a NextToken response element. The
130	// remaining results of the initial request can be seen by sending another
131	// DescribeSnapshots request with the returned NextToken value. This value can be
132	// between 5 and 1,000; if MaxResults is given a value larger than 1,000, only
133	// 1,000 results are returned. If this parameter is not used, then
134	// DescribeSnapshots returns all results. You cannot specify this parameter and the
135	// snapshot IDs parameter in the same request.
136	MaxResults int32
137
138	// The NextToken value returned from a previous paginated DescribeSnapshots request
139	// where MaxResults was used and the results exceeded the value of that parameter.
140	// Pagination continues from the end of the previous results that returned the
141	// NextToken value. This value is null when there are no more results to return.
142	NextToken *string
143
144	// Scopes the results to snapshots with the specified owners. You can specify a
145	// combination of AWS account IDs, self, and amazon.
146	OwnerIds []string
147
148	// The IDs of the AWS accounts that can create volumes from the snapshot.
149	RestorableByUserIds []string
150
151	// The snapshot IDs. Default: Describes the snapshots for which you have create
152	// volume permissions.
153	SnapshotIds []string
154}
155
156type DescribeSnapshotsOutput struct {
157
158	// The NextToken value to include in a future DescribeSnapshots request. When the
159	// results of a DescribeSnapshots request exceed MaxResults, this value can be used
160	// to retrieve the next page of results. This value is null when there are no more
161	// results to return.
162	NextToken *string
163
164	// Information about the snapshots.
165	Snapshots []types.Snapshot
166
167	// Metadata pertaining to the operation's result.
168	ResultMetadata middleware.Metadata
169}
170
171func addOperationDescribeSnapshotsMiddlewares(stack *middleware.Stack, options Options) (err error) {
172	err = stack.Serialize.Add(&awsEc2query_serializeOpDescribeSnapshots{}, middleware.After)
173	if err != nil {
174		return err
175	}
176	err = stack.Deserialize.Add(&awsEc2query_deserializeOpDescribeSnapshots{}, middleware.After)
177	if err != nil {
178		return err
179	}
180	if err = addSetLoggerMiddleware(stack, options); err != nil {
181		return err
182	}
183	if err = awsmiddleware.AddClientRequestIDMiddleware(stack); err != nil {
184		return err
185	}
186	if err = smithyhttp.AddComputeContentLengthMiddleware(stack); err != nil {
187		return err
188	}
189	if err = addResolveEndpointMiddleware(stack, options); err != nil {
190		return err
191	}
192	if err = v4.AddComputePayloadSHA256Middleware(stack); err != nil {
193		return err
194	}
195	if err = addRetryMiddlewares(stack, options); err != nil {
196		return err
197	}
198	if err = addHTTPSignerV4Middleware(stack, options); err != nil {
199		return err
200	}
201	if err = awsmiddleware.AddRawResponseToMetadata(stack); err != nil {
202		return err
203	}
204	if err = awsmiddleware.AddRecordResponseTiming(stack); err != nil {
205		return err
206	}
207	if err = addClientUserAgent(stack); err != nil {
208		return err
209	}
210	if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil {
211		return err
212	}
213	if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil {
214		return err
215	}
216	if err = stack.Initialize.Add(newServiceMetadataMiddleware_opDescribeSnapshots(options.Region), middleware.Before); err != nil {
217		return err
218	}
219	if err = addRequestIDRetrieverMiddleware(stack); err != nil {
220		return err
221	}
222	if err = addResponseErrorMiddleware(stack); err != nil {
223		return err
224	}
225	if err = addRequestResponseLogging(stack, options); err != nil {
226		return err
227	}
228	return nil
229}
230
231// DescribeSnapshotsAPIClient is a client that implements the DescribeSnapshots
232// operation.
233type DescribeSnapshotsAPIClient interface {
234	DescribeSnapshots(context.Context, *DescribeSnapshotsInput, ...func(*Options)) (*DescribeSnapshotsOutput, error)
235}
236
237var _ DescribeSnapshotsAPIClient = (*Client)(nil)
238
239// DescribeSnapshotsPaginatorOptions is the paginator options for DescribeSnapshots
240type DescribeSnapshotsPaginatorOptions struct {
241	// The maximum number of snapshot results returned by DescribeSnapshots in
242	// paginated output. When this parameter is used, DescribeSnapshots only returns
243	// MaxResults results in a single page along with a NextToken response element. The
244	// remaining results of the initial request can be seen by sending another
245	// DescribeSnapshots request with the returned NextToken value. This value can be
246	// between 5 and 1,000; if MaxResults is given a value larger than 1,000, only
247	// 1,000 results are returned. If this parameter is not used, then
248	// DescribeSnapshots returns all results. You cannot specify this parameter and the
249	// snapshot IDs parameter in the same request.
250	Limit int32
251
252	// Set to true if pagination should stop if the service returns a pagination token
253	// that matches the most recent token provided to the service.
254	StopOnDuplicateToken bool
255}
256
257// DescribeSnapshotsPaginator is a paginator for DescribeSnapshots
258type DescribeSnapshotsPaginator struct {
259	options   DescribeSnapshotsPaginatorOptions
260	client    DescribeSnapshotsAPIClient
261	params    *DescribeSnapshotsInput
262	nextToken *string
263	firstPage bool
264}
265
266// NewDescribeSnapshotsPaginator returns a new DescribeSnapshotsPaginator
267func NewDescribeSnapshotsPaginator(client DescribeSnapshotsAPIClient, params *DescribeSnapshotsInput, optFns ...func(*DescribeSnapshotsPaginatorOptions)) *DescribeSnapshotsPaginator {
268	options := DescribeSnapshotsPaginatorOptions{}
269	if params.MaxResults != 0 {
270		options.Limit = params.MaxResults
271	}
272
273	for _, fn := range optFns {
274		fn(&options)
275	}
276
277	if params == nil {
278		params = &DescribeSnapshotsInput{}
279	}
280
281	return &DescribeSnapshotsPaginator{
282		options:   options,
283		client:    client,
284		params:    params,
285		firstPage: true,
286	}
287}
288
289// HasMorePages returns a boolean indicating whether more pages are available
290func (p *DescribeSnapshotsPaginator) HasMorePages() bool {
291	return p.firstPage || p.nextToken != nil
292}
293
294// NextPage retrieves the next DescribeSnapshots page.
295func (p *DescribeSnapshotsPaginator) NextPage(ctx context.Context, optFns ...func(*Options)) (*DescribeSnapshotsOutput, error) {
296	if !p.HasMorePages() {
297		return nil, fmt.Errorf("no more pages available")
298	}
299
300	params := *p.params
301	params.NextToken = p.nextToken
302
303	params.MaxResults = p.options.Limit
304
305	result, err := p.client.DescribeSnapshots(ctx, &params, optFns...)
306	if err != nil {
307		return nil, err
308	}
309	p.firstPage = false
310
311	prevToken := p.nextToken
312	p.nextToken = result.NextToken
313
314	if p.options.StopOnDuplicateToken && prevToken != nil && p.nextToken != nil && *prevToken == *p.nextToken {
315		p.nextToken = nil
316	}
317
318	return result, nil
319}
320
321// SnapshotCompletedWaiterOptions are waiter options for SnapshotCompletedWaiter
322type SnapshotCompletedWaiterOptions struct {
323
324	// Set of options to modify how an operation is invoked. These apply to all
325	// operations invoked for this client. Use functional options on operation call to
326	// modify this list for per operation behavior.
327	APIOptions []func(*middleware.Stack) error
328
329	// MinDelay is the minimum amount of time to delay between retries. If unset,
330	// SnapshotCompletedWaiter will use default minimum delay of 15 seconds. Note that
331	// MinDelay must resolve to a value lesser than or equal to the MaxDelay.
332	MinDelay time.Duration
333
334	// MaxDelay is the maximum amount of time to delay between retries. If unset or set
335	// to zero, SnapshotCompletedWaiter will use default max delay of 120 seconds. Note
336	// that MaxDelay must resolve to value greater than or equal to the MinDelay.
337	MaxDelay time.Duration
338
339	// LogWaitAttempts is used to enable logging for waiter retry attempts
340	LogWaitAttempts bool
341
342	// Retryable is function that can be used to override the service defined
343	// waiter-behavior based on operation output, or returned error. This function is
344	// used by the waiter to decide if a state is retryable or a terminal state. By
345	// default service-modeled logic will populate this option. This option can thus be
346	// used to define a custom waiter state with fall-back to service-modeled waiter
347	// state mutators.The function returns an error in case of a failure state. In case
348	// of retry state, this function returns a bool value of true and nil error, while
349	// in case of success it returns a bool value of false and nil error.
350	Retryable func(context.Context, *DescribeSnapshotsInput, *DescribeSnapshotsOutput, error) (bool, error)
351}
352
353// SnapshotCompletedWaiter defines the waiters for SnapshotCompleted
354type SnapshotCompletedWaiter struct {
355	client DescribeSnapshotsAPIClient
356
357	options SnapshotCompletedWaiterOptions
358}
359
360// NewSnapshotCompletedWaiter constructs a SnapshotCompletedWaiter.
361func NewSnapshotCompletedWaiter(client DescribeSnapshotsAPIClient, optFns ...func(*SnapshotCompletedWaiterOptions)) *SnapshotCompletedWaiter {
362	options := SnapshotCompletedWaiterOptions{}
363	options.MinDelay = 15 * time.Second
364	options.MaxDelay = 120 * time.Second
365	options.Retryable = snapshotCompletedStateRetryable
366
367	for _, fn := range optFns {
368		fn(&options)
369	}
370	return &SnapshotCompletedWaiter{
371		client:  client,
372		options: options,
373	}
374}
375
376// Wait calls the waiter function for SnapshotCompleted waiter. The maxWaitDur is
377// the maximum wait duration the waiter will wait. The maxWaitDur is required and
378// must be greater than zero.
379func (w *SnapshotCompletedWaiter) Wait(ctx context.Context, params *DescribeSnapshotsInput, maxWaitDur time.Duration, optFns ...func(*SnapshotCompletedWaiterOptions)) error {
380	if maxWaitDur <= 0 {
381		return fmt.Errorf("maximum wait time for waiter must be greater than zero")
382	}
383
384	options := w.options
385	for _, fn := range optFns {
386		fn(&options)
387	}
388
389	if options.MaxDelay <= 0 {
390		options.MaxDelay = 120 * time.Second
391	}
392
393	if options.MinDelay > options.MaxDelay {
394		return fmt.Errorf("minimum waiter delay %v must be lesser than or equal to maximum waiter delay of %v.", options.MinDelay, options.MaxDelay)
395	}
396
397	ctx, cancelFn := context.WithTimeout(ctx, maxWaitDur)
398	defer cancelFn()
399
400	logger := smithywaiter.Logger{}
401	remainingTime := maxWaitDur
402
403	var attempt int64
404	for {
405
406		attempt++
407		apiOptions := options.APIOptions
408		start := time.Now()
409
410		if options.LogWaitAttempts {
411			logger.Attempt = attempt
412			apiOptions = append([]func(*middleware.Stack) error{}, options.APIOptions...)
413			apiOptions = append(apiOptions, logger.AddLogger)
414		}
415
416		out, err := w.client.DescribeSnapshots(ctx, params, func(o *Options) {
417			o.APIOptions = append(o.APIOptions, apiOptions...)
418		})
419
420		retryable, err := options.Retryable(ctx, params, out, err)
421		if err != nil {
422			return err
423		}
424		if !retryable {
425			return nil
426		}
427
428		remainingTime -= time.Since(start)
429		if remainingTime < options.MinDelay || remainingTime <= 0 {
430			break
431		}
432
433		// compute exponential backoff between waiter retries
434		delay, err := smithywaiter.ComputeDelay(
435			attempt, options.MinDelay, options.MaxDelay, remainingTime,
436		)
437		if err != nil {
438			return fmt.Errorf("error computing waiter delay, %w", err)
439		}
440
441		remainingTime -= delay
442		// sleep for the delay amount before invoking a request
443		if err := smithytime.SleepWithContext(ctx, delay); err != nil {
444			return fmt.Errorf("request cancelled while waiting, %w", err)
445		}
446	}
447	return fmt.Errorf("exceeded max wait time for SnapshotCompleted waiter")
448}
449
450func snapshotCompletedStateRetryable(ctx context.Context, input *DescribeSnapshotsInput, output *DescribeSnapshotsOutput, err error) (bool, error) {
451
452	if err == nil {
453		pathValue, err := jmespath.Search("Snapshots[].State", output)
454		if err != nil {
455			return false, fmt.Errorf("error evaluating waiter state: %w", err)
456		}
457
458		expectedValue := "completed"
459		var match = true
460		listOfValues, ok := pathValue.([]interface{})
461		if !ok {
462			return false, fmt.Errorf("waiter comparator expected list got %T", pathValue)
463		}
464
465		if len(listOfValues) == 0 {
466			match = false
467		}
468		for _, v := range listOfValues {
469			value, ok := v.(types.SnapshotState)
470			if !ok {
471				return false, fmt.Errorf("waiter comparator expected types.SnapshotState value, got %T", pathValue)
472			}
473
474			if string(value) != expectedValue {
475				match = false
476			}
477		}
478
479		if match {
480			return false, nil
481		}
482	}
483
484	return true, nil
485}
486
487func newServiceMetadataMiddleware_opDescribeSnapshots(region string) *awsmiddleware.RegisterServiceMetadata {
488	return &awsmiddleware.RegisterServiceMetadata{
489		Region:        region,
490		ServiceID:     ServiceID,
491		SigningName:   "ec2",
492		OperationName: "DescribeSnapshots",
493	}
494}
495