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 images (AMIs, AKIs, and ARIs) available to you or all of
20// the images available to you. The images available to you include public images,
21// private images that you own, and private images owned by other AWS accounts for
22// which you have explicit launch permissions. Recently deregistered images appear
23// in the returned results for a short interval and then return empty results.
24// After all instances that reference a deregistered AMI are terminated, specifying
25// the ID of the image results in an error indicating that the AMI ID cannot be
26// found.
27func (c *Client) DescribeImages(ctx context.Context, params *DescribeImagesInput, optFns ...func(*Options)) (*DescribeImagesOutput, error) {
28	if params == nil {
29		params = &DescribeImagesInput{}
30	}
31
32	result, metadata, err := c.invokeOperation(ctx, "DescribeImages", params, optFns, addOperationDescribeImagesMiddlewares)
33	if err != nil {
34		return nil, err
35	}
36
37	out := result.(*DescribeImagesOutput)
38	out.ResultMetadata = metadata
39	return out, nil
40}
41
42type DescribeImagesInput struct {
43
44	// Checks whether you have the required permissions for the action, without
45	// actually making the request, and provides an error response. If you have the
46	// required permissions, the error response is DryRunOperation. Otherwise, it is
47	// UnauthorizedOperation.
48	DryRun bool
49
50	// Scopes the images by users with explicit launch permissions. Specify an AWS
51	// account ID, self (the sender of the request), or all (public AMIs).
52	ExecutableUsers []string
53
54	// The filters.
55	//
56	// * architecture - The image architecture (i386 | x86_64 |
57	// arm64).
58	//
59	// * block-device-mapping.delete-on-termination - A Boolean value that
60	// indicates whether the Amazon EBS volume is deleted on instance termination.
61	//
62	// *
63	// block-device-mapping.device-name - The device name specified in the block device
64	// mapping (for example, /dev/sdh or xvdh).
65	//
66	// * block-device-mapping.snapshot-id -
67	// The ID of the snapshot used for the EBS volume.
68	//
69	// *
70	// block-device-mapping.volume-size - The volume size of the EBS volume, in GiB.
71	//
72	// *
73	// block-device-mapping.volume-type - The volume type of the EBS volume (gp2 | io1
74	// | io2 | st1 | sc1 | standard).
75	//
76	// * block-device-mapping.encrypted - A Boolean
77	// that indicates whether the EBS volume is encrypted.
78	//
79	// * description - The
80	// description of the image (provided during image creation).
81	//
82	// * ena-support - A
83	// Boolean that indicates whether enhanced networking with ENA is enabled.
84	//
85	// *
86	// hypervisor - The hypervisor type (ovm | xen).
87	//
88	// * image-id - The ID of the
89	// image.
90	//
91	// * image-type - The image type (machine | kernel | ramdisk).
92	//
93	// * is-public
94	// - A Boolean that indicates whether the image is public.
95	//
96	// * kernel-id - The
97	// kernel ID.
98	//
99	// * manifest-location - The location of the image manifest.
100	//
101	// * name -
102	// The name of the AMI (provided during image creation).
103	//
104	// * owner-alias - The owner
105	// alias, from an Amazon-maintained list (amazon | aws-marketplace). This is not
106	// the user-configured AWS account alias set using the IAM console. We recommend
107	// that you use the related parameter instead of this filter.
108	//
109	// * owner-id - The AWS
110	// account ID of the owner. We recommend that you use the related parameter instead
111	// of this filter.
112	//
113	// * platform - The platform. To only list Windows-based AMIs, use
114	// windows.
115	//
116	// * product-code - The product code.
117	//
118	// * product-code.type - The type of
119	// the product code (devpay | marketplace).
120	//
121	// * ramdisk-id - The RAM disk ID.
122	//
123	// *
124	// root-device-name - The device name of the root device volume (for example,
125	// /dev/sda1).
126	//
127	// * root-device-type - The type of the root device volume (ebs |
128	// instance-store).
129	//
130	// * state - The state of the image (available | pending |
131	// failed).
132	//
133	// * state-reason-code - The reason code for the state change.
134	//
135	// *
136	// state-reason-message - The message for the state change.
137	//
138	// * sriov-net-support -
139	// A value of simple indicates that enhanced networking with the Intel 82599 VF
140	// interface is enabled.
141	//
142	// * tag: - The key/value combination of a tag assigned to
143	// the resource. Use the tag key in the filter name and the tag value as the filter
144	// value. For example, to find all resources that have a tag with the key Owner and
145	// the value TeamA, specify tag:Owner for the filter name and TeamA for the filter
146	// value.
147	//
148	// * tag-key - The key of a tag assigned to the resource. Use this filter
149	// to find all resources assigned a tag with a specific key, regardless of the tag
150	// value.
151	//
152	// * virtualization-type - The virtualization type (paravirtual | hvm).
153	Filters []types.Filter
154
155	// The image IDs. Default: Describes all images available to you.
156	ImageIds []string
157
158	// Scopes the results to images with the specified owners. You can specify a
159	// combination of AWS account IDs, self, amazon, and aws-marketplace. If you omit
160	// this parameter, the results include all images for which you have launch
161	// permissions, regardless of ownership.
162	Owners []string
163}
164
165type DescribeImagesOutput struct {
166
167	// Information about the images.
168	Images []types.Image
169
170	// Metadata pertaining to the operation's result.
171	ResultMetadata middleware.Metadata
172}
173
174func addOperationDescribeImagesMiddlewares(stack *middleware.Stack, options Options) (err error) {
175	err = stack.Serialize.Add(&awsEc2query_serializeOpDescribeImages{}, middleware.After)
176	if err != nil {
177		return err
178	}
179	err = stack.Deserialize.Add(&awsEc2query_deserializeOpDescribeImages{}, middleware.After)
180	if err != nil {
181		return err
182	}
183	if err = addSetLoggerMiddleware(stack, options); err != nil {
184		return err
185	}
186	if err = awsmiddleware.AddClientRequestIDMiddleware(stack); err != nil {
187		return err
188	}
189	if err = smithyhttp.AddComputeContentLengthMiddleware(stack); err != nil {
190		return err
191	}
192	if err = addResolveEndpointMiddleware(stack, options); err != nil {
193		return err
194	}
195	if err = v4.AddComputePayloadSHA256Middleware(stack); err != nil {
196		return err
197	}
198	if err = addRetryMiddlewares(stack, options); err != nil {
199		return err
200	}
201	if err = addHTTPSignerV4Middleware(stack, options); err != nil {
202		return err
203	}
204	if err = awsmiddleware.AddRawResponseToMetadata(stack); err != nil {
205		return err
206	}
207	if err = awsmiddleware.AddRecordResponseTiming(stack); err != nil {
208		return err
209	}
210	if err = addClientUserAgent(stack); err != nil {
211		return err
212	}
213	if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil {
214		return err
215	}
216	if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil {
217		return err
218	}
219	if err = stack.Initialize.Add(newServiceMetadataMiddleware_opDescribeImages(options.Region), middleware.Before); err != nil {
220		return err
221	}
222	if err = addRequestIDRetrieverMiddleware(stack); err != nil {
223		return err
224	}
225	if err = addResponseErrorMiddleware(stack); err != nil {
226		return err
227	}
228	if err = addRequestResponseLogging(stack, options); err != nil {
229		return err
230	}
231	return nil
232}
233
234// DescribeImagesAPIClient is a client that implements the DescribeImages
235// operation.
236type DescribeImagesAPIClient interface {
237	DescribeImages(context.Context, *DescribeImagesInput, ...func(*Options)) (*DescribeImagesOutput, error)
238}
239
240var _ DescribeImagesAPIClient = (*Client)(nil)
241
242// ImageAvailableWaiterOptions are waiter options for ImageAvailableWaiter
243type ImageAvailableWaiterOptions struct {
244
245	// Set of options to modify how an operation is invoked. These apply to all
246	// operations invoked for this client. Use functional options on operation call to
247	// modify this list for per operation behavior.
248	APIOptions []func(*middleware.Stack) error
249
250	// MinDelay is the minimum amount of time to delay between retries. If unset,
251	// ImageAvailableWaiter will use default minimum delay of 15 seconds. Note that
252	// MinDelay must resolve to a value lesser than or equal to the MaxDelay.
253	MinDelay time.Duration
254
255	// MaxDelay is the maximum amount of time to delay between retries. If unset or set
256	// to zero, ImageAvailableWaiter will use default max delay of 120 seconds. Note
257	// that MaxDelay must resolve to value greater than or equal to the MinDelay.
258	MaxDelay time.Duration
259
260	// LogWaitAttempts is used to enable logging for waiter retry attempts
261	LogWaitAttempts bool
262
263	// Retryable is function that can be used to override the service defined
264	// waiter-behavior based on operation output, or returned error. This function is
265	// used by the waiter to decide if a state is retryable or a terminal state. By
266	// default service-modeled logic will populate this option. This option can thus be
267	// used to define a custom waiter state with fall-back to service-modeled waiter
268	// state mutators.The function returns an error in case of a failure state. In case
269	// of retry state, this function returns a bool value of true and nil error, while
270	// in case of success it returns a bool value of false and nil error.
271	Retryable func(context.Context, *DescribeImagesInput, *DescribeImagesOutput, error) (bool, error)
272}
273
274// ImageAvailableWaiter defines the waiters for ImageAvailable
275type ImageAvailableWaiter struct {
276	client DescribeImagesAPIClient
277
278	options ImageAvailableWaiterOptions
279}
280
281// NewImageAvailableWaiter constructs a ImageAvailableWaiter.
282func NewImageAvailableWaiter(client DescribeImagesAPIClient, optFns ...func(*ImageAvailableWaiterOptions)) *ImageAvailableWaiter {
283	options := ImageAvailableWaiterOptions{}
284	options.MinDelay = 15 * time.Second
285	options.MaxDelay = 120 * time.Second
286	options.Retryable = imageAvailableStateRetryable
287
288	for _, fn := range optFns {
289		fn(&options)
290	}
291	return &ImageAvailableWaiter{
292		client:  client,
293		options: options,
294	}
295}
296
297// Wait calls the waiter function for ImageAvailable waiter. The maxWaitDur is the
298// maximum wait duration the waiter will wait. The maxWaitDur is required and must
299// be greater than zero.
300func (w *ImageAvailableWaiter) Wait(ctx context.Context, params *DescribeImagesInput, maxWaitDur time.Duration, optFns ...func(*ImageAvailableWaiterOptions)) error {
301	if maxWaitDur <= 0 {
302		return fmt.Errorf("maximum wait time for waiter must be greater than zero")
303	}
304
305	options := w.options
306	for _, fn := range optFns {
307		fn(&options)
308	}
309
310	if options.MaxDelay <= 0 {
311		options.MaxDelay = 120 * time.Second
312	}
313
314	if options.MinDelay > options.MaxDelay {
315		return fmt.Errorf("minimum waiter delay %v must be lesser than or equal to maximum waiter delay of %v.", options.MinDelay, options.MaxDelay)
316	}
317
318	ctx, cancelFn := context.WithTimeout(ctx, maxWaitDur)
319	defer cancelFn()
320
321	logger := smithywaiter.Logger{}
322	remainingTime := maxWaitDur
323
324	var attempt int64
325	for {
326
327		attempt++
328		apiOptions := options.APIOptions
329		start := time.Now()
330
331		if options.LogWaitAttempts {
332			logger.Attempt = attempt
333			apiOptions = append([]func(*middleware.Stack) error{}, options.APIOptions...)
334			apiOptions = append(apiOptions, logger.AddLogger)
335		}
336
337		out, err := w.client.DescribeImages(ctx, params, func(o *Options) {
338			o.APIOptions = append(o.APIOptions, apiOptions...)
339		})
340
341		retryable, err := options.Retryable(ctx, params, out, err)
342		if err != nil {
343			return err
344		}
345		if !retryable {
346			return nil
347		}
348
349		remainingTime -= time.Since(start)
350		if remainingTime < options.MinDelay || remainingTime <= 0 {
351			break
352		}
353
354		// compute exponential backoff between waiter retries
355		delay, err := smithywaiter.ComputeDelay(
356			attempt, options.MinDelay, options.MaxDelay, remainingTime,
357		)
358		if err != nil {
359			return fmt.Errorf("error computing waiter delay, %w", err)
360		}
361
362		remainingTime -= delay
363		// sleep for the delay amount before invoking a request
364		if err := smithytime.SleepWithContext(ctx, delay); err != nil {
365			return fmt.Errorf("request cancelled while waiting, %w", err)
366		}
367	}
368	return fmt.Errorf("exceeded max wait time for ImageAvailable waiter")
369}
370
371func imageAvailableStateRetryable(ctx context.Context, input *DescribeImagesInput, output *DescribeImagesOutput, err error) (bool, error) {
372
373	if err == nil {
374		pathValue, err := jmespath.Search("Images[].State", output)
375		if err != nil {
376			return false, fmt.Errorf("error evaluating waiter state: %w", err)
377		}
378
379		expectedValue := "available"
380		var match = true
381		listOfValues, ok := pathValue.([]interface{})
382		if !ok {
383			return false, fmt.Errorf("waiter comparator expected list got %T", pathValue)
384		}
385
386		if len(listOfValues) == 0 {
387			match = false
388		}
389		for _, v := range listOfValues {
390			value, ok := v.(types.ImageState)
391			if !ok {
392				return false, fmt.Errorf("waiter comparator expected types.ImageState value, got %T", pathValue)
393			}
394
395			if string(value) != expectedValue {
396				match = false
397			}
398		}
399
400		if match {
401			return false, nil
402		}
403	}
404
405	if err == nil {
406		pathValue, err := jmespath.Search("Images[].State", output)
407		if err != nil {
408			return false, fmt.Errorf("error evaluating waiter state: %w", err)
409		}
410
411		expectedValue := "failed"
412		listOfValues, ok := pathValue.([]interface{})
413		if !ok {
414			return false, fmt.Errorf("waiter comparator expected list got %T", pathValue)
415		}
416
417		for _, v := range listOfValues {
418			value, ok := v.(types.ImageState)
419			if !ok {
420				return false, fmt.Errorf("waiter comparator expected types.ImageState value, got %T", pathValue)
421			}
422
423			if string(value) == expectedValue {
424				return false, fmt.Errorf("waiter state transitioned to Failure")
425			}
426		}
427	}
428
429	return true, nil
430}
431
432func newServiceMetadataMiddleware_opDescribeImages(region string) *awsmiddleware.RegisterServiceMetadata {
433	return &awsmiddleware.RegisterServiceMetadata{
434		Region:        region,
435		ServiceID:     ServiceID,
436		SigningName:   "ec2",
437		OperationName: "DescribeImages",
438	}
439}
440