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 EBS volumes or all of your EBS volumes. If you are 20// describing a long list of volumes, we recommend that you paginate the output to 21// make the list more manageable. The MaxResults parameter sets the maximum number 22// of results returned in a single page. If the list of results exceeds your 23// MaxResults value, then that number of results is returned along with a NextToken 24// value that can be passed to a subsequent DescribeVolumes request to retrieve the 25// remaining results. For more information about EBS volumes, see Amazon EBS 26// volumes (https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EBSVolumes.html) in 27// the Amazon Elastic Compute Cloud User Guide. 28func (c *Client) DescribeVolumes(ctx context.Context, params *DescribeVolumesInput, optFns ...func(*Options)) (*DescribeVolumesOutput, error) { 29 if params == nil { 30 params = &DescribeVolumesInput{} 31 } 32 33 result, metadata, err := c.invokeOperation(ctx, "DescribeVolumes", params, optFns, addOperationDescribeVolumesMiddlewares) 34 if err != nil { 35 return nil, err 36 } 37 38 out := result.(*DescribeVolumesOutput) 39 out.ResultMetadata = metadata 40 return out, nil 41} 42 43type DescribeVolumesInput struct { 44 45 // Checks whether you have the required permissions for the action, without 46 // actually making the request, and provides an error response. If you have the 47 // required permissions, the error response is DryRunOperation. Otherwise, it is 48 // UnauthorizedOperation. 49 DryRun bool 50 51 // The filters. 52 // 53 // * attachment.attach-time - The time stamp when the attachment 54 // initiated. 55 // 56 // * attachment.delete-on-termination - Whether the volume is deleted 57 // on instance termination. 58 // 59 // * attachment.device - The device name specified in the 60 // block device mapping (for example, /dev/sda1). 61 // 62 // * attachment.instance-id - The 63 // ID of the instance the volume is attached to. 64 // 65 // * attachment.status - The 66 // attachment state (attaching | attached | detaching). 67 // 68 // * availability-zone - The 69 // Availability Zone in which the volume was created. 70 // 71 // * create-time - The time 72 // stamp when the volume was created. 73 // 74 // * encrypted - Indicates whether the volume 75 // is encrypted (true | false) 76 // 77 // * multi-attach-enabled - Indicates whether the 78 // volume is enabled for Multi-Attach (true | false) 79 // 80 // * fast-restored - Indicates 81 // whether the volume was created from a snapshot that is enabled for fast snapshot 82 // restore (true | false). 83 // 84 // * size - The size of the volume, in GiB. 85 // 86 // * snapshot-id 87 // - The snapshot from which the volume was created. 88 // 89 // * status - The state of the 90 // volume (creating | available | in-use | deleting | deleted | error). 91 // 92 // * tag: - 93 // The key/value combination of a tag assigned to the resource. Use the tag key in 94 // the filter name and the tag value as the filter value. For example, to find all 95 // resources that have a tag with the key Owner and the value TeamA, specify 96 // tag:Owner for the filter name and TeamA for the filter value. 97 // 98 // * tag-key - The 99 // key of a tag assigned to the resource. Use this filter to find all resources 100 // assigned a tag with a specific key, regardless of the tag value. 101 // 102 // * volume-id - 103 // The volume ID. 104 // 105 // * volume-type - The Amazon EBS volume type (gp2 | gp3 | io1 | 106 // io2 | st1 | sc1| standard) 107 Filters []types.Filter 108 109 // The maximum number of volume results returned by DescribeVolumes in paginated 110 // output. When this parameter is used, DescribeVolumes only returns MaxResults 111 // results in a single page along with a NextToken response element. The remaining 112 // results of the initial request can be seen by sending another DescribeVolumes 113 // request with the returned NextToken value. This value can be between 5 and 500; 114 // if MaxResults is given a value larger than 500, only 500 results are returned. 115 // If this parameter is not used, then DescribeVolumes returns all results. You 116 // cannot specify this parameter and the volume IDs parameter in the same request. 117 MaxResults int32 118 119 // The NextToken value returned from a previous paginated DescribeVolumes request 120 // where MaxResults was used and the results exceeded the value of that parameter. 121 // Pagination continues from the end of the previous results that returned the 122 // NextToken value. This value is null when there are no more results to return. 123 NextToken *string 124 125 // The volume IDs. 126 VolumeIds []string 127} 128 129type DescribeVolumesOutput struct { 130 131 // The NextToken value to include in a future DescribeVolumes request. When the 132 // results of a DescribeVolumes request exceed MaxResults, this value can be used 133 // to retrieve the next page of results. This value is null when there are no more 134 // results to return. 135 NextToken *string 136 137 // Information about the volumes. 138 Volumes []types.Volume 139 140 // Metadata pertaining to the operation's result. 141 ResultMetadata middleware.Metadata 142} 143 144func addOperationDescribeVolumesMiddlewares(stack *middleware.Stack, options Options) (err error) { 145 err = stack.Serialize.Add(&awsEc2query_serializeOpDescribeVolumes{}, middleware.After) 146 if err != nil { 147 return err 148 } 149 err = stack.Deserialize.Add(&awsEc2query_deserializeOpDescribeVolumes{}, middleware.After) 150 if err != nil { 151 return err 152 } 153 if err = addSetLoggerMiddleware(stack, options); err != nil { 154 return err 155 } 156 if err = awsmiddleware.AddClientRequestIDMiddleware(stack); err != nil { 157 return err 158 } 159 if err = smithyhttp.AddComputeContentLengthMiddleware(stack); err != nil { 160 return err 161 } 162 if err = addResolveEndpointMiddleware(stack, options); err != nil { 163 return err 164 } 165 if err = v4.AddComputePayloadSHA256Middleware(stack); err != nil { 166 return err 167 } 168 if err = addRetryMiddlewares(stack, options); err != nil { 169 return err 170 } 171 if err = addHTTPSignerV4Middleware(stack, options); err != nil { 172 return err 173 } 174 if err = awsmiddleware.AddRawResponseToMetadata(stack); err != nil { 175 return err 176 } 177 if err = awsmiddleware.AddRecordResponseTiming(stack); err != nil { 178 return err 179 } 180 if err = addClientUserAgent(stack); err != nil { 181 return err 182 } 183 if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { 184 return err 185 } 186 if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil { 187 return err 188 } 189 if err = stack.Initialize.Add(newServiceMetadataMiddleware_opDescribeVolumes(options.Region), middleware.Before); err != nil { 190 return err 191 } 192 if err = addRequestIDRetrieverMiddleware(stack); err != nil { 193 return err 194 } 195 if err = addResponseErrorMiddleware(stack); err != nil { 196 return err 197 } 198 if err = addRequestResponseLogging(stack, options); err != nil { 199 return err 200 } 201 return nil 202} 203 204// DescribeVolumesAPIClient is a client that implements the DescribeVolumes 205// operation. 206type DescribeVolumesAPIClient interface { 207 DescribeVolumes(context.Context, *DescribeVolumesInput, ...func(*Options)) (*DescribeVolumesOutput, error) 208} 209 210var _ DescribeVolumesAPIClient = (*Client)(nil) 211 212// DescribeVolumesPaginatorOptions is the paginator options for DescribeVolumes 213type DescribeVolumesPaginatorOptions struct { 214 // The maximum number of volume results returned by DescribeVolumes in paginated 215 // output. When this parameter is used, DescribeVolumes only returns MaxResults 216 // results in a single page along with a NextToken response element. The remaining 217 // results of the initial request can be seen by sending another DescribeVolumes 218 // request with the returned NextToken value. This value can be between 5 and 500; 219 // if MaxResults is given a value larger than 500, only 500 results are returned. 220 // If this parameter is not used, then DescribeVolumes returns all results. You 221 // cannot specify this parameter and the volume IDs parameter in the same request. 222 Limit int32 223 224 // Set to true if pagination should stop if the service returns a pagination token 225 // that matches the most recent token provided to the service. 226 StopOnDuplicateToken bool 227} 228 229// DescribeVolumesPaginator is a paginator for DescribeVolumes 230type DescribeVolumesPaginator struct { 231 options DescribeVolumesPaginatorOptions 232 client DescribeVolumesAPIClient 233 params *DescribeVolumesInput 234 nextToken *string 235 firstPage bool 236} 237 238// NewDescribeVolumesPaginator returns a new DescribeVolumesPaginator 239func NewDescribeVolumesPaginator(client DescribeVolumesAPIClient, params *DescribeVolumesInput, optFns ...func(*DescribeVolumesPaginatorOptions)) *DescribeVolumesPaginator { 240 options := DescribeVolumesPaginatorOptions{} 241 if params.MaxResults != 0 { 242 options.Limit = params.MaxResults 243 } 244 245 for _, fn := range optFns { 246 fn(&options) 247 } 248 249 if params == nil { 250 params = &DescribeVolumesInput{} 251 } 252 253 return &DescribeVolumesPaginator{ 254 options: options, 255 client: client, 256 params: params, 257 firstPage: true, 258 } 259} 260 261// HasMorePages returns a boolean indicating whether more pages are available 262func (p *DescribeVolumesPaginator) HasMorePages() bool { 263 return p.firstPage || p.nextToken != nil 264} 265 266// NextPage retrieves the next DescribeVolumes page. 267func (p *DescribeVolumesPaginator) NextPage(ctx context.Context, optFns ...func(*Options)) (*DescribeVolumesOutput, error) { 268 if !p.HasMorePages() { 269 return nil, fmt.Errorf("no more pages available") 270 } 271 272 params := *p.params 273 params.NextToken = p.nextToken 274 275 params.MaxResults = p.options.Limit 276 277 result, err := p.client.DescribeVolumes(ctx, ¶ms, optFns...) 278 if err != nil { 279 return nil, err 280 } 281 p.firstPage = false 282 283 prevToken := p.nextToken 284 p.nextToken = result.NextToken 285 286 if p.options.StopOnDuplicateToken && prevToken != nil && p.nextToken != nil && *prevToken == *p.nextToken { 287 p.nextToken = nil 288 } 289 290 return result, nil 291} 292 293// VolumeAvailableWaiterOptions are waiter options for VolumeAvailableWaiter 294type VolumeAvailableWaiterOptions struct { 295 296 // Set of options to modify how an operation is invoked. These apply to all 297 // operations invoked for this client. Use functional options on operation call to 298 // modify this list for per operation behavior. 299 APIOptions []func(*middleware.Stack) error 300 301 // MinDelay is the minimum amount of time to delay between retries. If unset, 302 // VolumeAvailableWaiter will use default minimum delay of 15 seconds. Note that 303 // MinDelay must resolve to a value lesser than or equal to the MaxDelay. 304 MinDelay time.Duration 305 306 // MaxDelay is the maximum amount of time to delay between retries. If unset or set 307 // to zero, VolumeAvailableWaiter will use default max delay of 120 seconds. Note 308 // that MaxDelay must resolve to value greater than or equal to the MinDelay. 309 MaxDelay time.Duration 310 311 // LogWaitAttempts is used to enable logging for waiter retry attempts 312 LogWaitAttempts bool 313 314 // Retryable is function that can be used to override the service defined 315 // waiter-behavior based on operation output, or returned error. This function is 316 // used by the waiter to decide if a state is retryable or a terminal state. By 317 // default service-modeled logic will populate this option. This option can thus be 318 // used to define a custom waiter state with fall-back to service-modeled waiter 319 // state mutators.The function returns an error in case of a failure state. In case 320 // of retry state, this function returns a bool value of true and nil error, while 321 // in case of success it returns a bool value of false and nil error. 322 Retryable func(context.Context, *DescribeVolumesInput, *DescribeVolumesOutput, error) (bool, error) 323} 324 325// VolumeAvailableWaiter defines the waiters for VolumeAvailable 326type VolumeAvailableWaiter struct { 327 client DescribeVolumesAPIClient 328 329 options VolumeAvailableWaiterOptions 330} 331 332// NewVolumeAvailableWaiter constructs a VolumeAvailableWaiter. 333func NewVolumeAvailableWaiter(client DescribeVolumesAPIClient, optFns ...func(*VolumeAvailableWaiterOptions)) *VolumeAvailableWaiter { 334 options := VolumeAvailableWaiterOptions{} 335 options.MinDelay = 15 * time.Second 336 options.MaxDelay = 120 * time.Second 337 options.Retryable = volumeAvailableStateRetryable 338 339 for _, fn := range optFns { 340 fn(&options) 341 } 342 return &VolumeAvailableWaiter{ 343 client: client, 344 options: options, 345 } 346} 347 348// Wait calls the waiter function for VolumeAvailable waiter. The maxWaitDur is the 349// maximum wait duration the waiter will wait. The maxWaitDur is required and must 350// be greater than zero. 351func (w *VolumeAvailableWaiter) Wait(ctx context.Context, params *DescribeVolumesInput, maxWaitDur time.Duration, optFns ...func(*VolumeAvailableWaiterOptions)) error { 352 if maxWaitDur <= 0 { 353 return fmt.Errorf("maximum wait time for waiter must be greater than zero") 354 } 355 356 options := w.options 357 for _, fn := range optFns { 358 fn(&options) 359 } 360 361 if options.MaxDelay <= 0 { 362 options.MaxDelay = 120 * time.Second 363 } 364 365 if options.MinDelay > options.MaxDelay { 366 return fmt.Errorf("minimum waiter delay %v must be lesser than or equal to maximum waiter delay of %v.", options.MinDelay, options.MaxDelay) 367 } 368 369 ctx, cancelFn := context.WithTimeout(ctx, maxWaitDur) 370 defer cancelFn() 371 372 logger := smithywaiter.Logger{} 373 remainingTime := maxWaitDur 374 375 var attempt int64 376 for { 377 378 attempt++ 379 apiOptions := options.APIOptions 380 start := time.Now() 381 382 if options.LogWaitAttempts { 383 logger.Attempt = attempt 384 apiOptions = append([]func(*middleware.Stack) error{}, options.APIOptions...) 385 apiOptions = append(apiOptions, logger.AddLogger) 386 } 387 388 out, err := w.client.DescribeVolumes(ctx, params, func(o *Options) { 389 o.APIOptions = append(o.APIOptions, apiOptions...) 390 }) 391 392 retryable, err := options.Retryable(ctx, params, out, err) 393 if err != nil { 394 return err 395 } 396 if !retryable { 397 return nil 398 } 399 400 remainingTime -= time.Since(start) 401 if remainingTime < options.MinDelay || remainingTime <= 0 { 402 break 403 } 404 405 // compute exponential backoff between waiter retries 406 delay, err := smithywaiter.ComputeDelay( 407 attempt, options.MinDelay, options.MaxDelay, remainingTime, 408 ) 409 if err != nil { 410 return fmt.Errorf("error computing waiter delay, %w", err) 411 } 412 413 remainingTime -= delay 414 // sleep for the delay amount before invoking a request 415 if err := smithytime.SleepWithContext(ctx, delay); err != nil { 416 return fmt.Errorf("request cancelled while waiting, %w", err) 417 } 418 } 419 return fmt.Errorf("exceeded max wait time for VolumeAvailable waiter") 420} 421 422func volumeAvailableStateRetryable(ctx context.Context, input *DescribeVolumesInput, output *DescribeVolumesOutput, err error) (bool, error) { 423 424 if err == nil { 425 pathValue, err := jmespath.Search("Volumes[].State", output) 426 if err != nil { 427 return false, fmt.Errorf("error evaluating waiter state: %w", err) 428 } 429 430 expectedValue := "available" 431 var match = true 432 listOfValues, ok := pathValue.([]interface{}) 433 if !ok { 434 return false, fmt.Errorf("waiter comparator expected list got %T", pathValue) 435 } 436 437 if len(listOfValues) == 0 { 438 match = false 439 } 440 for _, v := range listOfValues { 441 value, ok := v.(types.VolumeState) 442 if !ok { 443 return false, fmt.Errorf("waiter comparator expected types.VolumeState value, got %T", pathValue) 444 } 445 446 if string(value) != expectedValue { 447 match = false 448 } 449 } 450 451 if match { 452 return false, nil 453 } 454 } 455 456 if err == nil { 457 pathValue, err := jmespath.Search("Volumes[].State", output) 458 if err != nil { 459 return false, fmt.Errorf("error evaluating waiter state: %w", err) 460 } 461 462 expectedValue := "deleted" 463 listOfValues, ok := pathValue.([]interface{}) 464 if !ok { 465 return false, fmt.Errorf("waiter comparator expected list got %T", pathValue) 466 } 467 468 for _, v := range listOfValues { 469 value, ok := v.(types.VolumeState) 470 if !ok { 471 return false, fmt.Errorf("waiter comparator expected types.VolumeState value, got %T", pathValue) 472 } 473 474 if string(value) == expectedValue { 475 return false, fmt.Errorf("waiter state transitioned to Failure") 476 } 477 } 478 } 479 480 return true, nil 481} 482 483// VolumeInUseWaiterOptions are waiter options for VolumeInUseWaiter 484type VolumeInUseWaiterOptions struct { 485 486 // Set of options to modify how an operation is invoked. These apply to all 487 // operations invoked for this client. Use functional options on operation call to 488 // modify this list for per operation behavior. 489 APIOptions []func(*middleware.Stack) error 490 491 // MinDelay is the minimum amount of time to delay between retries. If unset, 492 // VolumeInUseWaiter will use default minimum delay of 15 seconds. Note that 493 // MinDelay must resolve to a value lesser than or equal to the MaxDelay. 494 MinDelay time.Duration 495 496 // MaxDelay is the maximum amount of time to delay between retries. If unset or set 497 // to zero, VolumeInUseWaiter will use default max delay of 120 seconds. Note that 498 // MaxDelay must resolve to value greater than or equal to the MinDelay. 499 MaxDelay time.Duration 500 501 // LogWaitAttempts is used to enable logging for waiter retry attempts 502 LogWaitAttempts bool 503 504 // Retryable is function that can be used to override the service defined 505 // waiter-behavior based on operation output, or returned error. This function is 506 // used by the waiter to decide if a state is retryable or a terminal state. By 507 // default service-modeled logic will populate this option. This option can thus be 508 // used to define a custom waiter state with fall-back to service-modeled waiter 509 // state mutators.The function returns an error in case of a failure state. In case 510 // of retry state, this function returns a bool value of true and nil error, while 511 // in case of success it returns a bool value of false and nil error. 512 Retryable func(context.Context, *DescribeVolumesInput, *DescribeVolumesOutput, error) (bool, error) 513} 514 515// VolumeInUseWaiter defines the waiters for VolumeInUse 516type VolumeInUseWaiter struct { 517 client DescribeVolumesAPIClient 518 519 options VolumeInUseWaiterOptions 520} 521 522// NewVolumeInUseWaiter constructs a VolumeInUseWaiter. 523func NewVolumeInUseWaiter(client DescribeVolumesAPIClient, optFns ...func(*VolumeInUseWaiterOptions)) *VolumeInUseWaiter { 524 options := VolumeInUseWaiterOptions{} 525 options.MinDelay = 15 * time.Second 526 options.MaxDelay = 120 * time.Second 527 options.Retryable = volumeInUseStateRetryable 528 529 for _, fn := range optFns { 530 fn(&options) 531 } 532 return &VolumeInUseWaiter{ 533 client: client, 534 options: options, 535 } 536} 537 538// Wait calls the waiter function for VolumeInUse waiter. The maxWaitDur is the 539// maximum wait duration the waiter will wait. The maxWaitDur is required and must 540// be greater than zero. 541func (w *VolumeInUseWaiter) Wait(ctx context.Context, params *DescribeVolumesInput, maxWaitDur time.Duration, optFns ...func(*VolumeInUseWaiterOptions)) error { 542 if maxWaitDur <= 0 { 543 return fmt.Errorf("maximum wait time for waiter must be greater than zero") 544 } 545 546 options := w.options 547 for _, fn := range optFns { 548 fn(&options) 549 } 550 551 if options.MaxDelay <= 0 { 552 options.MaxDelay = 120 * time.Second 553 } 554 555 if options.MinDelay > options.MaxDelay { 556 return fmt.Errorf("minimum waiter delay %v must be lesser than or equal to maximum waiter delay of %v.", options.MinDelay, options.MaxDelay) 557 } 558 559 ctx, cancelFn := context.WithTimeout(ctx, maxWaitDur) 560 defer cancelFn() 561 562 logger := smithywaiter.Logger{} 563 remainingTime := maxWaitDur 564 565 var attempt int64 566 for { 567 568 attempt++ 569 apiOptions := options.APIOptions 570 start := time.Now() 571 572 if options.LogWaitAttempts { 573 logger.Attempt = attempt 574 apiOptions = append([]func(*middleware.Stack) error{}, options.APIOptions...) 575 apiOptions = append(apiOptions, logger.AddLogger) 576 } 577 578 out, err := w.client.DescribeVolumes(ctx, params, func(o *Options) { 579 o.APIOptions = append(o.APIOptions, apiOptions...) 580 }) 581 582 retryable, err := options.Retryable(ctx, params, out, err) 583 if err != nil { 584 return err 585 } 586 if !retryable { 587 return nil 588 } 589 590 remainingTime -= time.Since(start) 591 if remainingTime < options.MinDelay || remainingTime <= 0 { 592 break 593 } 594 595 // compute exponential backoff between waiter retries 596 delay, err := smithywaiter.ComputeDelay( 597 attempt, options.MinDelay, options.MaxDelay, remainingTime, 598 ) 599 if err != nil { 600 return fmt.Errorf("error computing waiter delay, %w", err) 601 } 602 603 remainingTime -= delay 604 // sleep for the delay amount before invoking a request 605 if err := smithytime.SleepWithContext(ctx, delay); err != nil { 606 return fmt.Errorf("request cancelled while waiting, %w", err) 607 } 608 } 609 return fmt.Errorf("exceeded max wait time for VolumeInUse waiter") 610} 611 612func volumeInUseStateRetryable(ctx context.Context, input *DescribeVolumesInput, output *DescribeVolumesOutput, err error) (bool, error) { 613 614 if err == nil { 615 pathValue, err := jmespath.Search("Volumes[].State", output) 616 if err != nil { 617 return false, fmt.Errorf("error evaluating waiter state: %w", err) 618 } 619 620 expectedValue := "in-use" 621 var match = true 622 listOfValues, ok := pathValue.([]interface{}) 623 if !ok { 624 return false, fmt.Errorf("waiter comparator expected list got %T", pathValue) 625 } 626 627 if len(listOfValues) == 0 { 628 match = false 629 } 630 for _, v := range listOfValues { 631 value, ok := v.(types.VolumeState) 632 if !ok { 633 return false, fmt.Errorf("waiter comparator expected types.VolumeState value, got %T", pathValue) 634 } 635 636 if string(value) != expectedValue { 637 match = false 638 } 639 } 640 641 if match { 642 return false, nil 643 } 644 } 645 646 if err == nil { 647 pathValue, err := jmespath.Search("Volumes[].State", output) 648 if err != nil { 649 return false, fmt.Errorf("error evaluating waiter state: %w", err) 650 } 651 652 expectedValue := "deleted" 653 listOfValues, ok := pathValue.([]interface{}) 654 if !ok { 655 return false, fmt.Errorf("waiter comparator expected list got %T", pathValue) 656 } 657 658 for _, v := range listOfValues { 659 value, ok := v.(types.VolumeState) 660 if !ok { 661 return false, fmt.Errorf("waiter comparator expected types.VolumeState value, got %T", pathValue) 662 } 663 664 if string(value) == expectedValue { 665 return false, fmt.Errorf("waiter state transitioned to Failure") 666 } 667 } 668 } 669 670 return true, nil 671} 672 673func newServiceMetadataMiddleware_opDescribeVolumes(region string) *awsmiddleware.RegisterServiceMetadata { 674 return &awsmiddleware.RegisterServiceMetadata{ 675 Region: region, 676 ServiceID: ServiceID, 677 SigningName: "ec2", 678 OperationName: "DescribeVolumes", 679 } 680} 681