builder/amazon/common: support user_data_file

This commit is contained in:
Mitchell Hashimoto 2013-08-12 11:52:43 -07:00
parent 97b4c7d22b
commit c1f8e5c3b3
3 changed files with 63 additions and 1 deletions

View File

@ -4,6 +4,7 @@ import (
"errors"
"fmt"
"github.com/mitchellh/packer/common"
"os"
"time"
)
@ -14,6 +15,7 @@ type RunConfig struct {
IamInstanceProfile string `mapstructure:"iam_instance_profile"`
InstanceType string `mapstructure:"instance_type"`
UserData string `mapstructure:"user_data"`
UserDataFile string `mapstructure:"user_data_file"`
RawSSHTimeout string `mapstructure:"ssh_timeout"`
SSHUsername string `mapstructure:"ssh_username"`
SSHPort int `mapstructure:"ssh_port"`
@ -58,6 +60,14 @@ func (c *RunConfig) Prepare(t *common.Template) []error {
errs = append(errs, errors.New("An ssh_username must be specified"))
}
if c.UserData != "" && c.UserDataFile != "" {
errs = append(errs, fmt.Errorf("Only one of user_data or user_data_file can be specified."))
} else if c.UserDataFile != "" {
if _, err := os.Stat(c.UserDataFile); err != nil {
errs = append(errs, fmt.Errorf("user_data_file not found: %s", c.UserDataFile))
}
}
templates := map[string]*string{
"iam_instance_profile": &c.IamInstanceProfile,
"instance_type": &c.InstanceType,

View File

@ -1,6 +1,7 @@
package common
import (
"io/ioutil"
"os"
"testing"
)
@ -87,3 +88,41 @@ func TestRunConfigPrepare_SSHUsername(t *testing.T) {
t.Fatalf("err: %s", err)
}
}
func TestRunConfigPrepare_UserData(t *testing.T) {
c := testConfig()
tf, err := ioutil.TempFile("", "packer")
if err != nil {
t.Fatalf("err: %s", err)
}
defer tf.Close()
c.UserData = "foo"
c.UserDataFile = tf.Name()
if err := c.Prepare(nil); len(err) != 1 {
t.Fatalf("err: %s", err)
}
}
func TestRunConfigPrepare_UserDataFile(t *testing.T) {
c := testConfig()
if err := c.Prepare(nil); len(err) != 0 {
t.Fatalf("err: %s", err)
}
c.UserDataFile = "idontexistidontthink"
if err := c.Prepare(nil); len(err) != 1 {
t.Fatalf("err: %s", err)
}
tf, err := ioutil.TempFile("", "packer")
if err != nil {
t.Fatalf("err: %s", err)
}
defer tf.Close()
c.UserDataFile = tf.Name()
if err := c.Prepare(nil); len(err) != 0 {
t.Fatalf("err: %s", err)
}
}

View File

@ -5,6 +5,7 @@ import (
"github.com/mitchellh/goamz/ec2"
"github.com/mitchellh/multistep"
"github.com/mitchellh/packer/packer"
"io/ioutil"
"log"
)
@ -12,6 +13,7 @@ type StepRunSourceInstance struct {
ExpectedRootDevice string
InstanceType string
UserData string
UserDataFile string
SourceAMI string
IamInstanceProfile string
SubnetId string
@ -25,11 +27,22 @@ func (s *StepRunSourceInstance) Run(state map[string]interface{}) multistep.Step
securityGroupId := state["securityGroupId"].(string)
ui := state["ui"].(packer.Ui)
userData := s.UserData
if s.UserDataFile != "" {
contents, err := ioutil.ReadFile(s.UserDataFile)
if err != nil {
state["error"] = fmt.Errorf("Problem reading user data file: %s", err)
return multistep.ActionHalt
}
userData = string(contents)
}
runOpts := &ec2.RunInstances{
KeyName: keyName,
ImageId: s.SourceAMI,
InstanceType: s.InstanceType,
UserData: []byte(s.UserData),
UserData: []byte(userData),
MinCount: 0,
MaxCount: 0,
SecurityGroups: []ec2.SecurityGroup{ec2.SecurityGroup{Id: securityGroupId}},