builder/amazon/*: use WaitForState for AMIs
This commit is contained in:
parent
a6139af9ea
commit
27608a7b0f
|
@ -1,7 +1,12 @@
|
|||
## 0.3.8 (unreleased)
|
||||
|
||||
IMPROVEMENTS:
|
||||
|
||||
* builder/amazon/*: Interrupts work while waiting for AMI to be ready.
|
||||
|
||||
BUG FIXES:
|
||||
|
||||
* builder/amazon/*: While waiting for AMI, will detect "failed" state.
|
||||
* provisioner/puppet-masterless: Fix failure case when both facter vars
|
||||
are used and prevent_sudo. [GH-415]
|
||||
|
||||
|
|
|
@ -52,8 +52,16 @@ func (s *StepRegisterAMI) Run(state multistep.StateBag) multistep.StepAction {
|
|||
state.Put("amis", amis)
|
||||
|
||||
// Wait for the image to become ready
|
||||
stateChange := awscommon.StateChangeConf{
|
||||
Conn: ec2conn,
|
||||
Pending: []string{"pending"},
|
||||
Target: "available",
|
||||
Refresh: awscommon.AMIStateRefreshFunc(ec2conn, registerResp.ImageId),
|
||||
StepState: state,
|
||||
}
|
||||
|
||||
ui.Say("Waiting for AMI to become ready...")
|
||||
if err := awscommon.WaitForAMI(ec2conn, registerResp.ImageId); err != nil {
|
||||
if _, err := awscommon.WaitForState(&stateChange); err != nil {
|
||||
err := fmt.Errorf("Error waiting for AMI: %s", err)
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
"github.com/mitchellh/goamz/ec2"
|
||||
"log"
|
||||
"time"
|
||||
)
|
||||
|
||||
// WaitForAMI waits for the given AMI ID to become ready.
|
||||
func WaitForAMI(c *ec2.EC2, imageId string) error {
|
||||
for {
|
||||
imageResp, err := c.Images([]string{imageId}, ec2.NewFilter())
|
||||
if err != nil {
|
||||
if ec2err, ok := err.(*ec2.Error); ok && ec2err.Code == "InvalidAMIID.NotFound" {
|
||||
log.Println("AMI not found, probably state issues on AWS side. Trying again.")
|
||||
continue
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
if imageResp.Images[0].State == "available" {
|
||||
return nil
|
||||
}
|
||||
|
||||
log.Printf("Image in state %s, sleeping 2s before checking again",
|
||||
imageResp.Images[0].State)
|
||||
time.Sleep(2 * time.Second)
|
||||
}
|
||||
}
|
|
@ -30,6 +30,32 @@ type StateChangeConf struct {
|
|||
Target string
|
||||
}
|
||||
|
||||
// AMIStateRefreshFunc returns a StateRefreshFunc that is used to watch
|
||||
// an AMI for state changes.
|
||||
func AMIStateRefreshFunc(conn *ec2.EC2, imageId string) StateRefreshFunc {
|
||||
return func() (interface{}, string, error) {
|
||||
resp, err := conn.Images([]string{imageId}, ec2.NewFilter())
|
||||
if err != nil {
|
||||
if ec2err, ok := err.(*ec2.Error); ok && ec2err.Code == "InvalidAMIID.NotFound" {
|
||||
// Set this to nil as if we didn't find anything.
|
||||
resp = nil
|
||||
} else {
|
||||
log.Printf("Error on AMIStateRefresh: %s", err)
|
||||
return nil, "", err
|
||||
}
|
||||
}
|
||||
|
||||
if resp == nil || len(resp.Images) == 0 {
|
||||
// Sometimes AWS has consistency issues and doesn't see the
|
||||
// AMI. Return an empty state.
|
||||
return nil, "", nil
|
||||
}
|
||||
|
||||
i := resp.Images[0]
|
||||
return i, i.State, nil
|
||||
}
|
||||
}
|
||||
|
||||
// InstanceStateRefreshFunc returns a StateRefreshFunc that is used to watch
|
||||
// an EC2 instance.
|
||||
func InstanceStateRefreshFunc(conn *ec2.EC2, i *ec2.Instance) StateRefreshFunc {
|
||||
|
|
|
@ -40,8 +40,17 @@ func (s *StepAMIRegionCopy) Run(state multistep.StateBag) multistep.StepAction {
|
|||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
ui.Say(fmt.Sprintf("Waiting for AMI (%s) in region (%s) to become ready...", resp.ImageId, region))
|
||||
if err := WaitForAMI(regionconn, resp.ImageId); err != nil {
|
||||
stateChange := StateChangeConf{
|
||||
Conn: regionconn,
|
||||
Pending: []string{"pending"},
|
||||
Target: "available",
|
||||
Refresh: AMIStateRefreshFunc(regionconn, resp.ImageId),
|
||||
StepState: state,
|
||||
}
|
||||
|
||||
ui.Say(fmt.Sprintf("Waiting for AMI (%s) in region (%s) to become ready...",
|
||||
resp.ImageId, region))
|
||||
if _, err := WaitForState(&stateChange); err != nil {
|
||||
err := fmt.Errorf("Error waiting for AMI (%s) in region (%s): %s", resp.ImageId, region, err)
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
|
|
|
@ -39,8 +39,16 @@ func (s *stepCreateAMI) Run(state multistep.StateBag) multistep.StepAction {
|
|||
state.Put("amis", amis)
|
||||
|
||||
// Wait for the image to become ready
|
||||
stateChange := awscommon.StateChangeConf{
|
||||
Conn: ec2conn,
|
||||
Pending: []string{"pending"},
|
||||
Target: "available",
|
||||
Refresh: awscommon.AMIStateRefreshFunc(ec2conn, createResp.ImageId),
|
||||
StepState: state,
|
||||
}
|
||||
|
||||
ui.Say("Waiting for AMI to become ready...")
|
||||
if err := awscommon.WaitForAMI(ec2conn, createResp.ImageId); err != nil {
|
||||
if _, err := awscommon.WaitForState(&stateChange); err != nil {
|
||||
err := fmt.Errorf("Error waiting for AMI: %s", err)
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
|
|
|
@ -37,8 +37,16 @@ func (s *StepRegisterAMI) Run(state multistep.StateBag) multistep.StepAction {
|
|||
state.Put("amis", amis)
|
||||
|
||||
// Wait for the image to become ready
|
||||
stateChange := awscommon.StateChangeConf{
|
||||
Conn: ec2conn,
|
||||
Pending: []string{"pending"},
|
||||
Target: "available",
|
||||
Refresh: awscommon.AMIStateRefreshFunc(ec2conn, registerResp.ImageId),
|
||||
StepState: state,
|
||||
}
|
||||
|
||||
ui.Say("Waiting for AMI to become ready...")
|
||||
if err := awscommon.WaitForAMI(ec2conn, registerResp.ImageId); err != nil {
|
||||
if _, err := awscommon.WaitForState(&stateChange); err != nil {
|
||||
err := fmt.Errorf("Error waiting for AMI: %s", err)
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
|
|
Loading…
Reference in New Issue