builder/amazon/common: support user_data_file

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

View File

@ -4,6 +4,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"github.com/mitchellh/packer/common" "github.com/mitchellh/packer/common"
"os"
"time" "time"
) )
@ -14,6 +15,7 @@ type RunConfig struct {
IamInstanceProfile string `mapstructure:"iam_instance_profile"` IamInstanceProfile string `mapstructure:"iam_instance_profile"`
InstanceType string `mapstructure:"instance_type"` InstanceType string `mapstructure:"instance_type"`
UserData string `mapstructure:"user_data"` UserData string `mapstructure:"user_data"`
UserDataFile string `mapstructure:"user_data_file"`
RawSSHTimeout string `mapstructure:"ssh_timeout"` RawSSHTimeout string `mapstructure:"ssh_timeout"`
SSHUsername string `mapstructure:"ssh_username"` SSHUsername string `mapstructure:"ssh_username"`
SSHPort int `mapstructure:"ssh_port"` 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")) 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{ templates := map[string]*string{
"iam_instance_profile": &c.IamInstanceProfile, "iam_instance_profile": &c.IamInstanceProfile,
"instance_type": &c.InstanceType, "instance_type": &c.InstanceType,

View File

@ -1,6 +1,7 @@
package common package common
import ( import (
"io/ioutil"
"os" "os"
"testing" "testing"
) )
@ -87,3 +88,41 @@ func TestRunConfigPrepare_SSHUsername(t *testing.T) {
t.Fatalf("err: %s", err) 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/goamz/ec2"
"github.com/mitchellh/multistep" "github.com/mitchellh/multistep"
"github.com/mitchellh/packer/packer" "github.com/mitchellh/packer/packer"
"io/ioutil"
"log" "log"
) )
@ -12,6 +13,7 @@ type StepRunSourceInstance struct {
ExpectedRootDevice string ExpectedRootDevice string
InstanceType string InstanceType string
UserData string UserData string
UserDataFile string
SourceAMI string SourceAMI string
IamInstanceProfile string IamInstanceProfile string
SubnetId string SubnetId string
@ -25,11 +27,22 @@ func (s *StepRunSourceInstance) Run(state map[string]interface{}) multistep.Step
securityGroupId := state["securityGroupId"].(string) securityGroupId := state["securityGroupId"].(string)
ui := state["ui"].(packer.Ui) 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{ runOpts := &ec2.RunInstances{
KeyName: keyName, KeyName: keyName,
ImageId: s.SourceAMI, ImageId: s.SourceAMI,
InstanceType: s.InstanceType, InstanceType: s.InstanceType,
UserData: []byte(s.UserData), UserData: []byte(userData),
MinCount: 0, MinCount: 0,
MaxCount: 0, MaxCount: 0,
SecurityGroups: []ec2.SecurityGroup{ec2.SecurityGroup{Id: securityGroupId}}, SecurityGroups: []ec2.SecurityGroup{ec2.SecurityGroup{Id: securityGroupId}},