示例#1
0
// InstanceStateRefreshFunc returns a resource.StateRefreshFunc that is used to watch
// an EC2 instance.
func InstanceStateRefreshFunc(conn *ec2.EC2, instanceID string) resource.StateRefreshFunc {
	return func() (interface{}, string, error) {
		resp, err := conn.DescribeInstances(&ec2.DescribeInstancesRequest{
			InstanceIDs: []string{instanceID},
		})
		if err != nil {
			if ec2err, ok := err.(aws.APIError); ok && ec2err.Code == "InvalidInstanceID.NotFound" {
				// Set this to nil 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
	}
}
// 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.DescribeVPCPeeringConnectionsRequest{
			VPCPeeringConnectionIDs: []string{id},
		})
		if err != nil {
			if ec2err, ok := err.(aws.APIError); ok && ec2err.Code == "InvalidVpcPeeringConnectionID.NotFound" {
				resp = nil
			} else {
				log.Printf("Error on VpcPeeringConnectionStateRefresh: %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, "ready", 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.DescribeSecurityGroupsRequest{
			GroupIDs: []string{id},
		}
		resp, err := conn.DescribeSecurityGroups(req)
		if err != nil {
			if ec2err, ok := err.(aws.APIError); 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
	}
}
示例#4
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", remove)
			err := conn.DeleteTags(&ec2.DeleteTagsRequest{
				Resources: []string{d.Id()},
				Tags:      remove,
			})
			if err != nil {
				return err
			}
		}
		if len(create) > 0 {
			log.Printf("[DEBUG] Creating tags: %#v", create)
			err := conn.CreateTags(&ec2.CreateTagsRequest{
				Resources: []string{d.Id()},
				Tags:      create,
			})
			if err != nil {
				return err
			}
		}
	}

	return nil
}
func updateNetworkAclEntries(d *schema.ResourceData, entryType string, ec2conn *ec2.EC2) error {

	o, n := d.GetChange(entryType)

	if o == nil {
		o = new(schema.Set)
	}
	if n == nil {
		n = new(schema.Set)
	}

	os := o.(*schema.Set)
	ns := n.(*schema.Set)

	toBeDeleted, err := expandNetworkAclEntries(os.Difference(ns).List(), entryType)
	if err != nil {
		return err
	}
	for _, remove := range toBeDeleted {
		// Delete old Acl
		err := ec2conn.DeleteNetworkACLEntry(&ec2.DeleteNetworkACLEntryRequest{
			NetworkACLID: aws.String(d.Id()),
			RuleNumber:   remove.RuleNumber,
			Egress:       remove.Egress,
		})
		if err != nil {
			return fmt.Errorf("Error deleting %s entry: %s", entryType, err)
		}
	}

	toBeCreated, err := expandNetworkAclEntries(ns.Difference(os).List(), entryType)
	if err != nil {
		return err
	}
	for _, add := range toBeCreated {
		// Add new Acl entry
		err := ec2conn.CreateNetworkACLEntry(&ec2.CreateNetworkACLEntryRequest{
			NetworkACLID: aws.String(d.Id()),
			CIDRBlock:    add.CIDRBlock,
			Egress:       add.Egress,
			PortRange:    add.PortRange,
			Protocol:     add.Protocol,
			RuleAction:   add.RuleAction,
			RuleNumber:   add.RuleNumber,
		})
		if err != nil {
			return fmt.Errorf("Error creating %s entry: %s", entryType, err)
		}
	}
	return nil
}
示例#6
0
func fetchRootDeviceName(ami string, conn *ec2.EC2) (aws.StringValue, error) {
	if ami == "" {
		return nil, fmt.Errorf("Cannot fetch root device name for blank AMI ID.")
	}

	log.Printf("[DEBUG] Describing AMI %q to get root block device name", ami)
	req := &ec2.DescribeImagesRequest{ImageIDs: []string{ami}}
	if res, err := conn.DescribeImages(req); err == nil {
		if len(res.Images) == 1 {
			return res.Images[0].RootDeviceName, nil
		} else {
			return nil, fmt.Errorf("Expected 1 AMI for ID: %s, got: %#v", ami, res.Images)
		}
	} else {
		return nil, err
	}
}
func networkInterfaceAttachmentRefreshFunc(ec2conn *ec2.EC2, id string) resource.StateRefreshFunc {
	return func() (interface{}, string, error) {

		describe_network_interfaces_request := &ec2.DescribeNetworkInterfacesRequest{
			NetworkInterfaceIDs: []string{id},
		}
		describeResp, err := ec2conn.DescribeNetworkInterfaces(describe_network_interfaces_request)

		if err != nil {
			log.Printf("[ERROR] Could not find network interface %s. %s", id, err)
			return nil, "", err
		}

		eni := describeResp.NetworkInterfaces[0]
		hasAttachment := strconv.FormatBool(eni.Attachment != nil)
		log.Printf("[DEBUG] ENI %s has attachment state %s", id, hasAttachment)
		return eni, hasAttachment, nil
	}
}
func getDefaultNetworkAcl(vpc_id string, ec2conn *ec2.EC2) (defaultAcl *ec2.NetworkACL, err error) {
	resp, err := ec2conn.DescribeNetworkACLs(&ec2.DescribeNetworkACLsRequest{
		NetworkACLIDs: []string{},
		Filters: []ec2.Filter{
			ec2.Filter{
				Name:   aws.String("default"),
				Values: []string{"true"},
			},
			ec2.Filter{
				Name:   aws.String("vpc-id"),
				Values: []string{vpc_id},
			},
		},
	})

	if err != nil {
		return nil, err
	}
	return &resp.NetworkACLs[0], nil
}
func findNetworkAclAssociation(subnetId string, ec2conn *ec2.EC2) (networkAclAssociation *ec2.NetworkACLAssociation, err error) {
	resp, err := ec2conn.DescribeNetworkACLs(&ec2.DescribeNetworkACLsRequest{
		NetworkACLIDs: []string{},
		Filters: []ec2.Filter{
			ec2.Filter{
				Name:   aws.String("association.subnet-id"),
				Values: []string{subnetId},
			},
		},
	})

	if err != nil {
		return nil, err
	}
	for _, association := range resp.NetworkACLs[0].Associations {
		if *association.SubnetID == subnetId {
			return &association, nil
		}
	}
	return nil, fmt.Errorf("could not find association for subnet %s ", subnetId)
}
// VpnGatewayAttachStateRefreshFunc returns a resource.StateRefreshFunc that is used to watch
// the state of a VPN gateway's attachment
func VpnGatewayAttachStateRefreshFunc(conn *ec2.EC2, id string, expected string) resource.StateRefreshFunc {
	var start time.Time
	return func() (interface{}, string, error) {
		if start.IsZero() {
			start = time.Now()
		}

		resp, err := conn.DescribeVPNGateways(&ec2.DescribeVPNGatewaysRequest{
			VPNGatewayIDs: []string{id},
		})
		if err != nil {
			if ec2err, ok := err.(aws.APIError); ok && ec2err.Code == "InvalidVpnGatewayID.NotFound" {
				resp = nil
			} else {
				log.Printf("[ERROR] Error on VpnGatewayStateRefresh: %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
		}

		vpnGateway := &resp.VPNGateways[0]

		if time.Now().Sub(start) > 10*time.Second {
			return vpnGateway, expected, nil
		}

		if len(vpnGateway.VPCAttachments) == 0 {
			// No attachments, we're detached
			return vpnGateway, "detached", nil
		}

		return vpnGateway, *vpnGateway.VPCAttachments[0].State, nil
	}
}
func findMainRouteTable(ec2conn *ec2.EC2, vpcId string) (*ec2.RouteTable, error) {
	mainFilter := ec2.Filter{
		aws.String("association.main"),
		[]string{"true"},
	}
	vpcFilter := ec2.Filter{
		aws.String("vpc-id"),
		[]string{vpcId},
	}
	routeResp, err := ec2conn.DescribeRouteTables(&ec2.DescribeRouteTablesRequest{
		Filters: []ec2.Filter{mainFilter, vpcFilter},
	})
	if err != nil {
		return nil, err
	} else if len(routeResp.RouteTables) != 1 {
		return nil, fmt.Errorf(
			"Expected to find a single main routing table for VPC: %s, but found %d",
			vpcId,
			len(routeResp.RouteTables))
	}

	return &routeResp.RouteTables[0], nil
}
// vpnGatewayStateRefreshFunc returns a resource.StateRefreshFunc that is used to watch a VPNGateway.
func vpnGatewayStateRefreshFunc(conn *ec2.EC2, id string) resource.StateRefreshFunc {
	return func() (interface{}, string, error) {
		resp, err := conn.DescribeVPNGateways(&ec2.DescribeVPNGatewaysRequest{
			VPNGatewayIDs: []string{id},
		})
		if err != nil {
			if ec2err, ok := err.(aws.APIError); ok && ec2err.Code == "InvalidVpnGatewayID.NotFound" {
				resp = nil
			} else {
				log.Printf("[ERROR] Error on VpnGatewayStateRefresh: %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
		}

		vpnGateway := &resp.VPNGateways[0]
		return vpnGateway, *vpnGateway.State, nil
	}
}
示例#13
0
// SubnetStateRefreshFunc returns a resource.StateRefreshFunc that is used to watch a Subnet.
func SubnetStateRefreshFunc(conn *ec2.EC2, id string) resource.StateRefreshFunc {
	return func() (interface{}, string, error) {
		resp, err := conn.DescribeSubnets(&ec2.DescribeSubnetsRequest{
			SubnetIDs: []string{id},
		})
		if err != nil {
			if ec2err, ok := err.(aws.APIError); ok && ec2err.Code == "InvalidSubnetID.NotFound" {
				resp = nil
			} else {
				log.Printf("Error on SubnetStateRefresh: %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
		}

		subnet := &resp.Subnets[0]
		return subnet, *subnet.State, nil
	}
}
示例#14
0
func readBlockDevicesFromInstance(instance *ec2.Instance, ec2conn *ec2.EC2) (map[string]interface{}, error) {
	blockDevices := make(map[string]interface{})
	blockDevices["ebs"] = make([]map[string]interface{}, 0)
	blockDevices["root"] = nil

	instanceBlockDevices := make(map[string]ec2.InstanceBlockDeviceMapping)
	for _, bd := range instance.BlockDeviceMappings {
		if bd.EBS != nil {
			instanceBlockDevices[*(bd.EBS.VolumeID)] = bd
		}
	}

	if len(instanceBlockDevices) == 0 {
		return nil, nil
	}

	volIDs := make([]string, 0, len(instanceBlockDevices))
	for volID := range instanceBlockDevices {
		volIDs = append(volIDs, volID)
	}

	// Need to call DescribeVolumes to get volume_size and volume_type for each
	// EBS block device
	volResp, err := ec2conn.DescribeVolumes(&ec2.DescribeVolumesRequest{
		VolumeIDs: volIDs,
	})
	if err != nil {
		return nil, err
	}

	for _, vol := range volResp.Volumes {
		instanceBd := instanceBlockDevices[*vol.VolumeID]
		bd := make(map[string]interface{})

		if instanceBd.EBS != nil && instanceBd.EBS.DeleteOnTermination != nil {
			bd["delete_on_termination"] = *instanceBd.EBS.DeleteOnTermination
		}
		if vol.Size != nil {
			bd["volume_size"] = *vol.Size
		}
		if vol.VolumeType != nil {
			bd["volume_type"] = *vol.VolumeType
		}
		if vol.IOPS != nil {
			bd["iops"] = *vol.IOPS
		}

		if blockDeviceIsRoot(instanceBd, instance) {
			blockDevices["root"] = bd
		} else {
			if instanceBd.DeviceName != nil {
				bd["device_name"] = *instanceBd.DeviceName
			}
			if vol.Encrypted != nil {
				bd["encrypted"] = *vol.Encrypted
			}
			if vol.SnapshotID != nil {
				bd["snapshot_id"] = *vol.SnapshotID
			}

			blockDevices["ebs"] = append(blockDevices["ebs"].([]map[string]interface{}), bd)
		}
	}

	return blockDevices, nil
}