Exemple #1
1
// 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)
}
Exemple #4
0
// 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
	}
}
Exemple #6
0
// 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
	}
}
Exemple #8
0
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

}
Exemple #9
0
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
	}
}
Exemple #11
0
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

}
Exemple #12
0
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,
	})
}
Exemple #14
0
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
	}
}
Exemple #16
0
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
	}
}
Exemple #18
0
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))

}
Exemple #19
0
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
}
Exemple #20
0
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
}
Exemple #22
0
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
	}
}
Exemple #24
0
// 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
	}
}
Exemple #27
0
// 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
	}
}
Exemple #30
0
// 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
}