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 instances or all instances. If you specify instance IDs,
20// the output includes information for only the specified instances. If you specify
21// filters, the output includes information for only those instances that meet the
22// filter criteria. If you do not specify instance IDs or filters, the output
23// includes information for all instances, which can affect performance. We
24// recommend that you use pagination to ensure that the operation returns quickly
25// and successfully. If you specify an instance ID that is not valid, an error is
26// returned. If you specify an instance that you do not own, it is not included in
27// the output. Recently terminated instances might appear in the returned results.
28// This interval is usually less than one hour. If you describe instances in the
29// rare case where an Availability Zone is experiencing a service disruption and
30// you specify instance IDs that are in the affected zone, or do not specify any
31// instance IDs at all, the call fails. If you describe instances and specify only
32// instance IDs that are in an unaffected zone, the call works normally.
33func (c *Client) DescribeInstances(ctx context.Context, params *DescribeInstancesInput, optFns ...func(*Options)) (*DescribeInstancesOutput, error) {
34	if params == nil {
35		params = &DescribeInstancesInput{}
36	}
37
38	result, metadata, err := c.invokeOperation(ctx, "DescribeInstances", params, optFns, addOperationDescribeInstancesMiddlewares)
39	if err != nil {
40		return nil, err
41	}
42
43	out := result.(*DescribeInstancesOutput)
44	out.ResultMetadata = metadata
45	return out, nil
46}
47
48type DescribeInstancesInput struct {
49
50	// Checks whether you have the required permissions for the action, without
51	// actually making the request, and provides an error response. If you have the
52	// required permissions, the error response is DryRunOperation. Otherwise, it is
53	// UnauthorizedOperation.
54	DryRun bool
55
56	// The filters.
57	//
58	// * affinity - The affinity setting for an instance running on a
59	// Dedicated Host (default | host).
60	//
61	// * architecture - The instance architecture
62	// (i386 | x86_64 | arm64).
63	//
64	// * availability-zone - The Availability Zone of the
65	// instance.
66	//
67	// * block-device-mapping.attach-time - The attach time for an EBS
68	// volume mapped to the instance, for example, 2010-09-15T17:15:20.000Z.
69	//
70	// *
71	// block-device-mapping.delete-on-termination - A Boolean that indicates whether
72	// the EBS volume is deleted on instance termination.
73	//
74	// *
75	// block-device-mapping.device-name - The device name specified in the block device
76	// mapping (for example, /dev/sdh or xvdh).
77	//
78	// * block-device-mapping.status - The
79	// status for the EBS volume (attaching | attached | detaching | detached).
80	//
81	// *
82	// block-device-mapping.volume-id - The volume ID of the EBS volume.
83	//
84	// *
85	// client-token - The idempotency token you provided when you launched the
86	// instance.
87	//
88	// * dns-name - The public DNS name of the instance.
89	//
90	// * group-id - The
91	// ID of the security group for the instance. EC2-Classic only.
92	//
93	// * group-name - The
94	// name of the security group for the instance. EC2-Classic only.
95	//
96	// *
97	// hibernation-options.configured - A Boolean that indicates whether the instance
98	// is enabled for hibernation. A value of true means that the instance is enabled
99	// for hibernation.
100	//
101	// * host-id - The ID of the Dedicated Host on which the instance
102	// is running, if applicable.
103	//
104	// * hypervisor - The hypervisor type of the instance
105	// (ovm | xen). The value xen is used for both Xen and Nitro hypervisors.
106	//
107	// *
108	// iam-instance-profile.arn - The instance profile associated with the instance.
109	// Specified as an ARN.
110	//
111	// * image-id - The ID of the image used to launch the
112	// instance.
113	//
114	// * instance-id - The ID of the instance.
115	//
116	// * instance-lifecycle -
117	// Indicates whether this is a Spot Instance or a Scheduled Instance (spot |
118	// scheduled).
119	//
120	// * instance-state-code - The state of the instance, as a 16-bit
121	// unsigned integer. The high byte is used for internal purposes and should be
122	// ignored. The low byte is set based on the state represented. The valid values
123	// are: 0 (pending), 16 (running), 32 (shutting-down), 48 (terminated), 64
124	// (stopping), and 80 (stopped).
125	//
126	// * instance-state-name - The state of the instance
127	// (pending | running | shutting-down | terminated | stopping | stopped).
128	//
129	// *
130	// instance-type - The type of instance (for example, t2.micro).
131	//
132	// *
133	// instance.group-id - The ID of the security group for the instance.
134	//
135	// *
136	// instance.group-name - The name of the security group for the instance.
137	//
138	// *
139	// ip-address - The public IPv4 address of the instance.
140	//
141	// * kernel-id - The kernel
142	// ID.
143	//
144	// * key-name - The name of the key pair used when the instance was
145	// launched.
146	//
147	// * launch-index - When launching multiple instances, this is the index
148	// for the instance in the launch group (for example, 0, 1, 2, and so on).
149	//
150	// *
151	// launch-time - The time when the instance was launched.
152	//
153	// *
154	// metadata-options.http-tokens - The metadata request authorization state
155	// (optional | required)
156	//
157	// * metadata-options.http-put-response-hop-limit - The http
158	// metadata request put response hop limit (integer, possible values 1 to 64)
159	//
160	// *
161	// metadata-options.http-endpoint - Enable or disable metadata access on http
162	// endpoint (enabled | disabled)
163	//
164	// * monitoring-state - Indicates whether detailed
165	// monitoring is enabled (disabled | enabled).
166	//
167	// *
168	// network-interface.addresses.private-ip-address - The private IPv4 address
169	// associated with the network interface.
170	//
171	// * network-interface.addresses.primary -
172	// Specifies whether the IPv4 address of the network interface is the primary
173	// private IPv4 address.
174	//
175	// * network-interface.addresses.association.public-ip - The
176	// ID of the association of an Elastic IP address (IPv4) with a network
177	// interface.
178	//
179	// * network-interface.addresses.association.ip-owner-id - The owner ID
180	// of the private IPv4 address associated with the network interface.
181	//
182	// *
183	// network-interface.association.public-ip - The address of the Elastic IP address
184	// (IPv4) bound to the network interface.
185	//
186	// *
187	// network-interface.association.ip-owner-id - The owner of the Elastic IP address
188	// (IPv4) associated with the network interface.
189	//
190	// *
191	// network-interface.association.allocation-id - The allocation ID returned when
192	// you allocated the Elastic IP address (IPv4) for your network interface.
193	//
194	// *
195	// network-interface.association.association-id - The association ID returned when
196	// the network interface was associated with an IPv4 address.
197	//
198	// *
199	// network-interface.attachment.attachment-id - The ID of the interface
200	// attachment.
201	//
202	// * network-interface.attachment.instance-id - The ID of the instance
203	// to which the network interface is attached.
204	//
205	// *
206	// network-interface.attachment.instance-owner-id - The owner ID of the instance to
207	// which the network interface is attached.
208	//
209	// *
210	// network-interface.attachment.device-index - The device index to which the
211	// network interface is attached.
212	//
213	// * network-interface.attachment.status - The
214	// status of the attachment (attaching | attached | detaching | detached).
215	//
216	// *
217	// network-interface.attachment.attach-time - The time that the network interface
218	// was attached to an instance.
219	//
220	// *
221	// network-interface.attachment.delete-on-termination - Specifies whether the
222	// attachment is deleted when an instance is terminated.
223	//
224	// *
225	// network-interface.availability-zone - The Availability Zone for the network
226	// interface.
227	//
228	// * network-interface.description - The description of the network
229	// interface.
230	//
231	// * network-interface.group-id - The ID of a security group associated
232	// with the network interface.
233	//
234	// * network-interface.group-name - The name of a
235	// security group associated with the network interface.
236	//
237	// *
238	// network-interface.ipv6-addresses.ipv6-address - The IPv6 address associated with
239	// the network interface.
240	//
241	// * network-interface.mac-address - The MAC address of the
242	// network interface.
243	//
244	// * network-interface.network-interface-id - The ID of the
245	// network interface.
246	//
247	// * network-interface.owner-id - The ID of the owner of the
248	// network interface.
249	//
250	// * network-interface.private-dns-name - The private DNS name
251	// of the network interface.
252	//
253	// * network-interface.requester-id - The requester ID
254	// for the network interface.
255	//
256	// * network-interface.requester-managed - Indicates
257	// whether the network interface is being managed by AWS.
258	//
259	// *
260	// network-interface.status - The status of the network interface (available) |
261	// in-use).
262	//
263	// * network-interface.source-dest-check - Whether the network interface
264	// performs source/destination checking. A value of true means that checking is
265	// enabled, and false means that checking is disabled. The value must be false for
266	// the network interface to perform network address translation (NAT) in your
267	// VPC.
268	//
269	// * network-interface.subnet-id - The ID of the subnet for the network
270	// interface.
271	//
272	// * network-interface.vpc-id - The ID of the VPC for the network
273	// interface.
274	//
275	// * owner-id - The AWS account ID of the instance owner.
276	//
277	// *
278	// placement-group-name - The name of the placement group for the instance.
279	//
280	// *
281	// placement-partition-number - The partition in which the instance is located.
282	//
283	// *
284	// platform - The platform. To list only Windows instances, use windows.
285	//
286	// *
287	// private-dns-name - The private IPv4 DNS name of the instance.
288	//
289	// *
290	// private-ip-address - The private IPv4 address of the instance.
291	//
292	// * product-code -
293	// The product code associated with the AMI used to launch the instance.
294	//
295	// *
296	// product-code.type - The type of product code (devpay | marketplace).
297	//
298	// *
299	// ramdisk-id - The RAM disk ID.
300	//
301	// * reason - The reason for the current state of
302	// the instance (for example, shows "User Initiated [date]" when you stop or
303	// terminate the instance). Similar to the state-reason-code filter.
304	//
305	// *
306	// requester-id - The ID of the entity that launched the instance on your behalf
307	// (for example, AWS Management Console, Auto Scaling, and so on).
308	//
309	// *
310	// reservation-id - The ID of the instance's reservation. A reservation ID is
311	// created any time you launch an instance. A reservation ID has a one-to-one
312	// relationship with an instance launch request, but can be associated with more
313	// than one instance if you launch multiple instances using the same launch
314	// request. For example, if you launch one instance, you get one reservation ID. If
315	// you launch ten instances using the same launch request, you also get one
316	// reservation ID.
317	//
318	// * root-device-name - The device name of the root device volume
319	// (for example, /dev/sda1).
320	//
321	// * root-device-type - The type of the root device
322	// volume (ebs | instance-store).
323	//
324	// * source-dest-check - Indicates whether the
325	// instance performs source/destination checking. A value of true means that
326	// checking is enabled, and false means that checking is disabled. The value must
327	// be false for the instance to perform network address translation (NAT) in your
328	// VPC.
329	//
330	// * spot-instance-request-id - The ID of the Spot Instance request.
331	//
332	// *
333	// state-reason-code - The reason code for the state change.
334	//
335	// *
336	// state-reason-message - A message that describes the state change.
337	//
338	// * subnet-id -
339	// The ID of the subnet for the instance.
340	//
341	// * tag: - The key/value combination of a
342	// tag assigned to the resource. Use the tag key in the filter name and the tag
343	// value as the filter value. For example, to find all resources that have a tag
344	// with the key Owner and the value TeamA, specify tag:Owner for the filter name
345	// and TeamA for the filter value.
346	//
347	// * tag-key - The key of a tag assigned to the
348	// resource. Use this filter to find all resources that have a tag with a specific
349	// key, regardless of the tag value.
350	//
351	// * tenancy - The tenancy of an instance
352	// (dedicated | default | host).
353	//
354	// * virtualization-type - The virtualization type
355	// of the instance (paravirtual | hvm).
356	//
357	// * vpc-id - The ID of the VPC that the
358	// instance is running in.
359	Filters []types.Filter
360
361	// The instance IDs. Default: Describes all your instances.
362	InstanceIds []string
363
364	// The maximum number of results to return in a single call. To retrieve the
365	// remaining results, make another call with the returned NextToken value. This
366	// value can be between 5 and 1000. You cannot specify this parameter and the
367	// instance IDs parameter in the same call.
368	MaxResults int32
369
370	// The token to request the next page of results.
371	NextToken *string
372}
373
374type DescribeInstancesOutput struct {
375
376	// The token to use to retrieve the next page of results. This value is null when
377	// there are no more results to return.
378	NextToken *string
379
380	// Information about the reservations.
381	Reservations []types.Reservation
382
383	// Metadata pertaining to the operation's result.
384	ResultMetadata middleware.Metadata
385}
386
387func addOperationDescribeInstancesMiddlewares(stack *middleware.Stack, options Options) (err error) {
388	err = stack.Serialize.Add(&awsEc2query_serializeOpDescribeInstances{}, middleware.After)
389	if err != nil {
390		return err
391	}
392	err = stack.Deserialize.Add(&awsEc2query_deserializeOpDescribeInstances{}, middleware.After)
393	if err != nil {
394		return err
395	}
396	if err = addSetLoggerMiddleware(stack, options); err != nil {
397		return err
398	}
399	if err = awsmiddleware.AddClientRequestIDMiddleware(stack); err != nil {
400		return err
401	}
402	if err = smithyhttp.AddComputeContentLengthMiddleware(stack); err != nil {
403		return err
404	}
405	if err = addResolveEndpointMiddleware(stack, options); err != nil {
406		return err
407	}
408	if err = v4.AddComputePayloadSHA256Middleware(stack); err != nil {
409		return err
410	}
411	if err = addRetryMiddlewares(stack, options); err != nil {
412		return err
413	}
414	if err = addHTTPSignerV4Middleware(stack, options); err != nil {
415		return err
416	}
417	if err = awsmiddleware.AddRawResponseToMetadata(stack); err != nil {
418		return err
419	}
420	if err = awsmiddleware.AddRecordResponseTiming(stack); err != nil {
421		return err
422	}
423	if err = addClientUserAgent(stack); err != nil {
424		return err
425	}
426	if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil {
427		return err
428	}
429	if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil {
430		return err
431	}
432	if err = stack.Initialize.Add(newServiceMetadataMiddleware_opDescribeInstances(options.Region), middleware.Before); err != nil {
433		return err
434	}
435	if err = addRequestIDRetrieverMiddleware(stack); err != nil {
436		return err
437	}
438	if err = addResponseErrorMiddleware(stack); err != nil {
439		return err
440	}
441	if err = addRequestResponseLogging(stack, options); err != nil {
442		return err
443	}
444	return nil
445}
446
447// DescribeInstancesAPIClient is a client that implements the DescribeInstances
448// operation.
449type DescribeInstancesAPIClient interface {
450	DescribeInstances(context.Context, *DescribeInstancesInput, ...func(*Options)) (*DescribeInstancesOutput, error)
451}
452
453var _ DescribeInstancesAPIClient = (*Client)(nil)
454
455// DescribeInstancesPaginatorOptions is the paginator options for DescribeInstances
456type DescribeInstancesPaginatorOptions struct {
457	// The maximum number of results to return in a single call. To retrieve the
458	// remaining results, make another call with the returned NextToken value. This
459	// value can be between 5 and 1000. You cannot specify this parameter and the
460	// instance IDs parameter in the same call.
461	Limit int32
462
463	// Set to true if pagination should stop if the service returns a pagination token
464	// that matches the most recent token provided to the service.
465	StopOnDuplicateToken bool
466}
467
468// DescribeInstancesPaginator is a paginator for DescribeInstances
469type DescribeInstancesPaginator struct {
470	options   DescribeInstancesPaginatorOptions
471	client    DescribeInstancesAPIClient
472	params    *DescribeInstancesInput
473	nextToken *string
474	firstPage bool
475}
476
477// NewDescribeInstancesPaginator returns a new DescribeInstancesPaginator
478func NewDescribeInstancesPaginator(client DescribeInstancesAPIClient, params *DescribeInstancesInput, optFns ...func(*DescribeInstancesPaginatorOptions)) *DescribeInstancesPaginator {
479	options := DescribeInstancesPaginatorOptions{}
480	if params.MaxResults != 0 {
481		options.Limit = params.MaxResults
482	}
483
484	for _, fn := range optFns {
485		fn(&options)
486	}
487
488	if params == nil {
489		params = &DescribeInstancesInput{}
490	}
491
492	return &DescribeInstancesPaginator{
493		options:   options,
494		client:    client,
495		params:    params,
496		firstPage: true,
497	}
498}
499
500// HasMorePages returns a boolean indicating whether more pages are available
501func (p *DescribeInstancesPaginator) HasMorePages() bool {
502	return p.firstPage || p.nextToken != nil
503}
504
505// NextPage retrieves the next DescribeInstances page.
506func (p *DescribeInstancesPaginator) NextPage(ctx context.Context, optFns ...func(*Options)) (*DescribeInstancesOutput, error) {
507	if !p.HasMorePages() {
508		return nil, fmt.Errorf("no more pages available")
509	}
510
511	params := *p.params
512	params.NextToken = p.nextToken
513
514	params.MaxResults = p.options.Limit
515
516	result, err := p.client.DescribeInstances(ctx, &params, optFns...)
517	if err != nil {
518		return nil, err
519	}
520	p.firstPage = false
521
522	prevToken := p.nextToken
523	p.nextToken = result.NextToken
524
525	if p.options.StopOnDuplicateToken && prevToken != nil && p.nextToken != nil && *prevToken == *p.nextToken {
526		p.nextToken = nil
527	}
528
529	return result, nil
530}
531
532// InstanceStoppedWaiterOptions are waiter options for InstanceStoppedWaiter
533type InstanceStoppedWaiterOptions struct {
534
535	// Set of options to modify how an operation is invoked. These apply to all
536	// operations invoked for this client. Use functional options on operation call to
537	// modify this list for per operation behavior.
538	APIOptions []func(*middleware.Stack) error
539
540	// MinDelay is the minimum amount of time to delay between retries. If unset,
541	// InstanceStoppedWaiter will use default minimum delay of 15 seconds. Note that
542	// MinDelay must resolve to a value lesser than or equal to the MaxDelay.
543	MinDelay time.Duration
544
545	// MaxDelay is the maximum amount of time to delay between retries. If unset or set
546	// to zero, InstanceStoppedWaiter will use default max delay of 120 seconds. Note
547	// that MaxDelay must resolve to value greater than or equal to the MinDelay.
548	MaxDelay time.Duration
549
550	// LogWaitAttempts is used to enable logging for waiter retry attempts
551	LogWaitAttempts bool
552
553	// Retryable is function that can be used to override the service defined
554	// waiter-behavior based on operation output, or returned error. This function is
555	// used by the waiter to decide if a state is retryable or a terminal state. By
556	// default service-modeled logic will populate this option. This option can thus be
557	// used to define a custom waiter state with fall-back to service-modeled waiter
558	// state mutators.The function returns an error in case of a failure state. In case
559	// of retry state, this function returns a bool value of true and nil error, while
560	// in case of success it returns a bool value of false and nil error.
561	Retryable func(context.Context, *DescribeInstancesInput, *DescribeInstancesOutput, error) (bool, error)
562}
563
564// InstanceStoppedWaiter defines the waiters for InstanceStopped
565type InstanceStoppedWaiter struct {
566	client DescribeInstancesAPIClient
567
568	options InstanceStoppedWaiterOptions
569}
570
571// NewInstanceStoppedWaiter constructs a InstanceStoppedWaiter.
572func NewInstanceStoppedWaiter(client DescribeInstancesAPIClient, optFns ...func(*InstanceStoppedWaiterOptions)) *InstanceStoppedWaiter {
573	options := InstanceStoppedWaiterOptions{}
574	options.MinDelay = 15 * time.Second
575	options.MaxDelay = 120 * time.Second
576	options.Retryable = instanceStoppedStateRetryable
577
578	for _, fn := range optFns {
579		fn(&options)
580	}
581	return &InstanceStoppedWaiter{
582		client:  client,
583		options: options,
584	}
585}
586
587// Wait calls the waiter function for InstanceStopped waiter. The maxWaitDur is the
588// maximum wait duration the waiter will wait. The maxWaitDur is required and must
589// be greater than zero.
590func (w *InstanceStoppedWaiter) Wait(ctx context.Context, params *DescribeInstancesInput, maxWaitDur time.Duration, optFns ...func(*InstanceStoppedWaiterOptions)) error {
591	if maxWaitDur <= 0 {
592		return fmt.Errorf("maximum wait time for waiter must be greater than zero")
593	}
594
595	options := w.options
596	for _, fn := range optFns {
597		fn(&options)
598	}
599
600	if options.MaxDelay <= 0 {
601		options.MaxDelay = 120 * time.Second
602	}
603
604	if options.MinDelay > options.MaxDelay {
605		return fmt.Errorf("minimum waiter delay %v must be lesser than or equal to maximum waiter delay of %v.", options.MinDelay, options.MaxDelay)
606	}
607
608	ctx, cancelFn := context.WithTimeout(ctx, maxWaitDur)
609	defer cancelFn()
610
611	logger := smithywaiter.Logger{}
612	remainingTime := maxWaitDur
613
614	var attempt int64
615	for {
616
617		attempt++
618		apiOptions := options.APIOptions
619		start := time.Now()
620
621		if options.LogWaitAttempts {
622			logger.Attempt = attempt
623			apiOptions = append([]func(*middleware.Stack) error{}, options.APIOptions...)
624			apiOptions = append(apiOptions, logger.AddLogger)
625		}
626
627		out, err := w.client.DescribeInstances(ctx, params, func(o *Options) {
628			o.APIOptions = append(o.APIOptions, apiOptions...)
629		})
630
631		retryable, err := options.Retryable(ctx, params, out, err)
632		if err != nil {
633			return err
634		}
635		if !retryable {
636			return nil
637		}
638
639		remainingTime -= time.Since(start)
640		if remainingTime < options.MinDelay || remainingTime <= 0 {
641			break
642		}
643
644		// compute exponential backoff between waiter retries
645		delay, err := smithywaiter.ComputeDelay(
646			attempt, options.MinDelay, options.MaxDelay, remainingTime,
647		)
648		if err != nil {
649			return fmt.Errorf("error computing waiter delay, %w", err)
650		}
651
652		remainingTime -= delay
653		// sleep for the delay amount before invoking a request
654		if err := smithytime.SleepWithContext(ctx, delay); err != nil {
655			return fmt.Errorf("request cancelled while waiting, %w", err)
656		}
657	}
658	return fmt.Errorf("exceeded max wait time for InstanceStopped waiter")
659}
660
661func instanceStoppedStateRetryable(ctx context.Context, input *DescribeInstancesInput, output *DescribeInstancesOutput, err error) (bool, error) {
662
663	if err == nil {
664		pathValue, err := jmespath.Search("Reservations[].Instances[].State.Name", output)
665		if err != nil {
666			return false, fmt.Errorf("error evaluating waiter state: %w", err)
667		}
668
669		expectedValue := "stopped"
670		var match = true
671		listOfValues, ok := pathValue.([]interface{})
672		if !ok {
673			return false, fmt.Errorf("waiter comparator expected list got %T", pathValue)
674		}
675
676		if len(listOfValues) == 0 {
677			match = false
678		}
679		for _, v := range listOfValues {
680			value, ok := v.(types.InstanceStateName)
681			if !ok {
682				return false, fmt.Errorf("waiter comparator expected types.InstanceStateName value, got %T", pathValue)
683			}
684
685			if string(value) != expectedValue {
686				match = false
687			}
688		}
689
690		if match {
691			return false, nil
692		}
693	}
694
695	if err == nil {
696		pathValue, err := jmespath.Search("Reservations[].Instances[].State.Name", output)
697		if err != nil {
698			return false, fmt.Errorf("error evaluating waiter state: %w", err)
699		}
700
701		expectedValue := "pending"
702		listOfValues, ok := pathValue.([]interface{})
703		if !ok {
704			return false, fmt.Errorf("waiter comparator expected list got %T", pathValue)
705		}
706
707		for _, v := range listOfValues {
708			value, ok := v.(types.InstanceStateName)
709			if !ok {
710				return false, fmt.Errorf("waiter comparator expected types.InstanceStateName value, got %T", pathValue)
711			}
712
713			if string(value) == expectedValue {
714				return false, fmt.Errorf("waiter state transitioned to Failure")
715			}
716		}
717	}
718
719	if err == nil {
720		pathValue, err := jmespath.Search("Reservations[].Instances[].State.Name", output)
721		if err != nil {
722			return false, fmt.Errorf("error evaluating waiter state: %w", err)
723		}
724
725		expectedValue := "terminated"
726		listOfValues, ok := pathValue.([]interface{})
727		if !ok {
728			return false, fmt.Errorf("waiter comparator expected list got %T", pathValue)
729		}
730
731		for _, v := range listOfValues {
732			value, ok := v.(types.InstanceStateName)
733			if !ok {
734				return false, fmt.Errorf("waiter comparator expected types.InstanceStateName value, got %T", pathValue)
735			}
736
737			if string(value) == expectedValue {
738				return false, fmt.Errorf("waiter state transitioned to Failure")
739			}
740		}
741	}
742
743	return true, nil
744}
745
746// InstanceTerminatedWaiterOptions are waiter options for InstanceTerminatedWaiter
747type InstanceTerminatedWaiterOptions struct {
748
749	// Set of options to modify how an operation is invoked. These apply to all
750	// operations invoked for this client. Use functional options on operation call to
751	// modify this list for per operation behavior.
752	APIOptions []func(*middleware.Stack) error
753
754	// MinDelay is the minimum amount of time to delay between retries. If unset,
755	// InstanceTerminatedWaiter will use default minimum delay of 15 seconds. Note that
756	// MinDelay must resolve to a value lesser than or equal to the MaxDelay.
757	MinDelay time.Duration
758
759	// MaxDelay is the maximum amount of time to delay between retries. If unset or set
760	// to zero, InstanceTerminatedWaiter will use default max delay of 120 seconds.
761	// Note that MaxDelay must resolve to value greater than or equal to the MinDelay.
762	MaxDelay time.Duration
763
764	// LogWaitAttempts is used to enable logging for waiter retry attempts
765	LogWaitAttempts bool
766
767	// Retryable is function that can be used to override the service defined
768	// waiter-behavior based on operation output, or returned error. This function is
769	// used by the waiter to decide if a state is retryable or a terminal state. By
770	// default service-modeled logic will populate this option. This option can thus be
771	// used to define a custom waiter state with fall-back to service-modeled waiter
772	// state mutators.The function returns an error in case of a failure state. In case
773	// of retry state, this function returns a bool value of true and nil error, while
774	// in case of success it returns a bool value of false and nil error.
775	Retryable func(context.Context, *DescribeInstancesInput, *DescribeInstancesOutput, error) (bool, error)
776}
777
778// InstanceTerminatedWaiter defines the waiters for InstanceTerminated
779type InstanceTerminatedWaiter struct {
780	client DescribeInstancesAPIClient
781
782	options InstanceTerminatedWaiterOptions
783}
784
785// NewInstanceTerminatedWaiter constructs a InstanceTerminatedWaiter.
786func NewInstanceTerminatedWaiter(client DescribeInstancesAPIClient, optFns ...func(*InstanceTerminatedWaiterOptions)) *InstanceTerminatedWaiter {
787	options := InstanceTerminatedWaiterOptions{}
788	options.MinDelay = 15 * time.Second
789	options.MaxDelay = 120 * time.Second
790	options.Retryable = instanceTerminatedStateRetryable
791
792	for _, fn := range optFns {
793		fn(&options)
794	}
795	return &InstanceTerminatedWaiter{
796		client:  client,
797		options: options,
798	}
799}
800
801// Wait calls the waiter function for InstanceTerminated waiter. The maxWaitDur is
802// the maximum wait duration the waiter will wait. The maxWaitDur is required and
803// must be greater than zero.
804func (w *InstanceTerminatedWaiter) Wait(ctx context.Context, params *DescribeInstancesInput, maxWaitDur time.Duration, optFns ...func(*InstanceTerminatedWaiterOptions)) error {
805	if maxWaitDur <= 0 {
806		return fmt.Errorf("maximum wait time for waiter must be greater than zero")
807	}
808
809	options := w.options
810	for _, fn := range optFns {
811		fn(&options)
812	}
813
814	if options.MaxDelay <= 0 {
815		options.MaxDelay = 120 * time.Second
816	}
817
818	if options.MinDelay > options.MaxDelay {
819		return fmt.Errorf("minimum waiter delay %v must be lesser than or equal to maximum waiter delay of %v.", options.MinDelay, options.MaxDelay)
820	}
821
822	ctx, cancelFn := context.WithTimeout(ctx, maxWaitDur)
823	defer cancelFn()
824
825	logger := smithywaiter.Logger{}
826	remainingTime := maxWaitDur
827
828	var attempt int64
829	for {
830
831		attempt++
832		apiOptions := options.APIOptions
833		start := time.Now()
834
835		if options.LogWaitAttempts {
836			logger.Attempt = attempt
837			apiOptions = append([]func(*middleware.Stack) error{}, options.APIOptions...)
838			apiOptions = append(apiOptions, logger.AddLogger)
839		}
840
841		out, err := w.client.DescribeInstances(ctx, params, func(o *Options) {
842			o.APIOptions = append(o.APIOptions, apiOptions...)
843		})
844
845		retryable, err := options.Retryable(ctx, params, out, err)
846		if err != nil {
847			return err
848		}
849		if !retryable {
850			return nil
851		}
852
853		remainingTime -= time.Since(start)
854		if remainingTime < options.MinDelay || remainingTime <= 0 {
855			break
856		}
857
858		// compute exponential backoff between waiter retries
859		delay, err := smithywaiter.ComputeDelay(
860			attempt, options.MinDelay, options.MaxDelay, remainingTime,
861		)
862		if err != nil {
863			return fmt.Errorf("error computing waiter delay, %w", err)
864		}
865
866		remainingTime -= delay
867		// sleep for the delay amount before invoking a request
868		if err := smithytime.SleepWithContext(ctx, delay); err != nil {
869			return fmt.Errorf("request cancelled while waiting, %w", err)
870		}
871	}
872	return fmt.Errorf("exceeded max wait time for InstanceTerminated waiter")
873}
874
875func instanceTerminatedStateRetryable(ctx context.Context, input *DescribeInstancesInput, output *DescribeInstancesOutput, err error) (bool, error) {
876
877	if err == nil {
878		pathValue, err := jmespath.Search("Reservations[].Instances[].State.Name", output)
879		if err != nil {
880			return false, fmt.Errorf("error evaluating waiter state: %w", err)
881		}
882
883		expectedValue := "terminated"
884		var match = true
885		listOfValues, ok := pathValue.([]interface{})
886		if !ok {
887			return false, fmt.Errorf("waiter comparator expected list got %T", pathValue)
888		}
889
890		if len(listOfValues) == 0 {
891			match = false
892		}
893		for _, v := range listOfValues {
894			value, ok := v.(types.InstanceStateName)
895			if !ok {
896				return false, fmt.Errorf("waiter comparator expected types.InstanceStateName value, got %T", pathValue)
897			}
898
899			if string(value) != expectedValue {
900				match = false
901			}
902		}
903
904		if match {
905			return false, nil
906		}
907	}
908
909	if err == nil {
910		pathValue, err := jmespath.Search("Reservations[].Instances[].State.Name", output)
911		if err != nil {
912			return false, fmt.Errorf("error evaluating waiter state: %w", err)
913		}
914
915		expectedValue := "pending"
916		listOfValues, ok := pathValue.([]interface{})
917		if !ok {
918			return false, fmt.Errorf("waiter comparator expected list got %T", pathValue)
919		}
920
921		for _, v := range listOfValues {
922			value, ok := v.(types.InstanceStateName)
923			if !ok {
924				return false, fmt.Errorf("waiter comparator expected types.InstanceStateName value, got %T", pathValue)
925			}
926
927			if string(value) == expectedValue {
928				return false, fmt.Errorf("waiter state transitioned to Failure")
929			}
930		}
931	}
932
933	if err == nil {
934		pathValue, err := jmespath.Search("Reservations[].Instances[].State.Name", output)
935		if err != nil {
936			return false, fmt.Errorf("error evaluating waiter state: %w", err)
937		}
938
939		expectedValue := "stopping"
940		listOfValues, ok := pathValue.([]interface{})
941		if !ok {
942			return false, fmt.Errorf("waiter comparator expected list got %T", pathValue)
943		}
944
945		for _, v := range listOfValues {
946			value, ok := v.(types.InstanceStateName)
947			if !ok {
948				return false, fmt.Errorf("waiter comparator expected types.InstanceStateName value, got %T", pathValue)
949			}
950
951			if string(value) == expectedValue {
952				return false, fmt.Errorf("waiter state transitioned to Failure")
953			}
954		}
955	}
956
957	return true, nil
958}
959
960func newServiceMetadataMiddleware_opDescribeInstances(region string) *awsmiddleware.RegisterServiceMetadata {
961	return &awsmiddleware.RegisterServiceMetadata{
962		Region:        region,
963		ServiceID:     ServiceID,
964		SigningName:   "ec2",
965		OperationName: "DescribeInstances",
966	}
967}
968