// Sets up a security group based on it's ID. Returns an error if it isn't able. func setupSecurityGroup(name, desc, vpc string, ec2client *ec2.EC2) (string, error) { //Create the input struct with the appropriate settings, making sure to use the aws string pointer type sgReq := ec2.CreateSecurityGroupInput{ GroupName: aws.String(name), Description: aws.String(desc), VpcId: aws.String(vpc), } //Attempt to create the security group sgResp, err := ec2client.CreateSecurityGroup(&sgReq) if err != nil { return "", err } authReq := ec2.AuthorizeSecurityGroupIngressInput{ CidrIp: aws.String("0.0.0.0/0"), FromPort: aws.Int64(9443), ToPort: aws.Int64(9443), IpProtocol: aws.String("tcp"), GroupId: sgResp.GroupId, } _, err = ec2client.AuthorizeSecurityGroupIngress(&authReq) if err != nil { return "", err } return *sgResp.GroupId, nil }
func volumeAttachmentStateRefreshFunc(conn *ec2.EC2, volumeID, instanceID string) resource.StateRefreshFunc { return func() (interface{}, string, error) { request := &ec2.DescribeVolumesInput{ VolumeIds: []*string{aws.String(volumeID)}, Filters: []*ec2.Filter{ &ec2.Filter{ Name: aws.String("attachment.instance-id"), Values: []*string{aws.String(instanceID)}, }, }, } resp, err := conn.DescribeVolumes(request) if err != nil { if awsErr, ok := err.(awserr.Error); ok { return nil, "failed", fmt.Errorf("code: %s, message: %s", awsErr.Code(), awsErr.Message()) } return nil, "failed", err } if len(resp.Volumes) > 0 { v := resp.Volumes[0] for _, a := range v.Attachments { if a.InstanceId != nil && *a.InstanceId == instanceID { return a, *a.State, nil } } } // assume detached if volume count is 0 return 42, "detached", nil } }
// Helper: retrieve a route func findResourceRoute(conn *ec2.EC2, rtbid string, cidr string) (*ec2.Route, error) { routeTableID := rtbid findOpts := &ec2.DescribeRouteTablesInput{ RouteTableIds: []*string{&routeTableID}, } resp, err := conn.DescribeRouteTables(findOpts) if err != nil { return nil, err } if len(resp.RouteTables) < 1 || resp.RouteTables[0] == nil { return nil, fmt.Errorf("Route table %s is gone, so route does not exist.", routeTableID) } for _, route := range (*resp.RouteTables[0]).Routes { if *route.DestinationCidrBlock == cidr { return route, nil } } return nil, fmt.Errorf(` error finding matching route for Route table (%s) and destination CIDR block (%s)`, rtbid, cidr) }
// SpotRequestStateRefreshFunc returns a StateRefreshFunc that is used to watch // a spot request for state changes. func SpotRequestStateRefreshFunc(conn *ec2.EC2, spotRequestId string) StateRefreshFunc { return func() (interface{}, string, error) { resp, err := conn.DescribeSpotInstanceRequests(&ec2.DescribeSpotInstanceRequestsInput{ SpotInstanceRequestIDs: []*string{&spotRequestId}, }) if err != nil { if ec2err, ok := err.(awserr.Error); ok && ec2err.Code() == "InvalidSpotInstanceRequestID.NotFound" { // Set this to nil as if we didn't find anything. resp = nil } else if isTransientNetworkError(err) { // Transient network error, treat it as if we didn't find anything resp = nil } else { log.Printf("Error on SpotRequestStateRefresh: %s", err) return nil, "", err } } if resp == nil || len(resp.SpotInstanceRequests) == 0 { // Sometimes AWS has consistency issues and doesn't see the // SpotRequest. Return an empty state. return nil, "", nil } i := resp.SpotInstanceRequests[0] return i, *i.State, nil } }
// VPCStateRefreshFunc returns a resource.StateRefreshFunc that is used to watch // a VPC. func VPCStateRefreshFunc(conn *ec2.EC2, id string) resource.StateRefreshFunc { return func() (interface{}, string, error) { DescribeVpcOpts := &ec2.DescribeVPCsInput{ VPCIDs: []*string{aws.String(id)}, } resp, err := conn.DescribeVPCs(DescribeVpcOpts) if err != nil { if ec2err, ok := err.(awserr.Error); ok && ec2err.Code() == "InvalidVpcID.NotFound" { resp = nil } else { log.Printf("Error on VPCStateRefresh: %s", err) return nil, "", err } } if resp == nil { // Sometimes AWS just has consistency issues and doesn't see // our instance yet. Return an empty state. return nil, "", nil } vpc := resp.VPCs[0] return vpc, *vpc.State, nil } }
// GetContainerInstances will return a slice of ECS Container Instances within a cluster func GetContainerInstances(svc *ecs.ECS, ec2svc *ec2.EC2, cluster *string) (containerInstances []*ecs.ContainerInstance, instances []*ec2.Reservation, e error) { var ciArns []*string // List clusters reqParams := &ecs.ListContainerInstancesInput{ Cluster: cluster, MaxResults: aws.Int64(100), NextToken: aws.String(""), } // Loop through tokens until no more results remain for { resp, err := svc.ListContainerInstances(reqParams) // Error check if err != nil { return nil, nil, fmt.Errorf("ecs.ListContainerInstances: %s", err.Error()) } // Expand slice of container instances and append to our comprehensive list ciArns = append(ciArns, resp.ContainerInstanceArns...) // Cycle token if resp.NextToken != nil { reqParams.NextToken = resp.NextToken } else { // Kill loop ... out of response pages break } } // Describe the tasks that we just got back ciResponse, err := svc.DescribeContainerInstances(&ecs.DescribeContainerInstancesInput{ Cluster: cluster, ContainerInstances: ciArns, }) if err != nil { return nil, nil, fmt.Errorf("ecs.DescribeContainerInstances: %s", err.Error()) } var instanceIds []*string for _, k := range ciResponse.ContainerInstances { instanceIds = append(instanceIds, k.Ec2InstanceId) } // Create a map of container instances by ci arn... // Note: Will work for <= 1000 instances w/o having to use NextToken ec2Resp, err := ec2svc.DescribeInstances(&ec2.DescribeInstancesInput{ InstanceIds: instanceIds, }) if err != nil { return nil, nil, fmt.Errorf("ec2.DescribeInstances: %s", err.Error()) } return ciResponse.ContainerInstances, ec2Resp.Reservations, nil }
func customerGatewayRefreshFunc(conn *ec2.EC2, gatewayId string) resource.StateRefreshFunc { return func() (interface{}, string, error) { gatewayFilter := &ec2.Filter{ Name: aws.String("customer-gateway-id"), Values: []*string{aws.String(gatewayId)}, } resp, err := conn.DescribeCustomerGateways(&ec2.DescribeCustomerGatewaysInput{ Filters: []*ec2.Filter{gatewayFilter}, }) if err != nil { if ec2err, ok := err.(awserr.Error); ok && ec2err.Code() == "InvalidCustomerGatewayID.NotFound" { resp = nil } else { log.Printf("Error on CustomerGatewayRefresh: %s", err) return nil, "", err } } if resp == nil || len(resp.CustomerGateways) == 0 { // handle consistency issues return nil, "", nil } gateway := resp.CustomerGateways[0] return gateway, *gateway.State, nil } }
func getSecurityGroupIdsByVPC(c *ec2.EC2, vpcid string) []*string { secgroupids := make([]*string, 0) filters := make([]*ec2.Filter, 0) keyname := "vpc-id" filter := ec2.Filter{ Name: &keyname, Values: []*string{&vpcid}} filters = append(filters, &filter) dsgi := &ec2.DescribeSecurityGroupsInput{Filters: filters} dsgo, err := c.DescribeSecurityGroups(dsgi) if err != nil { fmt.Println("Describe security groups failed.") panic(err) } for i := range dsgo.SecurityGroups { if *dsgo.SecurityGroups[i].GroupName == "default" { continue } else { secgroupids = append(secgroupids, dsgo.SecurityGroups[i].GroupId) } } return secgroupids }
func getSecurityGroupIds(c *ec2.EC2, config *Config, secgroups []string) []*string { //secgroups := make([]*string,0) secgroupids := make([]*string, 0) for i := range secgroups { filters := make([]*ec2.Filter, 0) keyname := "group-name" keyname2 := "vpc-id" filter := ec2.Filter{ Name: &keyname, Values: []*string{&secgroups[i]}} filter2 := ec2.Filter{ Name: &keyname2, Values: []*string{&config.VpcId}} filters = append(filters, &filter) filters = append(filters, &filter2) //fmt.Println("Filters ", filters) dsgi := &ec2.DescribeSecurityGroupsInput{Filters: filters} dsgo, err := c.DescribeSecurityGroups(dsgi) if err != nil { fmt.Println("Describe security groups failed.") panic(err) } for i := range dsgo.SecurityGroups { secgroupids = append(secgroupids, dsgo.SecurityGroups[i].GroupId) } } //fmt.Println("Security Groups!", secgroupids) return secgroupids }
func resourceDHCPOptionsStateRefreshFunc(conn *ec2.EC2, id string) resource.StateRefreshFunc { return func() (interface{}, string, error) { DescribeDhcpOpts := &ec2.DescribeDhcpOptionsInput{ DhcpOptionsIds: []*string{ aws.String(id), }, } resp, err := conn.DescribeDhcpOptions(DescribeDhcpOpts) if err != nil { if ec2err, ok := err.(awserr.Error); ok && ec2err.Code() == "InvalidDhcpOptionsID.NotFound" { resp = nil } else { log.Printf("Error on DHCPOptionsStateRefresh: %s", err) return nil, "", err } } if resp == nil { // Sometimes AWS just has consistency issues and doesn't see // our instance yet. Return an empty state. return nil, "", nil } dos := resp.DhcpOptions[0] return dos, "created", nil } }
func createSubnets(svc *ec2.EC2, config *Config) (*ec2.CreateSubnetOutput, *ec2.CreateSubnetOutput, error) { var csi *ec2.CreateSubnetInput if config.AvailZone1 != "" { csi = &ec2.CreateSubnetInput{CidrBlock: &config.PublicNet, VpcId: &config.VpcId, AvailabilityZone: &config.AvailZone1} } else { csi = &ec2.CreateSubnetInput{CidrBlock: &config.PublicNet, VpcId: &config.VpcId} } //csi := &ec2.CreateSubnetInput{ CidrBlock: &config.PublicNet, VpcId: &config.VpcId } cso1, err := svc.CreateSubnet(csi) if err != nil { fmt.Println("Create public subnet failed") return nil, nil, err } //fmt.Println(cso1) config.PublicSubnetId = *cso1.Subnet.SubnetId if config.AvailZone2 != "" { csi = &ec2.CreateSubnetInput{CidrBlock: &config.PrivateNet, VpcId: &config.VpcId, AvailabilityZone: &config.AvailZone2} } else { csi = &ec2.CreateSubnetInput{CidrBlock: &config.PrivateNet, VpcId: &config.VpcId} } //csi := &ec2.CreateSubnetInput{ CidrBlock: &config.PublicNet, VpcId: &config.VpcId } //csi = &ec2.CreateSubnetInput{ CidrBlock: &config.PrivateNet, VpcId: &config.VpcId} cso2, err := svc.CreateSubnet(csi) if err != nil { fmt.Println("Create private subnet failed") return nil, nil, err } //fmt.Println(cso2) config.PrivateSubnetId = *cso2.Subnet.SubnetId return cso1, cso2, nil }
func getInstancesWithTag(ec2Client *ec2.EC2, key string, value string) ([]*ec2.Instance, error) { var instances []*ec2.Instance err := ec2Client.DescribeInstancesPages(&ec2.DescribeInstancesInput{ Filters: []*ec2.Filter{ &ec2.Filter{ Name: aws.String("instance-state-name"), Values: []*string{aws.String("running")}, }, &ec2.Filter{ Name: aws.String(fmt.Sprintf("tag:%s", key)), Values: []*string{aws.String(value)}, }, }, }, func(result *ec2.DescribeInstancesOutput, _ bool) bool { for _, reservation := range result.Reservations { instances = append(instances, reservation.Instances...) } return true // keep going }) if err != nil { return nil, err } return instances, nil }
func createSnapshot(svc *ec2.EC2, volumeId string) { description := descriptionPrefix + time.Now().Local().String() svc.CreateSnapshot(&ec2.CreateSnapshotInput{ VolumeId: &volumeId, Description: &description, }) }
func findInstance(ec2HostConfig *config.Ec2HostConfig, svc *ec2.EC2) (*ec2.Instance, error) { region, name := ec2HostConfig.Region, ec2HostConfig.Name log.Printf("Searching for instance named %q in region %s", name, region) params := &ec2.DescribeInstancesInput{ Filters: []*ec2.Filter{ { Name: aws.String("tag:Name"), Values: []*string{ aws.String(ec2HostConfig.Name), }, }, }, } resp, err := svc.DescribeInstances(params) if err != nil { return nil, err } if len(resp.Reservations) < 1 { return nil, fmt.Errorf("no instance found in %s with name %s", region, name) } if len(resp.Reservations) > 1 || len(resp.Reservations[0].Instances) != 1 { return nil, fmt.Errorf("multiple instances found in %s with name %s", region, name) } return resp.Reservations[0].Instances[0], nil }
// NGStateRefreshFunc returns a resource.StateRefreshFunc that is used to watch // a NAT Gateway. func NGStateRefreshFunc(conn *ec2.EC2, id string) resource.StateRefreshFunc { return func() (interface{}, string, error) { opts := &ec2.DescribeNatGatewaysInput{ NatGatewayIds: []*string{aws.String(id)}, } resp, err := conn.DescribeNatGateways(opts) if err != nil { if ec2err, ok := err.(awserr.Error); ok && ec2err.Code() == "NatGatewayNotFound" { resp = nil } else { log.Printf("Error on NGStateRefresh: %s", err) return nil, "", err } } if resp == nil { // Sometimes AWS just has consistency issues and doesn't see // our instance yet. Return an empty state. return nil, "", nil } ng := resp.NatGateways[0] return ng, *ng.State, nil } }
func waitForDetachedNetwork(svc *ec2.EC2, instanceid *string) error { iids := []*string{instanceid} dii := &ec2.DescribeInstancesInput{ InstanceIds: iids, } dio, err := svc.DescribeInstances(dii) if err != nil { panic(err) } //fmt.Println(dio) count := 0 for { dio, err = svc.DescribeInstances(dii) if err != nil { panic(err) } if len(dio.Reservations[0].Instances[0].NetworkInterfaces) == 0 { return nil } if count > 60 { break } time.Sleep(2 * time.Second) count++ } return errors.New(fmt.Sprintf("Waited too long for EC2 to remove networking.")) }
// resourceAwsVPCPeeringConnectionStateRefreshFunc returns a resource.StateRefreshFunc that is used to watch // a VPCPeeringConnection. func resourceAwsVPCPeeringConnectionStateRefreshFunc(conn *ec2.EC2, id string) resource.StateRefreshFunc { return func() (interface{}, string, error) { resp, err := conn.DescribeVpcPeeringConnections(&ec2.DescribeVpcPeeringConnectionsInput{ VpcPeeringConnectionIds: []*string{aws.String(id)}, }) if err != nil { if ec2err, ok := err.(awserr.Error); ok && ec2err.Code() == "InvalidVpcPeeringConnectionID.NotFound" { resp = nil } else { log.Printf("Error reading VPC Peering Connection details: %s", err) return nil, "", err } } if resp == nil { // Sometimes AWS just has consistency issues and doesn't see // our instance yet. Return an empty state. return nil, "", nil } pc := resp.VpcPeeringConnections[0] return pc, *pc.Status.Code, nil } }
func getMainRouteTableFromVPC(svc *ec2.EC2, VpcId *string) (*string, error) { keyname := "association.main" asbool := "true" filters := make([]*ec2.Filter, 0) filter := ec2.Filter{ Name: &keyname, Values: []*string{&asbool}} filters = append(filters, &filter) //fmt.Println("Filters ", filters) drti := &ec2.DescribeRouteTablesInput{Filters: filters} drto, err := svc.DescribeRouteTables(drti) if err != nil { panic(err) } for i := range drto.RouteTables { if *drto.RouteTables[i].VpcId == *VpcId { //fmt.Println("Route table is", *drto.RouteTables[i].RouteTableId) return drto.RouteTables[i].RouteTableId, nil } } return nil, errors.New(fmt.Sprintf("No main route table found for vpc", *VpcId)) }
func resourceAwsVpcSetDefaultRouteTable(conn *ec2.EC2, d *schema.ResourceData) error { filter1 := &ec2.Filter{ Name: aws.String("association.main"), Values: []*string{aws.String("true")}, } filter2 := &ec2.Filter{ Name: aws.String("vpc-id"), Values: []*string{aws.String(d.Id())}, } findOpts := &ec2.DescribeRouteTablesInput{ Filters: []*ec2.Filter{filter1, filter2}, } resp, err := conn.DescribeRouteTables(findOpts) if err != nil { return err } if len(resp.RouteTables) < 1 || resp.RouteTables[0] == nil { return fmt.Errorf("Default Route table not found") } // There Can Be Only 1 ... Default Route Table d.Set("default_route_table_id", resp.RouteTables[0].RouteTableId) return nil }
func getPrivateRouteTable(svc *ec2.EC2, subnetid *string, VpcId string) (*string, error) { keyname := "association.subnet-id" filters := make([]*ec2.Filter, 0) filter := ec2.Filter{ Name: &keyname, Values: []*string{subnetid}} filters = append(filters, &filter) //fmt.Println("Filters ", filters) drti := &ec2.DescribeRouteTablesInput{Filters: filters} drto, err := svc.DescribeRouteTables(drti) if err != nil { panic(err) } for i := range drto.RouteTables { if *drto.RouteTables[i].VpcId == VpcId { //fmt.Println("Route table is", *drto.RouteTables[i].RouteTableId) return drto.RouteTables[i].RouteTableId, nil } } return nil, errors.New(fmt.Sprintf("No route table found for subnet", *subnetid)) }
func getPrivateIPs(ec2region *ec2.EC2) []string { instances := []string{} filters, err := buildFilter(*tags) if err != nil { log.Println(err) } request := ec2.DescribeInstancesInput{Filters: filters} result, err := ec2region.DescribeInstances(&request) if err != nil { log.Println(err) } for _, reservation := range result.Reservations { for _, instance := range reservation.Instances { if instance.PrivateIpAddress != nil { if *debug { log.Printf("Adding %s to IP list\n", *instance.PrivateIpAddress) } instances = append(instances, *instance.PrivateIpAddress) } } } return instances }
func createSecurityGroups(c *ec2.EC2, config *Config) error { for j := range config.AllSecurityGroups { csgi := &ec2.CreateSecurityGroupInput{GroupName: &config.AllSecurityGroups[j].Name, VpcId: &config.VpcId, Description: &config.AllSecurityGroups[j].Name} csgo, err := c.CreateSecurityGroup(csgi) //fmt.Println(err) if err != nil { if !strings.Contains(fmt.Sprintf("%s", err), "InvalidGroup.Duplicate") { fmt.Println("Failed to create security group.") return err } continue } everywhere := "0.0.0.0/0" proto := "tcp" //var fromPort int64 //fromPort = -1 asgii := &ec2.AuthorizeSecurityGroupIngressInput{CidrIp: &everywhere, FromPort: &config.AllSecurityGroups[j].TcpPort, ToPort: &config.AllSecurityGroups[j].TcpPort, GroupId: csgo.GroupId, IpProtocol: &proto} _, err = c.AuthorizeSecurityGroupIngress(asgii) //fmt.Println("Adding security group", asgii) if err != nil { fmt.Println("Failed to add rule to security group: ", err) return err } } return nil }
// SpotInstanceStateRefreshFunc returns a resource.StateRefreshFunc that is used to watch // an EC2 spot instance request func SpotInstanceStateRefreshFunc( conn *ec2.EC2, sir ec2.SpotInstanceRequest) resource.StateRefreshFunc { return func() (interface{}, string, error) { resp, err := conn.DescribeSpotInstanceRequests(&ec2.DescribeSpotInstanceRequestsInput{ SpotInstanceRequestIDs: []*string{sir.SpotInstanceRequestID}, }) if err != nil { if ec2err, ok := err.(awserr.Error); ok && ec2err.Code() == "InvalidSpotInstanceRequestID.NotFound" { // Set this to nil as if we didn't find anything. resp = nil } else { log.Printf("Error on StateRefresh: %s", err) return nil, "", err } } if resp == nil || len(resp.SpotInstanceRequests) == 0 { // Sometimes AWS just has consistency issues and doesn't see // our request yet. Return an empty state. return nil, "", nil } req := resp.SpotInstanceRequests[0] return req, *req.Status.Code, nil } }
// setTags is a helper to set the tags for a resource. It expects the // tags field to be named "tags" func setTags(conn *ec2.EC2, d *schema.ResourceData) error { if d.HasChange("tags") { oraw, nraw := d.GetChange("tags") o := oraw.(map[string]interface{}) n := nraw.(map[string]interface{}) create, remove := diffTags(tagsFromMap(o), tagsFromMap(n)) // Set tags if len(remove) > 0 { log.Printf("[DEBUG] Removing tags: %#v from %s", remove, d.Id()) _, err := conn.DeleteTags(&ec2.DeleteTagsInput{ Resources: []*string{aws.String(d.Id())}, Tags: remove, }) if err != nil { return err } } if len(create) > 0 { log.Printf("[DEBUG] Creating tags: %s for %s", awsutil.StringValue(create), d.Id()) _, err := conn.CreateTags(&ec2.CreateTagsInput{ Resources: []*string{aws.String(d.Id())}, Tags: create, }) if err != nil { return err } } } return nil }
func awsTerminateInstance(conn *ec2.EC2, id string) error { log.Printf("[INFO] Terminating instance: %s", id) req := &ec2.TerminateInstancesInput{ InstanceIds: []*string{aws.String(id)}, } if _, err := conn.TerminateInstances(req); err != nil { return fmt.Errorf("Error terminating instance: %s", err) } log.Printf("[DEBUG] Waiting for instance (%s) to become terminated", id) stateConf := &resource.StateChangeConf{ Pending: []string{"pending", "running", "shutting-down", "stopped", "stopping"}, Target: []string{"terminated"}, Refresh: InstanceStateRefreshFunc(conn, id), Timeout: 10 * time.Minute, Delay: 10 * time.Second, MinTimeout: 3 * time.Second, } _, err := stateConf.WaitForState() if err != nil { return fmt.Errorf( "Error waiting for instance (%s) to terminate: %s", id, err) } return nil }
// resourceAwsVPCPeeringConnectionStateRefreshFunc returns a resource.StateRefreshFunc that is used to watch // a VPCPeeringConnection. func resourceAwsVPCPeeringConnectionStateRefreshFunc(conn *ec2.EC2, id string) resource.StateRefreshFunc { return func() (interface{}, string, error) { resp, err := conn.DescribeVpcPeeringConnections(&ec2.DescribeVpcPeeringConnectionsInput{ VpcPeeringConnectionIds: []*string{aws.String(id)}, }) if err != nil { if ec2err, ok := err.(awserr.Error); ok && ec2err.Code() == "InvalidVpcPeeringConnectionID.NotFound" { resp = nil } else { log.Printf("Error reading VPC Peering Connection details: %s", err) return nil, "error", err } } if resp == nil { // Sometimes AWS just has consistency issues and doesn't see // our instance yet. Return an empty state. return nil, "", nil } pc := resp.VpcPeeringConnections[0] // A VPC Peering Connection can exist in a failed state due to // incorrect VPC ID, account ID, or overlapping IP address range, // thus we short circuit before the time out would occur. if pc != nil && *pc.Status.Code == "failed" { return nil, "failed", errors.New(*pc.Status.Message) } return pc, *pc.Status.Code, nil } }
// InstanceStateRefreshFunc returns a StateRefreshFunc that is used to watch // an EC2 instance. func InstanceStateRefreshFunc(conn *ec2.EC2, instanceId string) StateRefreshFunc { return func() (interface{}, string, error) { resp, err := conn.DescribeInstances(&ec2.DescribeInstancesInput{ InstanceIDs: []*string{&instanceId}, }) if err != nil { if ec2err, ok := err.(awserr.Error); ok && ec2err.Code() == "InvalidInstanceID.NotFound" { // Set this to nil as if we didn't find anything. resp = nil } else if isTransientNetworkError(err) { // Transient network error, treat it as if we didn't find anything resp = nil } else { log.Printf("Error on InstanceStateRefresh: %s", err) return nil, "", err } } if resp == nil || len(resp.Reservations) == 0 || len(resp.Reservations[0].Instances) == 0 { // Sometimes AWS just has consistency issues and doesn't see // our instance yet. Return an empty state. return nil, "", nil } i := resp.Reservations[0].Instances[0] return i, *i.State.Name, nil } }
// SGStateRefreshFunc returns a resource.StateRefreshFunc that is used to watch // a security group. func SGStateRefreshFunc(conn *ec2.EC2, id string) resource.StateRefreshFunc { return func() (interface{}, string, error) { req := &ec2.DescribeSecurityGroupsInput{ GroupIds: []*string{aws.String(id)}, } resp, err := conn.DescribeSecurityGroups(req) if err != nil { if ec2err, ok := err.(awserr.Error); ok { if ec2err.Code() == "InvalidSecurityGroupID.NotFound" || ec2err.Code() == "InvalidGroup.NotFound" { resp = nil err = nil } } if err != nil { log.Printf("Error on SGStateRefresh: %s", err) return nil, "", err } } if resp == nil { return nil, "", nil } group := resp.SecurityGroups[0] return group, "exists", nil } }
// IGStateRefreshFunc returns a resource.StateRefreshFunc that is used to watch // an internet gateway. func IGStateRefreshFunc(conn *ec2.EC2, id string) resource.StateRefreshFunc { return func() (interface{}, string, error) { resp, err := conn.DescribeInternetGateways(&ec2.DescribeInternetGatewaysInput{ InternetGatewayIds: []*string{aws.String(id)}, }) if err != nil { ec2err, ok := err.(awserr.Error) if ok && ec2err.Code() == "InvalidInternetGatewayID.NotFound" { resp = nil } else { log.Printf("[ERROR] Error on IGStateRefresh: %s", err) return nil, "", err } } if resp == nil { // Sometimes AWS just has consistency issues and doesn't see // our instance yet. Return an empty state. return nil, "", nil } ig := resp.InternetGateways[0] return ig, "available", nil } }
// Returns a single insance when given it's ID func getInstanceByID(instanceid string, ec2client *ec2.EC2) (ec2.Instance, error) { instanceReq := ec2.DescribeInstancesInput{ InstanceIds: []*string{ aws.String(instanceid), }, } instanceResp, err := ec2client.DescribeInstances(&instanceReq) if err != nil { return ec2.Instance{}, err } //We only requested one instance, so we should only get one if len(instanceResp.Reservations) != 1 { return ec2.Instance{}, errors.New("The total number of reservations did not match the request") } reservation := instanceResp.Reservations[0] // Now let's make sure we only got one instance in this reservation if len(reservation.Instances) != 1 { return ec2.Instance{}, errors.New("The total number of instances did not match the request for full instance data") } instance := reservation.Instances[0] return *instance, nil }