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 @@