in internal/aws/ec2/instance_waiter.go [84:165]
func (w *InstanceConditionWaiter) WaitForOutput(ctx context.Context, params *ec2.DescribeInstancesInput, maxWaitDur time.Duration, optFns ...func(*InstanceConditionWaiterOptions)) (*ec2.DescribeInstancesOutput, error) {
if maxWaitDur <= 0 {
return nil, fmt.Errorf("maximum wait time for waiter must be greater than zero")
}
options := w.options
for _, fn := range optFns {
fn(&options)
}
if options.MaxDelay <= 0 {
options.MaxDelay = 120 * time.Second
}
if options.MinDelay > options.MaxDelay {
return nil, fmt.Errorf("minimum waiter delay %v must be lesser than or equal to maximum waiter delay of %v", options.MinDelay, options.MaxDelay)
}
ctx, cancelFn := context.WithTimeout(ctx, maxWaitDur)
defer cancelFn()
logger := smithywaiter.Logger{}
remainingTime := maxWaitDur
var attempt int64
for {
attempt++
apiOptions := options.APIOptions
start := time.Now()
if options.LogWaitAttempts {
logger.Attempt = attempt
apiOptions = append([]func(*middleware.Stack) error{}, options.APIOptions...)
apiOptions = append(apiOptions, logger.AddLogger)
}
out, err := w.client.DescribeInstances(ctx, params, func(o *ec2.Options) {
o.APIOptions = append(o.APIOptions, apiOptions...)
for _, opt := range options.ClientOptions {
opt(o)
}
})
if err != nil {
retryable, err := instanceRetryable(err)
if err != nil {
return nil, err
}
if !retryable {
return out, nil
}
} else {
conditionMet, err := w.condition(out)
if err != nil {
return nil, err
}
if conditionMet {
return out, nil
}
}
remainingTime -= time.Since(start)
if remainingTime < options.MinDelay || remainingTime <= 0 {
break
}
// compute exponential backoff between waiter retries
delay, err := smithywaiter.ComputeDelay(
attempt, options.MinDelay, options.MaxDelay, remainingTime,
)
if err != nil {
return nil, fmt.Errorf("error computing waiter delay, %w", err)
}
remainingTime -= delay
// sleep for the delay amount before invoking a request
if err := smithytime.SleepWithContext(ctx, delay); err != nil {
return nil, fmt.Errorf("request cancelled while waiting, %w", err)
}
}
return nil, fmt.Errorf("exceeded max wait time for InstanceCondition waiter")
}