1// Code generated by smithy-go-codegen DO NOT EDIT.
2
3package appstream
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/appstream/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// Retrieves a list that describes one or more specified fleets, if the fleet names
20// are provided. Otherwise, all fleets in the account are described.
21func (c *Client) DescribeFleets(ctx context.Context, params *DescribeFleetsInput, optFns ...func(*Options)) (*DescribeFleetsOutput, error) {
22	if params == nil {
23		params = &DescribeFleetsInput{}
24	}
25
26	result, metadata, err := c.invokeOperation(ctx, "DescribeFleets", params, optFns, addOperationDescribeFleetsMiddlewares)
27	if err != nil {
28		return nil, err
29	}
30
31	out := result.(*DescribeFleetsOutput)
32	out.ResultMetadata = metadata
33	return out, nil
34}
35
36type DescribeFleetsInput struct {
37
38	// The names of the fleets to describe.
39	Names []string
40
41	// The pagination token to use to retrieve the next page of results for this
42	// operation. If this value is null, it retrieves the first page.
43	NextToken *string
44}
45
46type DescribeFleetsOutput struct {
47
48	// Information about the fleets.
49	Fleets []types.Fleet
50
51	// The pagination token to use to retrieve the next page of results for this
52	// operation. If there are no more pages, this value is null.
53	NextToken *string
54
55	// Metadata pertaining to the operation's result.
56	ResultMetadata middleware.Metadata
57}
58
59func addOperationDescribeFleetsMiddlewares(stack *middleware.Stack, options Options) (err error) {
60	err = stack.Serialize.Add(&awsAwsjson11_serializeOpDescribeFleets{}, middleware.After)
61	if err != nil {
62		return err
63	}
64	err = stack.Deserialize.Add(&awsAwsjson11_deserializeOpDescribeFleets{}, middleware.After)
65	if err != nil {
66		return err
67	}
68	if err = addSetLoggerMiddleware(stack, options); err != nil {
69		return err
70	}
71	if err = awsmiddleware.AddClientRequestIDMiddleware(stack); err != nil {
72		return err
73	}
74	if err = smithyhttp.AddComputeContentLengthMiddleware(stack); err != nil {
75		return err
76	}
77	if err = addResolveEndpointMiddleware(stack, options); err != nil {
78		return err
79	}
80	if err = v4.AddComputePayloadSHA256Middleware(stack); err != nil {
81		return err
82	}
83	if err = addRetryMiddlewares(stack, options); err != nil {
84		return err
85	}
86	if err = addHTTPSignerV4Middleware(stack, options); err != nil {
87		return err
88	}
89	if err = awsmiddleware.AddRawResponseToMetadata(stack); err != nil {
90		return err
91	}
92	if err = awsmiddleware.AddRecordResponseTiming(stack); err != nil {
93		return err
94	}
95	if err = addClientUserAgent(stack); err != nil {
96		return err
97	}
98	if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil {
99		return err
100	}
101	if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil {
102		return err
103	}
104	if err = stack.Initialize.Add(newServiceMetadataMiddleware_opDescribeFleets(options.Region), middleware.Before); err != nil {
105		return err
106	}
107	if err = addRequestIDRetrieverMiddleware(stack); err != nil {
108		return err
109	}
110	if err = addResponseErrorMiddleware(stack); err != nil {
111		return err
112	}
113	if err = addRequestResponseLogging(stack, options); err != nil {
114		return err
115	}
116	return nil
117}
118
119// DescribeFleetsAPIClient is a client that implements the DescribeFleets
120// operation.
121type DescribeFleetsAPIClient interface {
122	DescribeFleets(context.Context, *DescribeFleetsInput, ...func(*Options)) (*DescribeFleetsOutput, error)
123}
124
125var _ DescribeFleetsAPIClient = (*Client)(nil)
126
127// FleetStartedWaiterOptions are waiter options for FleetStartedWaiter
128type FleetStartedWaiterOptions struct {
129
130	// Set of options to modify how an operation is invoked. These apply to all
131	// operations invoked for this client. Use functional options on operation call to
132	// modify this list for per operation behavior.
133	APIOptions []func(*middleware.Stack) error
134
135	// MinDelay is the minimum amount of time to delay between retries. If unset,
136	// FleetStartedWaiter will use default minimum delay of 30 seconds. Note that
137	// MinDelay must resolve to a value lesser than or equal to the MaxDelay.
138	MinDelay time.Duration
139
140	// MaxDelay is the maximum amount of time to delay between retries. If unset or set
141	// to zero, FleetStartedWaiter will use default max delay of 120 seconds. Note that
142	// MaxDelay must resolve to value greater than or equal to the MinDelay.
143	MaxDelay time.Duration
144
145	// LogWaitAttempts is used to enable logging for waiter retry attempts
146	LogWaitAttempts bool
147
148	// Retryable is function that can be used to override the service defined
149	// waiter-behavior based on operation output, or returned error. This function is
150	// used by the waiter to decide if a state is retryable or a terminal state. By
151	// default service-modeled logic will populate this option. This option can thus be
152	// used to define a custom waiter state with fall-back to service-modeled waiter
153	// state mutators.The function returns an error in case of a failure state. In case
154	// of retry state, this function returns a bool value of true and nil error, while
155	// in case of success it returns a bool value of false and nil error.
156	Retryable func(context.Context, *DescribeFleetsInput, *DescribeFleetsOutput, error) (bool, error)
157}
158
159// FleetStartedWaiter defines the waiters for FleetStarted
160type FleetStartedWaiter struct {
161	client DescribeFleetsAPIClient
162
163	options FleetStartedWaiterOptions
164}
165
166// NewFleetStartedWaiter constructs a FleetStartedWaiter.
167func NewFleetStartedWaiter(client DescribeFleetsAPIClient, optFns ...func(*FleetStartedWaiterOptions)) *FleetStartedWaiter {
168	options := FleetStartedWaiterOptions{}
169	options.MinDelay = 30 * time.Second
170	options.MaxDelay = 120 * time.Second
171	options.Retryable = fleetStartedStateRetryable
172
173	for _, fn := range optFns {
174		fn(&options)
175	}
176	return &FleetStartedWaiter{
177		client:  client,
178		options: options,
179	}
180}
181
182// Wait calls the waiter function for FleetStarted waiter. The maxWaitDur is the
183// maximum wait duration the waiter will wait. The maxWaitDur is required and must
184// be greater than zero.
185func (w *FleetStartedWaiter) Wait(ctx context.Context, params *DescribeFleetsInput, maxWaitDur time.Duration, optFns ...func(*FleetStartedWaiterOptions)) error {
186	if maxWaitDur <= 0 {
187		return fmt.Errorf("maximum wait time for waiter must be greater than zero")
188	}
189
190	options := w.options
191	for _, fn := range optFns {
192		fn(&options)
193	}
194
195	if options.MaxDelay <= 0 {
196		options.MaxDelay = 120 * time.Second
197	}
198
199	if options.MinDelay > options.MaxDelay {
200		return fmt.Errorf("minimum waiter delay %v must be lesser than or equal to maximum waiter delay of %v.", options.MinDelay, options.MaxDelay)
201	}
202
203	ctx, cancelFn := context.WithTimeout(ctx, maxWaitDur)
204	defer cancelFn()
205
206	logger := smithywaiter.Logger{}
207	remainingTime := maxWaitDur
208
209	var attempt int64
210	for {
211
212		attempt++
213		apiOptions := options.APIOptions
214		start := time.Now()
215
216		if options.LogWaitAttempts {
217			logger.Attempt = attempt
218			apiOptions = append([]func(*middleware.Stack) error{}, options.APIOptions...)
219			apiOptions = append(apiOptions, logger.AddLogger)
220		}
221
222		out, err := w.client.DescribeFleets(ctx, params, func(o *Options) {
223			o.APIOptions = append(o.APIOptions, apiOptions...)
224		})
225
226		retryable, err := options.Retryable(ctx, params, out, err)
227		if err != nil {
228			return err
229		}
230		if !retryable {
231			return nil
232		}
233
234		remainingTime -= time.Since(start)
235		if remainingTime < options.MinDelay || remainingTime <= 0 {
236			break
237		}
238
239		// compute exponential backoff between waiter retries
240		delay, err := smithywaiter.ComputeDelay(
241			attempt, options.MinDelay, options.MaxDelay, remainingTime,
242		)
243		if err != nil {
244			return fmt.Errorf("error computing waiter delay, %w", err)
245		}
246
247		remainingTime -= delay
248		// sleep for the delay amount before invoking a request
249		if err := smithytime.SleepWithContext(ctx, delay); err != nil {
250			return fmt.Errorf("request cancelled while waiting, %w", err)
251		}
252	}
253	return fmt.Errorf("exceeded max wait time for FleetStarted waiter")
254}
255
256func fleetStartedStateRetryable(ctx context.Context, input *DescribeFleetsInput, output *DescribeFleetsOutput, err error) (bool, error) {
257
258	if err == nil {
259		pathValue, err := jmespath.Search("Fleets[].State", output)
260		if err != nil {
261			return false, fmt.Errorf("error evaluating waiter state: %w", err)
262		}
263
264		expectedValue := "ACTIVE"
265		var match = true
266		listOfValues, ok := pathValue.([]interface{})
267		if !ok {
268			return false, fmt.Errorf("waiter comparator expected list got %T", pathValue)
269		}
270
271		if len(listOfValues) == 0 {
272			match = false
273		}
274		for _, v := range listOfValues {
275			value, ok := v.(types.FleetState)
276			if !ok {
277				return false, fmt.Errorf("waiter comparator expected types.FleetState value, got %T", pathValue)
278			}
279
280			if string(value) != expectedValue {
281				match = false
282			}
283		}
284
285		if match {
286			return false, nil
287		}
288	}
289
290	if err == nil {
291		pathValue, err := jmespath.Search("Fleets[].State", output)
292		if err != nil {
293			return false, fmt.Errorf("error evaluating waiter state: %w", err)
294		}
295
296		expectedValue := "PENDING_DEACTIVATE"
297		listOfValues, ok := pathValue.([]interface{})
298		if !ok {
299			return false, fmt.Errorf("waiter comparator expected list got %T", pathValue)
300		}
301
302		for _, v := range listOfValues {
303			value, ok := v.(types.FleetState)
304			if !ok {
305				return false, fmt.Errorf("waiter comparator expected types.FleetState value, got %T", pathValue)
306			}
307
308			if string(value) == expectedValue {
309				return false, fmt.Errorf("waiter state transitioned to Failure")
310			}
311		}
312	}
313
314	if err == nil {
315		pathValue, err := jmespath.Search("Fleets[].State", output)
316		if err != nil {
317			return false, fmt.Errorf("error evaluating waiter state: %w", err)
318		}
319
320		expectedValue := "INACTIVE"
321		listOfValues, ok := pathValue.([]interface{})
322		if !ok {
323			return false, fmt.Errorf("waiter comparator expected list got %T", pathValue)
324		}
325
326		for _, v := range listOfValues {
327			value, ok := v.(types.FleetState)
328			if !ok {
329				return false, fmt.Errorf("waiter comparator expected types.FleetState value, got %T", pathValue)
330			}
331
332			if string(value) == expectedValue {
333				return false, fmt.Errorf("waiter state transitioned to Failure")
334			}
335		}
336	}
337
338	return true, nil
339}
340
341// FleetStoppedWaiterOptions are waiter options for FleetStoppedWaiter
342type FleetStoppedWaiterOptions struct {
343
344	// Set of options to modify how an operation is invoked. These apply to all
345	// operations invoked for this client. Use functional options on operation call to
346	// modify this list for per operation behavior.
347	APIOptions []func(*middleware.Stack) error
348
349	// MinDelay is the minimum amount of time to delay between retries. If unset,
350	// FleetStoppedWaiter will use default minimum delay of 30 seconds. Note that
351	// MinDelay must resolve to a value lesser than or equal to the MaxDelay.
352	MinDelay time.Duration
353
354	// MaxDelay is the maximum amount of time to delay between retries. If unset or set
355	// to zero, FleetStoppedWaiter will use default max delay of 120 seconds. Note that
356	// MaxDelay must resolve to value greater than or equal to the MinDelay.
357	MaxDelay time.Duration
358
359	// LogWaitAttempts is used to enable logging for waiter retry attempts
360	LogWaitAttempts bool
361
362	// Retryable is function that can be used to override the service defined
363	// waiter-behavior based on operation output, or returned error. This function is
364	// used by the waiter to decide if a state is retryable or a terminal state. By
365	// default service-modeled logic will populate this option. This option can thus be
366	// used to define a custom waiter state with fall-back to service-modeled waiter
367	// state mutators.The function returns an error in case of a failure state. In case
368	// of retry state, this function returns a bool value of true and nil error, while
369	// in case of success it returns a bool value of false and nil error.
370	Retryable func(context.Context, *DescribeFleetsInput, *DescribeFleetsOutput, error) (bool, error)
371}
372
373// FleetStoppedWaiter defines the waiters for FleetStopped
374type FleetStoppedWaiter struct {
375	client DescribeFleetsAPIClient
376
377	options FleetStoppedWaiterOptions
378}
379
380// NewFleetStoppedWaiter constructs a FleetStoppedWaiter.
381func NewFleetStoppedWaiter(client DescribeFleetsAPIClient, optFns ...func(*FleetStoppedWaiterOptions)) *FleetStoppedWaiter {
382	options := FleetStoppedWaiterOptions{}
383	options.MinDelay = 30 * time.Second
384	options.MaxDelay = 120 * time.Second
385	options.Retryable = fleetStoppedStateRetryable
386
387	for _, fn := range optFns {
388		fn(&options)
389	}
390	return &FleetStoppedWaiter{
391		client:  client,
392		options: options,
393	}
394}
395
396// Wait calls the waiter function for FleetStopped waiter. The maxWaitDur is the
397// maximum wait duration the waiter will wait. The maxWaitDur is required and must
398// be greater than zero.
399func (w *FleetStoppedWaiter) Wait(ctx context.Context, params *DescribeFleetsInput, maxWaitDur time.Duration, optFns ...func(*FleetStoppedWaiterOptions)) error {
400	if maxWaitDur <= 0 {
401		return fmt.Errorf("maximum wait time for waiter must be greater than zero")
402	}
403
404	options := w.options
405	for _, fn := range optFns {
406		fn(&options)
407	}
408
409	if options.MaxDelay <= 0 {
410		options.MaxDelay = 120 * time.Second
411	}
412
413	if options.MinDelay > options.MaxDelay {
414		return fmt.Errorf("minimum waiter delay %v must be lesser than or equal to maximum waiter delay of %v.", options.MinDelay, options.MaxDelay)
415	}
416
417	ctx, cancelFn := context.WithTimeout(ctx, maxWaitDur)
418	defer cancelFn()
419
420	logger := smithywaiter.Logger{}
421	remainingTime := maxWaitDur
422
423	var attempt int64
424	for {
425
426		attempt++
427		apiOptions := options.APIOptions
428		start := time.Now()
429
430		if options.LogWaitAttempts {
431			logger.Attempt = attempt
432			apiOptions = append([]func(*middleware.Stack) error{}, options.APIOptions...)
433			apiOptions = append(apiOptions, logger.AddLogger)
434		}
435
436		out, err := w.client.DescribeFleets(ctx, params, func(o *Options) {
437			o.APIOptions = append(o.APIOptions, apiOptions...)
438		})
439
440		retryable, err := options.Retryable(ctx, params, out, err)
441		if err != nil {
442			return err
443		}
444		if !retryable {
445			return nil
446		}
447
448		remainingTime -= time.Since(start)
449		if remainingTime < options.MinDelay || remainingTime <= 0 {
450			break
451		}
452
453		// compute exponential backoff between waiter retries
454		delay, err := smithywaiter.ComputeDelay(
455			attempt, options.MinDelay, options.MaxDelay, remainingTime,
456		)
457		if err != nil {
458			return fmt.Errorf("error computing waiter delay, %w", err)
459		}
460
461		remainingTime -= delay
462		// sleep for the delay amount before invoking a request
463		if err := smithytime.SleepWithContext(ctx, delay); err != nil {
464			return fmt.Errorf("request cancelled while waiting, %w", err)
465		}
466	}
467	return fmt.Errorf("exceeded max wait time for FleetStopped waiter")
468}
469
470func fleetStoppedStateRetryable(ctx context.Context, input *DescribeFleetsInput, output *DescribeFleetsOutput, err error) (bool, error) {
471
472	if err == nil {
473		pathValue, err := jmespath.Search("Fleets[].State", output)
474		if err != nil {
475			return false, fmt.Errorf("error evaluating waiter state: %w", err)
476		}
477
478		expectedValue := "INACTIVE"
479		var match = true
480		listOfValues, ok := pathValue.([]interface{})
481		if !ok {
482			return false, fmt.Errorf("waiter comparator expected list got %T", pathValue)
483		}
484
485		if len(listOfValues) == 0 {
486			match = false
487		}
488		for _, v := range listOfValues {
489			value, ok := v.(types.FleetState)
490			if !ok {
491				return false, fmt.Errorf("waiter comparator expected types.FleetState value, got %T", pathValue)
492			}
493
494			if string(value) != expectedValue {
495				match = false
496			}
497		}
498
499		if match {
500			return false, nil
501		}
502	}
503
504	if err == nil {
505		pathValue, err := jmespath.Search("Fleets[].State", output)
506		if err != nil {
507			return false, fmt.Errorf("error evaluating waiter state: %w", err)
508		}
509
510		expectedValue := "PENDING_ACTIVATE"
511		listOfValues, ok := pathValue.([]interface{})
512		if !ok {
513			return false, fmt.Errorf("waiter comparator expected list got %T", pathValue)
514		}
515
516		for _, v := range listOfValues {
517			value, ok := v.(types.FleetState)
518			if !ok {
519				return false, fmt.Errorf("waiter comparator expected types.FleetState value, got %T", pathValue)
520			}
521
522			if string(value) == expectedValue {
523				return false, fmt.Errorf("waiter state transitioned to Failure")
524			}
525		}
526	}
527
528	if err == nil {
529		pathValue, err := jmespath.Search("Fleets[].State", output)
530		if err != nil {
531			return false, fmt.Errorf("error evaluating waiter state: %w", err)
532		}
533
534		expectedValue := "ACTIVE"
535		listOfValues, ok := pathValue.([]interface{})
536		if !ok {
537			return false, fmt.Errorf("waiter comparator expected list got %T", pathValue)
538		}
539
540		for _, v := range listOfValues {
541			value, ok := v.(types.FleetState)
542			if !ok {
543				return false, fmt.Errorf("waiter comparator expected types.FleetState value, got %T", pathValue)
544			}
545
546			if string(value) == expectedValue {
547				return false, fmt.Errorf("waiter state transitioned to Failure")
548			}
549		}
550	}
551
552	return true, nil
553}
554
555func newServiceMetadataMiddleware_opDescribeFleets(region string) *awsmiddleware.RegisterServiceMetadata {
556	return &awsmiddleware.RegisterServiceMetadata{
557		Region:        region,
558		ServiceID:     ServiceID,
559		SigningName:   "appstream",
560		OperationName: "DescribeFleets",
561	}
562}
563