diff --git a/aws/data_source_aws_network_interface.go b/aws/data_source_aws_network_interface.go new file mode 100644 index 000000000000..6a8f56729ac7 --- /dev/null +++ b/aws/data_source_aws_network_interface.go @@ -0,0 +1,174 @@ +package aws + +import ( + "fmt" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/ec2" + "github.com/hashicorp/terraform/helper/schema" +) + +func dataSourceAwsNetworkInterface() *schema.Resource { + return &schema.Resource{ + Read: dataSourceAwsNetworkInterfaceRead, + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Required: true, + }, + "association": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "allocation_id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + "association_id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + "ip_owner_id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + "public_dns_name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + "public_ip": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + "attachment": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "attachment_id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + "device_index": &schema.Schema{ + Type: schema.TypeInt, + Computed: true, + }, + "instance_id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + "instance_owner_id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + "availability_zone": { + Type: schema.TypeString, + Computed: true, + }, + "description": { + Type: schema.TypeString, + Computed: true, + }, + "security_groups": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "interface_type": { + Type: schema.TypeString, + Computed: true, + }, + "ipv6_addresses": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "mac_address": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + "owner_id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + "private_dns_name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + "private_ip": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + "private_ips": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "requester_id": { + Type: schema.TypeString, + Computed: true, + }, + "subnet_id": { + Type: schema.TypeString, + Computed: true, + }, + "vpc_id": { + Type: schema.TypeString, + Computed: true, + }, + "tags": tagsSchemaComputed(), + }, + } +} + +func dataSourceAwsNetworkInterfaceRead(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).ec2conn + + input := &ec2.DescribeNetworkInterfacesInput{ + NetworkInterfaceIds: []*string{aws.String(d.Get("id").(string))}, + } + + resp, err := conn.DescribeNetworkInterfaces(input) + if err != nil { + return err + } + if resp == nil || len(resp.NetworkInterfaces) == 0 { + return fmt.Errorf("no matching network interface found") + } + if len(resp.NetworkInterfaces) > 1 { + return fmt.Errorf("multiple network interfaces matched %s", d.Id()) + } + + eni := resp.NetworkInterfaces[0] + + d.SetId(*eni.NetworkInterfaceId) + if eni.Association != nil { + d.Set("association", flattenEc2NetworkInterfaceAssociation(eni.Association)) + } + if eni.Attachment != nil { + attachment := []interface{}{flattenAttachment(eni.Attachment)} + d.Set("attachment", attachment) + } + d.Set("availability_zone", eni.AvailabilityZone) + d.Set("description", eni.Description) + d.Set("security_groups", flattenGroupIdentifiers(eni.Groups)) + d.Set("interface_type", eni.InterfaceType) + d.Set("ipv6_addresses", flattenEc2NetworkInterfaceIpv6Address(eni.Ipv6Addresses)) + d.Set("mac_address", eni.MacAddress) + d.Set("owner_id", eni.OwnerId) + d.Set("private_dns_name", eni.PrivateDnsName) + d.Set("private_id", eni.PrivateIpAddress) + d.Set("private_ips", flattenNetworkInterfacesPrivateIPAddresses(eni.PrivateIpAddresses)) + d.Set("requester_id", eni.RequesterId) + d.Set("subnet_id", eni.SubnetId) + d.Set("vpc_id", eni.VpcId) + d.Set("tags", tagsToMap(eni.TagSet)) + return nil +} diff --git a/aws/data_source_aws_network_interface_test.go b/aws/data_source_aws_network_interface_test.go new file mode 100644 index 000000000000..f598b621059f --- /dev/null +++ b/aws/data_source_aws_network_interface_test.go @@ -0,0 +1,57 @@ +package aws + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform/helper/acctest" + "github.com/hashicorp/terraform/helper/resource" +) + +func TestAccDataSourceAwsNetworkInterface_basic(t *testing.T) { + rName := acctest.RandString(5) + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccDataSourceAwsNetworkInterface_basic(rName), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("data.aws_network_interface.test", "private_ips.#", "1"), + resource.TestCheckResourceAttr("data.aws_network_interface.test", "security_groups.#", "1"), + ), + }, + }, + }) +} + +func testAccDataSourceAwsNetworkInterface_basic(rName string) string { + return fmt.Sprintf(` +data "aws_availability_zones" "available" {} + +resource "aws_vpc" "test" { + cidr_block = "10.0.0.0/16" +} + +resource "aws_subnet" "test" { + cidr_block = "10.0.0.0/24" + availability_zone = "${data.aws_availability_zones.available.names[0]}" + vpc_id = "${aws_vpc.test.id}" +} + +resource "aws_security_group" "test" { + name = "tf-sg-%s" + vpc_id = "${aws_vpc.test.id}" +} + +resource "aws_network_interface" "test" { + subnet_id = "${aws_subnet.test.id}" + private_ips = ["10.0.0.50"] + security_groups = ["${aws_security_group.test.id}"] +} + +data "aws_network_interface" "test" { + id = "${aws_network_interface.test.id}" +} + `, rName) +} diff --git a/aws/provider.go b/aws/provider.go index 2f75284e220b..a3804550da81 100644 --- a/aws/provider.go +++ b/aws/provider.go @@ -205,6 +205,7 @@ func Provider() terraform.ResourceProvider { "aws_kms_ciphertext": dataSourceAwsKmsCiphertext(), "aws_kms_secret": dataSourceAwsKmsSecret(), "aws_nat_gateway": dataSourceAwsNatGateway(), + "aws_network_interface": dataSourceAwsNetworkInterface(), "aws_partition": dataSourceAwsPartition(), "aws_prefix_list": dataSourceAwsPrefixList(), "aws_rds_cluster": dataSourceAwsRdsCluster(), diff --git a/aws/structure.go b/aws/structure.go index 2aee465c24ae..21244ef38e9a 100644 --- a/aws/structure.go +++ b/aws/structure.go @@ -797,6 +797,34 @@ func flattenAttachment(a *ec2.NetworkInterfaceAttachment) map[string]interface{} return att } +func flattenEc2NetworkInterfaceAssociation(a *ec2.NetworkInterfaceAssociation) []interface{} { + att := make(map[string]interface{}) + if a.AllocationId != nil { + att["allocation_id"] = *a.AllocationId + } + if a.AssociationId != nil { + att["association_id"] = *a.AssociationId + } + if a.IpOwnerId != nil { + att["ip_owner_id"] = *a.IpOwnerId + } + if a.PublicDnsName != nil { + att["public_dns_name"] = *a.PublicDnsName + } + if a.PublicIp != nil { + att["public_ip"] = *a.PublicIp + } + return []interface{}{att} +} + +func flattenEc2NetworkInterfaceIpv6Address(niia []*ec2.NetworkInterfaceIpv6Address) []string { + ips := make([]string, 0, len(niia)) + for _, v := range niia { + ips = append(ips, *v.Ipv6Address) + } + return ips +} + func flattenElastiCacheSecurityGroupNames(securityGroups []*elasticache.CacheSecurityGroupMembership) []string { result := make([]string, 0, len(securityGroups)) for _, sg := range securityGroups { diff --git a/website/aws.erb b/website/aws.erb index 7c085d7b6467..70a0dc83a5aa 100644 --- a/website/aws.erb +++ b/website/aws.erb @@ -157,6 +157,10 @@ > aws_nat_gateway + + > + aws_network_interface + > aws_lb diff --git a/website/docs/d/network_interface.html.markdown b/website/docs/d/network_interface.html.markdown new file mode 100644 index 000000000000..14def5dca255 --- /dev/null +++ b/website/docs/d/network_interface.html.markdown @@ -0,0 +1,47 @@ +--- +layout: "aws" +page_title: "AWS: aws_network_interface" +sidebar_current: "docs-aws-datasource-network-interface" +description: |- + Get information on a Network Interface resource. +--- + +# aws_network_interface + +Use this data source to get information about a Network Interface. + +## Example Usage + +```hcl +data "aws_network_interface" "bar" { + id = "eni-01234567" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `id` – (Required) The identifier for the network interface. + +## Attributes Reference + +See the [Network Interface](/docs/providers/aws/r/network_interface.html) for details on the returned attributes. + +Additionally, the following attributes are exported: + +* `association` - The association information for an Elastic IP address (IPv4) associated with the network interface. See supported fields below. +* `availability_zone` - The Availability Zone. +* `interface_type` - The type of interface. +* `ipv6_addresses` - List of IPv6 addresses to assign to the ENI. +* `mac_address` - The MAC address. +* `owner_id` - The AWS account ID of the owner of the network interface. +* `requester_id` - The ID of the entity that launched the instance on your behalf. + +### `association` + +* `allocation_id` - The allocation ID. +* `association_id` - The association ID. +* `ip_owner_id` - The ID of the Elastic IP address owner. +* `public_dns_name` - The public DNS name. +* `public_ip` - The address of the Elastic IP address bound to the network interface.