diff --git a/.changelog/17641.txt b/.changelog/17641.txt new file mode 100644 index 000000000000..9b6da489e960 --- /dev/null +++ b/.changelog/17641.txt @@ -0,0 +1,7 @@ +```release-note:note +data-source/aws_vpc_endpoint_service: The `service_type` argument filtering has been switched from client-side to new EC2 API functionality +``` + +```release-note:bug +data-source/aws_vpc_endpoint_service: Prevent panic with incorrect `service_type` argument values +``` diff --git a/aws/data_source_aws_vpc_endpoint_service.go b/aws/data_source_aws_vpc_endpoint_service.go index ce7ba5e0eb65..15626866d16c 100644 --- a/aws/data_source_aws_vpc_endpoint_service.go +++ b/aws/data_source_aws_vpc_endpoint_service.go @@ -9,6 +9,7 @@ import ( "github.com/aws/aws-sdk-go/aws/arn" "github.com/aws/aws-sdk-go/service/ec2" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/terraform-providers/terraform-provider-aws/aws/internal/hashcode" "github.com/terraform-providers/terraform-provider-aws/aws/internal/keyvaluetags" ) @@ -66,9 +67,10 @@ func dataSourceAwsVpcEndpointService() *schema.Resource { ConflictsWith: []string{"service"}, }, "service_type": { - Type: schema.TypeString, - Optional: true, - Computed: true, + Type: schema.TypeString, + Optional: true, + Computed: true, + ValidateFunc: validation.StringInSlice(ec2.ServiceType_Values(), false), }, "tags": tagsSchemaComputed(), "vpc_endpoint_policy_supported": { @@ -104,6 +106,14 @@ func dataSourceAwsVpcEndpointServiceRead(d *schema.ResourceData, meta interface{ if serviceNameOk { req.ServiceNames = aws.StringSlice([]string{serviceName}) } + + if v, ok := d.GetOk("service_type"); ok { + req.Filters = append(req.Filters, &ec2.Filter{ + Name: aws.String("service-type"), + Values: aws.StringSlice([]string{v.(string)}), + }) + } + if tagsOk { req.Filters = append(req.Filters, ec2TagFiltersFromMap(tags.(map[string]interface{}))...) } @@ -134,29 +144,11 @@ func dataSourceAwsVpcEndpointServiceRead(d *schema.ResourceData, meta interface{ return fmt.Errorf("no matching VPC Endpoint Service found") } - var serviceDetails []*ec2.ServiceDetail - - // Client-side filtering. When the EC2 API supports this functionality - // server-side it should be moved. - for _, serviceDetail := range resp.ServiceDetails { - if serviceDetail == nil { - continue - } - - if v, ok := d.GetOk("service_type"); ok { - if len(serviceDetail.ServiceType) > 0 && serviceDetail.ServiceType[0] != nil && v.(string) != aws.StringValue(serviceDetail.ServiceType[0].ServiceType) { - continue - } - } - - serviceDetails = append(serviceDetails, serviceDetail) - } - - if len(serviceDetails) > 1 { + if len(resp.ServiceDetails) > 1 { return fmt.Errorf("multiple VPC Endpoint Services matched; use additional constraints to reduce matches to a single VPC Endpoint Service") } - sd := serviceDetails[0] + sd := resp.ServiceDetails[0] serviceId := aws.StringValue(sd.ServiceId) serviceName = aws.StringValue(sd.ServiceName)