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