provider/aws: Return errors from Elastic Beanstalk (#12425)
In the event that an unexpected state is returned from `environmentStateRefreshFunc` errors in the Elastic Beanstalk console will not be returned to the user.
This commit is contained in:
parent
8e53df6351
commit
01f995fed5
|
@ -8,6 +8,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/hashicorp/go-multierror"
|
||||||
"github.com/hashicorp/terraform/helper/hashcode"
|
"github.com/hashicorp/terraform/helper/hashcode"
|
||||||
"github.com/hashicorp/terraform/helper/resource"
|
"github.com/hashicorp/terraform/helper/resource"
|
||||||
"github.com/hashicorp/terraform/helper/schema"
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
|
@ -255,7 +256,7 @@ func resourceAwsElasticBeanstalkEnvironmentCreate(d *schema.ResourceData, meta i
|
||||||
createOpts.VersionLabel = aws.String(version)
|
createOpts.VersionLabel = aws.String(version)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the current time to filter describeBeanstalkEvents messages
|
// Get the current time to filter getBeanstalkEnvironmentErrors messages
|
||||||
t := time.Now()
|
t := time.Now()
|
||||||
log.Printf("[DEBUG] Elastic Beanstalk Environment create opts: %s", createOpts)
|
log.Printf("[DEBUG] Elastic Beanstalk Environment create opts: %s", createOpts)
|
||||||
resp, err := conn.CreateEnvironment(&createOpts)
|
resp, err := conn.CreateEnvironment(&createOpts)
|
||||||
|
@ -280,7 +281,7 @@ func resourceAwsElasticBeanstalkEnvironmentCreate(d *schema.ResourceData, meta i
|
||||||
stateConf := &resource.StateChangeConf{
|
stateConf := &resource.StateChangeConf{
|
||||||
Pending: []string{"Launching", "Updating"},
|
Pending: []string{"Launching", "Updating"},
|
||||||
Target: []string{"Ready"},
|
Target: []string{"Ready"},
|
||||||
Refresh: environmentStateRefreshFunc(conn, d.Id()),
|
Refresh: environmentStateRefreshFunc(conn, d.Id(), t),
|
||||||
Timeout: waitForReadyTimeOut,
|
Timeout: waitForReadyTimeOut,
|
||||||
Delay: 10 * time.Second,
|
Delay: 10 * time.Second,
|
||||||
PollInterval: pollInterval,
|
PollInterval: pollInterval,
|
||||||
|
@ -294,10 +295,13 @@ func resourceAwsElasticBeanstalkEnvironmentCreate(d *schema.ResourceData, meta i
|
||||||
d.Id(), err)
|
d.Id(), err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = describeBeanstalkEvents(conn, d.Id(), t)
|
envErrors, err := getBeanstalkEnvironmentErrors(conn, d.Id(), t)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if envErrors != nil {
|
||||||
|
return envErrors
|
||||||
|
}
|
||||||
|
|
||||||
return resourceAwsElasticBeanstalkEnvironmentRead(d, meta)
|
return resourceAwsElasticBeanstalkEnvironmentRead(d, meta)
|
||||||
}
|
}
|
||||||
|
@ -403,7 +407,7 @@ func resourceAwsElasticBeanstalkEnvironmentUpdate(d *schema.ResourceData, meta i
|
||||||
}
|
}
|
||||||
|
|
||||||
if hasChange {
|
if hasChange {
|
||||||
// Get the current time to filter describeBeanstalkEvents messages
|
// Get the current time to filter getBeanstalkEnvironmentErrors messages
|
||||||
t := time.Now()
|
t := time.Now()
|
||||||
log.Printf("[DEBUG] Elastic Beanstalk Environment update opts: %s", updateOpts)
|
log.Printf("[DEBUG] Elastic Beanstalk Environment update opts: %s", updateOpts)
|
||||||
_, err := conn.UpdateEnvironment(&updateOpts)
|
_, err := conn.UpdateEnvironment(&updateOpts)
|
||||||
|
@ -424,7 +428,7 @@ func resourceAwsElasticBeanstalkEnvironmentUpdate(d *schema.ResourceData, meta i
|
||||||
stateConf := &resource.StateChangeConf{
|
stateConf := &resource.StateChangeConf{
|
||||||
Pending: []string{"Launching", "Updating"},
|
Pending: []string{"Launching", "Updating"},
|
||||||
Target: []string{"Ready"},
|
Target: []string{"Ready"},
|
||||||
Refresh: environmentStateRefreshFunc(conn, d.Id()),
|
Refresh: environmentStateRefreshFunc(conn, d.Id(), t),
|
||||||
Timeout: waitForReadyTimeOut,
|
Timeout: waitForReadyTimeOut,
|
||||||
Delay: 10 * time.Second,
|
Delay: 10 * time.Second,
|
||||||
PollInterval: pollInterval,
|
PollInterval: pollInterval,
|
||||||
|
@ -438,10 +442,13 @@ func resourceAwsElasticBeanstalkEnvironmentUpdate(d *schema.ResourceData, meta i
|
||||||
d.Id(), err)
|
d.Id(), err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = describeBeanstalkEvents(conn, d.Id(), t)
|
envErrors, err := getBeanstalkEnvironmentErrors(conn, d.Id(), t)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if envErrors != nil {
|
||||||
|
return envErrors
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return resourceAwsElasticBeanstalkEnvironmentRead(d, meta)
|
return resourceAwsElasticBeanstalkEnvironmentRead(d, meta)
|
||||||
|
@ -663,7 +670,7 @@ func resourceAwsElasticBeanstalkEnvironmentDelete(d *schema.ResourceData, meta i
|
||||||
TerminateResources: aws.Bool(true),
|
TerminateResources: aws.Bool(true),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the current time to filter describeBeanstalkEvents messages
|
// Get the current time to filter getBeanstalkEnvironmentErrors messages
|
||||||
t := time.Now()
|
t := time.Now()
|
||||||
log.Printf("[DEBUG] Elastic Beanstalk Environment terminate opts: %s", opts)
|
log.Printf("[DEBUG] Elastic Beanstalk Environment terminate opts: %s", opts)
|
||||||
_, err := conn.TerminateEnvironment(&opts)
|
_, err := conn.TerminateEnvironment(&opts)
|
||||||
|
@ -685,7 +692,7 @@ func resourceAwsElasticBeanstalkEnvironmentDelete(d *schema.ResourceData, meta i
|
||||||
stateConf := &resource.StateChangeConf{
|
stateConf := &resource.StateChangeConf{
|
||||||
Pending: []string{"Terminating"},
|
Pending: []string{"Terminating"},
|
||||||
Target: []string{"Terminated"},
|
Target: []string{"Terminated"},
|
||||||
Refresh: environmentStateRefreshFunc(conn, d.Id()),
|
Refresh: environmentStateRefreshFunc(conn, d.Id(), t),
|
||||||
Timeout: waitForReadyTimeOut,
|
Timeout: waitForReadyTimeOut,
|
||||||
Delay: 10 * time.Second,
|
Delay: 10 * time.Second,
|
||||||
PollInterval: pollInterval,
|
PollInterval: pollInterval,
|
||||||
|
@ -699,17 +706,20 @@ func resourceAwsElasticBeanstalkEnvironmentDelete(d *schema.ResourceData, meta i
|
||||||
d.Id(), err)
|
d.Id(), err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = describeBeanstalkEvents(conn, d.Id(), t)
|
envErrors, err := getBeanstalkEnvironmentErrors(conn, d.Id(), t)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if envErrors != nil {
|
||||||
|
return envErrors
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// environmentStateRefreshFunc returns a resource.StateRefreshFunc that is used to watch
|
// environmentStateRefreshFunc returns a resource.StateRefreshFunc that is used to watch
|
||||||
// the creation of the Beanstalk Environment
|
// the creation of the Beanstalk Environment
|
||||||
func environmentStateRefreshFunc(conn *elasticbeanstalk.ElasticBeanstalk, environmentId string) resource.StateRefreshFunc {
|
func environmentStateRefreshFunc(conn *elasticbeanstalk.ElasticBeanstalk, environmentId string, t time.Time) resource.StateRefreshFunc {
|
||||||
return func() (interface{}, string, error) {
|
return func() (interface{}, string, error) {
|
||||||
resp, err := conn.DescribeEnvironments(&elasticbeanstalk.DescribeEnvironmentsInput{
|
resp, err := conn.DescribeEnvironments(&elasticbeanstalk.DescribeEnvironmentsInput{
|
||||||
EnvironmentIds: []*string{aws.String(environmentId)},
|
EnvironmentIds: []*string{aws.String(environmentId)},
|
||||||
|
@ -736,6 +746,14 @@ func environmentStateRefreshFunc(conn *elasticbeanstalk.ElasticBeanstalk, enviro
|
||||||
return -1, "failed", fmt.Errorf("[Err] Error finding Elastic Beanstalk Environment, environment not found")
|
return -1, "failed", fmt.Errorf("[Err] Error finding Elastic Beanstalk Environment, environment not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
envErrors, err := getBeanstalkEnvironmentErrors(conn, environmentId, t)
|
||||||
|
if err != nil {
|
||||||
|
return -1, "failed", err
|
||||||
|
}
|
||||||
|
if envErrors != nil {
|
||||||
|
return -1, "failed", envErrors
|
||||||
|
}
|
||||||
|
|
||||||
return env, *env.Status, nil
|
return env, *env.Status, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -848,25 +866,48 @@ func dropGeneratedSecurityGroup(settingValue string, meta interface{}) string {
|
||||||
return strings.Join(legitGroups, ",")
|
return strings.Join(legitGroups, ",")
|
||||||
}
|
}
|
||||||
|
|
||||||
func describeBeanstalkEvents(conn *elasticbeanstalk.ElasticBeanstalk, environmentId string, t time.Time) error {
|
type beanstalkEnvironmentError struct {
|
||||||
beanstalkErrors, err := conn.DescribeEvents(&elasticbeanstalk.DescribeEventsInput{
|
eventDate *time.Time
|
||||||
|
environmentID string
|
||||||
|
message *string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e beanstalkEnvironmentError) Error() string {
|
||||||
|
return e.eventDate.String() + " (" + e.environmentID + ") : " + *e.message
|
||||||
|
}
|
||||||
|
|
||||||
|
type beanstalkEnvironmentErrors []*beanstalkEnvironmentError
|
||||||
|
|
||||||
|
func (e beanstalkEnvironmentErrors) Len() int { return len(e) }
|
||||||
|
func (e beanstalkEnvironmentErrors) Swap(i, j int) { e[i], e[j] = e[j], e[i] }
|
||||||
|
func (e beanstalkEnvironmentErrors) Less(i, j int) bool { return e[i].eventDate.Before(*e[j].eventDate) }
|
||||||
|
|
||||||
|
func getBeanstalkEnvironmentErrors(conn *elasticbeanstalk.ElasticBeanstalk, environmentId string, t time.Time) (*multierror.Error, error) {
|
||||||
|
environmentErrors, err := conn.DescribeEvents(&elasticbeanstalk.DescribeEventsInput{
|
||||||
EnvironmentId: aws.String(environmentId),
|
EnvironmentId: aws.String(environmentId),
|
||||||
Severity: aws.String("ERROR"),
|
Severity: aws.String("ERROR"),
|
||||||
StartTime: aws.Time(t),
|
StartTime: aws.Time(t),
|
||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("[Err] Unable to get Elastic Beanstalk Evironment events: %s", err)
|
return nil, fmt.Errorf("[Err] Unable to get Elastic Beanstalk Evironment events: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
events := ""
|
var events beanstalkEnvironmentErrors
|
||||||
for _, event := range beanstalkErrors.Events {
|
for _, event := range environmentErrors.Events {
|
||||||
events = events + "\n" + event.EventDate.String() + ": " + *event.Message
|
e := &beanstalkEnvironmentError{
|
||||||
|
eventDate: event.EventDate,
|
||||||
|
environmentID: environmentId,
|
||||||
|
message: event.Message,
|
||||||
|
}
|
||||||
|
events = append(events, e)
|
||||||
|
}
|
||||||
|
sort.Sort(beanstalkEnvironmentErrors(events))
|
||||||
|
|
||||||
|
var result *multierror.Error
|
||||||
|
for _, event := range events {
|
||||||
|
result = multierror.Append(result, event)
|
||||||
}
|
}
|
||||||
|
|
||||||
if events != "" {
|
return result, nil
|
||||||
return fmt.Errorf("%s", events)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue