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