Merge pull request #7523 from hashicorp/f-aws-beanstalk-env-poll-timing
provider/aws: Beanstalk environments, bump the minimum timeout between API calls
This commit is contained in:
commit
261043fd1a
|
@ -135,6 +135,23 @@ func resourceAwsElasticBeanstalkEnvironment() *schema.Resource {
|
|||
return
|
||||
},
|
||||
},
|
||||
"poll_interval": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) {
|
||||
value := v.(string)
|
||||
duration, err := time.ParseDuration(value)
|
||||
if err != nil {
|
||||
errors = append(errors, fmt.Errorf(
|
||||
"%q cannot be parsed as a duration: %s", k, err))
|
||||
}
|
||||
if duration < 10*time.Second || duration > 60*time.Second {
|
||||
errors = append(errors, fmt.Errorf(
|
||||
"%q must be between 10s and 180s", k))
|
||||
}
|
||||
return
|
||||
},
|
||||
},
|
||||
"autoscaling_groups": &schema.Schema{
|
||||
Type: schema.TypeList,
|
||||
Computed: true,
|
||||
|
@ -183,10 +200,6 @@ func resourceAwsElasticBeanstalkEnvironmentCreate(d *schema.ResourceData, meta i
|
|||
settings := d.Get("setting").(*schema.Set)
|
||||
solutionStack := d.Get("solution_stack_name").(string)
|
||||
templateName := d.Get("template_name").(string)
|
||||
waitForReadyTimeOut, err := time.ParseDuration(d.Get("wait_for_ready_timeout").(string))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO set tags
|
||||
// Note: at time of writing, you cannot view or edit Tags after creation
|
||||
|
@ -244,13 +257,25 @@ func resourceAwsElasticBeanstalkEnvironmentCreate(d *schema.ResourceData, meta i
|
|||
// Assign the application name as the resource ID
|
||||
d.SetId(*resp.EnvironmentId)
|
||||
|
||||
waitForReadyTimeOut, err := time.ParseDuration(d.Get("wait_for_ready_timeout").(string))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pollInterval, err := time.ParseDuration(d.Get("poll_interval").(string))
|
||||
if err != nil {
|
||||
pollInterval = 0
|
||||
log.Printf("[WARN] Error parsing poll_interval, using default backoff")
|
||||
}
|
||||
|
||||
stateConf := &resource.StateChangeConf{
|
||||
Pending: []string{"Launching", "Updating"},
|
||||
Target: []string{"Ready"},
|
||||
Refresh: environmentStateRefreshFunc(conn, d.Id()),
|
||||
Timeout: waitForReadyTimeOut,
|
||||
Delay: 10 * time.Second,
|
||||
MinTimeout: 3 * time.Second,
|
||||
Pending: []string{"Launching", "Updating"},
|
||||
Target: []string{"Ready"},
|
||||
Refresh: environmentStateRefreshFunc(conn, d.Id()),
|
||||
Timeout: waitForReadyTimeOut,
|
||||
Delay: 10 * time.Second,
|
||||
PollInterval: pollInterval,
|
||||
MinTimeout: 3 * time.Second,
|
||||
}
|
||||
|
||||
_, err = stateConf.WaitForState()
|
||||
|
@ -272,24 +297,25 @@ func resourceAwsElasticBeanstalkEnvironmentUpdate(d *schema.ResourceData, meta i
|
|||
conn := meta.(*AWSClient).elasticbeanstalkconn
|
||||
|
||||
envId := d.Id()
|
||||
waitForReadyTimeOut, err := time.ParseDuration(d.Get("wait_for_ready_timeout").(string))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var hasChange bool
|
||||
|
||||
updateOpts := elasticbeanstalk.UpdateEnvironmentInput{
|
||||
EnvironmentId: aws.String(envId),
|
||||
}
|
||||
|
||||
if d.HasChange("description") {
|
||||
hasChange = true
|
||||
updateOpts.Description = aws.String(d.Get("description").(string))
|
||||
}
|
||||
|
||||
if d.HasChange("solution_stack_name") {
|
||||
hasChange = true
|
||||
updateOpts.SolutionStackName = aws.String(d.Get("solution_stack_name").(string))
|
||||
}
|
||||
|
||||
if d.HasChange("setting") {
|
||||
hasChange = true
|
||||
o, n := d.GetChange("setting")
|
||||
if o == nil {
|
||||
o = &schema.Set{F: optionSettingValueHash}
|
||||
|
@ -305,36 +331,50 @@ func resourceAwsElasticBeanstalkEnvironmentUpdate(d *schema.ResourceData, meta i
|
|||
}
|
||||
|
||||
if d.HasChange("template_name") {
|
||||
hasChange = true
|
||||
updateOpts.TemplateName = aws.String(d.Get("template_name").(string))
|
||||
}
|
||||
|
||||
// Get the current time to filter describeBeanstalkEvents messages
|
||||
t := time.Now()
|
||||
log.Printf("[DEBUG] Elastic Beanstalk Environment update opts: %s", updateOpts)
|
||||
_, err = conn.UpdateEnvironment(&updateOpts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if hasChange {
|
||||
// Get the current time to filter describeBeanstalkEvents messages
|
||||
t := time.Now()
|
||||
log.Printf("[DEBUG] Elastic Beanstalk Environment update opts: %s", updateOpts)
|
||||
_, err := conn.UpdateEnvironment(&updateOpts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
stateConf := &resource.StateChangeConf{
|
||||
Pending: []string{"Launching", "Updating"},
|
||||
Target: []string{"Ready"},
|
||||
Refresh: environmentStateRefreshFunc(conn, d.Id()),
|
||||
Timeout: waitForReadyTimeOut,
|
||||
Delay: 10 * time.Second,
|
||||
MinTimeout: 3 * time.Second,
|
||||
}
|
||||
waitForReadyTimeOut, err := time.ParseDuration(d.Get("wait_for_ready_timeout").(string))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pollInterval, err := time.ParseDuration(d.Get("poll_interval").(string))
|
||||
if err != nil {
|
||||
pollInterval = 0
|
||||
log.Printf("[WARN] Error parsing poll_interval, using default backoff")
|
||||
}
|
||||
|
||||
_, err = stateConf.WaitForState()
|
||||
if err != nil {
|
||||
return fmt.Errorf(
|
||||
"Error waiting for Elastic Beanstalk Environment (%s) to become ready: %s",
|
||||
d.Id(), err)
|
||||
}
|
||||
stateConf := &resource.StateChangeConf{
|
||||
Pending: []string{"Launching", "Updating"},
|
||||
Target: []string{"Ready"},
|
||||
Refresh: environmentStateRefreshFunc(conn, d.Id()),
|
||||
Timeout: waitForReadyTimeOut,
|
||||
Delay: 10 * time.Second,
|
||||
PollInterval: pollInterval,
|
||||
MinTimeout: 3 * time.Second,
|
||||
}
|
||||
|
||||
err = describeBeanstalkEvents(conn, d.Id(), t)
|
||||
if err != nil {
|
||||
return err
|
||||
_, err = stateConf.WaitForState()
|
||||
if err != nil {
|
||||
return fmt.Errorf(
|
||||
"Error waiting for Elastic Beanstalk Environment (%s) to become ready: %s",
|
||||
d.Id(), err)
|
||||
}
|
||||
|
||||
err = describeBeanstalkEvents(conn, d.Id(), t)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return resourceAwsElasticBeanstalkEnvironmentRead(d, meta)
|
||||
|
@ -547,11 +587,6 @@ func resourceAwsElasticBeanstalkEnvironmentSettingsRead(d *schema.ResourceData,
|
|||
func resourceAwsElasticBeanstalkEnvironmentDelete(d *schema.ResourceData, meta interface{}) error {
|
||||
conn := meta.(*AWSClient).elasticbeanstalkconn
|
||||
|
||||
waitForReadyTimeOut, err := time.ParseDuration(d.Get("wait_for_ready_timeout").(string))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
opts := elasticbeanstalk.TerminateEnvironmentInput{
|
||||
EnvironmentId: aws.String(d.Id()),
|
||||
TerminateResources: aws.Bool(true),
|
||||
|
@ -560,19 +595,30 @@ func resourceAwsElasticBeanstalkEnvironmentDelete(d *schema.ResourceData, meta i
|
|||
// Get the current time to filter describeBeanstalkEvents messages
|
||||
t := time.Now()
|
||||
log.Printf("[DEBUG] Elastic Beanstalk Environment terminate opts: %s", opts)
|
||||
_, err = conn.TerminateEnvironment(&opts)
|
||||
_, err := conn.TerminateEnvironment(&opts)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
waitForReadyTimeOut, err := time.ParseDuration(d.Get("wait_for_ready_timeout").(string))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pollInterval, err := time.ParseDuration(d.Get("poll_interval").(string))
|
||||
if err != nil {
|
||||
pollInterval = 0
|
||||
log.Printf("[WARN] Error parsing poll_interval, using default backoff")
|
||||
}
|
||||
|
||||
stateConf := &resource.StateChangeConf{
|
||||
Pending: []string{"Terminating"},
|
||||
Target: []string{"Terminated"},
|
||||
Refresh: environmentStateRefreshFunc(conn, d.Id()),
|
||||
Timeout: waitForReadyTimeOut,
|
||||
Delay: 10 * time.Second,
|
||||
MinTimeout: 3 * time.Second,
|
||||
Pending: []string{"Terminating"},
|
||||
Target: []string{"Terminated"},
|
||||
Refresh: environmentStateRefreshFunc(conn, d.Id()),
|
||||
Timeout: waitForReadyTimeOut,
|
||||
Delay: 10 * time.Second,
|
||||
PollInterval: pollInterval,
|
||||
MinTimeout: 3 * time.Second,
|
||||
}
|
||||
|
||||
_, err = stateConf.WaitForState()
|
||||
|
|
|
@ -26,6 +26,7 @@ type StateChangeConf struct {
|
|||
Target []string // Target state
|
||||
Timeout time.Duration // The amount of time to wait before timeout
|
||||
MinTimeout time.Duration // Smallest time to wait before refreshes
|
||||
PollInterval time.Duration // Override MinTimeout/backoff and only poll this often
|
||||
NotFoundChecks int // Number of times to allow not found
|
||||
|
||||
// This is to work around inconsistent APIs
|
||||
|
@ -72,14 +73,20 @@ func (conf *StateChangeConf) WaitForState() (interface{}, error) {
|
|||
time.Sleep(conf.Delay)
|
||||
|
||||
var err error
|
||||
var wait time.Duration
|
||||
for tries := 0; ; tries++ {
|
||||
// Wait between refreshes using an exponential backoff
|
||||
wait := time.Duration(math.Pow(2, float64(tries))) *
|
||||
100 * time.Millisecond
|
||||
if wait < conf.MinTimeout {
|
||||
wait = conf.MinTimeout
|
||||
} else if wait > 10*time.Second {
|
||||
wait = 10 * time.Second
|
||||
// If a poll interval has been specified, choose that interval
|
||||
if conf.PollInterval > 0 && conf.PollInterval < 180*time.Second {
|
||||
wait = conf.PollInterval
|
||||
} else {
|
||||
wait = time.Duration(math.Pow(2, float64(tries))) *
|
||||
100 * time.Millisecond
|
||||
if wait < conf.MinTimeout {
|
||||
wait = conf.MinTimeout
|
||||
} else if wait > 10*time.Second {
|
||||
wait = 10 * time.Second
|
||||
}
|
||||
}
|
||||
|
||||
log.Printf("[TRACE] Waiting %s before next try", wait)
|
||||
|
|
|
@ -51,10 +51,14 @@ The following arguments are supported:
|
|||
off of. Example stacks can be found in the [Amazon API documentation][1]
|
||||
* `template_name` – (Optional) The name of the Elastic Beanstalk Configuration
|
||||
template to use in deployment
|
||||
* `wait_for_ready_timeout` - (Default: "10m") The maximum
|
||||
* `wait_for_ready_timeout` - (Default: `10m`) The maximum
|
||||
[duration](https://golang.org/pkg/time/#ParseDuration) that Terraform should
|
||||
wait for an Elastic Beanstalk Environment to be in a ready state before timing
|
||||
out.
|
||||
* `poll_interval` – The time between polling the AWS API to
|
||||
check if changes have been applied. Use this to adjust the rate of API calls
|
||||
for any `create` or `update` action. Minimum `10s`, maximum `180s`. Omit this to
|
||||
use the default behavior, which is an exponential backoff
|
||||
* `tags` – (Optional) A set of tags to apply to the Environment. **Note:** at
|
||||
this time the Elastic Beanstalk API does not provide a programatic way of
|
||||
changing these tags after initial application
|
||||
|
|
Loading…
Reference in New Issue