Files
Packer-Cn/builder/amazon/common/step_stop_ebs_instance.go
T

100 lines
2.6 KiB
Go
Raw Normal View History

2016-10-31 16:44:41 -05:00
package common
import (
2018-01-22 15:32:33 -08:00
"context"
2013-06-19 20:54:02 -07:00
"fmt"
"github.com/aws/aws-sdk-go/aws/awserr"
2015-06-03 17:13:52 -04:00
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/packer/common"
2018-01-19 16:18:44 -08:00
"github.com/hashicorp/packer/helper/multistep"
2017-04-04 13:39:01 -07:00
"github.com/hashicorp/packer/packer"
)
2016-10-31 16:44:41 -05:00
type StepStopEBSBackedInstance struct {
2017-10-23 12:16:12 -07:00
Skip bool
2016-03-14 13:49:42 -04:00
DisableStopInstance bool
}
2018-04-23 12:57:04 -07:00
func (s *StepStopEBSBackedInstance) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
2013-08-31 13:00:43 -07:00
ec2conn := state.Get("ec2").(*ec2.EC2)
instance := state.Get("instance").(*ec2.Instance)
ui := state.Get("ui").(packer.Ui)
2014-05-08 13:58:05 +08:00
// Skip when it is a spot instance
2017-10-23 12:16:12 -07:00
if s.Skip {
2014-05-08 13:58:05 +08:00
return multistep.ActionContinue
}
2016-03-14 13:49:42 -04:00
var err error
if !s.DisableStopInstance {
2016-03-14 13:49:42 -04:00
// Stop the instance so we can create an AMI from it
ui.Say("Stopping the source instance...")
// Amazon EC2 API follows an eventual consistency model.
// This means that if you run a command to modify or describe a resource
// that you just created, its ID might not have propagated throughout
// the system, and you will get an error responding that the resource
// does not exist.
// Work around this by retrying a few times, up to about 5 minutes.
err := common.Retry(10, 60, 6, func(i uint) (bool, error) {
ui.Message(fmt.Sprintf("Stopping instance, attempt %d", i+1))
_, err = ec2conn.StopInstances(&ec2.StopInstancesInput{
InstanceIds: []*string{instance.InstanceId},
})
if err == nil {
// success
return true, nil
}
if awsErr, ok := err.(awserr.Error); ok {
if awsErr.Code() == "InvalidInstanceID.NotFound" {
ui.Message(fmt.Sprintf(
"Error stopping instance; will retry ..."+
"Error: %s", err))
// retry
return false, nil
}
}
// errored, but not in expected way. Don't want to retry
return true, err
2016-03-14 13:49:42 -04:00
})
2016-03-14 13:49:42 -04:00
if err != nil {
err := fmt.Errorf("Error stopping instance: %s", err)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
} else {
ui.Say("Automatic instance stop disabled. Please stop instance manually.")
2016-03-14 13:49:42 -04:00
}
// Wait for the instance to actually stop
ui.Say("Waiting for the instance to stop...")
err = ec2conn.WaitUntilInstanceStoppedWithContext(ctx,
&ec2.DescribeInstancesInput{
InstanceIds: []*string{instance.InstanceId},
},
getWaiterOptions()...)
if err != nil {
2013-06-19 20:54:02 -07:00
err := fmt.Errorf("Error waiting for instance to stop: %s", err)
2013-08-31 13:00:43 -07:00
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
return multistep.ActionContinue
}
2016-10-31 16:44:41 -05:00
func (s *StepStopEBSBackedInstance) Cleanup(multistep.StateBag) {
// No cleanup...
}