github.com/phobos182/packer@v0.2.3-0.20130819023704-c84d2aeffc68/builder/amazon/common/step_run_source_instance.go (about) 1 package common 2 3 import ( 4 "fmt" 5 "github.com/mitchellh/goamz/ec2" 6 "github.com/mitchellh/multistep" 7 "github.com/mitchellh/packer/packer" 8 "io/ioutil" 9 "log" 10 ) 11 12 type StepRunSourceInstance struct { 13 ExpectedRootDevice string 14 InstanceType string 15 UserData string 16 UserDataFile string 17 SourceAMI string 18 IamInstanceProfile string 19 SubnetId string 20 BlockDevices BlockDevices 21 22 instance *ec2.Instance 23 } 24 25 func (s *StepRunSourceInstance) Run(state map[string]interface{}) multistep.StepAction { 26 ec2conn := state["ec2"].(*ec2.EC2) 27 keyName := state["keyPair"].(string) 28 securityGroupId := state["securityGroupId"].(string) 29 ui := state["ui"].(packer.Ui) 30 31 userData := s.UserData 32 if s.UserDataFile != "" { 33 contents, err := ioutil.ReadFile(s.UserDataFile) 34 if err != nil { 35 state["error"] = fmt.Errorf("Problem reading user data file: %s", err) 36 return multistep.ActionHalt 37 } 38 39 userData = string(contents) 40 } 41 42 runOpts := &ec2.RunInstances{ 43 KeyName: keyName, 44 ImageId: s.SourceAMI, 45 InstanceType: s.InstanceType, 46 UserData: []byte(userData), 47 MinCount: 0, 48 MaxCount: 0, 49 SecurityGroups: []ec2.SecurityGroup{ec2.SecurityGroup{Id: securityGroupId}}, 50 IamInstanceProfile: s.IamInstanceProfile, 51 SubnetId: s.SubnetId, 52 BlockDevices: s.BlockDevices.BuildLaunchDevices(), 53 } 54 55 ui.Say("Launching a source AWS instance...") 56 imageResp, err := ec2conn.Images([]string{s.SourceAMI}, ec2.NewFilter()) 57 if err != nil { 58 state["error"] = fmt.Errorf("There was a problem with the source AMI: %s", err) 59 return multistep.ActionHalt 60 } 61 62 if len(imageResp.Images) != 1 { 63 state["error"] = fmt.Errorf("The source AMI '%s' could not be found.", s.SourceAMI) 64 return multistep.ActionHalt 65 } 66 67 if s.ExpectedRootDevice != "" && imageResp.Images[0].RootDeviceType != s.ExpectedRootDevice { 68 state["error"] = fmt.Errorf( 69 "The provided source AMI has an invalid root device type.\n"+ 70 "Expected '%s', got '%s'.", 71 s.ExpectedRootDevice, imageResp.Images[0].RootDeviceType) 72 return multistep.ActionHalt 73 } 74 75 runResp, err := ec2conn.RunInstances(runOpts) 76 if err != nil { 77 err := fmt.Errorf("Error launching source instance: %s", err) 78 state["error"] = err 79 ui.Error(err.Error()) 80 return multistep.ActionHalt 81 } 82 83 s.instance = &runResp.Instances[0] 84 log.Printf("instance id: %s", s.instance.InstanceId) 85 86 ui.Say(fmt.Sprintf("Waiting for instance (%s) to become ready...", s.instance.InstanceId)) 87 stateChange := StateChangeConf{ 88 Conn: ec2conn, 89 Pending: []string{"pending"}, 90 Target: "running", 91 Refresh: InstanceStateRefreshFunc(ec2conn, s.instance), 92 StepState: state, 93 } 94 latestInstance, err := WaitForState(&stateChange) 95 if err != nil { 96 err := fmt.Errorf("Error waiting for instance (%s) to become ready: %s", s.instance.InstanceId, err) 97 state["error"] = err 98 ui.Error(err.Error()) 99 return multistep.ActionHalt 100 } 101 102 s.instance = latestInstance.(*ec2.Instance) 103 state["instance"] = s.instance 104 105 return multistep.ActionContinue 106 } 107 108 func (s *StepRunSourceInstance) Cleanup(state map[string]interface{}) { 109 if s.instance == nil { 110 return 111 } 112 113 ec2conn := state["ec2"].(*ec2.EC2) 114 ui := state["ui"].(packer.Ui) 115 116 ui.Say("Terminating the source AWS instance...") 117 if _, err := ec2conn.TerminateInstances([]string{s.instance.InstanceId}); err != nil { 118 ui.Error(fmt.Sprintf("Error terminating instance, may still be around: %s", err)) 119 return 120 } 121 122 stateChange := StateChangeConf{ 123 Conn: ec2conn, 124 Pending: []string{"pending", "running", "shutting-down", "stopped", "stopping"}, 125 Refresh: InstanceStateRefreshFunc(ec2conn, s.instance), 126 Target: "terminated", 127 } 128 129 WaitForState(&stateChange) 130 }