builder/amazon/instance: register the AMI
This commit is contained in:
parent
03a2cc8b22
commit
0552bc7306
|
@ -14,6 +14,7 @@ import (
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
"text/template"
|
||||||
)
|
)
|
||||||
|
|
||||||
// The unique ID for this builder
|
// The unique ID for this builder
|
||||||
|
@ -27,6 +28,7 @@ type Config struct {
|
||||||
awscommon.RunConfig `mapstructure:",squash"`
|
awscommon.RunConfig `mapstructure:",squash"`
|
||||||
|
|
||||||
AccountId string `mapstructure:"account_id"`
|
AccountId string `mapstructure:"account_id"`
|
||||||
|
AMIName string `mapstructure:"ami_name"`
|
||||||
BundleDestination string `mapstructure:"bundle_destination"`
|
BundleDestination string `mapstructure:"bundle_destination"`
|
||||||
BundlePrefix string `mapstructure:"bundle_prefix"`
|
BundlePrefix string `mapstructure:"bundle_prefix"`
|
||||||
BundleUploadCommand string `mapstructure:"bundle_upload_command"`
|
BundleUploadCommand string `mapstructure:"bundle_upload_command"`
|
||||||
|
@ -90,6 +92,17 @@ func (b *Builder) Prepare(raws ...interface{}) error {
|
||||||
b.config.AccountId = strings.Replace(b.config.AccountId, "-", "", -1)
|
b.config.AccountId = strings.Replace(b.config.AccountId, "-", "", -1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if b.config.AMIName == "" {
|
||||||
|
errs = packer.MultiErrorAppend(
|
||||||
|
errs, errors.New("ami_name must be specified"))
|
||||||
|
} else {
|
||||||
|
_, err = template.New("ami").Parse(b.config.AMIName)
|
||||||
|
if err != nil {
|
||||||
|
errs = packer.MultiErrorAppend(
|
||||||
|
errs, fmt.Errorf("Failed parsing ami_name: %s", err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if b.config.S3Bucket == "" {
|
if b.config.S3Bucket == "" {
|
||||||
errs = packer.MultiErrorAppend(errs, errors.New("s3_bucket is required"))
|
errs = packer.MultiErrorAppend(errs, errors.New("s3_bucket is required"))
|
||||||
}
|
}
|
||||||
|
@ -163,6 +176,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
|
||||||
&StepUploadX509Cert{},
|
&StepUploadX509Cert{},
|
||||||
&StepBundleVolume{},
|
&StepBundleVolume{},
|
||||||
&StepUploadBundle{},
|
&StepUploadBundle{},
|
||||||
|
&StepRegisterAMI{},
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run!
|
// Run!
|
||||||
|
@ -187,7 +201,14 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, nil
|
// Build the artifact and return it
|
||||||
|
artifact := &awscommon.Artifact{
|
||||||
|
Amis: state["amis"].(map[string]string),
|
||||||
|
BuilderIdValue: BuilderId,
|
||||||
|
Conn: ec2conn,
|
||||||
|
}
|
||||||
|
|
||||||
|
return artifact, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Builder) Cancel() {
|
func (b *Builder) Cancel() {
|
||||||
|
|
|
@ -15,6 +15,7 @@ func testConfig() map[string]interface{} {
|
||||||
|
|
||||||
return map[string]interface{}{
|
return map[string]interface{}{
|
||||||
"account_id": "foo",
|
"account_id": "foo",
|
||||||
|
"ami_name": "foo",
|
||||||
"instance_type": "m1.small",
|
"instance_type": "m1.small",
|
||||||
"region": "us-east-1",
|
"region": "us-east-1",
|
||||||
"s3_bucket": "foo",
|
"s3_bucket": "foo",
|
||||||
|
@ -61,6 +62,34 @@ func TestBuilderPrepare_AccountId(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestBuilderPrepare_AMIName(t *testing.T) {
|
||||||
|
var b Builder
|
||||||
|
config := testConfig()
|
||||||
|
|
||||||
|
// Test good
|
||||||
|
config["ami_name"] = "foo"
|
||||||
|
err := b.Prepare(config)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("should not have error: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test bad
|
||||||
|
config["ami_name"] = "foo {{"
|
||||||
|
b = Builder{}
|
||||||
|
err = b.Prepare(config)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("should have error")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test bad
|
||||||
|
delete(config, "ami_name")
|
||||||
|
b = Builder{}
|
||||||
|
err = b.Prepare(config)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("should have error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestBuilderPrepare_BundleDestination(t *testing.T) {
|
func TestBuilderPrepare_BundleDestination(t *testing.T) {
|
||||||
b := &Builder{}
|
b := &Builder{}
|
||||||
config := testConfig()
|
config := testConfig()
|
||||||
|
|
|
@ -93,8 +93,10 @@ func (s *StepBundleVolume) Run(state map[string]interface{}) multistep.StepActio
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store the manifest path
|
// Store the manifest path
|
||||||
|
manifestName := bundlePrefix.String() + ".manifest.xml"
|
||||||
|
state["manifest_name"] = manifestName
|
||||||
state["manifest_path"] = fmt.Sprintf(
|
state["manifest_path"] = fmt.Sprintf(
|
||||||
"%s/%s.manifest.xml", config.BundleDestination, bundlePrefix.String())
|
"%s/%s", config.BundleDestination, manifestName)
|
||||||
|
|
||||||
return multistep.ActionContinue
|
return multistep.ActionContinue
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
package instance
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"github.com/mitchellh/multistep"
|
||||||
|
"github.com/mitchellh/packer/packer"
|
||||||
|
"strconv"
|
||||||
|
"text/template"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type amiNameData struct {
|
||||||
|
CreateTime string
|
||||||
|
}
|
||||||
|
|
||||||
|
type StepRegisterAMI struct{}
|
||||||
|
|
||||||
|
func (s *StepRegisterAMI) Run(state map[string]interface{}) multistep.StepAction {
|
||||||
|
comm := state["communicator"].(packer.Communicator)
|
||||||
|
config := state["config"].(*Config)
|
||||||
|
manifestPath := state["remote_manifest_path"].(string)
|
||||||
|
ui := state["ui"].(packer.Ui)
|
||||||
|
|
||||||
|
// Parse the name of the AMI
|
||||||
|
amiNameBuf := new(bytes.Buffer)
|
||||||
|
tData := amiNameData{
|
||||||
|
strconv.FormatInt(time.Now().UTC().Unix(), 10),
|
||||||
|
}
|
||||||
|
|
||||||
|
t := template.Must(template.New("ami").Parse(config.AMIName))
|
||||||
|
t.Execute(amiNameBuf, tData)
|
||||||
|
amiName := amiNameBuf.String()
|
||||||
|
|
||||||
|
ui.Say("Registering the AMI...")
|
||||||
|
cmd := &packer.RemoteCmd{
|
||||||
|
Command: fmt.Sprintf(
|
||||||
|
"ec2-register %s -n '%s' -O '%s' -W '%s'",
|
||||||
|
manifestPath,
|
||||||
|
amiName,
|
||||||
|
config.AccessKey,
|
||||||
|
config.SecretKey),
|
||||||
|
}
|
||||||
|
if err := cmd.StartWithUi(comm, ui); err != nil {
|
||||||
|
state["error"] = fmt.Errorf("Error registering AMI: %s", err)
|
||||||
|
ui.Error(state["error"].(error).Error())
|
||||||
|
return multistep.ActionHalt
|
||||||
|
}
|
||||||
|
|
||||||
|
if cmd.ExitStatus != 0 {
|
||||||
|
state["error"] = fmt.Errorf(
|
||||||
|
"AMI registration failed. Please see the output above for more\n" +
|
||||||
|
"details on what went wrong.")
|
||||||
|
ui.Error(state["error"].(error).Error())
|
||||||
|
return multistep.ActionHalt
|
||||||
|
}
|
||||||
|
|
||||||
|
return multistep.ActionContinue
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *StepRegisterAMI) Cleanup(map[string]interface{}) {}
|
|
@ -21,6 +21,7 @@ type StepUploadBundle struct{}
|
||||||
func (s *StepUploadBundle) Run(state map[string]interface{}) multistep.StepAction {
|
func (s *StepUploadBundle) Run(state map[string]interface{}) multistep.StepAction {
|
||||||
comm := state["communicator"].(packer.Communicator)
|
comm := state["communicator"].(packer.Communicator)
|
||||||
config := state["config"].(*Config)
|
config := state["config"].(*Config)
|
||||||
|
manifestName := state["manifest_name"].(string)
|
||||||
manifestPath := state["manifest_path"].(string)
|
manifestPath := state["manifest_path"].(string)
|
||||||
ui := state["ui"].(packer.Ui)
|
ui := state["ui"].(packer.Ui)
|
||||||
|
|
||||||
|
@ -51,6 +52,9 @@ func (s *StepUploadBundle) Run(state map[string]interface{}) multistep.StepActio
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
}
|
}
|
||||||
|
|
||||||
|
state["remote_manifest_path"] = fmt.Sprintf(
|
||||||
|
"%s/%s", config.S3Bucket, manifestName)
|
||||||
|
|
||||||
return multistep.ActionContinue
|
return multistep.ActionContinue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue