Skip to content

Commit 39b4408

Browse files
committed
Add data source 'aws_vpc_endpoints'
1 parent f266212 commit 39b4408

File tree

4 files changed

+651
-0
lines changed

4 files changed

+651
-0
lines changed

internal/service/ec2/service_package_gen.go

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 295 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,295 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
4+
package ec2
5+
6+
import (
7+
"context"
8+
"time"
9+
10+
"github.com/aws/aws-sdk-go-v2/aws"
11+
"github.com/aws/aws-sdk-go-v2/service/ec2"
12+
awstypes "github.com/aws/aws-sdk-go-v2/service/ec2/types"
13+
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
14+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
15+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/structure"
16+
"github.com/hashicorp/terraform-provider-aws/internal/conns"
17+
"github.com/hashicorp/terraform-provider-aws/internal/enum"
18+
"github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag"
19+
"github.com/hashicorp/terraform-provider-aws/internal/flex"
20+
"github.com/hashicorp/terraform-provider-aws/internal/retry"
21+
tftags "github.com/hashicorp/terraform-provider-aws/internal/tags"
22+
"github.com/hashicorp/terraform-provider-aws/names"
23+
)
24+
25+
// @SDKDataSource("aws_vpc_endpoints", name="Endpoints")
26+
func dataSourceVPCEndpoints() *schema.Resource {
27+
return &schema.Resource{
28+
ReadWithoutTimeout: dataSourceVPCEndpointsRead,
29+
30+
Timeouts: &schema.ResourceTimeout{
31+
Read: schema.DefaultTimeout(20 * time.Minute),
32+
},
33+
34+
Schema: map[string]*schema.Schema{
35+
names.AttrFilter: customFiltersSchema(),
36+
names.AttrIDs: {
37+
Type: schema.TypeList,
38+
Computed: true,
39+
Elem: &schema.Schema{Type: schema.TypeString},
40+
},
41+
names.AttrIPAddressType: {
42+
Type: schema.TypeString,
43+
Optional: true,
44+
},
45+
names.AttrServiceName: {
46+
Type: schema.TypeString,
47+
Optional: true,
48+
},
49+
"service_region": {
50+
Type: schema.TypeString,
51+
Optional: true,
52+
},
53+
names.AttrState: {
54+
Type: schema.TypeString,
55+
Optional: true,
56+
},
57+
names.AttrTags: tftags.TagsSchemaComputed(),
58+
"vpc_endpoint_ids": {
59+
Type: schema.TypeSet,
60+
Optional: true,
61+
Elem: &schema.Schema{Type: schema.TypeString},
62+
},
63+
"vpc_endpoint_type": {
64+
Type: schema.TypeString,
65+
Optional: true,
66+
ValidateDiagFunc: enum.Validate[awstypes.VpcEndpointType](),
67+
},
68+
names.AttrVPCID: {
69+
Type: schema.TypeString,
70+
Optional: true,
71+
},
72+
"vpc_endpoints": {
73+
Type: schema.TypeList,
74+
Computed: true,
75+
Elem: &schema.Resource{
76+
Schema: map[string]*schema.Schema{
77+
names.AttrARN: {
78+
Type: schema.TypeString,
79+
Computed: true,
80+
},
81+
"cidr_blocks": {
82+
Type: schema.TypeList,
83+
Computed: true,
84+
Elem: &schema.Schema{Type: schema.TypeString},
85+
},
86+
"dns_entry": {
87+
Type: schema.TypeList,
88+
Computed: true,
89+
Elem: &schema.Resource{
90+
Schema: map[string]*schema.Schema{
91+
names.AttrDNSName: {
92+
Type: schema.TypeString,
93+
Computed: true,
94+
},
95+
names.AttrHostedZoneID: {
96+
Type: schema.TypeString,
97+
Computed: true,
98+
},
99+
},
100+
},
101+
},
102+
"dns_options": {
103+
Type: schema.TypeList,
104+
Computed: true,
105+
Elem: &schema.Resource{
106+
Schema: map[string]*schema.Schema{
107+
"dns_record_ip_type": {
108+
Type: schema.TypeString,
109+
Computed: true,
110+
},
111+
"private_dns_only_for_inbound_resolver_endpoint": {
112+
Type: schema.TypeBool,
113+
Computed: true,
114+
},
115+
},
116+
},
117+
},
118+
names.AttrID: {
119+
Type: schema.TypeString,
120+
Computed: true,
121+
},
122+
names.AttrIPAddressType: {
123+
Type: schema.TypeString,
124+
Computed: true,
125+
},
126+
"network_interface_ids": {
127+
Type: schema.TypeSet,
128+
Computed: true,
129+
Elem: &schema.Schema{Type: schema.TypeString},
130+
},
131+
names.AttrOwnerID: {
132+
Type: schema.TypeString,
133+
Computed: true,
134+
},
135+
names.AttrPolicy: {
136+
Type: schema.TypeString,
137+
Computed: true,
138+
},
139+
"prefix_list_id": {
140+
Type: schema.TypeString,
141+
Computed: true,
142+
},
143+
"private_dns_enabled": {
144+
Type: schema.TypeBool,
145+
Computed: true,
146+
},
147+
"requester_managed": {
148+
Type: schema.TypeBool,
149+
Computed: true,
150+
},
151+
"route_table_ids": {
152+
Type: schema.TypeSet,
153+
Computed: true,
154+
Elem: &schema.Schema{Type: schema.TypeString},
155+
},
156+
names.AttrSecurityGroupIDs: {
157+
Type: schema.TypeSet,
158+
Computed: true,
159+
Elem: &schema.Schema{Type: schema.TypeString},
160+
},
161+
names.AttrServiceName: {
162+
Type: schema.TypeString,
163+
Computed: true,
164+
},
165+
names.AttrState: {
166+
Type: schema.TypeString,
167+
Computed: true,
168+
},
169+
names.AttrSubnetIDs: {
170+
Type: schema.TypeSet,
171+
Computed: true,
172+
Elem: &schema.Schema{Type: schema.TypeString},
173+
},
174+
names.AttrTags: tftags.TagsSchemaComputed(),
175+
"vpc_endpoint_type": {
176+
Type: schema.TypeString,
177+
Computed: true,
178+
},
179+
names.AttrVPCID: {
180+
Type: schema.TypeString,
181+
Computed: true,
182+
},
183+
},
184+
},
185+
},
186+
},
187+
}
188+
}
189+
190+
func dataSourceVPCEndpointsRead(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics {
191+
var diags diag.Diagnostics
192+
conn := meta.(*conns.AWSClient).EC2Client(ctx)
193+
ignoreTagsConfig := meta.(*conns.AWSClient).IgnoreTagsConfig(ctx)
194+
195+
input := &ec2.DescribeVpcEndpointsInput{}
196+
197+
if v, ok := d.GetOk("vpc_endpoint_ids"); ok && v.(*schema.Set).Len() > 0 {
198+
input.VpcEndpointIds = flex.ExpandStringValueSet(v.(*schema.Set))
199+
}
200+
201+
input.Filters = append(input.Filters, newAttributeFilterList(
202+
map[string]string{
203+
"ip-address-type": d.Get(names.AttrIPAddressType).(string),
204+
"service-name": d.Get(names.AttrServiceName).(string),
205+
"service-region": d.Get("service_region").(string),
206+
"vpc-endpoint-state": d.Get(names.AttrState).(string),
207+
"vpc-endpoint-type": d.Get("vpc_endpoint_type").(string),
208+
"vpc-id": d.Get(names.AttrVPCID).(string),
209+
},
210+
)...)
211+
212+
input.Filters = append(input.Filters, newTagFilterList(
213+
svcTags(tftags.New(ctx, d.Get(names.AttrTags).(map[string]any))),
214+
)...)
215+
input.Filters = append(input.Filters, newCustomFilterList(
216+
d.Get(names.AttrFilter).(*schema.Set),
217+
)...)
218+
if len(input.Filters) == 0 {
219+
// Don't send an empty filters list; the EC2 API won't accept it.
220+
input.Filters = nil
221+
}
222+
223+
vpces, err := findVPCEndpoints(ctx, conn, input)
224+
225+
if err != nil {
226+
return sdkdiag.AppendErrorf(diags, "reading EC2 VPC Endpoints: %s", err)
227+
}
228+
229+
var vpcEndpointIDs []string
230+
var vpcEndpoints []map[string]any
231+
232+
for _, vpce := range vpces {
233+
vpcEndpointID := aws.ToString(vpce.VpcEndpointId)
234+
vpcEndpointIDs = append(vpcEndpointIDs, vpcEndpointID)
235+
236+
ownerID := aws.ToString(vpce.OwnerId)
237+
vpcEndpointData := map[string]any{
238+
names.AttrARN: vpcEndpointARN(ctx, meta.(*conns.AWSClient), ownerID, vpcEndpointID),
239+
"dns_entry": flattenDNSEntries(vpce.DnsEntries),
240+
names.AttrID: vpcEndpointID,
241+
names.AttrIPAddressType: vpce.IpAddressType,
242+
"network_interface_ids": vpce.NetworkInterfaceIds,
243+
names.AttrOwnerID: ownerID,
244+
"private_dns_enabled": vpce.PrivateDnsEnabled,
245+
"requester_managed": vpce.RequesterManaged,
246+
"route_table_ids": vpce.RouteTableIds,
247+
names.AttrSecurityGroupIDs: flattenSecurityGroupIdentifiers(vpce.Groups),
248+
names.AttrServiceName: aws.ToString(vpce.ServiceName),
249+
names.AttrState: vpce.State,
250+
names.AttrSubnetIDs: vpce.SubnetIds,
251+
names.AttrVPCID: aws.ToString(vpce.VpcId),
252+
}
253+
254+
if vpce.DnsOptions != nil {
255+
vpcEndpointData["dns_options"] = []any{flattenDNSOptions(vpce.DnsOptions)}
256+
} else {
257+
vpcEndpointData["dns_options"] = nil
258+
}
259+
260+
// VPC endpoints don't have types in GovCloud, so set type to default if empty
261+
if v := string(vpce.VpcEndpointType); v == "" {
262+
vpcEndpointData["vpc_endpoint_type"] = awstypes.VpcEndpointTypeGateway
263+
} else {
264+
vpcEndpointData["vpc_endpoint_type"] = v
265+
}
266+
267+
serviceName := aws.ToString(vpce.ServiceName)
268+
if pl, err := findPrefixListByName(ctx, conn, serviceName); err != nil {
269+
if !retry.NotFound(err) {
270+
return sdkdiag.AppendErrorf(diags, "reading EC2 Prefix List (%s): %s", serviceName, err)
271+
}
272+
vpcEndpointData["cidr_blocks"] = nil
273+
vpcEndpointData["prefix_list_id"] = nil
274+
} else {
275+
vpcEndpointData["cidr_blocks"] = pl.Cidrs
276+
vpcEndpointData["prefix_list_id"] = aws.ToString(pl.PrefixListId)
277+
}
278+
279+
if policy, err := structure.NormalizeJsonString(aws.ToString(vpce.PolicyDocument)); err != nil {
280+
return sdkdiag.AppendErrorf(diags, "policy contains invalid JSON: %s", err)
281+
} else {
282+
vpcEndpointData[names.AttrPolicy] = policy
283+
}
284+
285+
vpcEndpointData[names.AttrTags] = keyValueTags(ctx, vpce.Tags).IgnoreAWS().IgnoreConfig(ignoreTagsConfig).Map()
286+
287+
vpcEndpoints = append(vpcEndpoints, vpcEndpointData)
288+
}
289+
290+
d.SetId(meta.(*conns.AWSClient).Region(ctx))
291+
d.Set(names.AttrIDs, vpcEndpointIDs)
292+
d.Set("vpc_endpoints", vpcEndpoints)
293+
294+
return diags
295+
}

0 commit comments

Comments
 (0)