Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

VPC endpoint service private dns name support #16495

Merged
merged 5 commits into from
Jan 5, 2021
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 68 additions & 1 deletion aws/resource_aws_vpc_endpoint_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,31 @@ func resourceAwsVpcEndpointService() *schema.Resource {
"private_dns_name": {
Type: schema.TypeString,
Computed: true,
Optional: true,
},
"private_dns_name_configuration": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Computed: true,
},
"state": {
Type: schema.TypeString,
Computed: true,
},
"type": {
Type: schema.TypeString,
Computed: true,
},
"value": {
Type: schema.TypeString,
Computed: true,
},
},
},
},
"service_name": {
Type: schema.TypeString,
Expand All @@ -104,6 +129,9 @@ func resourceAwsVpcEndpointServiceCreate(d *schema.ResourceData, meta interface{
AcceptanceRequired: aws.Bool(d.Get("acceptance_required").(bool)),
TagSpecifications: ec2TagSpecificationsFromMap(d.Get("tags").(map[string]interface{}), "vpc-endpoint-service"),
}
if v, ok := d.GetOk("private_dns_name"); ok {
req.PrivateDnsName = aws.String(v.(string))
}

if v, ok := d.GetOk("gateway_load_balancer_arns"); ok {
if v, ok := v.(*schema.Set); ok && v.Len() > 0 {
Expand Down Expand Up @@ -214,17 +242,56 @@ func resourceAwsVpcEndpointServiceRead(d *schema.ResourceData, meta interface{})
return fmt.Errorf("error setting allowed_principals: %s", err)
}

err = d.Set("private_dns_name_configuration", flattenPrivateDnsNameConfiguration(svcCfg.PrivateDnsNameConfiguration))
if err != nil {
return fmt.Errorf("error setting private_dns_name_configuration: %w", err)
}

return nil
}

func flattenPrivateDnsNameConfiguration(privateDnsNameConfiguration *ec2.PrivateDnsNameConfiguration) []interface{} {
if privateDnsNameConfiguration == nil {
return nil
}
tfMap := map[string]interface{}{}

if v := privateDnsNameConfiguration.Name; v != nil {
tfMap["name"] = aws.StringValue(v)
}

if v := privateDnsNameConfiguration.State; v != nil {
tfMap["state"] = aws.StringValue(v)
}

if v := privateDnsNameConfiguration.Type; v != nil {
tfMap["type"] = aws.StringValue(v)
}

if v := privateDnsNameConfiguration.Value; v != nil {
tfMap["value"] = aws.StringValue(v)
}
bflad marked this conversation as resolved.
Show resolved Hide resolved

// The EC2 API can return a XML structure with no elements
if len(tfMap) == 0 {
return nil
}

return []interface{}{tfMap}
}

func resourceAwsVpcEndpointServiceUpdate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).ec2conn

if d.HasChanges("acceptance_required", "gateway_load_balancer_arns", "network_load_balancer_arns") {
if d.HasChanges("acceptance_required", "gateway_load_balancer_arns", "network_load_balancer_arns", "private_dns_name") {
modifyCfgReq := &ec2.ModifyVpcEndpointServiceConfigurationInput{
ServiceId: aws.String(d.Id()),
}

if d.HasChange("private_dns_name") {
modifyCfgReq.PrivateDnsName = aws.String(d.Get("private_dns_name").(string))
}

if d.HasChange("acceptance_required") {
modifyCfgReq.AcceptanceRequired = aws.Bool(d.Get("acceptance_required").(bool))
}
Expand Down
54 changes: 54 additions & 0 deletions aws/resource_aws_vpc_endpoint_service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ func TestAccAWSVpcEndpointService_basic(t *testing.T) {
resource.TestCheckResourceAttr(resourceName, "allowed_principals.#", "0"),
resource.TestCheckResourceAttr(resourceName, "manages_vpc_endpoints", "false"),
resource.TestCheckResourceAttr(resourceName, "tags.%", "0"),
resource.TestCheckResourceAttr(resourceName, "private_dns_name_configuration.#", "0"),
testAccMatchResourceAttrRegionalARN(resourceName, "arn", "ec2", regexp.MustCompile(`vpc-endpoint-service/vpce-svc-.+`)),
),
},
Expand Down Expand Up @@ -256,6 +257,44 @@ func TestAccAWSVpcEndpointService_tags(t *testing.T) {
})
}

