From 09696a51c3f48c182c7516344b95046a29022e5c Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 19 Apr 2019 18:07:29 -0400 Subject: [PATCH 1/7] aws_vpc_endpoint_service: Add 'manages_vpc_endpoints' attribute. --- aws/data_source_aws_vpc_endpoint_service.go | 55 ++++---- ...ta_source_aws_vpc_endpoint_service_test.go | 123 +++++++----------- aws/resource_aws_vpc_endpoint_service.go | 91 +++++++------ aws/resource_aws_vpc_endpoint_service_test.go | 114 +++++++--------- .../docs/d/vpc_endpoint_service.html.markdown | 9 +- .../docs/r/vpc_endpoint_service.html.markdown | 9 +- 6 files changed, 195 insertions(+), 206 deletions(-) diff --git a/aws/data_source_aws_vpc_endpoint_service.go b/aws/data_source_aws_vpc_endpoint_service.go index b4eaa5e7dd93..fcbcef7b6588 100644 --- a/aws/data_source_aws_vpc_endpoint_service.go +++ b/aws/data_source_aws_vpc_endpoint_service.go @@ -27,37 +27,41 @@ func dataSourceAwsVpcEndpointService() *schema.Resource { Computed: true, ConflictsWith: []string{"service"}, }, - "service_type": { - Type: schema.TypeString, + "acceptance_required": { + Type: schema.TypeBool, Computed: true, }, - "owner": { - Type: schema.TypeString, + "availability_zones": { + Type: schema.TypeSet, + Elem: &schema.Schema{Type: schema.TypeString}, Computed: true, + Set: schema.HashString, }, - "vpc_endpoint_policy_supported": { - Type: schema.TypeBool, + "base_endpoint_dns_names": { + Type: schema.TypeSet, + Elem: &schema.Schema{Type: schema.TypeString}, Computed: true, + Set: schema.HashString, }, - "acceptance_required": { + "manages_vpc_endpoints": { Type: schema.TypeBool, Computed: true, }, - "availability_zones": { - Type: schema.TypeSet, - Elem: &schema.Schema{Type: schema.TypeString}, + "owner": { + Type: schema.TypeString, Computed: true, - Set: schema.HashString, }, "private_dns_name": { Type: schema.TypeString, Computed: true, }, - "base_endpoint_dns_names": { - Type: schema.TypeSet, - Elem: &schema.Schema{Type: schema.TypeString}, + "service_type": { + Type: schema.TypeString, + Computed: true, + }, + "vpc_endpoint_policy_supported": { + Type: schema.TypeBool, Computed: true, - Set: schema.HashString, }, }, } @@ -80,10 +84,10 @@ func dataSourceAwsVpcEndpointServiceRead(d *schema.ResourceData, meta interface{ ServiceNames: aws.StringSlice([]string{serviceName}), } - log.Printf("[DEBUG] Reading VPC Endpoint Services: %s", req) + log.Printf("[DEBUG] Reading VPC Endpoint Service: %s", req) resp, err := conn.DescribeVpcEndpointServices(req) if err != nil { - return fmt.Errorf("Error fetching VPC Endpoint Services: %s", err) + return fmt.Errorf("error reading VPC Endpoint Service (%s): %s", serviceName, err) } if resp == nil || (len(resp.ServiceNames) == 0 && len(resp.ServiceDetails) == 0) { @@ -114,13 +118,20 @@ func dataSourceAwsVpcEndpointServiceRead(d *schema.ResourceData, meta interface{ serviceName = aws.StringValue(sd.ServiceName) d.SetId(strconv.Itoa(hashcode.String(serviceName))) d.Set("service_name", serviceName) - d.Set("service_type", sd.ServiceType[0].ServiceType) - d.Set("owner", sd.Owner) - d.Set("vpc_endpoint_policy_supported", sd.VpcEndpointPolicySupported) d.Set("acceptance_required", sd.AcceptanceRequired) - d.Set("availability_zones", flattenStringList(sd.AvailabilityZones)) + err = d.Set("availability_zones", flattenStringSet(sd.AvailabilityZones)) + if err != nil { + return fmt.Errorf("error setting availability_zones: %s", err) + } + err = d.Set("base_endpoint_dns_names", flattenStringSet(sd.BaseEndpointDnsNames)) + if err != nil { + return fmt.Errorf("error setting base_endpoint_dns_names: %s", err) + } + d.Set("manages_vpc_endpoints", sd.ManagesVpcEndpoints) + d.Set("owner", sd.Owner) d.Set("private_dns_name", sd.PrivateDnsName) - d.Set("base_endpoint_dns_names", flattenStringList(sd.BaseEndpointDnsNames)) + d.Set("service_type", sd.ServiceType[0].ServiceType) + d.Set("vpc_endpoint_policy_supported", sd.VpcEndpointPolicySupported) return nil } diff --git a/aws/data_source_aws_vpc_endpoint_service_test.go b/aws/data_source_aws_vpc_endpoint_service_test.go index 1b99c8129438..22b42ae7d811 100644 --- a/aws/data_source_aws_vpc_endpoint_service_test.go +++ b/aws/data_source_aws_vpc_endpoint_service_test.go @@ -2,7 +2,6 @@ package aws import ( "fmt" - "regexp" "testing" "github.com/hashicorp/terraform/helper/acctest" @@ -10,6 +9,8 @@ import ( ) func TestAccDataSourceAwsVpcEndpointService_gateway(t *testing.T) { + datasourceName := "data.aws_vpc_endpoint_service.s3" + resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, @@ -17,32 +18,20 @@ func TestAccDataSourceAwsVpcEndpointService_gateway(t *testing.T) { { Config: testAccDataSourceAwsVpcEndpointServiceGatewayConfig, Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr( - "data.aws_vpc_endpoint_service.s3", "service_name", "com.amazonaws.us-west-2.s3"), - resource.TestCheckResourceAttr( - "data.aws_vpc_endpoint_service.s3", "service_type", "Gateway"), - resource.TestCheckResourceAttr( - "data.aws_vpc_endpoint_service.s3", "owner", "amazon"), - resource.TestCheckResourceAttr( - "data.aws_vpc_endpoint_service.s3", "vpc_endpoint_policy_supported", "true"), - resource.TestCheckResourceAttr( - "data.aws_vpc_endpoint_service.s3", "acceptance_required", "false"), - resource.TestCheckResourceAttr( - "data.aws_vpc_endpoint_service.s3", "availability_zones.#", "4"), - resource.TestCheckResourceAttr( - "data.aws_vpc_endpoint_service.s3", "availability_zones.2487133097", "us-west-2a"), - resource.TestCheckResourceAttr( - "data.aws_vpc_endpoint_service.s3", "availability_zones.221770259", "us-west-2b"), - resource.TestCheckResourceAttr( - "data.aws_vpc_endpoint_service.s3", "availability_zones.2050015877", "us-west-2c"), - resource.TestCheckResourceAttr( - "data.aws_vpc_endpoint_service.s3", "availability_zones.3830732582", "us-west-2d"), - resource.TestCheckResourceAttr( - "data.aws_vpc_endpoint_service.s3", "private_dns_name", ""), - resource.TestCheckResourceAttr( - "data.aws_vpc_endpoint_service.s3", "base_endpoint_dns_names.#", "1"), - resource.TestCheckResourceAttr( - "data.aws_vpc_endpoint_service.s3", "base_endpoint_dns_names.3003388505", "s3.us-west-2.amazonaws.com"), + resource.TestCheckResourceAttr(datasourceName, "service_name", "com.amazonaws.us-west-2.s3"), + resource.TestCheckResourceAttr(datasourceName, "acceptance_required", "false"), + resource.TestCheckResourceAttr(datasourceName, "availability_zones.#", "4"), + resource.TestCheckResourceAttr(datasourceName, "availability_zones.2487133097", "us-west-2a"), + resource.TestCheckResourceAttr(datasourceName, "availability_zones.221770259", "us-west-2b"), + resource.TestCheckResourceAttr(datasourceName, "availability_zones.2050015877", "us-west-2c"), + resource.TestCheckResourceAttr(datasourceName, "availability_zones.3830732582", "us-west-2d"), + resource.TestCheckResourceAttr(datasourceName, "base_endpoint_dns_names.#", "1"), + resource.TestCheckResourceAttr(datasourceName, "base_endpoint_dns_names.3003388505", "s3.us-west-2.amazonaws.com"), + resource.TestCheckResourceAttr(datasourceName, "manages_vpc_endpoints", "false"), + resource.TestCheckResourceAttr(datasourceName, "owner", "amazon"), + resource.TestCheckResourceAttr(datasourceName, "private_dns_name", ""), + resource.TestCheckResourceAttr(datasourceName, "service_type", "Gateway"), + resource.TestCheckResourceAttr(datasourceName, "vpc_endpoint_policy_supported", "true"), ), }, }, @@ -50,6 +39,8 @@ func TestAccDataSourceAwsVpcEndpointService_gateway(t *testing.T) { } func TestAccDataSourceAwsVpcEndpointService_interface(t *testing.T) { + datasourceName := "data.aws_vpc_endpoint_service.ec2" + resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, @@ -57,30 +48,19 @@ func TestAccDataSourceAwsVpcEndpointService_interface(t *testing.T) { { Config: testAccDataSourceAwsVpcEndpointServiceInterfaceConfig, Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr( - "data.aws_vpc_endpoint_service.ec2", "service_name", "com.amazonaws.us-west-2.ec2"), - resource.TestCheckResourceAttr( - "data.aws_vpc_endpoint_service.ec2", "service_type", "Interface"), - resource.TestCheckResourceAttr( - "data.aws_vpc_endpoint_service.ec2", "owner", "amazon"), - resource.TestCheckResourceAttr( - "data.aws_vpc_endpoint_service.ec2", "vpc_endpoint_policy_supported", "false"), - resource.TestCheckResourceAttr( - "data.aws_vpc_endpoint_service.ec2", "acceptance_required", "false"), - resource.TestCheckResourceAttr( - "data.aws_vpc_endpoint_service.ec2", "availability_zones.#", "3"), - resource.TestCheckResourceAttr( - "data.aws_vpc_endpoint_service.ec2", "availability_zones.2487133097", "us-west-2a"), - resource.TestCheckResourceAttr( - "data.aws_vpc_endpoint_service.ec2", "availability_zones.221770259", "us-west-2b"), - resource.TestCheckResourceAttr( - "data.aws_vpc_endpoint_service.ec2", "availability_zones.2050015877", "us-west-2c"), - resource.TestCheckResourceAttr( - "data.aws_vpc_endpoint_service.ec2", "private_dns_name", "ec2.us-west-2.amazonaws.com"), - resource.TestCheckResourceAttr( - "data.aws_vpc_endpoint_service.ec2", "base_endpoint_dns_names.#", "1"), - resource.TestCheckResourceAttr( - "data.aws_vpc_endpoint_service.ec2", "base_endpoint_dns_names.1880016359", "ec2.us-west-2.vpce.amazonaws.com"), + resource.TestCheckResourceAttr(datasourceName, "service_name", "com.amazonaws.us-west-2.ec2"), + resource.TestCheckResourceAttr(datasourceName, "acceptance_required", "false"), + resource.TestCheckResourceAttr(datasourceName, "availability_zones.#", "3"), + resource.TestCheckResourceAttr(datasourceName, "availability_zones.2487133097", "us-west-2a"), + resource.TestCheckResourceAttr(datasourceName, "availability_zones.221770259", "us-west-2b"), + resource.TestCheckResourceAttr(datasourceName, "availability_zones.2050015877", "us-west-2c"), + resource.TestCheckResourceAttr(datasourceName, "base_endpoint_dns_names.#", "1"), + resource.TestCheckResourceAttr(datasourceName, "base_endpoint_dns_names.1880016359", "ec2.us-west-2.vpce.amazonaws.com"), + resource.TestCheckResourceAttr(datasourceName, "manages_vpc_endpoints", "false"), + resource.TestCheckResourceAttr(datasourceName, "owner", "amazon"), + resource.TestCheckResourceAttr(datasourceName, "private_dns_name", "ec2.us-west-2.amazonaws.com"), + resource.TestCheckResourceAttr(datasourceName, "service_type", "Interface"), + resource.TestCheckResourceAttr(datasourceName, "vpc_endpoint_policy_supported", "false"), ), }, }, @@ -88,29 +68,24 @@ func TestAccDataSourceAwsVpcEndpointService_interface(t *testing.T) { } func TestAccDataSourceAwsVpcEndpointService_custom(t *testing.T) { - lbName := fmt.Sprintf("testaccawsnlb-basic-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) + datasourceName := "data.aws_vpc_endpoint_service.foo" + rName := fmt.Sprintf("tf-testacc-vpcesvc-%s", acctest.RandStringFromCharSet(13, acctest.CharSetAlphaNum)) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, Steps: []resource.TestStep{ { - Config: testAccDataSourceAwsVpcEndpointServiceCustomConfig(lbName), + Config: testAccDataSourceAwsVpcEndpointServiceCustomConfig(rName), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr( - "data.aws_vpc_endpoint_service.foo", "service_type", "Interface"), - resource.TestMatchResourceAttr( // AWS account ID - "data.aws_vpc_endpoint_service.foo", "owner", regexp.MustCompile("^[0-9]{12}$")), - resource.TestCheckResourceAttr( - "data.aws_vpc_endpoint_service.foo", "vpc_endpoint_policy_supported", "false"), - resource.TestCheckResourceAttr( - "data.aws_vpc_endpoint_service.foo", "acceptance_required", "true"), - resource.TestCheckResourceAttr( - "data.aws_vpc_endpoint_service.foo", "availability_zones.#", "2"), - resource.TestCheckResourceAttr( - "data.aws_vpc_endpoint_service.foo", "availability_zones.2487133097", "us-west-2a"), - resource.TestCheckResourceAttr( - "data.aws_vpc_endpoint_service.foo", "availability_zones.221770259", "us-west-2b"), + resource.TestCheckResourceAttr(datasourceName, "acceptance_required", "true"), + resource.TestCheckResourceAttr(datasourceName, "availability_zones.#", "2"), + resource.TestCheckResourceAttr(datasourceName, "availability_zones.2487133097", "us-west-2a"), + resource.TestCheckResourceAttr(datasourceName, "availability_zones.221770259", "us-west-2b"), + resource.TestCheckResourceAttr(datasourceName, "manages_vpc_endpoints", "false"), + testAccCheckResourceAttrAccountID(datasourceName, "owner"), + resource.TestCheckResourceAttr(datasourceName, "service_type", "Interface"), + resource.TestCheckResourceAttr(datasourceName, "vpc_endpoint_policy_supported", "false"), ), }, }, @@ -137,19 +112,19 @@ data "aws_vpc_endpoint_service" "ec2" { } ` -func testAccDataSourceAwsVpcEndpointServiceCustomConfig(lbName string) string { +func testAccDataSourceAwsVpcEndpointServiceCustomConfig(rName string) string { return fmt.Sprintf( ` resource "aws_vpc" "nlb_test" { cidr_block = "10.0.0.0/16" tags = { - Name = "terraform-testacc-vpc-endpoint-service-custom" + Name = %[1]q } } resource "aws_lb" "nlb_test_1" { - name = "%s" + name = %[1]q subnets = [ "${aws_subnet.nlb_test_1.id}", @@ -162,7 +137,7 @@ resource "aws_lb" "nlb_test_1" { enable_deletion_protection = false tags = { - Name = "testAccVpcEndpointServiceBasicConfig_nlb1" + Name = %[1]q } } @@ -172,7 +147,7 @@ resource "aws_subnet" "nlb_test_1" { availability_zone = "us-west-2a" tags = { - Name = "tf-acc-vpc-endpoint-service-custom" + Name = %[1]q } } @@ -182,7 +157,7 @@ resource "aws_subnet" "nlb_test_2" { availability_zone = "us-west-2b" tags = { - Name = "tf-acc-vpc-endpoint-service-custom" + Name = %[1]q } } @@ -197,5 +172,5 @@ resource "aws_vpc_endpoint_service" "foo" { data "aws_vpc_endpoint_service" "foo" { service_name = "${aws_vpc_endpoint_service.foo.service_name}" } -`, lbName) +`, rName) } diff --git a/aws/resource_aws_vpc_endpoint_service.go b/aws/resource_aws_vpc_endpoint_service.go index 0fbaa8320529..257fb2bb8d1a 100644 --- a/aws/resource_aws_vpc_endpoint_service.go +++ b/aws/resource_aws_vpc_endpoint_service.go @@ -41,33 +41,37 @@ func resourceAwsVpcEndpointService() *schema.Resource { Elem: &schema.Schema{Type: schema.TypeString}, Set: schema.HashString, }, - "state": { - Type: schema.TypeString, + "availability_zones": { + Type: schema.TypeSet, + Elem: &schema.Schema{Type: schema.TypeString}, Computed: true, + Set: schema.HashString, }, - "service_name": { - Type: schema.TypeString, + "base_endpoint_dns_names": { + Type: schema.TypeSet, + Elem: &schema.Schema{Type: schema.TypeString}, Computed: true, + Set: schema.HashString, }, - "service_type": { + "manages_vpc_endpoints": { + Type: schema.TypeBool, + Computed: true, + }, + "private_dns_name": { Type: schema.TypeString, Computed: true, }, - "availability_zones": { - Type: schema.TypeSet, - Elem: &schema.Schema{Type: schema.TypeString}, + "service_name": { + Type: schema.TypeString, Computed: true, - Set: schema.HashString, }, - "private_dns_name": { + "service_type": { Type: schema.TypeString, Computed: true, }, - "base_endpoint_dns_names": { - Type: schema.TypeSet, - Elem: &schema.Schema{Type: schema.TypeString}, + "state": { + Type: schema.TypeString, Computed: true, - Set: schema.HashString, }, }, } @@ -99,9 +103,9 @@ func resourceAwsVpcEndpointServiceCreate(d *schema.ResourceData, meta interface{ func resourceAwsVpcEndpointServiceRead(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).ec2conn - svcCfg, state, err := vpcEndpointServiceStateRefresh(conn, d.Id())() + svcCfgRaw, state, err := vpcEndpointServiceStateRefresh(conn, d.Id())() if err != nil && state != ec2.ServiceStateFailed { - return fmt.Errorf("Error reading VPC Endpoint Service: %s", err.Error()) + return fmt.Errorf("error reading VPC Endpoint Service (%s): %s", d.Id(), err.Error()) } terminalStates := map[string]bool{ @@ -115,7 +119,39 @@ func resourceAwsVpcEndpointServiceRead(d *schema.ResourceData, meta interface{}) return nil } - return vpcEndpointServiceAttributes(d, svcCfg.(*ec2.ServiceConfiguration), conn) + svcCfg := svcCfgRaw.(*ec2.ServiceConfiguration) + d.Set("acceptance_required", svcCfg.AcceptanceRequired) + err = d.Set("network_load_balancer_arns", flattenStringSet(svcCfg.NetworkLoadBalancerArns)) + if err != nil { + return fmt.Errorf("error setting network_load_balancer_arns: %s", err) + } + err = d.Set("availability_zones", flattenStringSet(svcCfg.AvailabilityZones)) + if err != nil { + return fmt.Errorf("error setting availability_zones: %s", err) + } + err = d.Set("base_endpoint_dns_names", flattenStringSet(svcCfg.BaseEndpointDnsNames)) + if err != nil { + return fmt.Errorf("error setting base_endpoint_dns_names: %s", err) + } + d.Set("manages_vpc_endpoints", svcCfg.ManagesVpcEndpoints) + d.Set("private_dns_name", svcCfg.PrivateDnsName) + d.Set("service_name", svcCfg.ServiceName) + d.Set("service_type", svcCfg.ServiceType[0].ServiceType) + d.Set("state", svcCfg.ServiceState) + + resp, err := conn.DescribeVpcEndpointServicePermissions(&ec2.DescribeVpcEndpointServicePermissionsInput{ + ServiceId: aws.String(d.Id()), + }) + if err != nil { + return fmt.Errorf("error reading VPC Endpoint Service permissions (%s): %s", d.Id(), err.Error()) + } + + err = d.Set("allowed_principals", flattenVpcEndpointServiceAllowedPrincipals(resp.AllowedPrincipals)) + if err != nil { + return fmt.Errorf("error setting allowed_principals: %s", err) + } + + return nil } func resourceAwsVpcEndpointServiceUpdate(d *schema.ResourceData, meta interface{}) error { @@ -242,27 +278,6 @@ func waitForVpcEndpointServiceDeletion(conn *ec2.EC2, serviceID string) error { return err } -func vpcEndpointServiceAttributes(d *schema.ResourceData, svcCfg *ec2.ServiceConfiguration, conn *ec2.EC2) error { - d.Set("acceptance_required", svcCfg.AcceptanceRequired) - d.Set("network_load_balancer_arns", flattenStringList(svcCfg.NetworkLoadBalancerArns)) - d.Set("state", svcCfg.ServiceState) - d.Set("service_name", svcCfg.ServiceName) - d.Set("service_type", svcCfg.ServiceType[0].ServiceType) - d.Set("availability_zones", flattenStringList(svcCfg.AvailabilityZones)) - d.Set("private_dns_name", svcCfg.PrivateDnsName) - d.Set("base_endpoint_dns_names", flattenStringList(svcCfg.BaseEndpointDnsNames)) - - resp, err := conn.DescribeVpcEndpointServicePermissions(&ec2.DescribeVpcEndpointServicePermissionsInput{ - ServiceId: aws.String(d.Id()), - }) - if err != nil { - return err - } - d.Set("allowed_principals", flattenVpcEndpointServiceAllowedPrincipals(resp.AllowedPrincipals)) - - return nil -} - func setVpcEndpointServiceUpdateLists(d *schema.ResourceData, key string, a, r *[]*string) bool { if !d.HasChange(key) { return false diff --git a/aws/resource_aws_vpc_endpoint_service_test.go b/aws/resource_aws_vpc_endpoint_service_test.go index 595adbba1d4e..d1ccfb06f0fc 100644 --- a/aws/resource_aws_vpc_endpoint_service_test.go +++ b/aws/resource_aws_vpc_endpoint_service_test.go @@ -80,32 +80,11 @@ func testSweepEc2VpcEndpointServices(region string) error { return nil } -func TestAccAWSVpcEndpointService_importBasic(t *testing.T) { - lbName := fmt.Sprintf("testaccawsnlb-basic-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) - resourceName := "aws_vpc_endpoint_service.foo" - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckVpcEndpointServiceDestroy, - Steps: []resource.TestStep{ - { - Config: testAccVpcEndpointServiceBasicConfig(lbName), - }, - - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - }, - }, - }) -} - func TestAccAWSVpcEndpointService_basic(t *testing.T) { var svcCfg ec2.ServiceConfiguration - lb1Name := fmt.Sprintf("testaccawsnlb-basic-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) - lb2Name := fmt.Sprintf("testaccawsnlb-basic-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) + resourceName := "aws_vpc_endpoint_service.foo" + rName1 := fmt.Sprintf("tf-testacc-vpcesvc-%s", acctest.RandStringFromCharSet(13, acctest.CharSetAlphaNum)) + rName2 := fmt.Sprintf("tf-testacc-vpcesvc-%s", acctest.RandStringFromCharSet(13, acctest.CharSetAlphaNum)) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -114,21 +93,27 @@ func TestAccAWSVpcEndpointService_basic(t *testing.T) { CheckDestroy: testAccCheckVpcEndpointServiceDestroy, Steps: []resource.TestStep{ { - Config: testAccVpcEndpointServiceBasicConfig(lb1Name), + Config: testAccVpcEndpointServiceBasicConfig(rName1), Check: resource.ComposeTestCheckFunc( - testAccCheckVpcEndpointServiceExists("aws_vpc_endpoint_service.foo", &svcCfg), - resource.TestCheckResourceAttr("aws_vpc_endpoint_service.foo", "acceptance_required", "false"), - resource.TestCheckResourceAttr("aws_vpc_endpoint_service.foo", "network_load_balancer_arns.#", "1"), - resource.TestCheckResourceAttr("aws_vpc_endpoint_service.foo", "allowed_principals.#", "1"), + testAccCheckVpcEndpointServiceExists(resourceName, &svcCfg), + resource.TestCheckResourceAttr(resourceName, "acceptance_required", "false"), + resource.TestCheckResourceAttr(resourceName, "network_load_balancer_arns.#", "1"), + resource.TestCheckResourceAttr(resourceName, "allowed_principals.#", "1"), + resource.TestCheckResourceAttr(resourceName, "manages_vpc_endpoints", "false"), ), }, { - Config: testAccVpcEndpointServiceModifiedConfig(lb1Name, lb2Name), + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccVpcEndpointServiceModifiedConfig(rName1, rName2), Check: resource.ComposeTestCheckFunc( testAccCheckVpcEndpointServiceExists("aws_vpc_endpoint_service.foo", &svcCfg), - resource.TestCheckResourceAttr("aws_vpc_endpoint_service.foo", "acceptance_required", "true"), - resource.TestCheckResourceAttr("aws_vpc_endpoint_service.foo", "network_load_balancer_arns.#", "2"), - resource.TestCheckResourceAttr("aws_vpc_endpoint_service.foo", "allowed_principals.#", "0"), + resource.TestCheckResourceAttr(resourceName, "acceptance_required", "true"), + resource.TestCheckResourceAttr(resourceName, "network_load_balancer_arns.#", "2"), + resource.TestCheckResourceAttr(resourceName, "allowed_principals.#", "0"), ), }, }, @@ -137,7 +122,8 @@ func TestAccAWSVpcEndpointService_basic(t *testing.T) { func TestAccAWSVpcEndpointService_removed(t *testing.T) { var svcCfg ec2.ServiceConfiguration - lbName := fmt.Sprintf("testaccawsnlb-basic-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) + resourceName := "aws_vpc_endpoint_service.foo" + rName := fmt.Sprintf("tf-testacc-vpcesvc-%s", acctest.RandStringFromCharSet(13, acctest.CharSetAlphaNum)) testDestroy := func(*terraform.State) error { conn := testAccProvider.Meta().(*AWSClient).ec2conn @@ -155,9 +141,9 @@ func TestAccAWSVpcEndpointService_removed(t *testing.T) { CheckDestroy: testAccCheckVpcEndpointServiceDestroy, Steps: []resource.TestStep{ { - Config: testAccVpcEndpointServiceBasicConfig(lbName), + Config: testAccVpcEndpointServiceBasicConfig(rName), Check: resource.ComposeTestCheckFunc( - testAccCheckVpcEndpointServiceExists("aws_vpc_endpoint_service.foo", &svcCfg), + testAccCheckVpcEndpointServiceExists(resourceName, &svcCfg), testDestroy, ), ExpectNonEmptyPlan: true, @@ -223,19 +209,19 @@ func testAccCheckVpcEndpointServiceExists(n string, svcCfg *ec2.ServiceConfigura } } -func testAccVpcEndpointServiceBasicConfig(lb1Name string) string { +func testAccVpcEndpointServiceBasicConfig(rName string) string { return fmt.Sprintf( ` resource "aws_vpc" "nlb_test" { cidr_block = "10.0.0.0/16" tags = { - Name = "terraform-testacc-vpc-endpoint-service" + Name = %[1]q } } resource "aws_lb" "nlb_test_1" { - name = "%s" + name = %[1]q subnets = [ "${aws_subnet.nlb_test_1.id}", @@ -248,7 +234,7 @@ resource "aws_lb" "nlb_test_1" { enable_deletion_protection = false tags = { - Name = "testAccVpcEndpointServiceBasicConfig_nlb1" + Name = %[1]q } } @@ -258,7 +244,7 @@ resource "aws_subnet" "nlb_test_1" { availability_zone = "us-west-2a" tags = { - Name = "tf-acc-vpc-endpoint-service-1" + Name = %[1]q } } @@ -268,7 +254,7 @@ resource "aws_subnet" "nlb_test_2" { availability_zone = "us-west-2b" tags = { - Name = "tf-acc-vpc-endpoint-service-2" + Name = %[1]q } } @@ -285,22 +271,22 @@ resource "aws_vpc_endpoint_service" "foo" { "${data.aws_caller_identity.current.arn}" ] } -`, lb1Name) +`, rName) } -func testAccVpcEndpointServiceModifiedConfig(lb1Name, lb2Name string) string { +func testAccVpcEndpointServiceModifiedConfig(rName1, rName2 string) string { return fmt.Sprintf( ` resource "aws_vpc" "nlb_test" { cidr_block = "10.0.0.0/16" tags = { - Name = "terraform-testacc-vpc-endpoint-service" + Name = %[1]q } } resource "aws_lb" "nlb_test_1" { - name = "%s" + name = %[1]q subnets = [ "${aws_subnet.nlb_test_1.id}", @@ -313,27 +299,27 @@ resource "aws_lb" "nlb_test_1" { enable_deletion_protection = false tags = { - Name = "testAccVpcEndpointServiceBasicConfig_nlb1" + Name = %[1]q } } resource "aws_lb" "nlb_test_2" { - name = "%s" + name = %[2]q - subnets = [ - "${aws_subnet.nlb_test_1.id}", - "${aws_subnet.nlb_test_2.id}", - ] + subnets = [ + "${aws_subnet.nlb_test_1.id}", + "${aws_subnet.nlb_test_2.id}", + ] - load_balancer_type = "network" - internal = true - idle_timeout = 60 - enable_deletion_protection = false + load_balancer_type = "network" + internal = true + idle_timeout = 60 + enable_deletion_protection = false - tags = { - Name = "testAccVpcEndpointServiceBasicConfig_nlb2" - } + tags = { + Name = %[2]q } +} resource "aws_subnet" "nlb_test_1" { vpc_id = "${aws_vpc.nlb_test.id}" @@ -341,7 +327,7 @@ resource "aws_subnet" "nlb_test_1" { availability_zone = "us-west-2a" tags = { - Name = "tf-acc-vpc-endpoint-service-1" + Name = %[1]q } } @@ -351,7 +337,7 @@ resource "aws_subnet" "nlb_test_2" { availability_zone = "us-west-2b" tags = { - Name = "tf-acc-vpc-endpoint-service-2" + Name = %[1]q } } @@ -361,11 +347,11 @@ resource "aws_vpc_endpoint_service" "foo" { acceptance_required = true network_load_balancer_arns = [ - "${aws_lb.nlb_test_1.id}", - "${aws_lb.nlb_test_2.id}", + "${aws_lb.nlb_test_1.id}", + "${aws_lb.nlb_test_2.id}", ] allowed_principals = [] } -`, lb1Name, lb2Name) +`, rName1, rName2) } diff --git a/website/docs/d/vpc_endpoint_service.html.markdown b/website/docs/d/vpc_endpoint_service.html.markdown index 96ec3c5ffc48..743e92fd9d39 100644 --- a/website/docs/d/vpc_endpoint_service.html.markdown +++ b/website/docs/d/vpc_endpoint_service.html.markdown @@ -55,10 +55,11 @@ The given filters must match exactly one VPC endpoint service whose data will be In addition to all arguments above, the following attributes are exported: -* `service_type` - The service type, `Gateway` or `Interface`. -* `owner` - The AWS account ID of the service owner or `amazon`. -* `vpc_endpoint_policy_supported` - Whether or not the service supports endpoint policies - `true` or `false`. * `acceptance_required` - Whether or not VPC endpoint connection requests to the service must be accepted by the service owner - `true` or `false`. * `availability_zones` - The Availability Zones in which the service is available. -* `private_dns_name` - The private DNS name for the service. * `base_endpoint_dns_names` - The DNS names for the service. +* `manages_vpc_endpoints` - Whether or not the service manages its VPC endpoints - `true` or `false`. +* `owner` - The AWS account ID of the service owner or `amazon`. +* `private_dns_name` - The private DNS name for the service. +* `service_type` - The service type, `Gateway` or `Interface`. +* `vpc_endpoint_policy_supported` - Whether or not the service supports endpoint policies - `true` or `false`. diff --git a/website/docs/r/vpc_endpoint_service.html.markdown b/website/docs/r/vpc_endpoint_service.html.markdown index 1003399e7c8d..7a30b0a47fed 100644 --- a/website/docs/r/vpc_endpoint_service.html.markdown +++ b/website/docs/r/vpc_endpoint_service.html.markdown @@ -41,12 +41,13 @@ The following arguments are supported: In addition to all arguments above, the following attributes are exported: * `id` - The ID of the VPC endpoint service. -* `state` - The state of the VPC endpoint service. -* `service_name` - The service name. -* `service_type` - The service type, `Gateway` or `Interface`. * `availability_zones` - The Availability Zones in which the service is available. -* `private_dns_name` - The private DNS name for the service. * `base_endpoint_dns_names` - The DNS names for the service. +* `manages_vpc_endpoints` - Whether or not the service manages its VPC endpoints - `true` or `false`. +* `private_dns_name` - The private DNS name for the service. +* `service_name` - The service name. +* `service_type` - The service type, `Gateway` or `Interface`. +* `state` - The state of the VPC endpoint service. ## Import From b3a37ac0da42f23e6ce8385698670b65b35c7a6b Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Sat, 20 Apr 2019 07:10:47 -0400 Subject: [PATCH 2/7] aws_vpc_endpoint: Add 'requester_managed' attribute. --- aws/data_source_aws_vpc_endpoint.go | 146 +++++-- aws/data_source_aws_vpc_endpoint_test.go | 98 ++--- aws/resource_aws_vpc_endpoint.go | 205 ++++----- aws/resource_aws_vpc_endpoint_test.go | 482 +++++++++++++--------- aws/structure.go | 23 ++ website/docs/d/vpc_endpoint.html.markdown | 22 +- website/docs/r/vpc_endpoint.html.markdown | 15 +- 7 files changed, 582 insertions(+), 409 deletions(-) diff --git a/aws/data_source_aws_vpc_endpoint.go b/aws/data_source_aws_vpc_endpoint.go index 2669ceb8e0e0..c8fc0acc0be5 100644 --- a/aws/data_source_aws_vpc_endpoint.go +++ b/aws/data_source_aws_vpc_endpoint.go @@ -7,6 +7,7 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/ec2" "github.com/hashicorp/terraform/helper/schema" + "github.com/hashicorp/terraform/helper/structure" ) func dataSourceAwsVpcEndpoint() *schema.Resource { @@ -19,51 +20,65 @@ func dataSourceAwsVpcEndpoint() *schema.Resource { Optional: true, Computed: true, }, - "vpc_id": { + "service_name": { Type: schema.TypeString, Optional: true, Computed: true, }, - "service_name": { + "state": { Type: schema.TypeString, Optional: true, Computed: true, }, - "state": { + "vpc_id": { Type: schema.TypeString, Optional: true, Computed: true, }, - "vpc_endpoint_type": { - Type: schema.TypeString, + "cidr_blocks": { + Type: schema.TypeList, Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, }, - "policy": { - Type: schema.TypeString, + "dns_entry": { + Type: schema.TypeList, Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "dns_name": { + Type: schema.TypeString, + Computed: true, + }, + "hosted_zone_id": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, }, - "route_table_ids": { + "network_interface_ids": { Type: schema.TypeSet, Computed: true, Elem: &schema.Schema{Type: schema.TypeString}, Set: schema.HashString, }, + "policy": { + Type: schema.TypeString, + Computed: true, + }, "prefix_list_id": { Type: schema.TypeString, Computed: true, }, - "cidr_blocks": { - Type: schema.TypeList, + "private_dns_enabled": { + Type: schema.TypeBool, Computed: true, - Elem: &schema.Schema{Type: schema.TypeString}, }, - "subnet_ids": { - Type: schema.TypeSet, + "requester_managed": { + Type: schema.TypeBool, Computed: true, - Elem: &schema.Schema{Type: schema.TypeString}, - Set: schema.HashString, }, - "network_interface_ids": { + "route_table_ids": { Type: schema.TypeSet, Computed: true, Elem: &schema.Schema{Type: schema.TypeString}, @@ -75,25 +90,15 @@ func dataSourceAwsVpcEndpoint() *schema.Resource { Elem: &schema.Schema{Type: schema.TypeString}, Set: schema.HashString, }, - "private_dns_enabled": { - Type: schema.TypeBool, + "subnet_ids": { + Type: schema.TypeSet, Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Set: schema.HashString, }, - "dns_entry": { - Type: schema.TypeList, + "vpc_endpoint_type": { + Type: schema.TypeString, Computed: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "dns_name": { - Type: schema.TypeString, - Computed: true, - }, - "hosted_zone_id": { - Type: schema.TypeString, - Computed: true, - }, - }, - }, }, }, } @@ -121,19 +126,80 @@ func dataSourceAwsVpcEndpointRead(d *schema.ResourceData, meta interface{}) erro } log.Printf("[DEBUG] Reading VPC Endpoint: %s", req) - resp, err := conn.DescribeVpcEndpoints(req) + respVpce, err := conn.DescribeVpcEndpoints(req) if err != nil { - return err + return fmt.Errorf("error reading VPC Endpoint: %s", err) } - if resp == nil || len(resp.VpcEndpoints) == 0 { - return fmt.Errorf("no matching VPC endpoint found") + if respVpce == nil || len(respVpce.VpcEndpoints) == 0 { + return fmt.Errorf("no matching VPC Endpoint found") } - if len(resp.VpcEndpoints) > 1 { - return fmt.Errorf("multiple VPC endpoints matched; use additional constraints to reduce matches to a single VPC endpoint") + if len(respVpce.VpcEndpoints) > 1 { + return fmt.Errorf("multiple VPC Endpoints matched; use additional constraints to reduce matches to a single VPC Endpoint") } - vpce := resp.VpcEndpoints[0] + vpce := respVpce.VpcEndpoints[0] d.SetId(aws.StringValue(vpce.VpcEndpointId)) - return vpcEndpointAttributes(d, vpce, conn) + serviceName := aws.StringValue(vpce.ServiceName) + d.Set("service_name", serviceName) + d.Set("state", vpce.State) + d.Set("vpc_id", vpce.VpcId) + + respPl, err := conn.DescribePrefixLists(&ec2.DescribePrefixListsInput{ + Filters: buildEC2AttributeFilterList(map[string]string{ + "prefix-list-name": serviceName, + }), + }) + if err != nil { + return fmt.Errorf("error reading Prefix List (%s): %s", serviceName, err) + } + if respPl == nil || len(respPl.PrefixLists) == 0 { + d.Set("cidr_blocks", []interface{}{}) + } else if len(respPl.PrefixLists) > 1 { + return fmt.Errorf("multiple prefix lists associated with the service name '%s'. Unexpected", serviceName) + } else { + pl := respPl.PrefixLists[0] + + d.Set("prefix_list_id", pl.PrefixListId) + err = d.Set("cidr_blocks", flattenStringList(pl.Cidrs)) + if err != nil { + return fmt.Errorf("error setting cidr_blocks: %s", err) + } + } + + err = d.Set("dns_entry", flattenVpcEndpointDnsEntries(vpce.DnsEntries)) + if err != nil { + return fmt.Errorf("error setting dns_entry: %s", err) + } + err = d.Set("network_interface_ids", flattenStringSet(vpce.NetworkInterfaceIds)) + if err != nil { + return fmt.Errorf("error setting network_interface_ids: %s", err) + } + policy, err := structure.NormalizeJsonString(aws.StringValue(vpce.PolicyDocument)) + if err != nil { + return fmt.Errorf("policy contains an invalid JSON: %s", err) + } + d.Set("policy", policy) + d.Set("private_dns_enabled", vpce.PrivateDnsEnabled) + err = d.Set("route_table_ids", flattenStringSet(vpce.RouteTableIds)) + if err != nil { + return fmt.Errorf("error setting route_table_ids: %s", err) + } + d.Set("requester_managed", vpce.RequesterManaged) + err = d.Set("security_group_ids", flattenVpcEndpointSecurityGroupIds(vpce.Groups)) + if err != nil { + return fmt.Errorf("error setting security_group_ids: %s", err) + } + err = d.Set("subnet_ids", flattenStringSet(vpce.SubnetIds)) + if err != nil { + return fmt.Errorf("error setting subnet_ids: %s", err) + } + // VPC endpoints don't have types in GovCloud, so set type to default if empty + if vpceType := aws.StringValue(vpce.VpcEndpointType); vpceType == "" { + d.Set("vpc_endpoint_type", ec2.VpcEndpointTypeGateway) + } else { + d.Set("vpc_endpoint_type", vpceType) + } + + return nil } diff --git a/aws/data_source_aws_vpc_endpoint_test.go b/aws/data_source_aws_vpc_endpoint_test.go index 532564e019de..bd8faca3a0a3 100644 --- a/aws/data_source_aws_vpc_endpoint_test.go +++ b/aws/data_source_aws_vpc_endpoint_test.go @@ -1,14 +1,14 @@ package aws import ( - "fmt" "testing" "github.com/hashicorp/terraform/helper/resource" - "github.com/hashicorp/terraform/terraform" ) func TestAccDataSourceAwsVpcEndpoint_gatewayBasic(t *testing.T) { + datasourceName := "data.aws_vpc_endpoint.s3" + resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, @@ -16,15 +16,15 @@ func TestAccDataSourceAwsVpcEndpoint_gatewayBasic(t *testing.T) { { Config: testAccDataSourceAwsVpcEndpointConfig_gatewayBasic, Check: resource.ComposeTestCheckFunc( - testAccDataSourceAwsVpcEndpointCheckExists("data.aws_vpc_endpoint.s3", "aws_vpc_endpoint.s3"), - resource.TestCheckResourceAttr( - "data.aws_vpc_endpoint.s3", "vpc_endpoint_type", "Gateway"), - resource.TestCheckResourceAttrSet("data.aws_vpc_endpoint.s3", "prefix_list_id"), - resource.TestCheckResourceAttrSet("data.aws_vpc_endpoint.s3", "cidr_blocks.#"), - resource.TestCheckResourceAttr("data.aws_vpc_endpoint.s3", "route_table_ids.#", "0"), - resource.TestCheckResourceAttr("data.aws_vpc_endpoint.s3", "subnet_ids.#", "0"), - resource.TestCheckResourceAttr("data.aws_vpc_endpoint.s3", "network_interface_ids.#", "0"), - resource.TestCheckResourceAttr("data.aws_vpc_endpoint.s3", "security_group_ids.#", "0"), + resource.TestCheckResourceAttr(datasourceName, "vpc_endpoint_type", "Gateway"), + resource.TestCheckResourceAttrSet(datasourceName, "prefix_list_id"), + resource.TestCheckResourceAttrSet(datasourceName, "cidr_blocks.#"), + resource.TestCheckResourceAttr(datasourceName, "route_table_ids.#", "0"), + resource.TestCheckResourceAttr(datasourceName, "subnet_ids.#", "0"), + resource.TestCheckResourceAttr(datasourceName, "network_interface_ids.#", "0"), + resource.TestCheckResourceAttr(datasourceName, "security_group_ids.#", "0"), + resource.TestCheckResourceAttr(datasourceName, "private_dns_enabled", "false"), + resource.TestCheckResourceAttr(datasourceName, "requester_managed", "false"), ), }, }, @@ -32,6 +32,8 @@ func TestAccDataSourceAwsVpcEndpoint_gatewayBasic(t *testing.T) { } func TestAccDataSourceAwsVpcEndpoint_byId(t *testing.T) { + datasourceName := "data.aws_vpc_endpoint.s3" + resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, @@ -39,7 +41,15 @@ func TestAccDataSourceAwsVpcEndpoint_byId(t *testing.T) { { Config: testAccDataSourceAwsVpcEndpointConfig_byId, Check: resource.ComposeTestCheckFunc( - testAccDataSourceAwsVpcEndpointCheckExists("data.aws_vpc_endpoint.by_id", "aws_vpc_endpoint.s3"), + resource.TestCheckResourceAttr(datasourceName, "vpc_endpoint_type", "Gateway"), + resource.TestCheckResourceAttrSet(datasourceName, "prefix_list_id"), + resource.TestCheckResourceAttrSet(datasourceName, "cidr_blocks.#"), + resource.TestCheckResourceAttr(datasourceName, "route_table_ids.#", "0"), + resource.TestCheckResourceAttr(datasourceName, "subnet_ids.#", "0"), + resource.TestCheckResourceAttr(datasourceName, "network_interface_ids.#", "0"), + resource.TestCheckResourceAttr(datasourceName, "security_group_ids.#", "0"), + resource.TestCheckResourceAttr(datasourceName, "private_dns_enabled", "false"), + resource.TestCheckResourceAttr(datasourceName, "requester_managed", "false"), ), }, }, @@ -47,6 +57,8 @@ func TestAccDataSourceAwsVpcEndpoint_byId(t *testing.T) { } func TestAccDataSourceAwsVpcEndpoint_gatewayWithRouteTable(t *testing.T) { + datasourceName := "data.aws_vpc_endpoint.s3" + resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, @@ -54,11 +66,15 @@ func TestAccDataSourceAwsVpcEndpoint_gatewayWithRouteTable(t *testing.T) { { Config: testAccDataSourceAwsVpcEndpointConfig_gatewayWithRouteTable, Check: resource.ComposeTestCheckFunc( - testAccDataSourceAwsVpcEndpointCheckExists("data.aws_vpc_endpoint.s3", "aws_vpc_endpoint.s3"), - resource.TestCheckResourceAttr( - "data.aws_vpc_endpoint.s3", "vpc_endpoint_type", "Gateway"), - resource.TestCheckResourceAttr( - "data.aws_vpc_endpoint.s3", "route_table_ids.#", "1"), + resource.TestCheckResourceAttr(datasourceName, "vpc_endpoint_type", "Gateway"), + resource.TestCheckResourceAttrSet(datasourceName, "prefix_list_id"), + resource.TestCheckResourceAttrSet(datasourceName, "cidr_blocks.#"), + resource.TestCheckResourceAttr(datasourceName, "route_table_ids.#", "1"), + resource.TestCheckResourceAttr(datasourceName, "subnet_ids.#", "0"), + resource.TestCheckResourceAttr(datasourceName, "network_interface_ids.#", "0"), + resource.TestCheckResourceAttr(datasourceName, "security_group_ids.#", "0"), + resource.TestCheckResourceAttr(datasourceName, "private_dns_enabled", "false"), + resource.TestCheckResourceAttr(datasourceName, "requester_managed", "false"), ), }, }, @@ -66,6 +82,8 @@ func TestAccDataSourceAwsVpcEndpoint_gatewayWithRouteTable(t *testing.T) { } func TestAccDataSourceAwsVpcEndpoint_interface(t *testing.T) { + datasourceName := "data.aws_vpc_endpoint.ec2" + resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, @@ -73,47 +91,21 @@ func TestAccDataSourceAwsVpcEndpoint_interface(t *testing.T) { { Config: testAccDataSourceAwsVpcEndpointConfig_interface, Check: resource.ComposeTestCheckFunc( - testAccDataSourceAwsVpcEndpointCheckExists("data.aws_vpc_endpoint.ec2", "aws_vpc_endpoint.ec2"), - resource.TestCheckResourceAttr( - "data.aws_vpc_endpoint.ec2", "vpc_endpoint_type", "Interface"), - resource.TestCheckNoResourceAttr("data.aws_vpc_endpoint.ec2", "prefix_list_id"), - resource.TestCheckResourceAttr("data.aws_vpc_endpoint.ec2", "cidr_blocks.#", "0"), - resource.TestCheckResourceAttr("data.aws_vpc_endpoint.ec2", "route_table_ids.#", "0"), - resource.TestCheckResourceAttr("data.aws_vpc_endpoint.ec2", "subnet_ids.#", "1"), - resource.TestCheckResourceAttr("data.aws_vpc_endpoint.ec2", "security_group_ids.#", "1"), - resource.TestCheckResourceAttr("data.aws_vpc_endpoint.ec2", "private_dns_enabled", "false"), + resource.TestCheckResourceAttr(datasourceName, "vpc_endpoint_type", "Interface"), + resource.TestCheckNoResourceAttr(datasourceName, "prefix_list_id"), + resource.TestCheckResourceAttr(datasourceName, "cidr_blocks.#", "0"), + resource.TestCheckResourceAttr(datasourceName, "route_table_ids.#", "0"), + resource.TestCheckResourceAttr(datasourceName, "subnet_ids.#", "1"), + resource.TestCheckResourceAttr(datasourceName, "network_interface_ids.#", "1"), + resource.TestCheckResourceAttr(datasourceName, "security_group_ids.#", "1"), + resource.TestCheckResourceAttr(datasourceName, "private_dns_enabled", "false"), + resource.TestCheckResourceAttr(datasourceName, "requester_managed", "false"), ), }, }, }) } -func testAccDataSourceAwsVpcEndpointCheckExists(dsName, rsName string) resource.TestCheckFunc { - return func(s *terraform.State) error { - rs, ok := s.RootModule().Resources[dsName] - if !ok { - return fmt.Errorf("root module has no resource called %s", dsName) - } - - vpceRs, ok := s.RootModule().Resources[rsName] - if !ok { - return fmt.Errorf("can't find %s in state", rsName) - } - - attr := rs.Primary.Attributes - - if attr["id"] != vpceRs.Primary.Attributes["id"] { - return fmt.Errorf( - "id is %s; want %s", - attr["id"], - vpceRs.Primary.Attributes["id"], - ) - } - - return nil - } -} - const testAccDataSourceAwsVpcEndpointConfig_gatewayBasic = ` provider "aws" { region = "us-west-2" @@ -157,7 +149,7 @@ resource "aws_vpc_endpoint" "s3" { service_name = "com.amazonaws.us-west-2.s3" } -data "aws_vpc_endpoint" "by_id" { +data "aws_vpc_endpoint" "s3" { id = "${aws_vpc_endpoint.s3.id}" } ` diff --git a/aws/resource_aws_vpc_endpoint.go b/aws/resource_aws_vpc_endpoint.go index aa5c4ec36c5f..7277e5bba8cc 100644 --- a/aws/resource_aws_vpc_endpoint.go +++ b/aws/resource_aws_vpc_endpoint.go @@ -25,26 +25,20 @@ func resourceAwsVpcEndpoint() *schema.Resource { }, Schema: map[string]*schema.Schema{ - "vpc_id": { + "service_name": { Type: schema.TypeString, Required: true, ForceNew: true, }, - "vpc_endpoint_type": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - Default: ec2.VpcEndpointTypeGateway, - ValidateFunc: validation.StringInSlice([]string{ - ec2.VpcEndpointTypeGateway, - ec2.VpcEndpointTypeInterface, - }, false), - }, - "service_name": { + "vpc_id": { Type: schema.TypeString, Required: true, ForceNew: true, }, + "auto_accept": { + Type: schema.TypeBool, + Optional: true, + }, "policy": { Type: schema.TypeString, Optional: true, @@ -56,6 +50,11 @@ func resourceAwsVpcEndpoint() *schema.Resource { return json }, }, + "private_dns_enabled": { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, "route_table_ids": { Type: schema.TypeSet, Optional: true, @@ -63,44 +62,35 @@ func resourceAwsVpcEndpoint() *schema.Resource { Elem: &schema.Schema{Type: schema.TypeString}, Set: schema.HashString, }, - "subnet_ids": { + "security_group_ids": { Type: schema.TypeSet, Optional: true, Computed: true, Elem: &schema.Schema{Type: schema.TypeString}, Set: schema.HashString, }, - "security_group_ids": { + "subnet_ids": { Type: schema.TypeSet, Optional: true, Computed: true, Elem: &schema.Schema{Type: schema.TypeString}, Set: schema.HashString, }, - "private_dns_enabled": { - Type: schema.TypeBool, - Optional: true, - Default: false, - }, - "state": { - Type: schema.TypeString, - Computed: true, - }, - "prefix_list_id": { + "vpc_endpoint_type": { Type: schema.TypeString, - Computed: true, + Optional: true, + ForceNew: true, + Default: ec2.VpcEndpointTypeGateway, + ValidateFunc: validation.StringInSlice([]string{ + ec2.VpcEndpointTypeGateway, + ec2.VpcEndpointTypeInterface, + }, false), }, "cidr_blocks": { Type: schema.TypeList, Computed: true, Elem: &schema.Schema{Type: schema.TypeString}, }, - "network_interface_ids": { - Type: schema.TypeSet, - Computed: true, - Elem: &schema.Schema{Type: schema.TypeString}, - Set: schema.HashString, - }, "dns_entry": { Type: schema.TypeList, Computed: true, @@ -117,9 +107,23 @@ func resourceAwsVpcEndpoint() *schema.Resource { }, }, }, - "auto_accept": { + "network_interface_ids": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Set: schema.HashString, + }, + "prefix_list_id": { + Type: schema.TypeString, + Computed: true, + }, + "requester_managed": { Type: schema.TypeBool, - Optional: true, + Computed: true, + }, + "state": { + Type: schema.TypeString, + Computed: true, }, }, @@ -183,9 +187,9 @@ func resourceAwsVpcEndpointCreate(d *schema.ResourceData, meta interface{}) erro func resourceAwsVpcEndpointRead(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).ec2conn - vpce, state, err := vpcEndpointStateRefresh(conn, d.Id())() + vpceRaw, state, err := vpcEndpointStateRefresh(conn, d.Id())() if err != nil && state != "failed" { - return fmt.Errorf("Error reading VPC Endpoint: %s", err) + return fmt.Errorf("error reading VPC Endpoint (%s): %s", d.Id(), err) } terminalStates := map[string]bool{ @@ -201,7 +205,70 @@ func resourceAwsVpcEndpointRead(d *schema.ResourceData, meta interface{}) error return nil } - return vpcEndpointAttributes(d, vpce.(*ec2.VpcEndpoint), conn) + vpce := vpceRaw.(*ec2.VpcEndpoint) + + serviceName := aws.StringValue(vpce.ServiceName) + d.Set("service_name", serviceName) + d.Set("state", vpce.State) + d.Set("vpc_id", vpce.VpcId) + + respPl, err := conn.DescribePrefixLists(&ec2.DescribePrefixListsInput{ + Filters: buildEC2AttributeFilterList(map[string]string{ + "prefix-list-name": serviceName, + }), + }) + if err != nil { + return fmt.Errorf("error reading Prefix List (%s): %s", serviceName, err) + } + if respPl == nil || len(respPl.PrefixLists) == 0 { + d.Set("cidr_blocks", []interface{}{}) + } else if len(respPl.PrefixLists) > 1 { + return fmt.Errorf("multiple prefix lists associated with the service name '%s'. Unexpected", serviceName) + } else { + pl := respPl.PrefixLists[0] + + d.Set("prefix_list_id", pl.PrefixListId) + err = d.Set("cidr_blocks", flattenStringList(pl.Cidrs)) + if err != nil { + return fmt.Errorf("error setting cidr_blocks: %s", err) + } + } + + err = d.Set("dns_entry", flattenVpcEndpointDnsEntries(vpce.DnsEntries)) + if err != nil { + return fmt.Errorf("error setting dns_entry: %s", err) + } + err = d.Set("network_interface_ids", flattenStringSet(vpce.NetworkInterfaceIds)) + if err != nil { + return fmt.Errorf("error setting network_interface_ids: %s", err) + } + policy, err := structure.NormalizeJsonString(aws.StringValue(vpce.PolicyDocument)) + if err != nil { + return fmt.Errorf("policy contains an invalid JSON: %s", err) + } + d.Set("policy", policy) + d.Set("private_dns_enabled", vpce.PrivateDnsEnabled) + err = d.Set("route_table_ids", flattenStringSet(vpce.RouteTableIds)) + if err != nil { + return fmt.Errorf("error setting route_table_ids: %s", err) + } + d.Set("requester_managed", vpce.RequesterManaged) + err = d.Set("security_group_ids", flattenVpcEndpointSecurityGroupIds(vpce.Groups)) + if err != nil { + return fmt.Errorf("error setting security_group_ids: %s", err) + } + err = d.Set("subnet_ids", flattenStringSet(vpce.SubnetIds)) + if err != nil { + return fmt.Errorf("error setting subnet_ids: %s", err) + } + // VPC endpoints don't have types in GovCloud, so set type to default if empty + if vpceType := aws.StringValue(vpce.VpcEndpointType); vpceType == "" { + d.Set("vpc_endpoint_type", ec2.VpcEndpointTypeGateway) + } else { + d.Set("vpc_endpoint_type", vpceType) + } + + return nil } func resourceAwsVpcEndpointUpdate(d *schema.ResourceData, meta interface{}) error { @@ -367,72 +434,6 @@ func vpcEndpointWaitUntilDeleted(conn *ec2.EC2, vpceId string, timeout time.Dura return err } -func vpcEndpointAttributes(d *schema.ResourceData, vpce *ec2.VpcEndpoint, conn *ec2.EC2) error { - d.Set("state", vpce.State) - d.Set("vpc_id", vpce.VpcId) - - serviceName := aws.StringValue(vpce.ServiceName) - d.Set("service_name", serviceName) - // VPC endpoints don't have types in GovCloud, so set type to default if empty - if aws.StringValue(vpce.VpcEndpointType) == "" { - d.Set("vpc_endpoint_type", ec2.VpcEndpointTypeGateway) - } else { - d.Set("vpc_endpoint_type", vpce.VpcEndpointType) - } - - policy, err := structure.NormalizeJsonString(aws.StringValue(vpce.PolicyDocument)) - if err != nil { - return fmt.Errorf("policy contains an invalid JSON: %s", err) - } - d.Set("policy", policy) - - d.Set("route_table_ids", flattenStringList(vpce.RouteTableIds)) - - req := &ec2.DescribePrefixListsInput{} - req.Filters = buildEC2AttributeFilterList( - map[string]string{ - "prefix-list-name": serviceName, - }, - ) - resp, err := conn.DescribePrefixLists(req) - if err != nil { - return err - } - if resp != nil && len(resp.PrefixLists) > 0 { - if len(resp.PrefixLists) > 1 { - return fmt.Errorf("multiple prefix lists associated with the service name '%s'. Unexpected", serviceName) - } - - pl := resp.PrefixLists[0] - d.Set("prefix_list_id", pl.PrefixListId) - d.Set("cidr_blocks", flattenStringList(pl.Cidrs)) - } else { - d.Set("cidr_blocks", make([]string, 0)) - } - - d.Set("subnet_ids", flattenStringList(vpce.SubnetIds)) - d.Set("network_interface_ids", flattenStringList(vpce.NetworkInterfaceIds)) - - sgIds := make([]interface{}, 0, len(vpce.Groups)) - for _, group := range vpce.Groups { - sgIds = append(sgIds, aws.StringValue(group.GroupId)) - } - d.Set("security_group_ids", sgIds) - - d.Set("private_dns_enabled", vpce.PrivateDnsEnabled) - - dnsEntries := make([]interface{}, len(vpce.DnsEntries)) - for i, entry := range vpce.DnsEntries { - m := make(map[string]interface{}) - m["dns_name"] = aws.StringValue(entry.DnsName) - m["hosted_zone_id"] = aws.StringValue(entry.HostedZoneId) - dnsEntries[i] = m - } - d.Set("dns_entry", dnsEntries) - - return nil -} - func setVpcEndpointCreateList(d *schema.ResourceData, key string, c *[]*string) { if v, ok := d.GetOk(key); ok { list := v.(*schema.Set).List() diff --git a/aws/resource_aws_vpc_endpoint_test.go b/aws/resource_aws_vpc_endpoint_test.go index 60460d456a5e..39a95ccbe4e2 100644 --- a/aws/resource_aws_vpc_endpoint_test.go +++ b/aws/resource_aws_vpc_endpoint_test.go @@ -81,8 +81,10 @@ func testSweepEc2VpcEndpoints(region string) error { return nil } -func TestAccAWSVpcEndpoint_importBasic(t *testing.T) { +func TestAccAWSVpcEndpoint_gatewayBasic(t *testing.T) { + var endpoint ec2.VpcEndpoint resourceName := "aws_vpc_endpoint.s3" + rName := fmt.Sprintf("tf-testacc-vpce-%s", acctest.RandStringFromCharSet(16, acctest.CharSetAlphaNum)) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -90,38 +92,17 @@ func TestAccAWSVpcEndpoint_importBasic(t *testing.T) { CheckDestroy: testAccCheckVpcEndpointDestroy, Steps: []resource.TestStep{ { - Config: testAccVpcEndpointConfig_gatewayWithRouteTableAndPolicy, - }, - - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - }, - }, - }) -} - -func TestAccAWSVpcEndpoint_gatewayBasic(t *testing.T) { - var endpoint ec2.VpcEndpoint - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - IDRefreshName: "aws_vpc_endpoint.s3", - Providers: testAccProviders, - CheckDestroy: testAccCheckVpcEndpointDestroy, - Steps: []resource.TestStep{ - { - Config: testAccVpcEndpointConfig_gatewayWithoutRouteTableOrPolicy, + Config: testAccVpcEndpointConfig_gatewayWithoutRouteTableOrPolicy(rName), Check: resource.ComposeTestCheckFunc( - testAccCheckVpcEndpointExists("aws_vpc_endpoint.s3", &endpoint), - testAccCheckVpcEndpointPrefixListAvailable("aws_vpc_endpoint.s3"), - resource.TestCheckResourceAttr("aws_vpc_endpoint.s3", "vpc_endpoint_type", "Gateway"), - resource.TestCheckResourceAttr("aws_vpc_endpoint.s3", "route_table_ids.#", "0"), - resource.TestCheckResourceAttr("aws_vpc_endpoint.s3", "subnet_ids.#", "0"), - resource.TestCheckResourceAttr("aws_vpc_endpoint.s3", "network_interface_ids.#", "0"), - resource.TestCheckResourceAttr("aws_vpc_endpoint.s3", "security_group_ids.#", "0"), - resource.TestCheckResourceAttr("aws_vpc_endpoint.s3", "private_dns_enabled", "false"), + testAccCheckVpcEndpointExists(resourceName, &endpoint), + testAccCheckVpcEndpointPrefixListAvailable(resourceName), + resource.TestCheckResourceAttr(resourceName, "vpc_endpoint_type", "Gateway"), + resource.TestCheckResourceAttr(resourceName, "route_table_ids.#", "0"), + resource.TestCheckResourceAttr(resourceName, "subnet_ids.#", "0"), + resource.TestCheckResourceAttr(resourceName, "network_interface_ids.#", "0"), + resource.TestCheckResourceAttr(resourceName, "security_group_ids.#", "0"), + resource.TestCheckResourceAttr(resourceName, "private_dns_enabled", "false"), + resource.TestCheckResourceAttr(resourceName, "requester_managed", "false"), ), }, }, @@ -131,44 +112,55 @@ func TestAccAWSVpcEndpoint_gatewayBasic(t *testing.T) { func TestAccAWSVpcEndpoint_gatewayWithRouteTableAndPolicy(t *testing.T) { var endpoint ec2.VpcEndpoint var routeTable ec2.RouteTable + resourceName := "aws_vpc_endpoint.s3" + resourceNameRt := "aws_route_table.default" + rName := fmt.Sprintf("tf-testacc-vpce-%s", acctest.RandStringFromCharSet(16, acctest.CharSetAlphaNum)) resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - IDRefreshName: "aws_vpc_endpoint.s3", - Providers: testAccProviders, - CheckDestroy: testAccCheckVpcEndpointDestroy, + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckVpcEndpointDestroy, Steps: []resource.TestStep{ { - Config: testAccVpcEndpointConfig_gatewayWithRouteTableAndPolicy, + Config: testAccVpcEndpointConfig_gatewayWithRouteTableAndPolicy(rName), Check: resource.ComposeTestCheckFunc( - testAccCheckVpcEndpointExists("aws_vpc_endpoint.s3", &endpoint), - testAccCheckRouteTableExists("aws_route_table.default", &routeTable), - resource.TestCheckResourceAttr("aws_vpc_endpoint.s3", "vpc_endpoint_type", "Gateway"), - resource.TestCheckResourceAttr("aws_vpc_endpoint.s3", "route_table_ids.#", "1"), - resource.TestCheckResourceAttr("aws_vpc_endpoint.s3", "subnet_ids.#", "0"), - resource.TestCheckResourceAttr("aws_vpc_endpoint.s3", "network_interface_ids.#", "0"), - resource.TestCheckResourceAttr("aws_vpc_endpoint.s3", "security_group_ids.#", "0"), - resource.TestCheckResourceAttr("aws_vpc_endpoint.s3", "private_dns_enabled", "false"), + testAccCheckVpcEndpointExists(resourceName, &endpoint), + testAccCheckRouteTableExists(resourceNameRt, &routeTable), + testAccCheckVpcEndpointPrefixListAvailable(resourceName), + resource.TestCheckResourceAttr(resourceName, "vpc_endpoint_type", "Gateway"), + resource.TestCheckResourceAttr(resourceName, "route_table_ids.#", "1"), + resource.TestCheckResourceAttr(resourceName, "subnet_ids.#", "0"), + resource.TestCheckResourceAttr(resourceName, "network_interface_ids.#", "0"), + resource.TestCheckResourceAttr(resourceName, "security_group_ids.#", "0"), + resource.TestCheckResourceAttr(resourceName, "private_dns_enabled", "false"), + resource.TestCheckResourceAttr(resourceName, "requester_managed", "false"), ), }, { - Config: testAccVpcEndpointConfig_gatewayWithRouteTableAndPolicyModified, + Config: testAccVpcEndpointConfig_gatewayWithRouteTableAndPolicyModified(rName), Check: resource.ComposeTestCheckFunc( - testAccCheckVpcEndpointExists("aws_vpc_endpoint.s3", &endpoint), - testAccCheckRouteTableExists("aws_route_table.default", &routeTable), - resource.TestCheckResourceAttr("aws_vpc_endpoint.s3", "vpc_endpoint_type", "Gateway"), - resource.TestCheckResourceAttr("aws_vpc_endpoint.s3", "route_table_ids.#", "0"), - resource.TestCheckResourceAttr("aws_vpc_endpoint.s3", "subnet_ids.#", "0"), - resource.TestCheckResourceAttr("aws_vpc_endpoint.s3", "network_interface_ids.#", "0"), - resource.TestCheckResourceAttr("aws_vpc_endpoint.s3", "security_group_ids.#", "0"), - resource.TestCheckResourceAttr("aws_vpc_endpoint.s3", "private_dns_enabled", "false"), + testAccCheckVpcEndpointExists(resourceName, &endpoint), + testAccCheckRouteTableExists(resourceNameRt, &routeTable), + testAccCheckVpcEndpointPrefixListAvailable(resourceName), + resource.TestCheckResourceAttr(resourceName, "vpc_endpoint_type", "Gateway"), + resource.TestCheckResourceAttr(resourceName, "route_table_ids.#", "0"), + resource.TestCheckResourceAttr(resourceName, "subnet_ids.#", "0"), + resource.TestCheckResourceAttr(resourceName, "network_interface_ids.#", "0"), + resource.TestCheckResourceAttr(resourceName, "security_group_ids.#", "0"), + resource.TestCheckResourceAttr(resourceName, "private_dns_enabled", "false"), + resource.TestCheckResourceAttr(resourceName, "requester_managed", "false"), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, }, }) } -func TestAccAWSVpcEndpoint_Gateway_Policy(t *testing.T) { +func TestAccAWSVpcEndpoint_gatewayPolicy(t *testing.T) { var endpoint ec2.VpcEndpoint // This policy checks the DiffSuppressFunc policy1 := ` @@ -202,6 +194,7 @@ func TestAccAWSVpcEndpoint_Gateway_Policy(t *testing.T) { } ` resourceName := "aws_vpc_endpoint.test" + rName := fmt.Sprintf("tf-testacc-vpce-%s", acctest.RandStringFromCharSet(16, acctest.CharSetAlphaNum)) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -209,7 +202,7 @@ func TestAccAWSVpcEndpoint_Gateway_Policy(t *testing.T) { CheckDestroy: testAccCheckVpcEndpointDestroy, Steps: []resource.TestStep{ { - Config: testAccVpcEndpointConfigGatewayPolicy(policy1), + Config: testAccVpcEndpointConfigGatewayPolicy(rName, policy1), Check: resource.ComposeTestCheckFunc( testAccCheckVpcEndpointExists(resourceName, &endpoint), ), @@ -220,7 +213,7 @@ func TestAccAWSVpcEndpoint_Gateway_Policy(t *testing.T) { ImportStateVerify: true, }, { - Config: testAccVpcEndpointConfigGatewayPolicy(policy2), + Config: testAccVpcEndpointConfigGatewayPolicy(rName, policy2), Check: resource.ComposeTestCheckFunc( testAccCheckVpcEndpointExists(resourceName, &endpoint), ), @@ -231,24 +224,27 @@ func TestAccAWSVpcEndpoint_Gateway_Policy(t *testing.T) { func TestAccAWSVpcEndpoint_interfaceBasic(t *testing.T) { var endpoint ec2.VpcEndpoint + resourceName := "aws_vpc_endpoint.ec2" + rName := fmt.Sprintf("tf-testacc-vpce-%s", acctest.RandStringFromCharSet(16, acctest.CharSetAlphaNum)) resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - IDRefreshName: "aws_vpc_endpoint.ec2", - Providers: testAccProviders, - CheckDestroy: testAccCheckVpcEndpointDestroy, + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckVpcEndpointDestroy, Steps: []resource.TestStep{ { - Config: testAccVpcEndpointConfig_interfaceWithoutSubnet, + Config: testAccVpcEndpointConfig_interfaceWithoutSubnet(rName), Check: resource.ComposeTestCheckFunc( - testAccCheckVpcEndpointExists("aws_vpc_endpoint.ec2", &endpoint), - resource.TestCheckResourceAttr("aws_vpc_endpoint.ec2", "cidr_blocks.#", "0"), - resource.TestCheckResourceAttr("aws_vpc_endpoint.ec2", "vpc_endpoint_type", "Interface"), - resource.TestCheckResourceAttr("aws_vpc_endpoint.ec2", "route_table_ids.#", "0"), - resource.TestCheckResourceAttr("aws_vpc_endpoint.ec2", "subnet_ids.#", "0"), - resource.TestCheckResourceAttr("aws_vpc_endpoint.ec2", "network_interface_ids.#", "0"), - resource.TestCheckResourceAttr("aws_vpc_endpoint.ec2", "security_group_ids.#", "1"), - resource.TestCheckResourceAttr("aws_vpc_endpoint.ec2", "private_dns_enabled", "false"), + testAccCheckVpcEndpointExists(resourceName, &endpoint), + resource.TestCheckNoResourceAttr(resourceName, "prefix_list_id"), + resource.TestCheckResourceAttr(resourceName, "cidr_blocks.#", "0"), + resource.TestCheckResourceAttr(resourceName, "vpc_endpoint_type", "Interface"), + resource.TestCheckResourceAttr(resourceName, "route_table_ids.#", "0"), + resource.TestCheckResourceAttr(resourceName, "subnet_ids.#", "0"), + resource.TestCheckResourceAttr(resourceName, "network_interface_ids.#", "0"), + resource.TestCheckResourceAttr(resourceName, "security_group_ids.#", "1"), + resource.TestCheckResourceAttr(resourceName, "private_dns_enabled", "false"), + resource.TestCheckResourceAttr(resourceName, "requester_managed", "false"), ), }, }, @@ -257,68 +253,87 @@ func TestAccAWSVpcEndpoint_interfaceBasic(t *testing.T) { func TestAccAWSVpcEndpoint_interfaceWithSubnetAndSecurityGroup(t *testing.T) { var endpoint ec2.VpcEndpoint + resourceName := "aws_vpc_endpoint.ec2" + rName := fmt.Sprintf("tf-testacc-vpce-%s", acctest.RandStringFromCharSet(16, acctest.CharSetAlphaNum)) resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - IDRefreshName: "aws_vpc_endpoint.ec2", - Providers: testAccProviders, - CheckDestroy: testAccCheckVpcEndpointDestroy, + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckVpcEndpointDestroy, Steps: []resource.TestStep{ { - Config: testAccVpcEndpointConfig_interfaceWithSubnet, + Config: testAccVpcEndpointConfig_interfaceWithSubnet(rName), Check: resource.ComposeTestCheckFunc( - testAccCheckVpcEndpointExists("aws_vpc_endpoint.ec2", &endpoint), - resource.TestCheckResourceAttr("aws_vpc_endpoint.ec2", "cidr_blocks.#", "0"), - resource.TestCheckResourceAttr("aws_vpc_endpoint.ec2", "vpc_endpoint_type", "Interface"), - resource.TestCheckResourceAttr("aws_vpc_endpoint.ec2", "route_table_ids.#", "0"), - resource.TestCheckResourceAttr("aws_vpc_endpoint.ec2", "subnet_ids.#", "1"), - resource.TestCheckResourceAttr("aws_vpc_endpoint.ec2", "security_group_ids.#", "2"), - resource.TestCheckResourceAttr("aws_vpc_endpoint.ec2", "private_dns_enabled", "false"), + testAccCheckVpcEndpointExists(resourceName, &endpoint), + resource.TestCheckNoResourceAttr(resourceName, "prefix_list_id"), + resource.TestCheckResourceAttr(resourceName, "cidr_blocks.#", "0"), + resource.TestCheckResourceAttr(resourceName, "vpc_endpoint_type", "Interface"), + resource.TestCheckResourceAttr(resourceName, "route_table_ids.#", "0"), + resource.TestCheckResourceAttr(resourceName, "subnet_ids.#", "1"), + resource.TestCheckResourceAttr(resourceName, "network_interface_ids.#", "1"), + resource.TestCheckResourceAttr(resourceName, "security_group_ids.#", "2"), + resource.TestCheckResourceAttr(resourceName, "private_dns_enabled", "false"), + resource.TestCheckResourceAttr(resourceName, "requester_managed", "false"), ), }, { - Config: testAccVpcEndpointConfig_interfaceWithSubnetModified, + Config: testAccVpcEndpointConfig_interfaceWithSubnetModified(rName), Check: resource.ComposeTestCheckFunc( - testAccCheckVpcEndpointExists("aws_vpc_endpoint.ec2", &endpoint), - resource.TestCheckResourceAttr("aws_vpc_endpoint.ec2", "cidr_blocks.#", "0"), - resource.TestCheckResourceAttr("aws_vpc_endpoint.ec2", "vpc_endpoint_type", "Interface"), - resource.TestCheckResourceAttr("aws_vpc_endpoint.ec2", "route_table_ids.#", "0"), - resource.TestCheckResourceAttr("aws_vpc_endpoint.ec2", "subnet_ids.#", "3"), - resource.TestCheckResourceAttr("aws_vpc_endpoint.ec2", "security_group_ids.#", "1"), - resource.TestCheckResourceAttr("aws_vpc_endpoint.ec2", "private_dns_enabled", "true"), + testAccCheckVpcEndpointExists(resourceName, &endpoint), + resource.TestCheckNoResourceAttr(resourceName, "prefix_list_id"), + resource.TestCheckResourceAttr(resourceName, "cidr_blocks.#", "0"), + resource.TestCheckResourceAttr(resourceName, "vpc_endpoint_type", "Interface"), + resource.TestCheckResourceAttr(resourceName, "route_table_ids.#", "0"), + resource.TestCheckResourceAttr(resourceName, "subnet_ids.#", "3"), + resource.TestCheckResourceAttr(resourceName, "network_interface_ids.#", "1"), + resource.TestCheckResourceAttr(resourceName, "security_group_ids.#", "1"), + resource.TestCheckResourceAttr(resourceName, "private_dns_enabled", "true"), + resource.TestCheckResourceAttr(resourceName, "requester_managed", "false"), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, }, }) } func TestAccAWSVpcEndpoint_interfaceNonAWSService(t *testing.T) { - lbName := fmt.Sprintf("testaccawsnlb-basic-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) var endpoint ec2.VpcEndpoint + resourceName := "aws_vpc_endpoint.foo" + rName := fmt.Sprintf("tf-testacc-vpce-%s", acctest.RandStringFromCharSet(16, acctest.CharSetAlphaNum)) resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - IDRefreshName: "aws_vpc_endpoint.foo", - Providers: testAccProviders, - CheckDestroy: testAccCheckVpcEndpointDestroy, + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckVpcEndpointDestroy, Steps: []resource.TestStep{ { - Config: testAccVpcEndpointConfig_interfaceNonAWSService(lbName), + Config: testAccVpcEndpointConfig_interfaceNonAWSService(rName), Check: resource.ComposeTestCheckFunc( - testAccCheckVpcEndpointExists("aws_vpc_endpoint.foo", &endpoint), - resource.TestCheckResourceAttr("aws_vpc_endpoint.foo", "vpc_endpoint_type", "Interface"), - resource.TestCheckResourceAttr("aws_vpc_endpoint.foo", "subnet_ids.#", "0"), - resource.TestCheckResourceAttr("aws_vpc_endpoint.foo", "network_interface_ids.#", "0"), - resource.TestCheckResourceAttr("aws_vpc_endpoint.foo", "security_group_ids.#", "1"), - resource.TestCheckResourceAttr("aws_vpc_endpoint.foo", "private_dns_enabled", "false"), - resource.TestCheckResourceAttr("aws_vpc_endpoint.foo", "state", "available"), + testAccCheckVpcEndpointExists(resourceName, &endpoint), + resource.TestCheckNoResourceAttr(resourceName, "prefix_list_id"), + resource.TestCheckResourceAttr(resourceName, "cidr_blocks.#", "0"), + resource.TestCheckResourceAttr(resourceName, "vpc_endpoint_type", "Interface"), + resource.TestCheckResourceAttr(resourceName, "route_table_ids.#", "0"), + resource.TestCheckResourceAttr(resourceName, "subnet_ids.#", "0"), + resource.TestCheckResourceAttr(resourceName, "network_interface_ids.#", "0"), + resource.TestCheckResourceAttr(resourceName, "security_group_ids.#", "1"), + resource.TestCheckResourceAttr(resourceName, "private_dns_enabled", "false"), + resource.TestCheckResourceAttr(resourceName, "requester_managed", "false"), + resource.TestCheckResourceAttr(resourceName, "state", "available"), ), }, }, }) } + func TestAccAWSVpcEndpoint_removed(t *testing.T) { var endpoint ec2.VpcEndpoint + resourceName := "aws_vpc_endpoint.s3" + rName := fmt.Sprintf("tf-testacc-vpce-%s", acctest.RandStringFromCharSet(16, acctest.CharSetAlphaNum)) // reach out and DELETE the VPC Endpoint outside of Terraform testDestroy := func(*terraform.State) error { @@ -338,9 +353,9 @@ func TestAccAWSVpcEndpoint_removed(t *testing.T) { CheckDestroy: testAccCheckVpcEndpointDestroy, Steps: []resource.TestStep{ { - Config: testAccVpcEndpointConfig_gatewayWithoutRouteTableOrPolicy, + Config: testAccVpcEndpointConfig_gatewayWithoutRouteTableOrPolicy(rName), Check: resource.ComposeTestCheckFunc( - testAccCheckVpcEndpointExists("aws_vpc_endpoint.s3", &endpoint), + testAccCheckVpcEndpointExists(resourceName, &endpoint), testDestroy, ), ExpectNonEmptyPlan: true, @@ -439,28 +454,53 @@ func testAccCheckVpcEndpointPrefixListAvailable(n string) resource.TestCheckFunc } } -const testAccVpcEndpointConfig_gatewayWithRouteTableAndPolicy = ` +func testAccVpcEndpointConfig_gatewayWithoutRouteTableOrPolicy(rName string) string { + return fmt.Sprintf(` +resource "aws_vpc" "foo" { + cidr_block = "10.0.0.0/16" + + tags = { + Name = %[1]q + } +} + +data "aws_region" "current" {} + +resource "aws_vpc_endpoint" "s3" { + vpc_id = "${aws_vpc.foo.id}" + service_name = "com.amazonaws.${data.aws_region.current.name}.s3" +} +`, rName) +} + +func testAccVpcEndpointConfig_gatewayWithRouteTableAndPolicy(rName string) string { + return fmt.Sprintf(` resource "aws_vpc" "foo" { cidr_block = "10.0.0.0/16" + tags = { - Name = "terraform-testacc-vpc-endpoint-gw-w-route-table-and-policy" + Name = %[1]q } } resource "aws_subnet" "foo" { - vpc_id = "${aws_vpc.foo.id}" + vpc_id = "${aws_vpc.foo.id}" cidr_block = "10.0.1.0/24" + tags = { - Name = "tf-acc-vpc-endpoint-gw-w-route-table-and-policy" + Name = %[1]q } } data "aws_region" "current" {} resource "aws_vpc_endpoint" "s3" { - vpc_id = "${aws_vpc.foo.id}" - service_name = "com.amazonaws.${data.aws_region.current.name}.s3" - route_table_ids = ["${aws_route_table.default.id}"] + vpc_id = "${aws_vpc.foo.id}" + service_name = "com.amazonaws.${data.aws_region.current.name}.s3" + route_table_ids = [ + "${aws_route_table.default.id}", + ] + policy = < Date: Tue, 14 May 2019 15:44:42 -0400 Subject: [PATCH 3/7] Move VPC Endpoint-specific 'flatten' routines out of 'structure.go'. --- aws/resource_aws_vpc_endpoint.go | 23 +++++++++++++++++ aws/resource_aws_vpc_endpoint_service.go | 12 +++++++++ aws/structure.go | 33 ------------------------ 3 files changed, 35 insertions(+), 33 deletions(-) diff --git a/aws/resource_aws_vpc_endpoint.go b/aws/resource_aws_vpc_endpoint.go index 7277e5bba8cc..c522f314b71e 100644 --- a/aws/resource_aws_vpc_endpoint.go +++ b/aws/resource_aws_vpc_endpoint.go @@ -460,3 +460,26 @@ func setVpcEndpointUpdateLists(d *schema.ResourceData, key string, a, r *[]*stri } } } + +func flattenVpcEndpointDnsEntries(dnsEntries []*ec2.DnsEntry) []interface{} { + vDnsEntries := []interface{}{} + + for _, dnsEntry := range dnsEntries { + vDnsEntries = append(vDnsEntries, map[string]interface{}{ + "dns_name": aws.StringValue(dnsEntry.DnsName), + "hosted_zone_id": aws.StringValue(dnsEntry.HostedZoneId), + }) + } + + return vDnsEntries +} + +func flattenVpcEndpointSecurityGroupIds(groups []*ec2.SecurityGroupIdentifier) *schema.Set { + vSecurityGroupIds := []interface{}{} + + for _, group := range groups { + vSecurityGroupIds = append(vSecurityGroupIds, aws.StringValue(group.GroupId)) + } + + return schema.NewSet(schema.HashString, vSecurityGroupIds) +} diff --git a/aws/resource_aws_vpc_endpoint_service.go b/aws/resource_aws_vpc_endpoint_service.go index 257fb2bb8d1a..e9546f90d211 100644 --- a/aws/resource_aws_vpc_endpoint_service.go +++ b/aws/resource_aws_vpc_endpoint_service.go @@ -299,3 +299,15 @@ func setVpcEndpointServiceUpdateLists(d *schema.ResourceData, key string, a, r * return true } + +func flattenVpcEndpointServiceAllowedPrincipals(allowedPrincipals []*ec2.AllowedPrincipal) *schema.Set { + vPrincipals := []interface{}{} + + for _, allowedPrincipal := range allowedPrincipals { + if allowedPrincipal.Principal != nil { + vPrincipals = append(vPrincipals, aws.StringValue(allowedPrincipal.Principal)) + } + } + + return schema.NewSet(schema.HashString, vPrincipals) +} diff --git a/aws/structure.go b/aws/structure.go index 22ec554dab99..acdc6e72aa6c 100644 --- a/aws/structure.go +++ b/aws/structure.go @@ -4471,39 +4471,6 @@ func expandDynamoDbEncryptAtRestOptions(m map[string]interface{}) *dynamodb.SSES return &options } -func flattenVpcEndpointServiceAllowedPrincipals(allowedPrincipals []*ec2.AllowedPrincipal) []string { - result := make([]string, 0, len(allowedPrincipals)) - for _, allowedPrincipal := range allowedPrincipals { - if allowedPrincipal.Principal != nil { - result = append(result, *allowedPrincipal.Principal) - } - } - return result -} - -func flattenVpcEndpointSecurityGroupIds(groups []*ec2.SecurityGroupIdentifier) *schema.Set { - vSecurityGroupIds := []interface{}{} - - for _, group := range groups { - vSecurityGroupIds = append(vSecurityGroupIds, aws.StringValue(group.GroupId)) - } - - return schema.NewSet(schema.HashString, vSecurityGroupIds) -} - -func flattenVpcEndpointDnsEntries(dnsEntries []*ec2.DnsEntry) []interface{} { - vDnsEntries := []interface{}{} - - for _, dnsEntry := range dnsEntries { - vDnsEntries = append(vDnsEntries, map[string]interface{}{ - "dns_name": aws.StringValue(dnsEntry.DnsName), - "hosted_zone_id": aws.StringValue(dnsEntry.HostedZoneId), - }) - } - - return vDnsEntries -} - func expandDynamoDbTableItemAttributes(input string) (map[string]*dynamodb.AttributeValue, error) { var attributes map[string]*dynamodb.AttributeValue From 864285b1bb6c014e2352c17d714969e9b9624712 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Wed, 15 May 2019 15:29:43 -0400 Subject: [PATCH 4/7] Tagging for VPC Endpoints and VPC Endpoint Services. --- aws/data_source_aws_vpc_endpoint.go | 45 +-- aws/data_source_aws_vpc_endpoint_service.go | 32 +- ...ta_source_aws_vpc_endpoint_service_test.go | 81 +++-- aws/data_source_aws_vpc_endpoint_test.go | 195 +++++++----- aws/resource_aws_vpc_endpoint.go | 107 ++++--- aws/resource_aws_vpc_endpoint_service.go | 24 +- aws/resource_aws_vpc_endpoint_service_test.go | 107 ++++--- aws/resource_aws_vpc_endpoint_test.go | 279 ++++++++++-------- website/docs/d/vpc_endpoint.html.markdown | 1 + .../docs/d/vpc_endpoint_service.html.markdown | 2 + website/docs/r/vpc_endpoint.html.markdown | 20 +- .../docs/r/vpc_endpoint_service.html.markdown | 20 +- 12 files changed, 538 insertions(+), 375 deletions(-) diff --git a/aws/data_source_aws_vpc_endpoint.go b/aws/data_source_aws_vpc_endpoint.go index c8fc0acc0be5..5b22bd94567d 100644 --- a/aws/data_source_aws_vpc_endpoint.go +++ b/aws/data_source_aws_vpc_endpoint.go @@ -15,26 +15,6 @@ func dataSourceAwsVpcEndpoint() *schema.Resource { Read: dataSourceAwsVpcEndpointRead, Schema: map[string]*schema.Schema{ - "id": { - Type: schema.TypeString, - Optional: true, - Computed: true, - }, - "service_name": { - Type: schema.TypeString, - Optional: true, - Computed: true, - }, - "state": { - Type: schema.TypeString, - Optional: true, - Computed: true, - }, - "vpc_id": { - Type: schema.TypeString, - Optional: true, - Computed: true, - }, "cidr_blocks": { Type: schema.TypeList, Computed: true, @@ -56,6 +36,11 @@ func dataSourceAwsVpcEndpoint() *schema.Resource { }, }, }, + "id": { + Type: schema.TypeString, + Optional: true, + Computed: true, + }, "network_interface_ids": { Type: schema.TypeSet, Computed: true, @@ -90,16 +75,32 @@ func dataSourceAwsVpcEndpoint() *schema.Resource { Elem: &schema.Schema{Type: schema.TypeString}, Set: schema.HashString, }, + "service_name": { + Type: schema.TypeString, + Optional: true, + Computed: true, + }, + "state": { + Type: schema.TypeString, + Optional: true, + Computed: true, + }, "subnet_ids": { Type: schema.TypeSet, Computed: true, Elem: &schema.Schema{Type: schema.TypeString}, Set: schema.HashString, }, + "tags": tagsSchemaComputed(), "vpc_endpoint_type": { Type: schema.TypeString, Computed: true, }, + "vpc_id": { + Type: schema.TypeString, + Optional: true, + Computed: true, + }, }, } } @@ -194,6 +195,10 @@ func dataSourceAwsVpcEndpointRead(d *schema.ResourceData, meta interface{}) erro if err != nil { return fmt.Errorf("error setting subnet_ids: %s", err) } + err = d.Set("tags", tagsToMap(vpce.Tags)) + if err != nil { + return fmt.Errorf("error setting tags: %s", err) + } // VPC endpoints don't have types in GovCloud, so set type to default if empty if vpceType := aws.StringValue(vpce.VpcEndpointType); vpceType == "" { d.Set("vpc_endpoint_type", ec2.VpcEndpointTypeGateway) diff --git a/aws/data_source_aws_vpc_endpoint_service.go b/aws/data_source_aws_vpc_endpoint_service.go index fcbcef7b6588..3a4fc93b65c7 100644 --- a/aws/data_source_aws_vpc_endpoint_service.go +++ b/aws/data_source_aws_vpc_endpoint_service.go @@ -16,17 +16,6 @@ func dataSourceAwsVpcEndpointService() *schema.Resource { Read: dataSourceAwsVpcEndpointServiceRead, Schema: map[string]*schema.Schema{ - "service": { - Type: schema.TypeString, - Optional: true, - ConflictsWith: []string{"service_name"}, - }, - "service_name": { - Type: schema.TypeString, - Optional: true, - Computed: true, - ConflictsWith: []string{"service"}, - }, "acceptance_required": { Type: schema.TypeBool, Computed: true, @@ -55,10 +44,26 @@ func dataSourceAwsVpcEndpointService() *schema.Resource { Type: schema.TypeString, Computed: true, }, + "service": { + Type: schema.TypeString, + Optional: true, + ConflictsWith: []string{"service_name"}, + }, + "service_id": { + Type: schema.TypeString, + Computed: true, + }, + "service_name": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ConflictsWith: []string{"service"}, + }, "service_type": { Type: schema.TypeString, Computed: true, }, + "tags": tagsSchemaComputed(), "vpc_endpoint_policy_supported": { Type: schema.TypeBool, Computed: true, @@ -130,7 +135,12 @@ func dataSourceAwsVpcEndpointServiceRead(d *schema.ResourceData, meta interface{ d.Set("manages_vpc_endpoints", sd.ManagesVpcEndpoints) d.Set("owner", sd.Owner) d.Set("private_dns_name", sd.PrivateDnsName) + d.Set("service_id", sd.ServiceId) d.Set("service_type", sd.ServiceType[0].ServiceType) + err = d.Set("tags", tagsToMap(sd.Tags)) + if err != nil { + return fmt.Errorf("error setting tags: %s", err) + } d.Set("vpc_endpoint_policy_supported", sd.VpcEndpointPolicySupported) return nil diff --git a/aws/data_source_aws_vpc_endpoint_service_test.go b/aws/data_source_aws_vpc_endpoint_service_test.go index 22b42ae7d811..b1cd15696025 100644 --- a/aws/data_source_aws_vpc_endpoint_service_test.go +++ b/aws/data_source_aws_vpc_endpoint_service_test.go @@ -9,7 +9,8 @@ import ( ) func TestAccDataSourceAwsVpcEndpointService_gateway(t *testing.T) { - datasourceName := "data.aws_vpc_endpoint_service.s3" + datasourceName := "data.aws_vpc_endpoint_service.test" + region := testAccGetRegion() resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -18,20 +19,16 @@ func TestAccDataSourceAwsVpcEndpointService_gateway(t *testing.T) { { Config: testAccDataSourceAwsVpcEndpointServiceGatewayConfig, Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(datasourceName, "service_name", "com.amazonaws.us-west-2.s3"), + resource.TestCheckResourceAttr(datasourceName, "service_name", fmt.Sprintf("com.amazonaws.%s.s3", region)), resource.TestCheckResourceAttr(datasourceName, "acceptance_required", "false"), - resource.TestCheckResourceAttr(datasourceName, "availability_zones.#", "4"), - resource.TestCheckResourceAttr(datasourceName, "availability_zones.2487133097", "us-west-2a"), - resource.TestCheckResourceAttr(datasourceName, "availability_zones.221770259", "us-west-2b"), - resource.TestCheckResourceAttr(datasourceName, "availability_zones.2050015877", "us-west-2c"), - resource.TestCheckResourceAttr(datasourceName, "availability_zones.3830732582", "us-west-2d"), + resource.TestCheckResourceAttrPair(datasourceName, "availability_zones.#", "data.aws_availability_zones.available", "names.#"), resource.TestCheckResourceAttr(datasourceName, "base_endpoint_dns_names.#", "1"), - resource.TestCheckResourceAttr(datasourceName, "base_endpoint_dns_names.3003388505", "s3.us-west-2.amazonaws.com"), resource.TestCheckResourceAttr(datasourceName, "manages_vpc_endpoints", "false"), resource.TestCheckResourceAttr(datasourceName, "owner", "amazon"), resource.TestCheckResourceAttr(datasourceName, "private_dns_name", ""), resource.TestCheckResourceAttr(datasourceName, "service_type", "Gateway"), resource.TestCheckResourceAttr(datasourceName, "vpc_endpoint_policy_supported", "true"), + resource.TestCheckResourceAttr(datasourceName, "tags.%", "0"), ), }, }, @@ -39,7 +36,8 @@ func TestAccDataSourceAwsVpcEndpointService_gateway(t *testing.T) { } func TestAccDataSourceAwsVpcEndpointService_interface(t *testing.T) { - datasourceName := "data.aws_vpc_endpoint_service.ec2" + datasourceName := "data.aws_vpc_endpoint_service.test" + region := testAccGetRegion() resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -48,19 +46,15 @@ func TestAccDataSourceAwsVpcEndpointService_interface(t *testing.T) { { Config: testAccDataSourceAwsVpcEndpointServiceInterfaceConfig, Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(datasourceName, "service_name", "com.amazonaws.us-west-2.ec2"), + resource.TestCheckResourceAttr(datasourceName, "service_name", fmt.Sprintf("com.amazonaws.%s.ec2", region)), resource.TestCheckResourceAttr(datasourceName, "acceptance_required", "false"), - resource.TestCheckResourceAttr(datasourceName, "availability_zones.#", "3"), - resource.TestCheckResourceAttr(datasourceName, "availability_zones.2487133097", "us-west-2a"), - resource.TestCheckResourceAttr(datasourceName, "availability_zones.221770259", "us-west-2b"), - resource.TestCheckResourceAttr(datasourceName, "availability_zones.2050015877", "us-west-2c"), resource.TestCheckResourceAttr(datasourceName, "base_endpoint_dns_names.#", "1"), - resource.TestCheckResourceAttr(datasourceName, "base_endpoint_dns_names.1880016359", "ec2.us-west-2.vpce.amazonaws.com"), resource.TestCheckResourceAttr(datasourceName, "manages_vpc_endpoints", "false"), resource.TestCheckResourceAttr(datasourceName, "owner", "amazon"), - resource.TestCheckResourceAttr(datasourceName, "private_dns_name", "ec2.us-west-2.amazonaws.com"), + resource.TestCheckResourceAttr(datasourceName, "private_dns_name", fmt.Sprintf("ec2.%s.amazonaws.com", region)), resource.TestCheckResourceAttr(datasourceName, "service_type", "Interface"), resource.TestCheckResourceAttr(datasourceName, "vpc_endpoint_policy_supported", "false"), + resource.TestCheckResourceAttr(datasourceName, "tags.%", "0"), ), }, }, @@ -68,7 +62,7 @@ func TestAccDataSourceAwsVpcEndpointService_interface(t *testing.T) { } func TestAccDataSourceAwsVpcEndpointService_custom(t *testing.T) { - datasourceName := "data.aws_vpc_endpoint_service.foo" + datasourceName := "data.aws_vpc_endpoint_service.test" rName := fmt.Sprintf("tf-testacc-vpcesvc-%s", acctest.RandStringFromCharSet(13, acctest.CharSetAlphaNum)) resource.ParallelTest(t, resource.TestCase{ @@ -80,12 +74,12 @@ func TestAccDataSourceAwsVpcEndpointService_custom(t *testing.T) { Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr(datasourceName, "acceptance_required", "true"), resource.TestCheckResourceAttr(datasourceName, "availability_zones.#", "2"), - resource.TestCheckResourceAttr(datasourceName, "availability_zones.2487133097", "us-west-2a"), - resource.TestCheckResourceAttr(datasourceName, "availability_zones.221770259", "us-west-2b"), resource.TestCheckResourceAttr(datasourceName, "manages_vpc_endpoints", "false"), testAccCheckResourceAttrAccountID(datasourceName, "owner"), resource.TestCheckResourceAttr(datasourceName, "service_type", "Interface"), resource.TestCheckResourceAttr(datasourceName, "vpc_endpoint_policy_supported", "false"), + resource.TestCheckResourceAttr(datasourceName, "tags.%", "1"), + resource.TestCheckResourceAttr(datasourceName, "tags.Name", rName), ), }, }, @@ -93,29 +87,22 @@ func TestAccDataSourceAwsVpcEndpointService_custom(t *testing.T) { } const testAccDataSourceAwsVpcEndpointServiceGatewayConfig = ` -provider "aws" { - region = "us-west-2" -} +data "aws_availability_zones" "available" {} -data "aws_vpc_endpoint_service" "s3" { +data "aws_vpc_endpoint_service" "test" { service = "s3" } ` const testAccDataSourceAwsVpcEndpointServiceInterfaceConfig = ` -provider "aws" { - region = "us-west-2" -} - -data "aws_vpc_endpoint_service" "ec2" { +data "aws_vpc_endpoint_service" "test" { service = "ec2" } ` func testAccDataSourceAwsVpcEndpointServiceCustomConfig(rName string) string { - return fmt.Sprintf( - ` -resource "aws_vpc" "nlb_test" { + return fmt.Sprintf(` +resource "aws_vpc" "test" { cidr_block = "10.0.0.0/16" tags = { @@ -123,12 +110,12 @@ resource "aws_vpc" "nlb_test" { } } -resource "aws_lb" "nlb_test_1" { +resource "aws_lb" "test" { name = %[1]q subnets = [ - "${aws_subnet.nlb_test_1.id}", - "${aws_subnet.nlb_test_2.id}", + "${aws_subnet.test1.id}", + "${aws_subnet.test2.id}", ] load_balancer_type = "network" @@ -141,36 +128,42 @@ resource "aws_lb" "nlb_test_1" { } } -resource "aws_subnet" "nlb_test_1" { - vpc_id = "${aws_vpc.nlb_test.id}" +data "aws_availability_zones" "available" {} + +resource "aws_subnet" "test1" { + vpc_id = "${aws_vpc.test.id}" cidr_block = "10.0.1.0/24" - availability_zone = "us-west-2a" + availability_zone = "${data.aws_availability_zones.available.names[0]}" tags = { Name = %[1]q } } -resource "aws_subnet" "nlb_test_2" { - vpc_id = "${aws_vpc.nlb_test.id}" +resource "aws_subnet" "test2" { + vpc_id = "${aws_vpc.test.id}" cidr_block = "10.0.2.0/24" - availability_zone = "us-west-2b" + availability_zone = "${data.aws_availability_zones.available.names[1]}" tags = { Name = %[1]q } } -resource "aws_vpc_endpoint_service" "foo" { +resource "aws_vpc_endpoint_service" "test" { acceptance_required = true network_load_balancer_arns = [ - "${aws_lb.nlb_test_1.id}", + "${aws_lb.test.id}", ] + + tags = { + Name = %[1]q + } } -data "aws_vpc_endpoint_service" "foo" { - service_name = "${aws_vpc_endpoint_service.foo.service_name}" +data "aws_vpc_endpoint_service" "test" { + service_name = "${aws_vpc_endpoint_service.test.service_name}" } `, rName) } diff --git a/aws/data_source_aws_vpc_endpoint_test.go b/aws/data_source_aws_vpc_endpoint_test.go index bd8faca3a0a3..e34065c56293 100644 --- a/aws/data_source_aws_vpc_endpoint_test.go +++ b/aws/data_source_aws_vpc_endpoint_test.go @@ -1,20 +1,23 @@ package aws import ( + "fmt" "testing" + "github.com/hashicorp/terraform/helper/acctest" "github.com/hashicorp/terraform/helper/resource" ) func TestAccDataSourceAwsVpcEndpoint_gatewayBasic(t *testing.T) { - datasourceName := "data.aws_vpc_endpoint.s3" + datasourceName := "data.aws_vpc_endpoint.test" + rName := fmt.Sprintf("tf-testacc-vpce-%s", acctest.RandStringFromCharSet(16, acctest.CharSetAlphaNum)) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, Steps: []resource.TestStep{ { - Config: testAccDataSourceAwsVpcEndpointConfig_gatewayBasic, + Config: testAccDataSourceAwsVpcEndpointConfig_gatewayBasic(rName), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr(datasourceName, "vpc_endpoint_type", "Gateway"), resource.TestCheckResourceAttrSet(datasourceName, "prefix_list_id"), @@ -25,6 +28,7 @@ func TestAccDataSourceAwsVpcEndpoint_gatewayBasic(t *testing.T) { resource.TestCheckResourceAttr(datasourceName, "security_group_ids.#", "0"), resource.TestCheckResourceAttr(datasourceName, "private_dns_enabled", "false"), resource.TestCheckResourceAttr(datasourceName, "requester_managed", "false"), + resource.TestCheckResourceAttr(datasourceName, "tags.%", "0"), ), }, }, @@ -32,14 +36,15 @@ func TestAccDataSourceAwsVpcEndpoint_gatewayBasic(t *testing.T) { } func TestAccDataSourceAwsVpcEndpoint_byId(t *testing.T) { - datasourceName := "data.aws_vpc_endpoint.s3" + datasourceName := "data.aws_vpc_endpoint.test" + rName := fmt.Sprintf("tf-testacc-vpce-%s", acctest.RandStringFromCharSet(16, acctest.CharSetAlphaNum)) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, Steps: []resource.TestStep{ { - Config: testAccDataSourceAwsVpcEndpointConfig_byId, + Config: testAccDataSourceAwsVpcEndpointConfig_byId(rName), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr(datasourceName, "vpc_endpoint_type", "Gateway"), resource.TestCheckResourceAttrSet(datasourceName, "prefix_list_id"), @@ -50,21 +55,23 @@ func TestAccDataSourceAwsVpcEndpoint_byId(t *testing.T) { resource.TestCheckResourceAttr(datasourceName, "security_group_ids.#", "0"), resource.TestCheckResourceAttr(datasourceName, "private_dns_enabled", "false"), resource.TestCheckResourceAttr(datasourceName, "requester_managed", "false"), + resource.TestCheckResourceAttr(datasourceName, "tags.%", "0"), ), }, }, }) } -func TestAccDataSourceAwsVpcEndpoint_gatewayWithRouteTable(t *testing.T) { - datasourceName := "data.aws_vpc_endpoint.s3" +func TestAccDataSourceAwsVpcEndpoint_gatewayWithRouteTableAndTags(t *testing.T) { + datasourceName := "data.aws_vpc_endpoint.test" + rName := fmt.Sprintf("tf-testacc-vpce-%s", acctest.RandStringFromCharSet(16, acctest.CharSetAlphaNum)) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, Steps: []resource.TestStep{ { - Config: testAccDataSourceAwsVpcEndpointConfig_gatewayWithRouteTable, + Config: testAccDataSourceAwsVpcEndpointConfig_gatewayWithRouteTableAndTags(rName), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr(datasourceName, "vpc_endpoint_type", "Gateway"), resource.TestCheckResourceAttrSet(datasourceName, "prefix_list_id"), @@ -75,6 +82,8 @@ func TestAccDataSourceAwsVpcEndpoint_gatewayWithRouteTable(t *testing.T) { resource.TestCheckResourceAttr(datasourceName, "security_group_ids.#", "0"), resource.TestCheckResourceAttr(datasourceName, "private_dns_enabled", "false"), resource.TestCheckResourceAttr(datasourceName, "requester_managed", "false"), + resource.TestCheckResourceAttr(datasourceName, "tags.%", "1"), + resource.TestCheckResourceAttr(datasourceName, "tags.Name", rName), ), }, }, @@ -82,14 +91,15 @@ func TestAccDataSourceAwsVpcEndpoint_gatewayWithRouteTable(t *testing.T) { } func TestAccDataSourceAwsVpcEndpoint_interface(t *testing.T) { - datasourceName := "data.aws_vpc_endpoint.ec2" + datasourceName := "data.aws_vpc_endpoint.test" + rName := fmt.Sprintf("tf-testacc-vpce-%s", acctest.RandStringFromCharSet(16, acctest.CharSetAlphaNum)) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, Steps: []resource.TestStep{ { - Config: testAccDataSourceAwsVpcEndpointConfig_interface, + Config: testAccDataSourceAwsVpcEndpointConfig_interface(rName), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr(datasourceName, "vpc_endpoint_type", "Interface"), resource.TestCheckNoResourceAttr(datasourceName, "prefix_list_id"), @@ -100,128 +110,159 @@ func TestAccDataSourceAwsVpcEndpoint_interface(t *testing.T) { resource.TestCheckResourceAttr(datasourceName, "security_group_ids.#", "1"), resource.TestCheckResourceAttr(datasourceName, "private_dns_enabled", "false"), resource.TestCheckResourceAttr(datasourceName, "requester_managed", "false"), + resource.TestCheckResourceAttr(datasourceName, "tags.%", "1"), + resource.TestCheckResourceAttr(datasourceName, "tags.Name", rName), ), }, }, }) } -const testAccDataSourceAwsVpcEndpointConfig_gatewayBasic = ` -provider "aws" { - region = "us-west-2" -} - -resource "aws_vpc" "foo" { +func testAccDataSourceAwsVpcEndpointConfig_gatewayBasic(rName string) string { + return fmt.Sprintf(` +resource "aws_vpc" "test" { cidr_block = "10.1.0.0/16" tags = { - Name = "terraform-testacc-vpc-endpoint-data-source-gw-basic" + Name = %[1]q } } -resource "aws_vpc_endpoint" "s3" { - vpc_id = "${aws_vpc.foo.id}" - service_name = "com.amazonaws.us-west-2.s3" -} +data "aws_region" "current" {} -data "aws_vpc_endpoint" "s3" { - vpc_id = "${aws_vpc.foo.id}" - service_name = "${aws_vpc_endpoint.s3.service_name}" - state = "available" +resource "aws_vpc_endpoint" "test" { + vpc_id = "${aws_vpc.test.id}" + service_name = "com.amazonaws.${data.aws_region.current.name}.s3" } -` -const testAccDataSourceAwsVpcEndpointConfig_byId = ` -provider "aws" { - region = "us-west-2" +data "aws_vpc_endpoint" "test" { + vpc_id = "${aws_vpc.test.id}" + service_name = "${aws_vpc_endpoint.test.service_name}" + state = "available" +} +`, rName) } -resource "aws_vpc" "foo" { +func testAccDataSourceAwsVpcEndpointConfig_byId(rName string) string { + return fmt.Sprintf(` +resource "aws_vpc" "test" { cidr_block = "10.1.0.0/16" tags = { - Name = "terraform-testacc-vpc-endpoint-data-source-by-id" + Name = %[1]q } } -resource "aws_vpc_endpoint" "s3" { - vpc_id = "${aws_vpc.foo.id}" - service_name = "com.amazonaws.us-west-2.s3" -} +data "aws_region" "current" {} -data "aws_vpc_endpoint" "s3" { - id = "${aws_vpc_endpoint.s3.id}" +resource "aws_vpc_endpoint" "test" { + vpc_id = "${aws_vpc.test.id}" + service_name = "com.amazonaws.${data.aws_region.current.name}.s3" } -` -const testAccDataSourceAwsVpcEndpointConfig_gatewayWithRouteTable = ` -provider "aws" { - region = "us-west-2" +data "aws_vpc_endpoint" "test" { + id = "${aws_vpc_endpoint.test.id}" +} +`, rName) } -resource "aws_vpc" "foo" { +func testAccDataSourceAwsVpcEndpointConfig_gatewayWithRouteTableAndTags(rName string) string { + return fmt.Sprintf(` +resource "aws_vpc" "test" { cidr_block = "10.1.0.0/16" tags = { - Name = "terraform-testacc-vpc-endpoint-data-source-with-route-table" + Name = %[1]q } } -resource "aws_route_table" "rt" { - vpc_id = "${aws_vpc.foo.id}" -} +resource "aws_route_table" "test" { + vpc_id = "${aws_vpc.test.id}" -resource "aws_vpc_endpoint" "s3" { - vpc_id = "${aws_vpc.foo.id}" - service_name = "com.amazonaws.us-west-2.s3" - route_table_ids = ["${aws_route_table.rt.id}"] + tags = { + Name = %[1]q + } } -data "aws_vpc_endpoint" "s3" { - vpc_id = "${aws_vpc.foo.id}" - service_name = "${aws_vpc_endpoint.s3.service_name}" - state = "available" +data "aws_region" "current" {} + +resource "aws_vpc_endpoint" "test" { + vpc_id = "${aws_vpc.test.id}" + service_name = "com.amazonaws.${data.aws_region.current.name}.s3" + + route_table_ids = [ + "${aws_route_table.test.id}", + ] + + tags = { + Name = %[1]q + } } -` -const testAccDataSourceAwsVpcEndpointConfig_interface = ` -provider "aws" { - region = "us-west-2" +data "aws_vpc_endpoint" "test" { + vpc_id = "${aws_vpc.test.id}" + service_name = "${aws_vpc_endpoint.test.service_name}" + state = "available" +} +`, rName) } -resource "aws_vpc" "foo" { +func testAccDataSourceAwsVpcEndpointConfig_interface(rName string) string { + return fmt.Sprintf(` +resource "aws_vpc" "test" { cidr_block = "10.1.0.0/16" tags = { - Name = "terraform-testacc-vpc-endpoint-data-source-interface" + Name = %[1]q } } -resource "aws_subnet" "sn" { - vpc_id = "${aws_vpc.foo.id}" - cidr_block = "${aws_vpc.foo.cidr_block}" - availability_zone = "us-west-2a" +data "aws_availability_zones" "available" {} + +resource "aws_subnet" "test" { + vpc_id = "${aws_vpc.test.id}" + cidr_block = "${aws_vpc.test.cidr_block}" + availability_zone = "${data.aws_availability_zones.available.names[0]}" + tags = { - Name = "tf-acc-vpc-endpoint-data-source-interface" + Name = %[1]q } } -resource "aws_security_group" "sg" { - vpc_id = "${aws_vpc.foo.id}" +resource "aws_security_group" "test" { + vpc_id = "${aws_vpc.test.id}" + name = %[1]q + + tags = { + Name = %[1]q + } } -resource "aws_vpc_endpoint" "ec2" { - vpc_id = "${aws_vpc.foo.id}" - vpc_endpoint_type = "Interface" - service_name = "com.amazonaws.us-west-2.ec2" - subnet_ids = ["${aws_subnet.sn.id}"] - security_group_ids = ["${aws_security_group.sg.id}"] +data "aws_region" "current" {} + +resource "aws_vpc_endpoint" "test" { + vpc_id = "${aws_vpc.test.id}" + vpc_endpoint_type = "Interface" + service_name = "com.amazonaws.${data.aws_region.current.name}.ec2" private_dns_enabled = false + + subnet_ids = [ + "${aws_subnet.test.id}", + ] + + security_group_ids = [ + "${aws_security_group.test.id}", + ] + + tags = { + Name = %[1]q + } } -data "aws_vpc_endpoint" "ec2" { - vpc_id = "${aws_vpc.foo.id}" - service_name = "${aws_vpc_endpoint.ec2.service_name}" - state = "available" +data "aws_vpc_endpoint" "test" { + vpc_id = "${aws_vpc.test.id}" + service_name = "${aws_vpc_endpoint.test.service_name}" + state = "available" +} +`, rName) } -` diff --git a/aws/resource_aws_vpc_endpoint.go b/aws/resource_aws_vpc_endpoint.go index c522f314b71e..dc7ab25b4db6 100644 --- a/aws/resource_aws_vpc_endpoint.go +++ b/aws/resource_aws_vpc_endpoint.go @@ -25,20 +25,37 @@ func resourceAwsVpcEndpoint() *schema.Resource { }, Schema: map[string]*schema.Schema{ - "service_name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "vpc_id": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, "auto_accept": { Type: schema.TypeBool, Optional: true, }, + "cidr_blocks": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "dns_entry": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "dns_name": { + Type: schema.TypeString, + Computed: true, + }, + "hosted_zone_id": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + "network_interface_ids": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Set: schema.HashString, + }, "policy": { Type: schema.TypeString, Optional: true, @@ -50,11 +67,19 @@ func resourceAwsVpcEndpoint() *schema.Resource { return json }, }, + "prefix_list_id": { + Type: schema.TypeString, + Computed: true, + }, "private_dns_enabled": { Type: schema.TypeBool, Optional: true, Default: false, }, + "requester_managed": { + Type: schema.TypeBool, + Computed: true, + }, "route_table_ids": { Type: schema.TypeSet, Optional: true, @@ -69,6 +94,15 @@ func resourceAwsVpcEndpoint() *schema.Resource { Elem: &schema.Schema{Type: schema.TypeString}, Set: schema.HashString, }, + "service_name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "state": { + Type: schema.TypeString, + Computed: true, + }, "subnet_ids": { Type: schema.TypeSet, Optional: true, @@ -76,6 +110,7 @@ func resourceAwsVpcEndpoint() *schema.Resource { Elem: &schema.Schema{Type: schema.TypeString}, Set: schema.HashString, }, + "tags": tagsSchema(), "vpc_endpoint_type": { Type: schema.TypeString, Optional: true, @@ -86,44 +121,10 @@ func resourceAwsVpcEndpoint() *schema.Resource { ec2.VpcEndpointTypeInterface, }, false), }, - "cidr_blocks": { - Type: schema.TypeList, - Computed: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - "dns_entry": { - Type: schema.TypeList, - Computed: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "dns_name": { - Type: schema.TypeString, - Computed: true, - }, - "hosted_zone_id": { - Type: schema.TypeString, - Computed: true, - }, - }, - }, - }, - "network_interface_ids": { - Type: schema.TypeSet, - Computed: true, - Elem: &schema.Schema{Type: schema.TypeString}, - Set: schema.HashString, - }, - "prefix_list_id": { - Type: schema.TypeString, - Computed: true, - }, - "requester_managed": { - Type: schema.TypeBool, - Computed: true, - }, - "state": { + "vpc_id": { Type: schema.TypeString, - Computed: true, + Required: true, + ForceNew: true, }, }, @@ -181,6 +182,10 @@ func resourceAwsVpcEndpointCreate(d *schema.ResourceData, meta interface{}) erro return err } + if err := setTags(conn, d); err != nil { + return err + } + return resourceAwsVpcEndpointRead(d, meta) } @@ -261,6 +266,10 @@ func resourceAwsVpcEndpointRead(d *schema.ResourceData, meta interface{}) error if err != nil { return fmt.Errorf("error setting subnet_ids: %s", err) } + err = d.Set("tags", tagsToMap(vpce.Tags)) + if err != nil { + return fmt.Errorf("error setting tags: %s", err) + } // VPC endpoints don't have types in GovCloud, so set type to default if empty if vpceType := aws.StringValue(vpce.VpcEndpointType); vpceType == "" { d.Set("vpc_endpoint_type", ec2.VpcEndpointTypeGateway) @@ -314,6 +323,10 @@ func resourceAwsVpcEndpointUpdate(d *schema.ResourceData, meta interface{}) erro return err } + if err := setTags(conn, d); err != nil { + return err + } + return resourceAwsVpcEndpointRead(d, meta) } diff --git a/aws/resource_aws_vpc_endpoint_service.go b/aws/resource_aws_vpc_endpoint_service.go index e9546f90d211..83b728752f5d 100644 --- a/aws/resource_aws_vpc_endpoint_service.go +++ b/aws/resource_aws_vpc_endpoint_service.go @@ -27,13 +27,6 @@ func resourceAwsVpcEndpointService() *schema.Resource { Type: schema.TypeBool, Required: true, }, - "network_load_balancer_arns": { - Type: schema.TypeSet, - Required: true, - MinItems: 1, - Elem: &schema.Schema{Type: schema.TypeString}, - Set: schema.HashString, - }, "allowed_principals": { Type: schema.TypeSet, Optional: true, @@ -57,6 +50,13 @@ func resourceAwsVpcEndpointService() *schema.Resource { Type: schema.TypeBool, Computed: true, }, + "network_load_balancer_arns": { + Type: schema.TypeSet, + Required: true, + MinItems: 1, + Elem: &schema.Schema{Type: schema.TypeString}, + Set: schema.HashString, + }, "private_dns_name": { Type: schema.TypeString, Computed: true, @@ -73,6 +73,7 @@ func resourceAwsVpcEndpointService() *schema.Resource { Type: schema.TypeString, Computed: true, }, + "tags": tagsSchema(), }, } } @@ -138,6 +139,10 @@ func resourceAwsVpcEndpointServiceRead(d *schema.ResourceData, meta interface{}) d.Set("service_name", svcCfg.ServiceName) d.Set("service_type", svcCfg.ServiceType[0].ServiceType) d.Set("state", svcCfg.ServiceState) + err = d.Set("tags", tagsToMap(svcCfg.Tags)) + if err != nil { + return fmt.Errorf("error setting tags: %s", err) + } resp, err := conn.DescribeVpcEndpointServicePermissions(&ec2.DescribeVpcEndpointServicePermissionsInput{ ServiceId: aws.String(d.Id()), @@ -197,6 +202,11 @@ func resourceAwsVpcEndpointServiceUpdate(d *schema.ResourceData, meta interface{ d.SetPartial("allowed_principals") } + if err := setTags(conn, d); err != nil { + return err + } + d.SetPartial("tags") + d.Partial(false) return resourceAwsVpcEndpointServiceRead(d, meta) } diff --git a/aws/resource_aws_vpc_endpoint_service_test.go b/aws/resource_aws_vpc_endpoint_service_test.go index d1ccfb06f0fc..a6177fd00ad1 100644 --- a/aws/resource_aws_vpc_endpoint_service_test.go +++ b/aws/resource_aws_vpc_endpoint_service_test.go @@ -82,24 +82,27 @@ func testSweepEc2VpcEndpointServices(region string) error { func TestAccAWSVpcEndpointService_basic(t *testing.T) { var svcCfg ec2.ServiceConfiguration - resourceName := "aws_vpc_endpoint_service.foo" + resourceName := "aws_vpc_endpoint_service.test" rName1 := fmt.Sprintf("tf-testacc-vpcesvc-%s", acctest.RandStringFromCharSet(13, acctest.CharSetAlphaNum)) rName2 := fmt.Sprintf("tf-testacc-vpcesvc-%s", acctest.RandStringFromCharSet(13, acctest.CharSetAlphaNum)) resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - IDRefreshName: "aws_vpc_endpoint_service.foo", - Providers: testAccProviders, - CheckDestroy: testAccCheckVpcEndpointServiceDestroy, + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckVpcEndpointServiceDestroy, Steps: []resource.TestStep{ { - Config: testAccVpcEndpointServiceBasicConfig(rName1), + Config: testAccVpcEndpointServiceConfig_basic(rName1), Check: resource.ComposeTestCheckFunc( testAccCheckVpcEndpointServiceExists(resourceName, &svcCfg), resource.TestCheckResourceAttr(resourceName, "acceptance_required", "false"), resource.TestCheckResourceAttr(resourceName, "network_load_balancer_arns.#", "1"), resource.TestCheckResourceAttr(resourceName, "allowed_principals.#", "1"), resource.TestCheckResourceAttr(resourceName, "manages_vpc_endpoints", "false"), + resource.TestCheckResourceAttr(resourceName, "tags.%", "3"), + resource.TestCheckResourceAttr(resourceName, "tags.Environment", "test"), + resource.TestCheckResourceAttr(resourceName, "tags.Usage", "original"), + resource.TestCheckResourceAttr(resourceName, "tags.Name", rName1), ), }, { @@ -108,12 +111,15 @@ func TestAccAWSVpcEndpointService_basic(t *testing.T) { ImportStateVerify: true, }, { - Config: testAccVpcEndpointServiceModifiedConfig(rName1, rName2), + Config: testAccVpcEndpointServiceConfig_modified(rName1, rName2), Check: resource.ComposeTestCheckFunc( - testAccCheckVpcEndpointServiceExists("aws_vpc_endpoint_service.foo", &svcCfg), + testAccCheckVpcEndpointServiceExists(resourceName, &svcCfg), resource.TestCheckResourceAttr(resourceName, "acceptance_required", "true"), resource.TestCheckResourceAttr(resourceName, "network_load_balancer_arns.#", "2"), resource.TestCheckResourceAttr(resourceName, "allowed_principals.#", "0"), + resource.TestCheckResourceAttr(resourceName, "tags.%", "2"), + resource.TestCheckResourceAttr(resourceName, "tags.Usage", "changed"), + resource.TestCheckResourceAttr(resourceName, "tags.Name", rName1), ), }, }, @@ -122,7 +128,7 @@ func TestAccAWSVpcEndpointService_basic(t *testing.T) { func TestAccAWSVpcEndpointService_removed(t *testing.T) { var svcCfg ec2.ServiceConfiguration - resourceName := "aws_vpc_endpoint_service.foo" + resourceName := "aws_vpc_endpoint_service.test" rName := fmt.Sprintf("tf-testacc-vpcesvc-%s", acctest.RandStringFromCharSet(13, acctest.CharSetAlphaNum)) testDestroy := func(*terraform.State) error { @@ -141,7 +147,7 @@ func TestAccAWSVpcEndpointService_removed(t *testing.T) { CheckDestroy: testAccCheckVpcEndpointServiceDestroy, Steps: []resource.TestStep{ { - Config: testAccVpcEndpointServiceBasicConfig(rName), + Config: testAccVpcEndpointServiceConfig_basic(rName), Check: resource.ComposeTestCheckFunc( testAccCheckVpcEndpointServiceExists(resourceName, &svcCfg), testDestroy, @@ -209,10 +215,9 @@ func testAccCheckVpcEndpointServiceExists(n string, svcCfg *ec2.ServiceConfigura } } -func testAccVpcEndpointServiceBasicConfig(rName string) string { - return fmt.Sprintf( - ` -resource "aws_vpc" "nlb_test" { +func testAccVpcEndpointServiceConfig_basic(rName string) string { + return fmt.Sprintf(` +resource "aws_vpc" "test" { cidr_block = "10.0.0.0/16" tags = { @@ -220,12 +225,12 @@ resource "aws_vpc" "nlb_test" { } } -resource "aws_lb" "nlb_test_1" { +resource "aws_lb" "test1" { name = %[1]q subnets = [ - "${aws_subnet.nlb_test_1.id}", - "${aws_subnet.nlb_test_2.id}", + "${aws_subnet.test1.id}", + "${aws_subnet.test2.id}", ] load_balancer_type = "network" @@ -238,20 +243,22 @@ resource "aws_lb" "nlb_test_1" { } } -resource "aws_subnet" "nlb_test_1" { - vpc_id = "${aws_vpc.nlb_test.id}" +data "aws_availability_zones" "available" {} + +resource "aws_subnet" "test1" { + vpc_id = "${aws_vpc.test.id}" cidr_block = "10.0.1.0/24" - availability_zone = "us-west-2a" + availability_zone = "${data.aws_availability_zones.available.names[0]}" tags = { Name = %[1]q } } -resource "aws_subnet" "nlb_test_2" { - vpc_id = "${aws_vpc.nlb_test.id}" +resource "aws_subnet" "test2" { + vpc_id = "${aws_vpc.test.id}" cidr_block = "10.0.2.0/24" - availability_zone = "us-west-2b" + availability_zone = "${data.aws_availability_zones.available.names[1]}" tags = { Name = %[1]q @@ -260,24 +267,29 @@ resource "aws_subnet" "nlb_test_2" { data "aws_caller_identity" "current" {} -resource "aws_vpc_endpoint_service" "foo" { +resource "aws_vpc_endpoint_service" "test" { acceptance_required = false network_load_balancer_arns = [ - "${aws_lb.nlb_test_1.id}", + "${aws_lb.test1.arn}", ] allowed_principals = [ "${data.aws_caller_identity.current.arn}" ] + + tags = { + Environment = "test" + Usage = "original" + Name = %[1]q + } } `, rName) } -func testAccVpcEndpointServiceModifiedConfig(rName1, rName2 string) string { - return fmt.Sprintf( - ` -resource "aws_vpc" "nlb_test" { +func testAccVpcEndpointServiceConfig_modified(rName1, rName2 string) string { + return fmt.Sprintf(` +resource "aws_vpc" "test" { cidr_block = "10.0.0.0/16" tags = { @@ -285,12 +297,12 @@ resource "aws_vpc" "nlb_test" { } } -resource "aws_lb" "nlb_test_1" { +resource "aws_lb" "test1" { name = %[1]q subnets = [ - "${aws_subnet.nlb_test_1.id}", - "${aws_subnet.nlb_test_2.id}", + "${aws_subnet.test1.id}", + "${aws_subnet.test2.id}", ] load_balancer_type = "network" @@ -303,12 +315,12 @@ resource "aws_lb" "nlb_test_1" { } } -resource "aws_lb" "nlb_test_2" { +resource "aws_lb" "test2" { name = %[2]q subnets = [ - "${aws_subnet.nlb_test_1.id}", - "${aws_subnet.nlb_test_2.id}", + "${aws_subnet.test1.id}", + "${aws_subnet.test2.id}", ] load_balancer_type = "network" @@ -321,20 +333,22 @@ resource "aws_lb" "nlb_test_2" { } } -resource "aws_subnet" "nlb_test_1" { - vpc_id = "${aws_vpc.nlb_test.id}" +data "aws_availability_zones" "available" {} + +resource "aws_subnet" "test1" { + vpc_id = "${aws_vpc.test.id}" cidr_block = "10.0.1.0/24" - availability_zone = "us-west-2a" + availability_zone = "${data.aws_availability_zones.available.names[0]}" tags = { Name = %[1]q } } -resource "aws_subnet" "nlb_test_2" { - vpc_id = "${aws_vpc.nlb_test.id}" +resource "aws_subnet" "test2" { + vpc_id = "${aws_vpc.test.id}" cidr_block = "10.0.2.0/24" - availability_zone = "us-west-2b" + availability_zone = "${data.aws_availability_zones.available.names[1]}" tags = { Name = %[1]q @@ -343,15 +357,20 @@ resource "aws_subnet" "nlb_test_2" { data "aws_caller_identity" "current" {} -resource "aws_vpc_endpoint_service" "foo" { +resource "aws_vpc_endpoint_service" "test" { acceptance_required = true network_load_balancer_arns = [ - "${aws_lb.nlb_test_1.id}", - "${aws_lb.nlb_test_2.id}", + "${aws_lb.test1.arn}", + "${aws_lb.test2.arn}", ] allowed_principals = [] + + tags = { + Usage = "changed" + Name = %[1]q + } } `, rName1, rName2) } diff --git a/aws/resource_aws_vpc_endpoint_test.go b/aws/resource_aws_vpc_endpoint_test.go index 39a95ccbe4e2..007028caf6be 100644 --- a/aws/resource_aws_vpc_endpoint_test.go +++ b/aws/resource_aws_vpc_endpoint_test.go @@ -83,7 +83,7 @@ func testSweepEc2VpcEndpoints(region string) error { func TestAccAWSVpcEndpoint_gatewayBasic(t *testing.T) { var endpoint ec2.VpcEndpoint - resourceName := "aws_vpc_endpoint.s3" + resourceName := "aws_vpc_endpoint.test" rName := fmt.Sprintf("tf-testacc-vpce-%s", acctest.RandStringFromCharSet(16, acctest.CharSetAlphaNum)) resource.ParallelTest(t, resource.TestCase{ @@ -92,7 +92,7 @@ func TestAccAWSVpcEndpoint_gatewayBasic(t *testing.T) { CheckDestroy: testAccCheckVpcEndpointDestroy, Steps: []resource.TestStep{ { - Config: testAccVpcEndpointConfig_gatewayWithoutRouteTableOrPolicy(rName), + Config: testAccVpcEndpointConfig_gatewayWithoutRouteTableOrPolicyOrTags(rName), Check: resource.ComposeTestCheckFunc( testAccCheckVpcEndpointExists(resourceName, &endpoint), testAccCheckVpcEndpointPrefixListAvailable(resourceName), @@ -103,17 +103,18 @@ func TestAccAWSVpcEndpoint_gatewayBasic(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "security_group_ids.#", "0"), resource.TestCheckResourceAttr(resourceName, "private_dns_enabled", "false"), resource.TestCheckResourceAttr(resourceName, "requester_managed", "false"), + resource.TestCheckResourceAttr(resourceName, "tags.%", "0"), ), }, }, }) } -func TestAccAWSVpcEndpoint_gatewayWithRouteTableAndPolicy(t *testing.T) { +func TestAccAWSVpcEndpoint_gatewayWithRouteTableAndPolicyAndTags(t *testing.T) { var endpoint ec2.VpcEndpoint var routeTable ec2.RouteTable - resourceName := "aws_vpc_endpoint.s3" - resourceNameRt := "aws_route_table.default" + resourceName := "aws_vpc_endpoint.test" + resourceNameRt := "aws_route_table.test" rName := fmt.Sprintf("tf-testacc-vpce-%s", acctest.RandStringFromCharSet(16, acctest.CharSetAlphaNum)) resource.ParallelTest(t, resource.TestCase{ @@ -122,7 +123,7 @@ func TestAccAWSVpcEndpoint_gatewayWithRouteTableAndPolicy(t *testing.T) { CheckDestroy: testAccCheckVpcEndpointDestroy, Steps: []resource.TestStep{ { - Config: testAccVpcEndpointConfig_gatewayWithRouteTableAndPolicy(rName), + Config: testAccVpcEndpointConfig_gatewayWithRouteTableAndPolicyAndTags(rName), Check: resource.ComposeTestCheckFunc( testAccCheckVpcEndpointExists(resourceName, &endpoint), testAccCheckRouteTableExists(resourceNameRt, &routeTable), @@ -134,10 +135,14 @@ func TestAccAWSVpcEndpoint_gatewayWithRouteTableAndPolicy(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "security_group_ids.#", "0"), resource.TestCheckResourceAttr(resourceName, "private_dns_enabled", "false"), resource.TestCheckResourceAttr(resourceName, "requester_managed", "false"), + resource.TestCheckResourceAttr(resourceName, "tags.%", "3"), + resource.TestCheckResourceAttr(resourceName, "tags.Environment", "test"), + resource.TestCheckResourceAttr(resourceName, "tags.Usage", "original"), + resource.TestCheckResourceAttr(resourceName, "tags.Name", rName), ), }, { - Config: testAccVpcEndpointConfig_gatewayWithRouteTableAndPolicyModified(rName), + Config: testAccVpcEndpointConfig_gatewayWithRouteTableAndPolicyAndTagsModified(rName), Check: resource.ComposeTestCheckFunc( testAccCheckVpcEndpointExists(resourceName, &endpoint), testAccCheckRouteTableExists(resourceNameRt, &routeTable), @@ -149,6 +154,9 @@ func TestAccAWSVpcEndpoint_gatewayWithRouteTableAndPolicy(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "security_group_ids.#", "0"), resource.TestCheckResourceAttr(resourceName, "private_dns_enabled", "false"), resource.TestCheckResourceAttr(resourceName, "requester_managed", "false"), + resource.TestCheckResourceAttr(resourceName, "tags.%", "2"), + resource.TestCheckResourceAttr(resourceName, "tags.Usage", "changed"), + resource.TestCheckResourceAttr(resourceName, "tags.Name", rName), ), }, { @@ -224,7 +232,7 @@ func TestAccAWSVpcEndpoint_gatewayPolicy(t *testing.T) { func TestAccAWSVpcEndpoint_interfaceBasic(t *testing.T) { var endpoint ec2.VpcEndpoint - resourceName := "aws_vpc_endpoint.ec2" + resourceName := "aws_vpc_endpoint.test" rName := fmt.Sprintf("tf-testacc-vpce-%s", acctest.RandStringFromCharSet(16, acctest.CharSetAlphaNum)) resource.ParallelTest(t, resource.TestCase{ @@ -245,6 +253,7 @@ func TestAccAWSVpcEndpoint_interfaceBasic(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "security_group_ids.#", "1"), resource.TestCheckResourceAttr(resourceName, "private_dns_enabled", "false"), resource.TestCheckResourceAttr(resourceName, "requester_managed", "false"), + resource.TestCheckResourceAttr(resourceName, "tags.%", "0"), ), }, }, @@ -253,7 +262,7 @@ func TestAccAWSVpcEndpoint_interfaceBasic(t *testing.T) { func TestAccAWSVpcEndpoint_interfaceWithSubnetAndSecurityGroup(t *testing.T) { var endpoint ec2.VpcEndpoint - resourceName := "aws_vpc_endpoint.ec2" + resourceName := "aws_vpc_endpoint.test" rName := fmt.Sprintf("tf-testacc-vpce-%s", acctest.RandStringFromCharSet(16, acctest.CharSetAlphaNum)) resource.ParallelTest(t, resource.TestCase{ @@ -274,6 +283,8 @@ func TestAccAWSVpcEndpoint_interfaceWithSubnetAndSecurityGroup(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "security_group_ids.#", "2"), resource.TestCheckResourceAttr(resourceName, "private_dns_enabled", "false"), resource.TestCheckResourceAttr(resourceName, "requester_managed", "false"), + resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), + resource.TestCheckResourceAttr(resourceName, "tags.Name", rName), ), }, { @@ -289,6 +300,7 @@ func TestAccAWSVpcEndpoint_interfaceWithSubnetAndSecurityGroup(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "security_group_ids.#", "1"), resource.TestCheckResourceAttr(resourceName, "private_dns_enabled", "true"), resource.TestCheckResourceAttr(resourceName, "requester_managed", "false"), + resource.TestCheckResourceAttr(resourceName, "tags.%", "0"), ), }, { @@ -302,7 +314,7 @@ func TestAccAWSVpcEndpoint_interfaceWithSubnetAndSecurityGroup(t *testing.T) { func TestAccAWSVpcEndpoint_interfaceNonAWSService(t *testing.T) { var endpoint ec2.VpcEndpoint - resourceName := "aws_vpc_endpoint.foo" + resourceName := "aws_vpc_endpoint.test" rName := fmt.Sprintf("tf-testacc-vpce-%s", acctest.RandStringFromCharSet(16, acctest.CharSetAlphaNum)) resource.ParallelTest(t, resource.TestCase{ @@ -324,6 +336,8 @@ func TestAccAWSVpcEndpoint_interfaceNonAWSService(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "private_dns_enabled", "false"), resource.TestCheckResourceAttr(resourceName, "requester_managed", "false"), resource.TestCheckResourceAttr(resourceName, "state", "available"), + resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), + resource.TestCheckResourceAttr(resourceName, "tags.Name", rName), ), }, }, @@ -332,7 +346,7 @@ func TestAccAWSVpcEndpoint_interfaceNonAWSService(t *testing.T) { func TestAccAWSVpcEndpoint_removed(t *testing.T) { var endpoint ec2.VpcEndpoint - resourceName := "aws_vpc_endpoint.s3" + resourceName := "aws_vpc_endpoint.test" rName := fmt.Sprintf("tf-testacc-vpce-%s", acctest.RandStringFromCharSet(16, acctest.CharSetAlphaNum)) // reach out and DELETE the VPC Endpoint outside of Terraform @@ -353,7 +367,7 @@ func TestAccAWSVpcEndpoint_removed(t *testing.T) { CheckDestroy: testAccCheckVpcEndpointDestroy, Steps: []resource.TestStep{ { - Config: testAccVpcEndpointConfig_gatewayWithoutRouteTableOrPolicy(rName), + Config: testAccVpcEndpointConfig_gatewayWithoutRouteTableOrPolicyOrTags(rName), Check: resource.ComposeTestCheckFunc( testAccCheckVpcEndpointExists(resourceName, &endpoint), testDestroy, @@ -454,9 +468,9 @@ func testAccCheckVpcEndpointPrefixListAvailable(n string) resource.TestCheckFunc } } -func testAccVpcEndpointConfig_gatewayWithoutRouteTableOrPolicy(rName string) string { +func testAccVpcEndpointConfig_gatewayWithoutRouteTableOrPolicyOrTags(rName string) string { return fmt.Sprintf(` -resource "aws_vpc" "foo" { +resource "aws_vpc" "test" { cidr_block = "10.0.0.0/16" tags = { @@ -466,16 +480,16 @@ resource "aws_vpc" "foo" { data "aws_region" "current" {} -resource "aws_vpc_endpoint" "s3" { - vpc_id = "${aws_vpc.foo.id}" +resource "aws_vpc_endpoint" "test" { + vpc_id = "${aws_vpc.test.id}" service_name = "com.amazonaws.${data.aws_region.current.name}.s3" } `, rName) } -func testAccVpcEndpointConfig_gatewayWithRouteTableAndPolicy(rName string) string { +func testAccVpcEndpointConfig_gatewayWithRouteTableAndPolicyAndTags(rName string) string { return fmt.Sprintf(` -resource "aws_vpc" "foo" { +resource "aws_vpc" "test" { cidr_block = "10.0.0.0/16" tags = { @@ -483,8 +497,8 @@ resource "aws_vpc" "foo" { } } -resource "aws_subnet" "foo" { - vpc_id = "${aws_vpc.foo.id}" +resource "aws_subnet" "test" { + vpc_id = "${aws_vpc.test.id}" cidr_block = "10.0.1.0/24" tags = { @@ -494,11 +508,12 @@ resource "aws_subnet" "foo" { data "aws_region" "current" {} -resource "aws_vpc_endpoint" "s3" { - vpc_id = "${aws_vpc.foo.id}" - service_name = "com.amazonaws.${data.aws_region.current.name}.s3" +resource "aws_vpc_endpoint" "test" { + vpc_id = "${aws_vpc.test.id}" + service_name = "com.amazonaws.${data.aws_region.current.name}.s3" + route_table_ids = [ - "${aws_route_table.default.id}", + "${aws_route_table.test.id}", ] policy = < Date: Thu, 30 May 2019 15:21:13 -0400 Subject: [PATCH 5/7] Run terrafmt. --- aws/resource_aws_vpc_endpoint_service_test.go | 10 +++++----- aws/resource_aws_vpc_endpoint_test.go | 12 ++++++------ 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/aws/resource_aws_vpc_endpoint_service_test.go b/aws/resource_aws_vpc_endpoint_service_test.go index a6177fd00ad1..4972b0f3d9fc 100644 --- a/aws/resource_aws_vpc_endpoint_service_test.go +++ b/aws/resource_aws_vpc_endpoint_service_test.go @@ -226,7 +226,7 @@ resource "aws_vpc" "test" { } resource "aws_lb" "test1" { - name = %[1]q + name = %[1]q subnets = [ "${aws_subnet.test1.id}", @@ -239,7 +239,7 @@ resource "aws_lb" "test1" { enable_deletion_protection = false tags = { - Name = %[1]q + Name = %[1]q } } @@ -251,7 +251,7 @@ resource "aws_subnet" "test1" { availability_zone = "${data.aws_availability_zones.available.names[0]}" tags = { - Name = %[1]q + Name = %[1]q } } @@ -261,7 +261,7 @@ resource "aws_subnet" "test2" { availability_zone = "${data.aws_availability_zones.available.names[1]}" tags = { - Name = %[1]q + Name = %[1]q } } @@ -275,7 +275,7 @@ resource "aws_vpc_endpoint_service" "test" { ] allowed_principals = [ - "${data.aws_caller_identity.current.arn}" + "${data.aws_caller_identity.current.arn}", ] tags = { diff --git a/aws/resource_aws_vpc_endpoint_test.go b/aws/resource_aws_vpc_endpoint_test.go index 007028caf6be..f3b5974a7aa7 100644 --- a/aws/resource_aws_vpc_endpoint_test.go +++ b/aws/resource_aws_vpc_endpoint_test.go @@ -510,7 +510,7 @@ data "aws_region" "current" {} resource "aws_vpc_endpoint" "test" { vpc_id = "${aws_vpc.test.id}" - service_name = "com.amazonaws.${data.aws_region.current.name}.s3" + service_name = "com.amazonaws.${data.aws_region.current.name}.s3" route_table_ids = [ "${aws_route_table.test.id}", @@ -574,7 +574,7 @@ data "aws_region" "current" {} resource "aws_vpc_endpoint" "test" { vpc_id = "${aws_vpc.test.id}" - service_name = "com.amazonaws.${data.aws_region.current.name}.s3" + service_name = "com.amazonaws.${data.aws_region.current.name}.s3" route_table_ids = [] @@ -634,7 +634,7 @@ data "aws_region" "current" {} resource "aws_vpc_endpoint" "test" { vpc_id = "${aws_vpc.test.id}" service_name = "com.amazonaws.${data.aws_region.current.name}.ec2" - vpc_endpoint_type = "Interface" + vpc_endpoint_type = "Interface" security_group_ids = [ "${data.aws_security_group.test.id}", @@ -730,12 +730,12 @@ resource "aws_security_group" "test2" { resource "aws_vpc_endpoint" "test" { vpc_id = "${aws_vpc.test.id}" service_name = "com.amazonaws.${data.aws_region.current.name}.ec2" - vpc_endpoint_type = "Interface" - private_dns_enabled = false + vpc_endpoint_type = "Interface" + private_dns_enabled = false subnet_ids = [ "${aws_subnet.test1.id}", - ] + ] security_group_ids = [ "${aws_security_group.test1.id}", From d5f72ee7dde8014e59f327c2cfad54d7e3266701 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Thu, 30 May 2019 15:43:27 -0400 Subject: [PATCH 6/7] Add a real '_basic' acceptance test. --- aws/resource_aws_vpc_endpoint_service_test.go | 152 +++++++++--------- 1 file changed, 75 insertions(+), 77 deletions(-) diff --git a/aws/resource_aws_vpc_endpoint_service_test.go b/aws/resource_aws_vpc_endpoint_service_test.go index 4972b0f3d9fc..2f800280f52a 100644 --- a/aws/resource_aws_vpc_endpoint_service_test.go +++ b/aws/resource_aws_vpc_endpoint_service_test.go @@ -92,7 +92,38 @@ func TestAccAWSVpcEndpointService_basic(t *testing.T) { CheckDestroy: testAccCheckVpcEndpointServiceDestroy, Steps: []resource.TestStep{ { - Config: testAccVpcEndpointServiceConfig_basic(rName1), + Config: testAccVpcEndpointServiceConfig_basic(rName1, rName2), + Check: resource.ComposeTestCheckFunc( + testAccCheckVpcEndpointServiceExists(resourceName, &svcCfg), + resource.TestCheckResourceAttr(resourceName, "acceptance_required", "false"), + resource.TestCheckResourceAttr(resourceName, "network_load_balancer_arns.#", "1"), + resource.TestCheckResourceAttr(resourceName, "allowed_principals.#", "0"), + resource.TestCheckResourceAttr(resourceName, "manages_vpc_endpoints", "false"), + resource.TestCheckResourceAttr(resourceName, "tags.%", "0"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccAWSVpcEndpointService_AllowedPrincipalsAndTags(t *testing.T) { + var svcCfg ec2.ServiceConfiguration + resourceName := "aws_vpc_endpoint_service.test" + rName1 := fmt.Sprintf("tf-testacc-vpcesvc-%s", acctest.RandStringFromCharSet(13, acctest.CharSetAlphaNum)) + rName2 := fmt.Sprintf("tf-testacc-vpcesvc-%s", acctest.RandStringFromCharSet(13, acctest.CharSetAlphaNum)) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckVpcEndpointServiceDestroy, + Steps: []resource.TestStep{ + { + Config: testAccVpcEndpointServiceConfig_allowedPrincipalsAndTags(rName1, rName2), Check: resource.ComposeTestCheckFunc( testAccCheckVpcEndpointServiceExists(resourceName, &svcCfg), resource.TestCheckResourceAttr(resourceName, "acceptance_required", "false"), @@ -111,7 +142,7 @@ func TestAccAWSVpcEndpointService_basic(t *testing.T) { ImportStateVerify: true, }, { - Config: testAccVpcEndpointServiceConfig_modified(rName1, rName2), + Config: testAccVpcEndpointServiceConfig_allowedPrincipalsAndTagsUpdated(rName1, rName2), Check: resource.ComposeTestCheckFunc( testAccCheckVpcEndpointServiceExists(resourceName, &svcCfg), resource.TestCheckResourceAttr(resourceName, "acceptance_required", "true"), @@ -129,7 +160,8 @@ func TestAccAWSVpcEndpointService_basic(t *testing.T) { func TestAccAWSVpcEndpointService_removed(t *testing.T) { var svcCfg ec2.ServiceConfiguration resourceName := "aws_vpc_endpoint_service.test" - rName := fmt.Sprintf("tf-testacc-vpcesvc-%s", acctest.RandStringFromCharSet(13, acctest.CharSetAlphaNum)) + rName1 := fmt.Sprintf("tf-testacc-vpcesvc-%s", acctest.RandStringFromCharSet(13, acctest.CharSetAlphaNum)) + rName2 := fmt.Sprintf("tf-testacc-vpcesvc-%s", acctest.RandStringFromCharSet(13, acctest.CharSetAlphaNum)) testDestroy := func(*terraform.State) error { conn := testAccProvider.Meta().(*AWSClient).ec2conn @@ -147,7 +179,7 @@ func TestAccAWSVpcEndpointService_removed(t *testing.T) { CheckDestroy: testAccCheckVpcEndpointServiceDestroy, Steps: []resource.TestStep{ { - Config: testAccVpcEndpointServiceConfig_basic(rName), + Config: testAccVpcEndpointServiceConfig_basic(rName1, rName2), Check: resource.ComposeTestCheckFunc( testAccCheckVpcEndpointServiceExists(resourceName, &svcCfg), testDestroy, @@ -215,7 +247,7 @@ func testAccCheckVpcEndpointServiceExists(n string, svcCfg *ec2.ServiceConfigura } } -func testAccVpcEndpointServiceConfig_basic(rName string) string { +func testAccVpcEndpointServiceConfig_base(rName1, rName2 string) string { return fmt.Sprintf(` resource "aws_vpc" "test" { cidr_block = "10.0.0.0/16" @@ -243,6 +275,24 @@ resource "aws_lb" "test1" { } } +resource "aws_lb" "test2" { + name = %[2]q + + subnets = [ + "${aws_subnet.test1.id}", + "${aws_subnet.test2.id}", + ] + + load_balancer_type = "network" + internal = true + idle_timeout = 60 + enable_deletion_protection = false + + tags = { + Name = %[2]q + } +} + data "aws_availability_zones" "available" {} resource "aws_subnet" "test1" { @@ -266,97 +316,45 @@ resource "aws_subnet" "test2" { } data "aws_caller_identity" "current" {} +`, rName1, rName2) +} +func testAccVpcEndpointServiceConfig_basic(rName1, rName2 string) string { + return testAccVpcEndpointServiceConfig_base(rName1, rName2) + fmt.Sprintf(` resource "aws_vpc_endpoint_service" "test" { acceptance_required = false network_load_balancer_arns = [ "${aws_lb.test1.arn}", ] - - allowed_principals = [ - "${data.aws_caller_identity.current.arn}", - ] - - tags = { - Environment = "test" - Usage = "original" - Name = %[1]q - } } -`, rName) +`) } -func testAccVpcEndpointServiceConfig_modified(rName1, rName2 string) string { - return fmt.Sprintf(` -resource "aws_vpc" "test" { - cidr_block = "10.0.0.0/16" - - tags = { - Name = %[1]q - } -} - -resource "aws_lb" "test1" { - name = %[1]q +func testAccVpcEndpointServiceConfig_allowedPrincipalsAndTags(rName1, rName2 string) string { + return testAccVpcEndpointServiceConfig_base(rName1, rName2) + fmt.Sprintf(` +resource "aws_vpc_endpoint_service" "test" { + acceptance_required = false - subnets = [ - "${aws_subnet.test1.id}", - "${aws_subnet.test2.id}", + network_load_balancer_arns = [ + "${aws_lb.test1.arn}", ] - load_balancer_type = "network" - internal = true - idle_timeout = 60 - enable_deletion_protection = false - - tags = { - Name = %[1]q - } -} - -resource "aws_lb" "test2" { - name = %[2]q - - subnets = [ - "${aws_subnet.test1.id}", - "${aws_subnet.test2.id}", + allowed_principals = [ + "${data.aws_caller_identity.current.arn}", ] - load_balancer_type = "network" - internal = true - idle_timeout = 60 - enable_deletion_protection = false - - tags = { - Name = %[2]q - } -} - -data "aws_availability_zones" "available" {} - -resource "aws_subnet" "test1" { - vpc_id = "${aws_vpc.test.id}" - cidr_block = "10.0.1.0/24" - availability_zone = "${data.aws_availability_zones.available.names[0]}" - tags = { - Name = %[1]q + Environment = "test" + Usage = "original" + Name = %[1]q } } - -resource "aws_subnet" "test2" { - vpc_id = "${aws_vpc.test.id}" - cidr_block = "10.0.2.0/24" - availability_zone = "${data.aws_availability_zones.available.names[1]}" - - tags = { - Name = %[1]q - } +`, rName1) } -data "aws_caller_identity" "current" {} - +func testAccVpcEndpointServiceConfig_allowedPrincipalsAndTagsUpdated(rName1, rName2 string) string { + return testAccVpcEndpointServiceConfig_base(rName1, rName2) + fmt.Sprintf(` resource "aws_vpc_endpoint_service" "test" { acceptance_required = true @@ -372,5 +370,5 @@ resource "aws_vpc_endpoint_service" "test" { Name = %[1]q } } -`, rName1, rName2) +`, rName1) } From cb4eeb20725184ff1facb87bdb8cb75159fe197d Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Mon, 10 Jun 2019 15:53:46 -0400 Subject: [PATCH 7/7] Add computed 'owner_id' attribute to VPC Endpoint resource and data source. --- aws/data_source_aws_vpc_endpoint.go | 5 +++++ aws/data_source_aws_vpc_endpoint_test.go | 4 ++++ aws/resource_aws_vpc_endpoint.go | 5 +++++ aws/resource_aws_vpc_endpoint_test.go | 7 +++++++ website/docs/d/vpc_endpoint.html.markdown | 1 + website/docs/r/vpc_endpoint.html.markdown | 1 + 6 files changed, 23 insertions(+) diff --git a/aws/data_source_aws_vpc_endpoint.go b/aws/data_source_aws_vpc_endpoint.go index 5b22bd94567d..d09812b3813b 100644 --- a/aws/data_source_aws_vpc_endpoint.go +++ b/aws/data_source_aws_vpc_endpoint.go @@ -47,6 +47,10 @@ func dataSourceAwsVpcEndpoint() *schema.Resource { Elem: &schema.Schema{Type: schema.TypeString}, Set: schema.HashString, }, + "owner_id": { + Type: schema.TypeString, + Computed: true, + }, "policy": { Type: schema.TypeString, Computed: true, @@ -176,6 +180,7 @@ func dataSourceAwsVpcEndpointRead(d *schema.ResourceData, meta interface{}) erro if err != nil { return fmt.Errorf("error setting network_interface_ids: %s", err) } + d.Set("owner_id", vpce.OwnerId) policy, err := structure.NormalizeJsonString(aws.StringValue(vpce.PolicyDocument)) if err != nil { return fmt.Errorf("policy contains an invalid JSON: %s", err) diff --git a/aws/data_source_aws_vpc_endpoint_test.go b/aws/data_source_aws_vpc_endpoint_test.go index e34065c56293..1bfccb09b5b4 100644 --- a/aws/data_source_aws_vpc_endpoint_test.go +++ b/aws/data_source_aws_vpc_endpoint_test.go @@ -29,6 +29,7 @@ func TestAccDataSourceAwsVpcEndpoint_gatewayBasic(t *testing.T) { resource.TestCheckResourceAttr(datasourceName, "private_dns_enabled", "false"), resource.TestCheckResourceAttr(datasourceName, "requester_managed", "false"), resource.TestCheckResourceAttr(datasourceName, "tags.%", "0"), + testAccCheckResourceAttrAccountID(datasourceName, "owner_id"), ), }, }, @@ -56,6 +57,7 @@ func TestAccDataSourceAwsVpcEndpoint_byId(t *testing.T) { resource.TestCheckResourceAttr(datasourceName, "private_dns_enabled", "false"), resource.TestCheckResourceAttr(datasourceName, "requester_managed", "false"), resource.TestCheckResourceAttr(datasourceName, "tags.%", "0"), + testAccCheckResourceAttrAccountID(datasourceName, "owner_id"), ), }, }, @@ -84,6 +86,7 @@ func TestAccDataSourceAwsVpcEndpoint_gatewayWithRouteTableAndTags(t *testing.T) resource.TestCheckResourceAttr(datasourceName, "requester_managed", "false"), resource.TestCheckResourceAttr(datasourceName, "tags.%", "1"), resource.TestCheckResourceAttr(datasourceName, "tags.Name", rName), + testAccCheckResourceAttrAccountID(datasourceName, "owner_id"), ), }, }, @@ -112,6 +115,7 @@ func TestAccDataSourceAwsVpcEndpoint_interface(t *testing.T) { resource.TestCheckResourceAttr(datasourceName, "requester_managed", "false"), resource.TestCheckResourceAttr(datasourceName, "tags.%", "1"), resource.TestCheckResourceAttr(datasourceName, "tags.Name", rName), + testAccCheckResourceAttrAccountID(datasourceName, "owner_id"), ), }, }, diff --git a/aws/resource_aws_vpc_endpoint.go b/aws/resource_aws_vpc_endpoint.go index dc7ab25b4db6..86c2434f8850 100644 --- a/aws/resource_aws_vpc_endpoint.go +++ b/aws/resource_aws_vpc_endpoint.go @@ -56,6 +56,10 @@ func resourceAwsVpcEndpoint() *schema.Resource { Elem: &schema.Schema{Type: schema.TypeString}, Set: schema.HashString, }, + "owner_id": { + Type: schema.TypeString, + Computed: true, + }, "policy": { Type: schema.TypeString, Optional: true, @@ -247,6 +251,7 @@ func resourceAwsVpcEndpointRead(d *schema.ResourceData, meta interface{}) error if err != nil { return fmt.Errorf("error setting network_interface_ids: %s", err) } + d.Set("owner_id", vpce.OwnerId) policy, err := structure.NormalizeJsonString(aws.StringValue(vpce.PolicyDocument)) if err != nil { return fmt.Errorf("policy contains an invalid JSON: %s", err) diff --git a/aws/resource_aws_vpc_endpoint_test.go b/aws/resource_aws_vpc_endpoint_test.go index f3b5974a7aa7..01bb046cd27d 100644 --- a/aws/resource_aws_vpc_endpoint_test.go +++ b/aws/resource_aws_vpc_endpoint_test.go @@ -104,6 +104,7 @@ func TestAccAWSVpcEndpoint_gatewayBasic(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "private_dns_enabled", "false"), resource.TestCheckResourceAttr(resourceName, "requester_managed", "false"), resource.TestCheckResourceAttr(resourceName, "tags.%", "0"), + testAccCheckResourceAttrAccountID(resourceName, "owner_id"), ), }, }, @@ -139,6 +140,7 @@ func TestAccAWSVpcEndpoint_gatewayWithRouteTableAndPolicyAndTags(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "tags.Environment", "test"), resource.TestCheckResourceAttr(resourceName, "tags.Usage", "original"), resource.TestCheckResourceAttr(resourceName, "tags.Name", rName), + testAccCheckResourceAttrAccountID(resourceName, "owner_id"), ), }, { @@ -157,6 +159,7 @@ func TestAccAWSVpcEndpoint_gatewayWithRouteTableAndPolicyAndTags(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "tags.%", "2"), resource.TestCheckResourceAttr(resourceName, "tags.Usage", "changed"), resource.TestCheckResourceAttr(resourceName, "tags.Name", rName), + testAccCheckResourceAttrAccountID(resourceName, "owner_id"), ), }, { @@ -254,6 +257,7 @@ func TestAccAWSVpcEndpoint_interfaceBasic(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "private_dns_enabled", "false"), resource.TestCheckResourceAttr(resourceName, "requester_managed", "false"), resource.TestCheckResourceAttr(resourceName, "tags.%", "0"), + testAccCheckResourceAttrAccountID(resourceName, "owner_id"), ), }, }, @@ -285,6 +289,7 @@ func TestAccAWSVpcEndpoint_interfaceWithSubnetAndSecurityGroup(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "requester_managed", "false"), resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), resource.TestCheckResourceAttr(resourceName, "tags.Name", rName), + testAccCheckResourceAttrAccountID(resourceName, "owner_id"), ), }, { @@ -301,6 +306,7 @@ func TestAccAWSVpcEndpoint_interfaceWithSubnetAndSecurityGroup(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "private_dns_enabled", "true"), resource.TestCheckResourceAttr(resourceName, "requester_managed", "false"), resource.TestCheckResourceAttr(resourceName, "tags.%", "0"), + testAccCheckResourceAttrAccountID(resourceName, "owner_id"), ), }, { @@ -338,6 +344,7 @@ func TestAccAWSVpcEndpoint_interfaceNonAWSService(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "state", "available"), resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), resource.TestCheckResourceAttr(resourceName, "tags.Name", rName), + testAccCheckResourceAttrAccountID(resourceName, "owner_id"), ), }, }, diff --git a/website/docs/d/vpc_endpoint.html.markdown b/website/docs/d/vpc_endpoint.html.markdown index 6759291f2778..360fcf631f74 100644 --- a/website/docs/d/vpc_endpoint.html.markdown +++ b/website/docs/d/vpc_endpoint.html.markdown @@ -43,6 +43,7 @@ In addition to all arguments above, the following attributes are exported: * `cidr_blocks` - The list of CIDR blocks for the exposed AWS service. Applicable for endpoints of type `Gateway`. * `dns_entry` - The DNS entries for the VPC Endpoint. Applicable for endpoints of type `Interface`. DNS blocks are documented below. * `network_interface_ids` - One or more network interfaces for the VPC Endpoint. Applicable for endpoints of type `Interface`. +* `owner_id` - The ID of the AWS account that owns the VPC endpoint. * `policy` - The policy document associated with the VPC Endpoint. Applicable for endpoints of type `Gateway`. * `prefix_list_id` - The prefix list ID of the exposed AWS service. Applicable for endpoints of type `Gateway`. * `private_dns_enabled` - Whether or not the VPC is associated with a private hosted zone - `true` or `false`. Applicable for endpoints of type `Interface`. diff --git a/website/docs/r/vpc_endpoint.html.markdown b/website/docs/r/vpc_endpoint.html.markdown index 03c6d8c06f84..9a96bea1774f 100644 --- a/website/docs/r/vpc_endpoint.html.markdown +++ b/website/docs/r/vpc_endpoint.html.markdown @@ -123,6 +123,7 @@ In addition to all arguments above, the following attributes are exported: * `cidr_blocks` - The list of CIDR blocks for the exposed AWS service. Applicable for endpoints of type `Gateway`. * `dns_entry` - The DNS entries for the VPC Endpoint. Applicable for endpoints of type `Interface`. DNS blocks are documented below. * `network_interface_ids` - One or more network interfaces for the VPC Endpoint. Applicable for endpoints of type `Interface`. +* `owner_id` - The ID of the AWS account that owns the VPC endpoint. * `prefix_list_id` - The prefix list ID of the exposed AWS service. Applicable for endpoints of type `Gateway`. * `requester_managed` - Whether or not the VPC Endpoint is being managed by its service - `true` or `false`. * `state` - The state of the VPC endpoint.