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 bundle tasks or all of your bundle tasks. Completed
20// bundle tasks are listed for only a limited time. If your bundle task is no
21// longer in the list, you can still register an AMI from it. Just use
22// RegisterImage with the Amazon S3 bucket name and image manifest name you
23// provided to the bundle task.
24func (c *Client) DescribeBundleTasks(ctx context.Context, params *DescribeBundleTasksInput, optFns ...func(*Options)) (*DescribeBundleTasksOutput, error) {
25	if params == nil {
26		params = &DescribeBundleTasksInput{}
27	}
28
29	result, metadata, err := c.invokeOperation(ctx, "DescribeBundleTasks", params, optFns, addOperationDescribeBundleTasksMiddlewares)
30	if err != nil {
31		return nil, err
32	}
33
34	out := result.(*DescribeBundleTasksOutput)
35	out.ResultMetadata = metadata
36	return out, nil
37}
38
39type DescribeBundleTasksInput struct {
40
41	// The bundle task IDs. Default: Describes all your bundle tasks.
42	BundleIds []string
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	// The filters.
51	//
52	// * bundle-id - The ID of the bundle task.
53	//
54	// * error-code - If the
55	// task failed, the error code returned.
56	//
57	// * error-message - If the task failed, the
58	// error message returned.
59	//
60	// * instance-id - The ID of the instance.
61	//
62	// * progress -
63	// The level of task completion, as a percentage (for example, 20%).
64	//
65	// * s3-bucket -
66	// The Amazon S3 bucket to store the AMI.
67	//
68	// * s3-prefix - The beginning of the AMI
69	// name.
70	//
71	// * start-time - The time the task started (for example,
72	// 2013-09-15T17:15:20.000Z).
73	//
74	// * state - The state of the task (pending |
75	// waiting-for-shutdown | bundling | storing | cancelling | complete | failed).
76	//
77	// *
78	// update-time - The time of the most recent update for the task.
79	Filters []types.Filter
80}
81
82type DescribeBundleTasksOutput struct {
83
84	// Information about the bundle tasks.
85	BundleTasks []types.BundleTask
86
87	// Metadata pertaining to the operation's result.
88	ResultMetadata middleware.Metadata
89}
90
91func addOperationDescribeBundleTasksMiddlewares(stack *middleware.Stack, options Options) (err error) {
92	err = stack.Serialize.Add(&awsEc2query_serializeOpDescribeBundleTasks{}, middleware.After)
93	if err != nil {
94		return err
95	}
96	err = stack.Deserialize.Add(&awsEc2query_deserializeOpDescribeBundleTasks{}, middleware.After)
97	if err != nil {
98		return err
99	}
100	if err = addSetLoggerMiddleware(stack, options); err != nil {
101		return err
102	}
103	if err = awsmiddleware.AddClientRequestIDMiddleware(stack); err != nil {
104		return err
105	}
106	if err = smithyhttp.AddComputeContentLengthMiddleware(stack); err != nil {
107		return err
108	}
109	if err = addResolveEndpointMiddleware(stack, options); err != nil {
110		return err
111	}
112	if err = v4.AddComputePayloadSHA256Middleware(stack); err != nil {
113		return err
114	}
115	if err = addRetryMiddlewares(stack, options); err != nil {
116		return err
117	}
118	if err = addHTTPSignerV4Middleware(stack, options); err != nil {
119		return err
120	}
121	if err = awsmiddleware.AddRawResponseToMetadata(stack); err != nil {
122		return err
123	}
124	if err = awsmiddleware.AddRecordResponseTiming(stack); err != nil {
125		return err
126	}
127	if err = addClientUserAgent(stack); err != nil {
128		return err
129	}
130	if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil {
131		return err
132	}
133	if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil {
134		return err
135	}
136	if err = stack.Initialize.Add(newServiceMetadataMiddleware_opDescribeBundleTasks(options.Region), middleware.Before); err != nil {
137		return err
138	}
139	if err = addRequestIDRetrieverMiddleware(stack); err != nil {
140		return err
141	}
142	if err = addResponseErrorMiddleware(stack); err != nil {
143		return err
144	}
145	if err = addRequestResponseLogging(stack, options); err != nil {
146		return err
147	}
148	return nil
149}
150
151// DescribeBundleTasksAPIClient is a client that implements the DescribeBundleTasks
152// operation.
153type DescribeBundleTasksAPIClient interface {
154	DescribeBundleTasks(context.Context, *DescribeBundleTasksInput, ...func(*Options)) (*DescribeBundleTasksOutput, error)
155}
156
157var _ DescribeBundleTasksAPIClient = (*Client)(nil)
158
159// BundleTaskCompleteWaiterOptions are waiter options for BundleTaskCompleteWaiter
160type BundleTaskCompleteWaiterOptions struct {
161
162	// Set of options to modify how an operation is invoked. These apply to all
163	// operations invoked for this client. Use functional options on operation call to
164	// modify this list for per operation behavior.
165	APIOptions []func(*middleware.Stack) error
166
167	// MinDelay is the minimum amount of time to delay between retries. If unset,
168	// BundleTaskCompleteWaiter will use default minimum delay of 15 seconds. Note that
169	// MinDelay must resolve to a value lesser than or equal to the MaxDelay.
170	MinDelay time.Duration
171
172	// MaxDelay is the maximum amount of time to delay between retries. If unset or set
173	// to zero, BundleTaskCompleteWaiter will use default max delay of 120 seconds.
174	// Note that MaxDelay must resolve to value greater than or equal to the MinDelay.
175	MaxDelay time.Duration
176
177	// LogWaitAttempts is used to enable logging for waiter retry attempts
178	LogWaitAttempts bool
179
180	// Retryable is function that can be used to override the service defined
181	// waiter-behavior based on operation output, or returned error. This function is
182	// used by the waiter to decide if a state is retryable or a terminal state. By
183	// default service-modeled logic will populate this option. This option can thus be
184	// used to define a custom waiter state with fall-back to service-modeled waiter
185	// state mutators.The function returns an error in case of a failure state. In case
186	// of retry state, this function returns a bool value of true and nil error, while
187	// in case of success it returns a bool value of false and nil error.
188	Retryable func(context.Context, *DescribeBundleTasksInput, *DescribeBundleTasksOutput, error) (bool, error)
189}
190
191// BundleTaskCompleteWaiter defines the waiters for BundleTaskComplete
192type BundleTaskCompleteWaiter struct {
193	client DescribeBundleTasksAPIClient
194
195	options BundleTaskCompleteWaiterOptions
196}
197
198// NewBundleTaskCompleteWaiter constructs a BundleTaskCompleteWaiter.
199func NewBundleTaskCompleteWaiter(client DescribeBundleTasksAPIClient, optFns ...func(*BundleTaskCompleteWaiterOptions)) *BundleTaskCompleteWaiter {
200	options := BundleTaskCompleteWaiterOptions{}
201	options.MinDelay = 15 * time.Second
202	options.MaxDelay = 120 * time.Second
203	options.Retryable = bundleTaskCompleteStateRetryable
204
205	for _, fn := range optFns {
206		fn(&options)
207	}
208	return &BundleTaskCompleteWaiter{
209		client:  client,
210		options: options,
211	}
212}
213
214// Wait calls the waiter function for BundleTaskComplete waiter. The maxWaitDur is
215// the maximum wait duration the waiter will wait. The maxWaitDur is required and
216// must be greater than zero.
217func (w *BundleTaskCompleteWaiter) Wait(ctx context.Context, params *DescribeBundleTasksInput, maxWaitDur time.Duration, optFns ...func(*BundleTaskCompleteWaiterOptions)) error {
218	if maxWaitDur <= 0 {
219		return fmt.Errorf("maximum wait time for waiter must be greater than zero")
220	}
221
222	options := w.options
223	for _, fn := range optFns {
224		fn(&options)
225	}
226
227	if options.MaxDelay <= 0 {
228		options.MaxDelay = 120 * time.Second
229	}
230
231	if options.MinDelay > options.MaxDelay {
232		return fmt.Errorf("minimum waiter delay %v must be lesser than or equal to maximum waiter delay of %v.", options.MinDelay, options.MaxDelay)
233	}
234
235	ctx, cancelFn := context.WithTimeout(ctx, maxWaitDur)
236	defer cancelFn()
237
238	logger := smithywaiter.Logger{}
239	remainingTime := maxWaitDur
240
241	var attempt int64
242	for {
243
244		attempt++
245		apiOptions := options.APIOptions
246		start := time.Now()
247
248		if options.LogWaitAttempts {
249			logger.Attempt = attempt
250			apiOptions = append([]func(*middleware.Stack) error{}, options.APIOptions...)
251			apiOptions = append(apiOptions, logger.AddLogger)
252		}
253
254		out, err := w.client.DescribeBundleTasks(ctx, params, func(o *Options) {
255			o.APIOptions = append(o.APIOptions, apiOptions...)
256		})
257
258		retryable, err := options.Retryable(ctx, params, out, err)
259		if err != nil {
260			return err
261		}
262		if !retryable {
263			return nil
264		}
265
266		remainingTime -= time.Since(start)
267		if remainingTime < options.MinDelay || remainingTime <= 0 {
268			break
269		}
270
271		// compute exponential backoff between waiter retries
272		delay, err := smithywaiter.ComputeDelay(
273			attempt, options.MinDelay, options.MaxDelay, remainingTime,
274		)
275		if err != nil {
276			return fmt.Errorf("error computing waiter delay, %w", err)
277		}
278
279		remainingTime -= delay
280		// sleep for the delay amount before invoking a request
281		if err := smithytime.SleepWithContext(ctx, delay); err != nil {
282			return fmt.Errorf("request cancelled while waiting, %w", err)
283		}
284	}
285	return fmt.Errorf("exceeded max wait time for BundleTaskComplete waiter")
286}
287
288func bundleTaskCompleteStateRetryable(ctx context.Context, input *DescribeBundleTasksInput, output *DescribeBundleTasksOutput, err error) (bool, error) {
289
290	if err == nil {
291		pathValue, err := jmespath.Search("BundleTasks[].State", output)
292		if err != nil {
293			return false, fmt.Errorf("error evaluating waiter state: %w", err)
294		}
295
296		expectedValue := "complete"
297		var match = true
298		listOfValues, ok := pathValue.([]interface{})
299		if !ok {
300			return false, fmt.Errorf("waiter comparator expected list got %T", pathValue)
301		}
302
303		if len(listOfValues) == 0 {
304			match = false
305		}
306		for _, v := range listOfValues {
307			value, ok := v.(types.BundleTaskState)
308			if !ok {
309				return false, fmt.Errorf("waiter comparator expected types.BundleTaskState value, got %T", pathValue)
310			}
311
312			if string(value) != expectedValue {
313				match = false
314			}
315		}
316
317		if match {
318			return false, nil
319		}
320	}
321
322	if err == nil {
323		pathValue, err := jmespath.Search("BundleTasks[].State", output)
324		if err != nil {
325			return false, fmt.Errorf("error evaluating waiter state: %w", err)
326		}
327
328		expectedValue := "failed"
329		listOfValues, ok := pathValue.([]interface{})
330		if !ok {
331			return false, fmt.Errorf("waiter comparator expected list got %T", pathValue)
332		}
333
334		for _, v := range listOfValues {
335			value, ok := v.(types.BundleTaskState)
336			if !ok {
337				return false, fmt.Errorf("waiter comparator expected types.BundleTaskState value, got %T", pathValue)
338			}
339
340			if string(value) == expectedValue {
341				return false, fmt.Errorf("waiter state transitioned to Failure")
342			}
343		}
344	}
345
346	return true, nil
347}
348
349func newServiceMetadataMiddleware_opDescribeBundleTasks(region string) *awsmiddleware.RegisterServiceMetadata {
350	return &awsmiddleware.RegisterServiceMetadata{
351		Region:        region,
352		ServiceID:     ServiceID,
353		SigningName:   "ec2",
354		OperationName: "DescribeBundleTasks",
355	}
356}
357