// This function will take several pieces of information and launch a new AWS instance // It requires the ID of the image, the security group to apply, the subnet ID to // start the instance in, the name of the key for authentication, the type of instance // as well as the number of instances to start. It'll return the reservation object // That we get back from the API. func launchInstance(amiid, secgrpid, subnet, instancetype, ca, crt, key string, number int, ec2client *ec2.EC2) (ec2.Reservation, error) { cloudconfig := `#cloud-config # vim: syntax=yaml # package_update: true package_upgrade: true packages: - cracklord-resourced write_files: - content: | ` + addSpacesToUserDataFile(ca) + ` path: /etc/cracklord/ssl/cracklord_ca.pem - content: | ` + addSpacesToUserDataFile(crt) + ` path: /etc/cracklord/ssl/resourced.crt - content: | ` + addSpacesToUserDataFile(key) + ` path: /etc/cracklord/ssl/resourced.key` userdata := base64.StdEncoding.EncodeToString([]byte(cloudconfig)) // Build our request, converting the go base types into the pointers required by the SDK instanceReq := ec2.RunInstancesInput{ ImageId: aws.String(amiid), MaxCount: aws.Int64(int64(number)), MinCount: aws.Int64(int64(number)), InstanceType: aws.String(instancetype), // Because we're making this VPC aware, we also have to include a network interface specification NetworkInterfaces: []*ec2.InstanceNetworkInterfaceSpecification{ { AssociatePublicIpAddress: aws.Bool(true), DeviceIndex: aws.Int64(0), SubnetId: aws.String(subnet), Groups: []*string{ aws.String(secgrpid), }, }, }, UserData: aws.String(userdata), } // Finally, we make our request instanceResp, err := ec2client.RunInstances(&instanceReq) if err != nil { return ec2.Reservation{}, err } return *instanceResp, nil }
func createInstance(svc *ec2.EC2, config *Config, ec2config EC2, userdata string, doneChan chan string) int { var min int64 var max int64 min = 1 max = 1 remainingSteps := 0 var subnet string if ec2config.HasExternalIP { subnet = config.PublicSubnetId } else { subnet = config.PrivateSubnetId } //fmt.Println("Public: ", config.PublicSubnetId) //fmt.Println("Private: ", config.PrivateSubnetId) //fmt.Println("Using: ", subnet) //if isEc2PartofLb(config, ec2config) { // subnet = config.PrivateSubnetId //} ec2config.SecurityGroupIds = getSecurityGroupIds(svc, config, ec2config.SecurityGroups) keyname := ec2config.KeyName if keyname == "" { keyname = config.KeyPair } params := &ec2.RunInstancesInput{ ImageId: &ec2config.AMI, InstanceType: &ec2config.InstanceType, MaxCount: &max, MinCount: &min, KeyName: &keyname, UserData: &userdata, SubnetId: &subnet, SecurityGroupIds: ec2config.SecurityGroupIds, } //fmt.Println("Create instance params:", params) rres, err := svc.RunInstances(params) if err != nil { fmt.Println("Failed to create instance", err) fmt.Println(rres) } else { fmt.Printf("Created instance %s: %s\n", ec2config.Name, *rres.Instances[0].InstanceId) ec2config.InstanceId = *rres.Instances[0].InstanceId //fmt.Println(rres) //fmt.Println("Sleeping for a sec to give AWS some time ...") time.Sleep(1 * time.Second) keyname := "Name" _, err := svc.CreateTags(&ec2.CreateTagsInput{ Resources: []*string{rres.Instances[0].InstanceId}, Tags: []*ec2.Tag{ &ec2.Tag{ Key: &keyname, Value: &ec2config.Name, }, }, }) //fmt.Println(tres) if err != nil { fmt.Println("Could not create tags for instance ", rres.Instances[0].InstanceId) fmt.Println(err) } //else { //fmt.Println("Created tag Name with value", ec2config.Name) //fmt.Println("isnat", ec2config.IsNat) if ec2config.IsNat { remainingSteps++ go func() { err = waitForNonPendingState(svc, rres.Instances[0].InstanceId) if err != nil { fmt.Println(err) doneChan <- "Gave up waiting on ec2 to leave pending state." return } bv := false abv := &ec2.AttributeBooleanValue{Value: &bv} miai := &ec2.ModifyInstanceAttributeInput{InstanceId: rres.Instances[0].InstanceId, SourceDestCheck: abv} _, err := svc.ModifyInstanceAttribute(miai) if err != nil { fmt.Println("Failed to change sourcedestcheck", err) } routeid, err := getPrivateRouteTable(svc, &config.PrivateSubnetId, config.VpcId) if err != nil { routeid, err = createPrivateRouteTable(svc, config) } else { _ = deleteDefaultRoute(svc, routeid) /*if err != nil { fmt.Println("Error deleting default route or default route existed", err) }*/ } defr := "0.0.0.0/0" cri := &ec2.CreateRouteInput{DestinationCidrBlock: &defr, InstanceId: rres.Instances[0].InstanceId, RouteTableId: routeid} _, err = svc.CreateRoute(cri) if err != nil { fmt.Println("Error adding new default route to NAT node", err) } doneChan <- fmt.Sprintf("Configured for NAT: %s", ec2config.Name) }() } //} //fmt.Println("hasexternalip ", ec2config.HasExternalIP) if ec2config.HasExternalIP { remainingSteps++ go func() { vpcs := "vpc" aao, err := svc.AllocateAddress(&ec2.AllocateAddressInput{Domain: &vpcs}) if err != nil { fmt.Println("Could not allocate addr:", err) } err = waitForNonPendingState(svc, rres.Instances[0].InstanceId) if err != nil { fmt.Println(err) } else { //aai,err := svc.AssociateAddress(&ec2.AssociateAddressInput{ PublicIp: aao.PublicIp, InstanceId: rres.Instances[0].InstanceId }) _, err := svc.AssociateAddress(&ec2.AssociateAddressInput{AllocationId: aao.AllocationId, InstanceId: rres.Instances[0].InstanceId}) if err != nil { fmt.Println("Could not assign addr:", err) } } //fmt.Println("External IP: ", *aao.PublicIp) doneChan <- fmt.Sprintf("External IP for %s assigned: %s", ec2config.Name, *aao.PublicIp) }() } } return remainingSteps }