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