func TestAccAWSVpcEndpointService_private_dns_name(t *testing.T) {
var svcCfg ec2.ServiceConfiguration
resourceName := "aws_vpc_endpoint_service.test"
rName1 := acctest.RandomWithPrefix("tf-acc-test")
rName2 := acctest.RandomWithPrefix("tf-acc-test")

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckVpcEndpointServiceDestroy,
Steps: []resource.TestStep{
{
Config: testAccVpcEndpointServiceConfigPrivateDnsName(rName1, rName2, "example.com"),
Check: resource.ComposeTestCheckFunc(
testAccCheckVpcEndpointServiceExists(resourceName, &svcCfg),
resource.TestCheckResourceAttr(resourceName, "private_dns_name", "example.com"),
resource.TestCheckResourceAttr(resourceName, "private_dns_name_configuration.#", "1"),
resource.TestCheckResourceAttr(resourceName, "private_dns_name_configuration.0.type", "TXT"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
{
Config: testAccVpcEndpointServiceConfigPrivateDnsName(rName1, rName2, "changed.com"),
Check: resource.ComposeTestCheckFunc(
testAccCheckVpcEndpointServiceExists(resourceName, &svcCfg),
resource.TestCheckResourceAttr(resourceName, "private_dns_name", "changed.com"),
resource.TestCheckResourceAttr(resourceName, "private_dns_name_configuration.#", "1"),
resource.TestCheckResourceAttr(resourceName, "private_dns_name_configuration.0.type", "TXT"),
),
},
},
})
}

func testAccCheckVpcEndpointServiceDestroy(s *terraform.State) error {
conn := testAccProvider.Meta().(*AWSClient).ec2conn

Expand Down Expand Up @@ -525,3 +564,18 @@ resource "aws_vpc_endpoint_service" "test" {
}
`, tagKey1, tagValue1, tagKey2, tagValue2))
}

func testAccVpcEndpointServiceConfigPrivateDnsName(rName1, rName2, dnsName string) string {
return composeConfig(
testAccVpcEndpointServiceConfig_base(rName1, rName2),
fmt.Sprintf(`
resource "aws_vpc_endpoint_service" "test" {
acceptance_required = false
private_dns_name = "%s"

network_load_balancer_arns = [
aws_lb.test1.arn,
]
}
`, dnsName))
}
7 changes: 6 additions & 1 deletion website/docs/r/vpc_endpoint_service.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ The following arguments are supported:
* `gateway_load_balancer_arns` - (Optional) Amazon Resource Names (ARNs) of one or more Gateway Load Balancers for the endpoint service.
* `network_load_balancer_arns` - (Optional) Amazon Resource Names (ARNs) of one or more Network Load Balancers for the endpoint service.
* `tags` - (Optional) A map of tags to assign to the resource.
* `private_dns_name` - (Optional) The private DNS name for the service.

## Attributes Reference

Expand All @@ -56,10 +57,14 @@ In addition to all arguments above, the following attributes are exported:
* `arn` - The Amazon Resource Name (ARN) of the VPC endpoint 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.
* `private_dns_name_configuration` - List of objects containing information about the endpoint service private DNS name configuration.
* `name` - Name of the record subdomain the service provider needs to create.
* `state` - Verification state of the VPC endpoint service. Consumers of the endpoint service can use the private name only when the state is `verified`.
* `type` - Endpoint service verification type, for example `TXT`.
* `value` - Value the service provider adds to the private DNS name domain record before verification.

## Import

Expand Down