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 instances or all instances. If you specify instance IDs, 20// the output includes information for only the specified instances. If you specify 21// filters, the output includes information for only those instances that meet the 22// filter criteria. If you do not specify instance IDs or filters, the output 23// includes information for all instances, which can affect performance. We 24// recommend that you use pagination to ensure that the operation returns quickly 25// and successfully. If you specify an instance ID that is not valid, an error is 26// returned. If you specify an instance that you do not own, it is not included in 27// the output. Recently terminated instances might appear in the returned results. 28// This interval is usually less than one hour. If you describe instances in the 29// rare case where an Availability Zone is experiencing a service disruption and 30// you specify instance IDs that are in the affected zone, or do not specify any 31// instance IDs at all, the call fails. If you describe instances and specify only 32// instance IDs that are in an unaffected zone, the call works normally. 33func (c *Client) DescribeInstances(ctx context.Context, params *DescribeInstancesInput, optFns ...func(*Options)) (*DescribeInstancesOutput, error) { 34 if params == nil { 35 params = &DescribeInstancesInput{} 36 } 37 38 result, metadata, err := c.invokeOperation(ctx, "DescribeInstances", params, optFns, addOperationDescribeInstancesMiddlewares) 39 if err != nil { 40 return nil, err 41 } 42 43 out := result.(*DescribeInstancesOutput) 44 out.ResultMetadata = metadata 45 return out, nil 46} 47 48type DescribeInstancesInput struct { 49 50 // Checks whether you have the required permissions for the action, without 51 // actually making the request, and provides an error response. If you have the 52 // required permissions, the error response is DryRunOperation. Otherwise, it is 53 // UnauthorizedOperation. 54 DryRun bool 55 56 // The filters. 57 // 58 // * affinity - The affinity setting for an instance running on a 59 // Dedicated Host (default | host). 60 // 61 // * architecture - The instance architecture 62 // (i386 | x86_64 | arm64). 63 // 64 // * availability-zone - The Availability Zone of the 65 // instance. 66 // 67 // * block-device-mapping.attach-time - The attach time for an EBS 68 // volume mapped to the instance, for example, 2010-09-15T17:15:20.000Z. 69 // 70 // * 71 // block-device-mapping.delete-on-termination - A Boolean that indicates whether 72 // the EBS volume is deleted on instance termination. 73 // 74 // * 75 // block-device-mapping.device-name - The device name specified in the block device 76 // mapping (for example, /dev/sdh or xvdh). 77 // 78 // * block-device-mapping.status - The 79 // status for the EBS volume (attaching | attached | detaching | detached). 80 // 81 // * 82 // block-device-mapping.volume-id - The volume ID of the EBS volume. 83 // 84 // * 85 // client-token - The idempotency token you provided when you launched the 86 // instance. 87 // 88 // * dns-name - The public DNS name of the instance. 89 // 90 // * group-id - The 91 // ID of the security group for the instance. EC2-Classic only. 92 // 93 // * group-name - The 94 // name of the security group for the instance. EC2-Classic only. 95 // 96 // * 97 // hibernation-options.configured - A Boolean that indicates whether the instance 98 // is enabled for hibernation. A value of true means that the instance is enabled 99 // for hibernation. 100 // 101 // * host-id - The ID of the Dedicated Host on which the instance 102 // is running, if applicable. 103 // 104 // * hypervisor - The hypervisor type of the instance 105 // (ovm | xen). The value xen is used for both Xen and Nitro hypervisors. 106 // 107 // * 108 // iam-instance-profile.arn - The instance profile associated with the instance. 109 // Specified as an ARN. 110 // 111 // * image-id - The ID of the image used to launch the 112 // instance. 113 // 114 // * instance-id - The ID of the instance. 115 // 116 // * instance-lifecycle - 117 // Indicates whether this is a Spot Instance or a Scheduled Instance (spot | 118 // scheduled). 119 // 120 // * instance-state-code - The state of the instance, as a 16-bit 121 // unsigned integer. The high byte is used for internal purposes and should be 122 // ignored. The low byte is set based on the state represented. The valid values 123 // are: 0 (pending), 16 (running), 32 (shutting-down), 48 (terminated), 64 124 // (stopping), and 80 (stopped). 125 // 126 // * instance-state-name - The state of the instance 127 // (pending | running | shutting-down | terminated | stopping | stopped). 128 // 129 // * 130 // instance-type - The type of instance (for example, t2.micro). 131 // 132 // * 133 // instance.group-id - The ID of the security group for the instance. 134 // 135 // * 136 // instance.group-name - The name of the security group for the instance. 137 // 138 // * 139 // ip-address - The public IPv4 address of the instance. 140 // 141 // * kernel-id - The kernel 142 // ID. 143 // 144 // * key-name - The name of the key pair used when the instance was 145 // launched. 146 // 147 // * launch-index - When launching multiple instances, this is the index 148 // for the instance in the launch group (for example, 0, 1, 2, and so on). 149 // 150 // * 151 // launch-time - The time when the instance was launched. 152 // 153 // * 154 // metadata-options.http-tokens - The metadata request authorization state 155 // (optional | required) 156 // 157 // * metadata-options.http-put-response-hop-limit - The http 158 // metadata request put response hop limit (integer, possible values 1 to 64) 159 // 160 // * 161 // metadata-options.http-endpoint - Enable or disable metadata access on http 162 // endpoint (enabled | disabled) 163 // 164 // * monitoring-state - Indicates whether detailed 165 // monitoring is enabled (disabled | enabled). 166 // 167 // * 168 // network-interface.addresses.private-ip-address - The private IPv4 address 169 // associated with the network interface. 170 // 171 // * network-interface.addresses.primary - 172 // Specifies whether the IPv4 address of the network interface is the primary 173 // private IPv4 address. 174 // 175 // * network-interface.addresses.association.public-ip - The 176 // ID of the association of an Elastic IP address (IPv4) with a network 177 // interface. 178 // 179 // * network-interface.addresses.association.ip-owner-id - The owner ID 180 // of the private IPv4 address associated with the network interface. 181 // 182 // * 183 // network-interface.association.public-ip - The address of the Elastic IP address 184 // (IPv4) bound to the network interface. 185 // 186 // * 187 // network-interface.association.ip-owner-id - The owner of the Elastic IP address 188 // (IPv4) associated with the network interface. 189 // 190 // * 191 // network-interface.association.allocation-id - The allocation ID returned when 192 // you allocated the Elastic IP address (IPv4) for your network interface. 193 // 194 // * 195 // network-interface.association.association-id - The association ID returned when 196 // the network interface was associated with an IPv4 address. 197 // 198 // * 199 // network-interface.attachment.attachment-id - The ID of the interface 200 // attachment. 201 // 202 // * network-interface.attachment.instance-id - The ID of the instance 203 // to which the network interface is attached. 204 // 205 // * 206 // network-interface.attachment.instance-owner-id - The owner ID of the instance to 207 // which the network interface is attached. 208 // 209 // * 210 // network-interface.attachment.device-index - The device index to which the 211 // network interface is attached. 212 // 213 // * network-interface.attachment.status - The 214 // status of the attachment (attaching | attached | detaching | detached). 215 // 216 // * 217 // network-interface.attachment.attach-time - The time that the network interface 218 // was attached to an instance. 219 // 220 // * 221 // network-interface.attachment.delete-on-termination - Specifies whether the 222 // attachment is deleted when an instance is terminated. 223 // 224 // * 225 // network-interface.availability-zone - The Availability Zone for the network 226 // interface. 227 // 228 // * network-interface.description - The description of the network 229 // interface. 230 // 231 // * network-interface.group-id - The ID of a security group associated 232 // with the network interface. 233 // 234 // * network-interface.group-name - The name of a 235 // security group associated with the network interface. 236 // 237 // * 238 // network-interface.ipv6-addresses.ipv6-address - The IPv6 address associated with 239 // the network interface. 240 // 241 // * network-interface.mac-address - The MAC address of the 242 // network interface. 243 // 244 // * network-interface.network-interface-id - The ID of the 245 // network interface. 246 // 247 // * network-interface.owner-id - The ID of the owner of the 248 // network interface. 249 // 250 // * network-interface.private-dns-name - The private DNS name 251 // of the network interface. 252 // 253 // * network-interface.requester-id - The requester ID 254 // for the network interface. 255 // 256 // * network-interface.requester-managed - Indicates 257 // whether the network interface is being managed by AWS. 258 // 259 // * 260 // network-interface.status - The status of the network interface (available) | 261 // in-use). 262 // 263 // * network-interface.source-dest-check - Whether the network interface 264 // performs source/destination checking. A value of true means that checking is 265 // enabled, and false means that checking is disabled. The value must be false for 266 // the network interface to perform network address translation (NAT) in your 267 // VPC. 268 // 269 // * network-interface.subnet-id - The ID of the subnet for the network 270 // interface. 271 // 272 // * network-interface.vpc-id - The ID of the VPC for the network 273 // interface. 274 // 275 // * owner-id - The AWS account ID of the instance owner. 276 // 277 // * 278 // placement-group-name - The name of the placement group for the instance. 279 // 280 // * 281 // placement-partition-number - The partition in which the instance is located. 282 // 283 // * 284 // platform - The platform. To list only Windows instances, use windows. 285 // 286 // * 287 // private-dns-name - The private IPv4 DNS name of the instance. 288 // 289 // * 290 // private-ip-address - The private IPv4 address of the instance. 291 // 292 // * product-code - 293 // The product code associated with the AMI used to launch the instance. 294 // 295 // * 296 // product-code.type - The type of product code (devpay | marketplace). 297 // 298 // * 299 // ramdisk-id - The RAM disk ID. 300 // 301 // * reason - The reason for the current state of 302 // the instance (for example, shows "User Initiated [date]" when you stop or 303 // terminate the instance). Similar to the state-reason-code filter. 304 // 305 // * 306 // requester-id - The ID of the entity that launched the instance on your behalf 307 // (for example, AWS Management Console, Auto Scaling, and so on). 308 // 309 // * 310 // reservation-id - The ID of the instance's reservation. A reservation ID is 311 // created any time you launch an instance. A reservation ID has a one-to-one 312 // relationship with an instance launch request, but can be associated with more 313 // than one instance if you launch multiple instances using the same launch 314 // request. For example, if you launch one instance, you get one reservation ID. If 315 // you launch ten instances using the same launch request, you also get one 316 // reservation ID. 317 // 318 // * root-device-name - The device name of the root device volume 319 // (for example, /dev/sda1). 320 // 321 // * root-device-type - The type of the root device 322 // volume (ebs | instance-store). 323 // 324 // * source-dest-check - Indicates whether the 325 // instance performs source/destination checking. A value of true means that 326 // checking is enabled, and false means that checking is disabled. The value must 327 // be false for the instance to perform network address translation (NAT) in your 328 // VPC. 329 // 330 // * spot-instance-request-id - The ID of the Spot Instance request. 331 // 332 // * 333 // state-reason-code - The reason code for the state change. 334 // 335 // * 336 // state-reason-message - A message that describes the state change. 337 // 338 // * subnet-id - 339 // The ID of the subnet for the instance. 340 // 341 // * tag: - The key/value combination of a 342 // tag assigned to the resource. Use the tag key in the filter name and the tag 343 // value as the filter value. For example, to find all resources that have a tag 344 // with the key Owner and the value TeamA, specify tag:Owner for the filter name 345 // and TeamA for the filter value. 346 // 347 // * tag-key - The key of a tag assigned to the 348 // resource. Use this filter to find all resources that have a tag with a specific 349 // key, regardless of the tag value. 350 // 351 // * tenancy - The tenancy of an instance 352 // (dedicated | default | host). 353 // 354 // * virtualization-type - The virtualization type 355 // of the instance (paravirtual | hvm). 356 // 357 // * vpc-id - The ID of the VPC that the 358 // instance is running in. 359 Filters []types.Filter 360 361 // The instance IDs. Default: Describes all your instances. 362 InstanceIds []string 363 364 // The maximum number of results to return in a single call. To retrieve the 365 // remaining results, make another call with the returned NextToken value. This 366 // value can be between 5 and 1000. You cannot specify this parameter and the 367 // instance IDs parameter in the same call. 368 MaxResults int32 369 370 // The token to request the next page of results. 371 NextToken *string 372} 373 374type DescribeInstancesOutput struct { 375 376 // The token to use to retrieve the next page of results. This value is null when 377 // there are no more results to return. 378 NextToken *string 379 380 // Information about the reservations. 381 Reservations []types.Reservation 382 383 // Metadata pertaining to the operation's result. 384 ResultMetadata middleware.Metadata 385} 386 387func addOperationDescribeInstancesMiddlewares(stack *middleware.Stack, options Options) (err error) { 388 err = stack.Serialize.Add(&awsEc2query_serializeOpDescribeInstances{}, middleware.After) 389 if err != nil { 390 return err 391 } 392 err = stack.Deserialize.Add(&awsEc2query_deserializeOpDescribeInstances{}, middleware.After) 393 if err != nil { 394 return err 395 } 396 if err = addSetLoggerMiddleware(stack, options); err != nil { 397 return err 398 } 399 if err = awsmiddleware.AddClientRequestIDMiddleware(stack); err != nil { 400 return err 401 } 402 if err = smithyhttp.AddComputeContentLengthMiddleware(stack); err != nil { 403 return err 404 } 405 if err = addResolveEndpointMiddleware(stack, options); err != nil { 406 return err 407 } 408 if err = v4.AddComputePayloadSHA256Middleware(stack); err != nil { 409 return err 410 } 411 if err = addRetryMiddlewares(stack, options); err != nil { 412 return err 413 } 414 if err = addHTTPSignerV4Middleware(stack, options); err != nil { 415 return err 416 } 417 if err = awsmiddleware.AddRawResponseToMetadata(stack); err != nil { 418 return err 419 } 420 if err = awsmiddleware.AddRecordResponseTiming(stack); err != nil { 421 return err 422 } 423 if err = addClientUserAgent(stack); err != nil { 424 return err 425 } 426 if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil { 427 return err 428 } 429 if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil { 430 return err 431 } 432 if err = stack.Initialize.Add(newServiceMetadataMiddleware_opDescribeInstances(options.Region), middleware.Before); err != nil { 433 return err 434 } 435 if err = addRequestIDRetrieverMiddleware(stack); err != nil { 436 return err 437 } 438 if err = addResponseErrorMiddleware(stack); err != nil { 439 return err 440 } 441 if err = addRequestResponseLogging(stack, options); err != nil { 442 return err 443 } 444 return nil 445} 446 447// DescribeInstancesAPIClient is a client that implements the DescribeInstances 448// operation. 449type DescribeInstancesAPIClient interface { 450 DescribeInstances(context.Context, *DescribeInstancesInput, ...func(*Options)) (*DescribeInstancesOutput, error) 451} 452 453var _ DescribeInstancesAPIClient = (*Client)(nil) 454 455// DescribeInstancesPaginatorOptions is the paginator options for DescribeInstances 456type DescribeInstancesPaginatorOptions struct { 457 // The maximum number of results to return in a single call. To retrieve the 458 // remaining results, make another call with the returned NextToken value. This 459 // value can be between 5 and 1000. You cannot specify this parameter and the 460 // instance IDs parameter in the same call. 461 Limit int32 462 463 // Set to true if pagination should stop if the service returns a pagination token 464 // that matches the most recent token provided to the service. 465 StopOnDuplicateToken bool 466} 467 468// DescribeInstancesPaginator is a paginator for DescribeInstances 469type DescribeInstancesPaginator struct { 470 options DescribeInstancesPaginatorOptions 471 client DescribeInstancesAPIClient 472 params *DescribeInstancesInput 473 nextToken *string 474 firstPage bool 475} 476 477// NewDescribeInstancesPaginator returns a new DescribeInstancesPaginator 478func NewDescribeInstancesPaginator(client DescribeInstancesAPIClient, params *DescribeInstancesInput, optFns ...func(*DescribeInstancesPaginatorOptions)) *DescribeInstancesPaginator { 479 options := DescribeInstancesPaginatorOptions{} 480 if params.MaxResults != 0 { 481 options.Limit = params.MaxResults 482 } 483 484 for _, fn := range optFns { 485 fn(&options) 486 } 487 488 if params == nil { 489 params = &DescribeInstancesInput{} 490 } 491 492 return &DescribeInstancesPaginator{ 493 options: options, 494 client: client, 495 params: params, 496 firstPage: true, 497 } 498} 499 500// HasMorePages returns a boolean indicating whether more pages are available 501func (p *DescribeInstancesPaginator) HasMorePages() bool { 502 return p.firstPage || p.nextToken != nil 503} 504 505// NextPage retrieves the next DescribeInstances page. 506func (p *DescribeInstancesPaginator) NextPage(ctx context.Context, optFns ...func(*Options)) (*DescribeInstancesOutput, error) { 507 if !p.HasMorePages() { 508 return nil, fmt.Errorf("no more pages available") 509 } 510 511 params := *p.params 512 params.NextToken = p.nextToken 513 514 params.MaxResults = p.options.Limit 515 516 result, err := p.client.DescribeInstances(ctx, ¶ms, optFns...) 517 if err != nil { 518 return nil, err 519 } 520 p.firstPage = false 521 522 prevToken := p.nextToken 523 p.nextToken = result.NextToken 524 525 if p.options.StopOnDuplicateToken && prevToken != nil && p.nextToken != nil && *prevToken == *p.nextToken { 526 p.nextToken = nil 527 } 528 529 return result, nil 530} 531 532// InstanceStoppedWaiterOptions are waiter options for InstanceStoppedWaiter 533type InstanceStoppedWaiterOptions struct { 534 535 // Set of options to modify how an operation is invoked. These apply to all 536 // operations invoked for this client. Use functional options on operation call to 537 // modify this list for per operation behavior. 538 APIOptions []func(*middleware.Stack) error 539 540 // MinDelay is the minimum amount of time to delay between retries. If unset, 541 // InstanceStoppedWaiter will use default minimum delay of 15 seconds. Note that 542 // MinDelay must resolve to a value lesser than or equal to the MaxDelay. 543 MinDelay time.Duration 544 545 // MaxDelay is the maximum amount of time to delay between retries. If unset or set 546 // to zero, InstanceStoppedWaiter will use default max delay of 120 seconds. Note 547 // that MaxDelay must resolve to value greater than or equal to the MinDelay. 548 MaxDelay time.Duration 549 550 // LogWaitAttempts is used to enable logging for waiter retry attempts 551 LogWaitAttempts bool 552 553 // Retryable is function that can be used to override the service defined 554 // waiter-behavior based on operation output, or returned error. This function is 555 // used by the waiter to decide if a state is retryable or a terminal state. By 556 // default service-modeled logic will populate this option. This option can thus be 557 // used to define a custom waiter state with fall-back to service-modeled waiter 558 // state mutators.The function returns an error in case of a failure state. In case 559 // of retry state, this function returns a bool value of true and nil error, while 560 // in case of success it returns a bool value of false and nil error. 561 Retryable func(context.Context, *DescribeInstancesInput, *DescribeInstancesOutput, error) (bool, error) 562} 563 564// InstanceStoppedWaiter defines the waiters for InstanceStopped 565type InstanceStoppedWaiter struct { 566 client DescribeInstancesAPIClient 567 568 options InstanceStoppedWaiterOptions 569} 570 571// NewInstanceStoppedWaiter constructs a InstanceStoppedWaiter. 572func NewInstanceStoppedWaiter(client DescribeInstancesAPIClient, optFns ...func(*InstanceStoppedWaiterOptions)) *InstanceStoppedWaiter { 573 options := InstanceStoppedWaiterOptions{} 574 options.MinDelay = 15 * time.Second 575 options.MaxDelay = 120 * time.Second 576 options.Retryable = instanceStoppedStateRetryable 577 578 for _, fn := range optFns { 579 fn(&options) 580 } 581 return &InstanceStoppedWaiter{ 582 client: client, 583 options: options, 584 } 585} 586 587// Wait calls the waiter function for InstanceStopped waiter. The maxWaitDur is the 588// maximum wait duration the waiter will wait. The maxWaitDur is required and must 589// be greater than zero. 590func (w *InstanceStoppedWaiter) Wait(ctx context.Context, params *DescribeInstancesInput, maxWaitDur time.Duration, optFns ...func(*InstanceStoppedWaiterOptions)) error { 591 if maxWaitDur <= 0 { 592 return fmt.Errorf("maximum wait time for waiter must be greater than zero") 593 } 594 595 options := w.options 596 for _, fn := range optFns { 597 fn(&options) 598 } 599 600 if options.MaxDelay <= 0 { 601 options.MaxDelay = 120 * time.Second 602 } 603 604 if options.MinDelay > options.MaxDelay { 605 return fmt.Errorf("minimum waiter delay %v must be lesser than or equal to maximum waiter delay of %v.", options.MinDelay, options.MaxDelay) 606 } 607 608 ctx, cancelFn := context.WithTimeout(ctx, maxWaitDur) 609 defer cancelFn() 610 611 logger := smithywaiter.Logger{} 612 remainingTime := maxWaitDur 613 614 var attempt int64 615 for { 616 617 attempt++ 618 apiOptions := options.APIOptions 619 start := time.Now() 620 621 if options.LogWaitAttempts { 622 logger.Attempt = attempt 623 apiOptions = append([]func(*middleware.Stack) error{}, options.APIOptions...) 624 apiOptions = append(apiOptions, logger.AddLogger) 625 } 626 627 out, err := w.client.DescribeInstances(ctx, params, func(o *Options) { 628 o.APIOptions = append(o.APIOptions, apiOptions...) 629 }) 630 631 retryable, err := options.Retryable(ctx, params, out, err) 632 if err != nil { 633 return err 634 } 635 if !retryable { 636 return nil 637 } 638 639 remainingTime -= time.Since(start) 640 if remainingTime < options.MinDelay || remainingTime <= 0 { 641 break 642 } 643 644 // compute exponential backoff between waiter retries 645 delay, err := smithywaiter.ComputeDelay( 646 attempt, options.MinDelay, options.MaxDelay, remainingTime, 647 ) 648 if err != nil { 649 return fmt.Errorf("error computing waiter delay, %w", err) 650 } 651 652 remainingTime -= delay 653 // sleep for the delay amount before invoking a request 654 if err := smithytime.SleepWithContext(ctx, delay); err != nil { 655 return fmt.Errorf("request cancelled while waiting, %w", err) 656 } 657 } 658 return fmt.Errorf("exceeded max wait time for InstanceStopped waiter") 659} 660 661func instanceStoppedStateRetryable(ctx context.Context, input *DescribeInstancesInput, output *DescribeInstancesOutput, err error) (bool, error) { 662 663 if err == nil { 664 pathValue, err := jmespath.Search("Reservations[].Instances[].State.Name", output) 665 if err != nil { 666 return false, fmt.Errorf("error evaluating waiter state: %w", err) 667 } 668 669 expectedValue := "stopped" 670 var match = true 671 listOfValues, ok := pathValue.([]interface{}) 672 if !ok { 673 return false, fmt.Errorf("waiter comparator expected list got %T", pathValue) 674 } 675 676 if len(listOfValues) == 0 { 677 match = false 678 } 679 for _, v := range listOfValues { 680 value, ok := v.(types.InstanceStateName) 681 if !ok { 682 return false, fmt.Errorf("waiter comparator expected types.InstanceStateName value, got %T", pathValue) 683 } 684 685 if string(value) != expectedValue { 686 match = false 687 } 688 } 689 690 if match { 691 return false, nil 692 } 693 } 694 695 if err == nil { 696 pathValue, err := jmespath.Search("Reservations[].Instances[].State.Name", output) 697 if err != nil { 698 return false, fmt.Errorf("error evaluating waiter state: %w", err) 699 } 700 701 expectedValue := "pending" 702 listOfValues, ok := pathValue.([]interface{}) 703 if !ok { 704 return false, fmt.Errorf("waiter comparator expected list got %T", pathValue) 705 } 706 707 for _, v := range listOfValues { 708 value, ok := v.(types.InstanceStateName) 709 if !ok { 710 return false, fmt.Errorf("waiter comparator expected types.InstanceStateName value, got %T", pathValue) 711 } 712 713 if string(value) == expectedValue { 714 return false, fmt.Errorf("waiter state transitioned to Failure") 715 } 716 } 717 } 718 719 if err == nil { 720 pathValue, err := jmespath.Search("Reservations[].Instances[].State.Name", output) 721 if err != nil { 722 return false, fmt.Errorf("error evaluating waiter state: %w", err) 723 } 724 725 expectedValue := "terminated" 726 listOfValues, ok := pathValue.([]interface{}) 727 if !ok { 728 return false, fmt.Errorf("waiter comparator expected list got %T", pathValue) 729 } 730 731 for _, v := range listOfValues { 732 value, ok := v.(types.InstanceStateName) 733 if !ok { 734 return false, fmt.Errorf("waiter comparator expected types.InstanceStateName value, got %T", pathValue) 735 } 736 737 if string(value) == expectedValue { 738 return false, fmt.Errorf("waiter state transitioned to Failure") 739 } 740 } 741 } 742 743 return true, nil 744} 745 746// InstanceTerminatedWaiterOptions are waiter options for InstanceTerminatedWaiter 747type InstanceTerminatedWaiterOptions struct { 748 749 // Set of options to modify how an operation is invoked. These apply to all 750 // operations invoked for this client. Use functional options on operation call to 751 // modify this list for per operation behavior. 752 APIOptions []func(*middleware.Stack) error 753 754 // MinDelay is the minimum amount of time to delay between retries. If unset, 755 // InstanceTerminatedWaiter will use default minimum delay of 15 seconds. Note that 756 // MinDelay must resolve to a value lesser than or equal to the MaxDelay. 757 MinDelay time.Duration 758 759 // MaxDelay is the maximum amount of time to delay between retries. If unset or set 760 // to zero, InstanceTerminatedWaiter will use default max delay of 120 seconds. 761 // Note that MaxDelay must resolve to value greater than or equal to the MinDelay. 762 MaxDelay time.Duration 763 764 // LogWaitAttempts is used to enable logging for waiter retry attempts 765 LogWaitAttempts bool 766 767 // Retryable is function that can be used to override the service defined 768 // waiter-behavior based on operation output, or returned error. This function is 769 // used by the waiter to decide if a state is retryable or a terminal state. By 770 // default service-modeled logic will populate this option. This option can thus be 771 // used to define a custom waiter state with fall-back to service-modeled waiter 772 // state mutators.The function returns an error in case of a failure state. In case 773 // of retry state, this function returns a bool value of true and nil error, while 774 // in case of success it returns a bool value of false and nil error. 775 Retryable func(context.Context, *DescribeInstancesInput, *DescribeInstancesOutput, error) (bool, error) 776} 777 778// InstanceTerminatedWaiter defines the waiters for InstanceTerminated 779type InstanceTerminatedWaiter struct { 780 client DescribeInstancesAPIClient 781 782 options InstanceTerminatedWaiterOptions 783} 784 785// NewInstanceTerminatedWaiter constructs a InstanceTerminatedWaiter. 786func NewInstanceTerminatedWaiter(client DescribeInstancesAPIClient, optFns ...func(*InstanceTerminatedWaiterOptions)) *InstanceTerminatedWaiter { 787 options := InstanceTerminatedWaiterOptions{} 788 options.MinDelay = 15 * time.Second 789 options.MaxDelay = 120 * time.Second 790 options.Retryable = instanceTerminatedStateRetryable 791 792 for _, fn := range optFns { 793 fn(&options) 794 } 795 return &InstanceTerminatedWaiter{ 796 client: client, 797 options: options, 798 } 799} 800 801// Wait calls the waiter function for InstanceTerminated waiter. The maxWaitDur is 802// the maximum wait duration the waiter will wait. The maxWaitDur is required and 803// must be greater than zero. 804func (w *InstanceTerminatedWaiter) Wait(ctx context.Context, params *DescribeInstancesInput, maxWaitDur time.Duration, optFns ...func(*InstanceTerminatedWaiterOptions)) error { 805 if maxWaitDur <= 0 { 806 return fmt.Errorf("maximum wait time for waiter must be greater than zero") 807 } 808 809 options := w.options 810 for _, fn := range optFns { 811 fn(&options) 812 } 813 814 if options.MaxDelay <= 0 { 815 options.MaxDelay = 120 * time.Second 816 } 817 818 if options.MinDelay > options.MaxDelay { 819 return fmt.Errorf("minimum waiter delay %v must be lesser than or equal to maximum waiter delay of %v.", options.MinDelay, options.MaxDelay) 820 } 821 822 ctx, cancelFn := context.WithTimeout(ctx, maxWaitDur) 823 defer cancelFn() 824 825 logger := smithywaiter.Logger{} 826 remainingTime := maxWaitDur 827 828 var attempt int64 829 for { 830 831 attempt++ 832 apiOptions := options.APIOptions 833 start := time.Now() 834 835 if options.LogWaitAttempts { 836 logger.Attempt = attempt 837 apiOptions = append([]func(*middleware.Stack) error{}, options.APIOptions...) 838 apiOptions = append(apiOptions, logger.AddLogger) 839 } 840 841 out, err := w.client.DescribeInstances(ctx, params, func(o *Options) { 842 o.APIOptions = append(o.APIOptions, apiOptions...) 843 }) 844 845 retryable, err := options.Retryable(ctx, params, out, err) 846 if err != nil { 847 return err 848 } 849 if !retryable { 850 return nil 851 } 852 853 remainingTime -= time.Since(start) 854 if remainingTime < options.MinDelay || remainingTime <= 0 { 855 break 856 } 857 858 // compute exponential backoff between waiter retries 859 delay, err := smithywaiter.ComputeDelay( 860 attempt, options.MinDelay, options.MaxDelay, remainingTime, 861 ) 862 if err != nil { 863 return fmt.Errorf("error computing waiter delay, %w", err) 864 } 865 866 remainingTime -= delay 867 // sleep for the delay amount before invoking a request 868 if err := smithytime.SleepWithContext(ctx, delay); err != nil { 869 return fmt.Errorf("request cancelled while waiting, %w", err) 870 } 871 } 872 return fmt.Errorf("exceeded max wait time for InstanceTerminated waiter") 873} 874 875func instanceTerminatedStateRetryable(ctx context.Context, input *DescribeInstancesInput, output *DescribeInstancesOutput, err error) (bool, error) { 876 877 if err == nil { 878 pathValue, err := jmespath.Search("Reservations[].Instances[].State.Name", output) 879 if err != nil { 880 return false, fmt.Errorf("error evaluating waiter state: %w", err) 881 } 882 883 expectedValue := "terminated" 884 var match = true 885 listOfValues, ok := pathValue.([]interface{}) 886 if !ok { 887 return false, fmt.Errorf("waiter comparator expected list got %T", pathValue) 888 } 889 890 if len(listOfValues) == 0 { 891 match = false 892 } 893 for _, v := range listOfValues { 894 value, ok := v.(types.InstanceStateName) 895 if !ok { 896 return false, fmt.Errorf("waiter comparator expected types.InstanceStateName value, got %T", pathValue) 897 } 898 899 if string(value) != expectedValue { 900 match = false 901 } 902 } 903 904 if match { 905 return false, nil 906 } 907 } 908 909 if err == nil { 910 pathValue, err := jmespath.Search("Reservations[].Instances[].State.Name", output) 911 if err != nil { 912 return false, fmt.Errorf("error evaluating waiter state: %w", err) 913 } 914 915 expectedValue := "pending" 916 listOfValues, ok := pathValue.([]interface{}) 917 if !ok { 918 return false, fmt.Errorf("waiter comparator expected list got %T", pathValue) 919 } 920 921 for _, v := range listOfValues { 922 value, ok := v.(types.InstanceStateName) 923 if !ok { 924 return false, fmt.Errorf("waiter comparator expected types.InstanceStateName value, got %T", pathValue) 925 } 926 927 if string(value) == expectedValue { 928 return false, fmt.Errorf("waiter state transitioned to Failure") 929 } 930 } 931 } 932 933 if err == nil { 934 pathValue, err := jmespath.Search("Reservations[].Instances[].State.Name", output) 935 if err != nil { 936 return false, fmt.Errorf("error evaluating waiter state: %w", err) 937 } 938 939 expectedValue := "stopping" 940 listOfValues, ok := pathValue.([]interface{}) 941 if !ok { 942 return false, fmt.Errorf("waiter comparator expected list got %T", pathValue) 943 } 944 945 for _, v := range listOfValues { 946 value, ok := v.(types.InstanceStateName) 947 if !ok { 948 return false, fmt.Errorf("waiter comparator expected types.InstanceStateName value, got %T", pathValue) 949 } 950 951 if string(value) == expectedValue { 952 return false, fmt.Errorf("waiter state transitioned to Failure") 953 } 954 } 955 } 956 957 return true, nil 958} 959 960func newServiceMetadataMiddleware_opDescribeInstances(region string) *awsmiddleware.RegisterServiceMetadata { 961 return &awsmiddleware.RegisterServiceMetadata{ 962 Region: region, 963 ServiceID: ServiceID, 964 SigningName: "ec2", 965 OperationName: "DescribeInstances", 966 } 967} 968