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 status of the specified instances or all of your instances. By
20// default, only running instances are described, unless you specifically indicate
21// to return the status of all instances. Instance status includes the following
22// components:
23//
24// * Status checks - Amazon EC2 performs status checks on running EC2
25// instances to identify hardware and software issues. For more information, see
26// Status checks for your instances
27// (https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/monitoring-system-instance-status-check.html)
28// and Troubleshooting instances with failed status checks
29// (https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/TroubleshootingInstances.html)
30// in the Amazon EC2 User Guide.
31//
32// * Scheduled events - Amazon EC2 can schedule
33// events (such as reboot, stop, or terminate) for your instances related to
34// hardware issues, software updates, or system maintenance. For more information,
35// see Scheduled events for your instances
36// (https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/monitoring-instances-status-check_sched.html)
37// in the Amazon EC2 User Guide.
38//
39// * Instance state - You can manage your instances
40// from the moment you launch them through their termination. For more information,
41// see Instance lifecycle
42// (https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-lifecycle.html)
43// in the Amazon EC2 User Guide.
44func (c *Client) DescribeInstanceStatus(ctx context.Context, params *DescribeInstanceStatusInput, optFns ...func(*Options)) (*DescribeInstanceStatusOutput, error) {
45	if params == nil {
46		params = &DescribeInstanceStatusInput{}
47	}
48
49	result, metadata, err := c.invokeOperation(ctx, "DescribeInstanceStatus", params, optFns, addOperationDescribeInstanceStatusMiddlewares)
50	if err != nil {
51		return nil, err
52	}
53
54	out := result.(*DescribeInstanceStatusOutput)
55	out.ResultMetadata = metadata
56	return out, nil
57}
58
59type DescribeInstanceStatusInput struct {
60
61	// Checks whether you have the required permissions for the action, without
62	// actually making the request, and provides an error response. If you have the
63	// required permissions, the error response is DryRunOperation. Otherwise, it is
64	// UnauthorizedOperation.
65	DryRun bool
66
67	// The filters.
68	//
69	// * availability-zone - The Availability Zone of the instance.
70	//
71	// *
72	// event.code - The code for the scheduled event (instance-reboot | system-reboot |
73	// system-maintenance | instance-retirement | instance-stop).
74	//
75	// * event.description
76	// - A description of the event.
77	//
78	// * event.instance-event-id - The ID of the event
79	// whose date and time you are modifying.
80	//
81	// * event.not-after - The latest end time
82	// for the scheduled event (for example, 2014-09-15T17:15:20.000Z).
83	//
84	// *
85	// event.not-before - The earliest start time for the scheduled event (for example,
86	// 2014-09-15T17:15:20.000Z).
87	//
88	// * event.not-before-deadline - The deadline for
89	// starting the event (for example, 2014-09-15T17:15:20.000Z).
90	//
91	// *
92	// instance-state-code - The code for the instance state, as a 16-bit unsigned
93	// integer. The high byte is used for internal purposes and should be ignored. The
94	// low byte is set based on the state represented. The valid values are 0
95	// (pending), 16 (running), 32 (shutting-down), 48 (terminated), 64 (stopping), and
96	// 80 (stopped).
97	//
98	// * instance-state-name - The state of the instance (pending |
99	// running | shutting-down | terminated | stopping | stopped).
100	//
101	// *
102	// instance-status.reachability - Filters on instance status where the name is
103	// reachability (passed | failed | initializing | insufficient-data).
104	//
105	// *
106	// instance-status.status - The status of the instance (ok | impaired |
107	// initializing | insufficient-data | not-applicable).
108	//
109	// *
110	// system-status.reachability - Filters on system status where the name is
111	// reachability (passed | failed | initializing | insufficient-data).
112	//
113	// *
114	// system-status.status - The system status of the instance (ok | impaired |
115	// initializing | insufficient-data | not-applicable).
116	Filters []types.Filter
117
118	// When true, includes the health status for all instances. When false, includes
119	// the health status for running instances only. Default: false
120	IncludeAllInstances bool
121
122	// The instance IDs. Default: Describes all your instances. Constraints: Maximum
123	// 100 explicitly specified instance IDs.
124	InstanceIds []string
125
126	// The maximum number of results to return in a single call. To retrieve the
127	// remaining results, make another call with the returned NextToken value. This
128	// value can be between 5 and 1000. You cannot specify this parameter and the
129	// instance IDs parameter in the same call.
130	MaxResults int32
131
132	// The token to retrieve the next page of results.
133	NextToken *string
134}
135
136type DescribeInstanceStatusOutput struct {
137
138	// Information about the status of the instances.
139	InstanceStatuses []types.InstanceStatus
140
141	// The token to use to retrieve the next page of results. This value is null when
142	// there are no more results to return.
143	NextToken *string
144
145	// Metadata pertaining to the operation's result.
146	ResultMetadata middleware.Metadata
147}
148
149func addOperationDescribeInstanceStatusMiddlewares(stack *middleware.Stack, options Options) (err error) {
150	err = stack.Serialize.Add(&awsEc2query_serializeOpDescribeInstanceStatus{}, middleware.After)
151	if err != nil {
152		return err
153	}
154	err = stack.Deserialize.Add(&awsEc2query_deserializeOpDescribeInstanceStatus{}, middleware.After)
155	if err != nil {
156		return err
157	}
158	if err = addSetLoggerMiddleware(stack, options); err != nil {
159		return err
160	}
161	if err = awsmiddleware.AddClientRequestIDMiddleware(stack); err != nil {
162		return err
163	}
164	if err = smithyhttp.AddComputeContentLengthMiddleware(stack); err != nil {
165		return err
166	}
167	if err = addResolveEndpointMiddleware(stack, options); err != nil {
168		return err
169	}
170	if err = v4.AddComputePayloadSHA256Middleware(stack); err != nil {
171		return err
172	}
173	if err = addRetryMiddlewares(stack, options); err != nil {
174		return err
175	}
176	if err = addHTTPSignerV4Middleware(stack, options); err != nil {
177		return err
178	}
179	if err = awsmiddleware.AddRawResponseToMetadata(stack); err != nil {
180		return err
181	}
182	if err = awsmiddleware.AddRecordResponseTiming(stack); err != nil {
183		return err
184	}
185	if err = addClientUserAgent(stack); err != nil {
186		return err
187	}
188	if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil {
189		return err
190	}
191	if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil {
192		return err
193	}
194	if err = stack.Initialize.Add(newServiceMetadataMiddleware_opDescribeInstanceStatus(options.Region), middleware.Before); err != nil {
195		return err
196	}
197	if err = addRequestIDRetrieverMiddleware(stack); err != nil {
198		return err
199	}
200	if err = addResponseErrorMiddleware(stack); err != nil {
201		return err
202	}
203	if err = addRequestResponseLogging(stack, options); err != nil {
204		return err
205	}
206	return nil
207}
208
209// DescribeInstanceStatusAPIClient is a client that implements the
210// DescribeInstanceStatus operation.
211type DescribeInstanceStatusAPIClient interface {
212	DescribeInstanceStatus(context.Context, *DescribeInstanceStatusInput, ...func(*Options)) (*DescribeInstanceStatusOutput, error)
213}
214
215var _ DescribeInstanceStatusAPIClient = (*Client)(nil)
216
217// DescribeInstanceStatusPaginatorOptions is the paginator options for
218// DescribeInstanceStatus
219type DescribeInstanceStatusPaginatorOptions struct {
220	// The maximum number of results to return in a single call. To retrieve the
221	// remaining results, make another call with the returned NextToken value. This
222	// value can be between 5 and 1000. You cannot specify this parameter and the
223	// instance IDs parameter in the same call.
224	Limit int32
225
226	// Set to true if pagination should stop if the service returns a pagination token
227	// that matches the most recent token provided to the service.
228	StopOnDuplicateToken bool
229}
230
231// DescribeInstanceStatusPaginator is a paginator for DescribeInstanceStatus
232type DescribeInstanceStatusPaginator struct {
233	options   DescribeInstanceStatusPaginatorOptions
234	client    DescribeInstanceStatusAPIClient
235	params    *DescribeInstanceStatusInput
236	nextToken *string
237	firstPage bool
238}
239
240// NewDescribeInstanceStatusPaginator returns a new DescribeInstanceStatusPaginator
241func NewDescribeInstanceStatusPaginator(client DescribeInstanceStatusAPIClient, params *DescribeInstanceStatusInput, optFns ...func(*DescribeInstanceStatusPaginatorOptions)) *DescribeInstanceStatusPaginator {
242	options := DescribeInstanceStatusPaginatorOptions{}
243	if params.MaxResults != 0 {
244		options.Limit = params.MaxResults
245	}
246
247	for _, fn := range optFns {
248		fn(&options)
249	}
250
251	if params == nil {
252		params = &DescribeInstanceStatusInput{}
253	}
254
255	return &DescribeInstanceStatusPaginator{
256		options:   options,
257		client:    client,
258		params:    params,
259		firstPage: true,
260	}
261}
262
263// HasMorePages returns a boolean indicating whether more pages are available
264func (p *DescribeInstanceStatusPaginator) HasMorePages() bool {
265	return p.firstPage || p.nextToken != nil
266}
267
268// NextPage retrieves the next DescribeInstanceStatus page.
269func (p *DescribeInstanceStatusPaginator) NextPage(ctx context.Context, optFns ...func(*Options)) (*DescribeInstanceStatusOutput, error) {
270	if !p.HasMorePages() {
271		return nil, fmt.Errorf("no more pages available")
272	}
273
274	params := *p.params
275	params.NextToken = p.nextToken
276
277	params.MaxResults = p.options.Limit
278
279	result, err := p.client.DescribeInstanceStatus(ctx, &params, optFns...)
280	if err != nil {
281		return nil, err
282	}
283	p.firstPage = false
284
285	prevToken := p.nextToken
286	p.nextToken = result.NextToken
287
288	if p.options.StopOnDuplicateToken && prevToken != nil && p.nextToken != nil && *prevToken == *p.nextToken {
289		p.nextToken = nil
290	}
291
292	return result, nil
293}
294
295// SystemStatusOkWaiterOptions are waiter options for SystemStatusOkWaiter
296type SystemStatusOkWaiterOptions struct {
297
298	// Set of options to modify how an operation is invoked. These apply to all
299	// operations invoked for this client. Use functional options on operation call to
300	// modify this list for per operation behavior.
301	APIOptions []func(*middleware.Stack) error
302
303	// MinDelay is the minimum amount of time to delay between retries. If unset,
304	// SystemStatusOkWaiter will use default minimum delay of 15 seconds. Note that
305	// MinDelay must resolve to a value lesser than or equal to the MaxDelay.
306	MinDelay time.Duration
307
308	// MaxDelay is the maximum amount of time to delay between retries. If unset or set
309	// to zero, SystemStatusOkWaiter will use default max delay of 120 seconds. Note
310	// that MaxDelay must resolve to value greater than or equal to the MinDelay.
311	MaxDelay time.Duration
312
313	// LogWaitAttempts is used to enable logging for waiter retry attempts
314	LogWaitAttempts bool
315
316	// Retryable is function that can be used to override the service defined
317	// waiter-behavior based on operation output, or returned error. This function is
318	// used by the waiter to decide if a state is retryable or a terminal state. By
319	// default service-modeled logic will populate this option. This option can thus be
320	// used to define a custom waiter state with fall-back to service-modeled waiter
321	// state mutators.The function returns an error in case of a failure state. In case
322	// of retry state, this function returns a bool value of true and nil error, while
323	// in case of success it returns a bool value of false and nil error.
324	Retryable func(context.Context, *DescribeInstanceStatusInput, *DescribeInstanceStatusOutput, error) (bool, error)
325}
326
327// SystemStatusOkWaiter defines the waiters for SystemStatusOk
328type SystemStatusOkWaiter struct {
329	client DescribeInstanceStatusAPIClient
330
331	options SystemStatusOkWaiterOptions
332}
333
334// NewSystemStatusOkWaiter constructs a SystemStatusOkWaiter.
335func NewSystemStatusOkWaiter(client DescribeInstanceStatusAPIClient, optFns ...func(*SystemStatusOkWaiterOptions)) *SystemStatusOkWaiter {
336	options := SystemStatusOkWaiterOptions{}
337	options.MinDelay = 15 * time.Second
338	options.MaxDelay = 120 * time.Second
339	options.Retryable = systemStatusOkStateRetryable
340
341	for _, fn := range optFns {
342		fn(&options)
343	}
344	return &SystemStatusOkWaiter{
345		client:  client,
346		options: options,
347	}
348}
349
350// Wait calls the waiter function for SystemStatusOk waiter. The maxWaitDur is the
351// maximum wait duration the waiter will wait. The maxWaitDur is required and must
352// be greater than zero.
353func (w *SystemStatusOkWaiter) Wait(ctx context.Context, params *DescribeInstanceStatusInput, maxWaitDur time.Duration, optFns ...func(*SystemStatusOkWaiterOptions)) error {
354	if maxWaitDur <= 0 {
355		return fmt.Errorf("maximum wait time for waiter must be greater than zero")
356	}
357
358	options := w.options
359	for _, fn := range optFns {
360		fn(&options)
361	}
362
363	if options.MaxDelay <= 0 {
364		options.MaxDelay = 120 * time.Second
365	}
366
367	if options.MinDelay > options.MaxDelay {
368		return fmt.Errorf("minimum waiter delay %v must be lesser than or equal to maximum waiter delay of %v.", options.MinDelay, options.MaxDelay)
369	}
370
371	ctx, cancelFn := context.WithTimeout(ctx, maxWaitDur)
372	defer cancelFn()
373
374	logger := smithywaiter.Logger{}
375	remainingTime := maxWaitDur
376
377	var attempt int64
378	for {
379
380		attempt++
381		apiOptions := options.APIOptions
382		start := time.Now()
383
384		if options.LogWaitAttempts {
385			logger.Attempt = attempt
386			apiOptions = append([]func(*middleware.Stack) error{}, options.APIOptions...)
387			apiOptions = append(apiOptions, logger.AddLogger)
388		}
389
390		out, err := w.client.DescribeInstanceStatus(ctx, params, func(o *Options) {
391			o.APIOptions = append(o.APIOptions, apiOptions...)
392		})
393
394		retryable, err := options.Retryable(ctx, params, out, err)
395		if err != nil {
396			return err
397		}
398		if !retryable {
399			return nil
400		}
401
402		remainingTime -= time.Since(start)
403		if remainingTime < options.MinDelay || remainingTime <= 0 {
404			break
405		}
406
407		// compute exponential backoff between waiter retries
408		delay, err := smithywaiter.ComputeDelay(
409			attempt, options.MinDelay, options.MaxDelay, remainingTime,
410		)
411		if err != nil {
412			return fmt.Errorf("error computing waiter delay, %w", err)
413		}
414
415		remainingTime -= delay
416		// sleep for the delay amount before invoking a request
417		if err := smithytime.SleepWithContext(ctx, delay); err != nil {
418			return fmt.Errorf("request cancelled while waiting, %w", err)
419		}
420	}
421	return fmt.Errorf("exceeded max wait time for SystemStatusOk waiter")
422}
423
424func systemStatusOkStateRetryable(ctx context.Context, input *DescribeInstanceStatusInput, output *DescribeInstanceStatusOutput, err error) (bool, error) {
425
426	if err == nil {
427		pathValue, err := jmespath.Search("InstanceStatuses[].SystemStatus.Status", output)
428		if err != nil {
429			return false, fmt.Errorf("error evaluating waiter state: %w", err)
430		}
431
432		expectedValue := "ok"
433		var match = true
434		listOfValues, ok := pathValue.([]interface{})
435		if !ok {
436			return false, fmt.Errorf("waiter comparator expected list got %T", pathValue)
437		}
438
439		if len(listOfValues) == 0 {
440			match = false
441		}
442		for _, v := range listOfValues {
443			value, ok := v.(types.SummaryStatus)
444			if !ok {
445				return false, fmt.Errorf("waiter comparator expected types.SummaryStatus value, got %T", pathValue)
446			}
447
448			if string(value) != expectedValue {
449				match = false
450			}
451		}
452
453		if match {
454			return false, nil
455		}
456	}
457
458	return true, nil
459}
460
461func newServiceMetadataMiddleware_opDescribeInstanceStatus(region string) *awsmiddleware.RegisterServiceMetadata {
462	return &awsmiddleware.RegisterServiceMetadata{
463		Region:        region,
464		ServiceID:     ServiceID,
465		SigningName:   "ec2",
466		OperationName: "DescribeInstanceStatus",
467	}
468}
469