Skip to content

Commit 4177649

Browse files
committed
Paginate all vpc calls.
1 parent 7a3266d commit 4177649

File tree

1 file changed

+62
-22
lines changed

1 file changed

+62
-22
lines changed

vpc.go

Lines changed: 62 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package main
22

33
import (
44
"context"
5+
"errors"
56
"sync"
67
"time"
78

@@ -153,13 +154,17 @@ func (c *VPCCollector) collectVpcsPerRegionQuota(ch chan<- prometheus.Metric) {
153154
func (c *VPCCollector) collectVpcsPerRegionUsage(ch chan<- prometheus.Metric) {
154155
ctx, cancelFunc := context.WithTimeout(context.Background(), c.e.timeout)
155156
defer cancelFunc()
156-
describeVpcsOutput, err := c.ec2.DescribeVpcsWithContext(ctx, &ec2.DescribeVpcsInput{})
157+
var vpcs []*ec2.Vpc
158+
err := c.ec2.DescribeVpcsPagesWithContext(ctx, &ec2.DescribeVpcsInput{}, func(page *ec2.DescribeVpcsOutput, lastPage bool) bool {
159+
vpcs = append(vpcs, page.Vpcs...)
160+
return !lastPage
161+
})
157162
if err != nil {
158163
level.Error(c.e.logger).Log("msg", "Call to DescribeVpcs failed", "region", c.region, "err", err)
159164
exporterMetrics.IncrementErrors()
160165
return
161166
}
162-
usage := len(describeVpcsOutput.Vpcs)
167+
usage := len(vpcs)
163168
ch <- prometheus.MustNewConstMetric(c.e.VpcsPerRegionUsage, prometheus.GaugeValue, float64(usage), *c.region)
164169
}
165170

@@ -176,18 +181,21 @@ func (c *VPCCollector) collectSubnetsPerVpcQuota(ch chan<- prometheus.Metric) {
176181
func (c *VPCCollector) collectSubnetsPerVpcUsage(ch chan<- prometheus.Metric, vpc *ec2.Vpc) {
177182
ctx, cancelFunc := context.WithTimeout(context.Background(), c.e.timeout)
178183
defer cancelFunc()
179-
describeSubnetsOutput, err := c.ec2.DescribeSubnetsWithContext(ctx, &ec2.DescribeSubnetsInput{
180-
Filters: []*ec2.Filter{&ec2.Filter{
184+
var subnets []*ec2.Subnet
185+
err := c.ec2.DescribeSubnetsPagesWithContext(ctx, &ec2.DescribeSubnetsInput{
186+
Filters: []*ec2.Filter{{
181187
Name: aws.String("vpc-id"),
182188
Values: []*string{vpc.VpcId},
183-
}},
189+
}}}, func(page *ec2.DescribeSubnetsOutput, lastPage bool) bool {
190+
subnets = append(subnets, page.Subnets...)
191+
return !lastPage
184192
})
185193
if err != nil {
186194
level.Error(c.e.logger).Log("msg", "Call to DescribeSubnets failed", "region", c.region, "err", err)
187195
exporterMetrics.IncrementErrors()
188196
return
189197
}
190-
usage := len(describeSubnetsOutput.Subnets)
198+
usage := len(subnets)
191199
ch <- prometheus.MustNewConstMetric(c.e.SubnetsPerVpcUsage, prometheus.GaugeValue, float64(usage), *c.region, *vpc.VpcId)
192200
}
193201

@@ -204,15 +212,25 @@ func (c *VPCCollector) collectRoutesPerRouteTableQuota(ch chan<- prometheus.Metr
204212
func (c *VPCCollector) collectRoutesPerRouteTableUsage(ch chan<- prometheus.Metric, rtb *ec2.RouteTable) {
205213
ctx, cancelFunc := context.WithTimeout(context.Background(), c.e.timeout)
206214
defer cancelFunc()
207-
descRouteTableOutput, err := c.ec2.DescribeRouteTablesWithContext(ctx, &ec2.DescribeRouteTablesInput{
215+
var routes []*ec2.Route
216+
var unexpectedNumberOfRouteTables error
217+
err := c.ec2.DescribeRouteTablesPagesWithContext(ctx, &ec2.DescribeRouteTablesInput{
208218
RouteTableIds: []*string{rtb.RouteTableId},
219+
}, func(page *ec2.DescribeRouteTablesOutput, lastPage bool) bool {
220+
if len(page.RouteTables) != 1 {
221+
// Indicate that one of the calls return too many routetables making data invalid
222+
unexpectedNumberOfRouteTables = errors.New("Unexpected number of routetables returned")
223+
return false
224+
}
225+
routes = append(routes, page.RouteTables[0].Routes...)
226+
return !lastPage
209227
})
210-
if err != nil {
228+
if err != nil || unexpectedNumberOfRouteTables != nil {
211229
level.Error(c.e.logger).Log("msg", "Call to DescribeRouteTables failed", "region", c.region, "err", err)
212230
exporterMetrics.IncrementErrors()
213231
return
214232
}
215-
quota := len(descRouteTableOutput.RouteTables)
233+
quota := len(routes)
216234
ch <- prometheus.MustNewConstMetric(c.e.RoutesPerRouteTableUsage, prometheus.GaugeValue, float64(quota), *c.region, *rtb.VpcId, *rtb.RouteTableId)
217235
}
218236

@@ -229,19 +247,27 @@ func (c *VPCCollector) collectInterfaceVpcEndpointsPerVpcQuota(ch chan<- prometh
229247
func (c *VPCCollector) collectInterfaceVpcEndpointsPerVpcUsage(ch chan<- prometheus.Metric, vpc *ec2.Vpc) {
230248
ctx, cancelFunc := context.WithTimeout(context.Background(), c.e.timeout)
231249
defer cancelFunc()
232-
descVpcEndpoints, err := c.ec2.DescribeVpcEndpointsWithContext(ctx, &ec2.DescribeVpcEndpointsInput{
233-
Filters: []*ec2.Filter{{
234-
Name: aws.String("vpc-id"),
235-
Values: []*string{vpc.VpcId},
236-
}},
250+
251+
numEndpoints := 0
252+
descEndpointsInput := &ec2.DescribeVpcEndpointsInput{
253+
Filters: []*ec2.Filter{{Name: aws.String("vpc-id"), Values: []*string{vpc.VpcId}}},
254+
MaxResults: aws.Int64(1000),
255+
}
256+
257+
var vpcEndpoints []*ec2.VpcEndpoint
258+
err := c.ec2.DescribeVpcEndpointsPagesWithContext(ctx, descEndpointsInput, func(page *ec2.DescribeVpcEndpointsOutput, lastPage bool) bool {
259+
vpcEndpoints = append(vpcEndpoints, page.VpcEndpoints...)
260+
return !lastPage
237261
})
262+
238263
if err != nil {
239264
level.Error(c.e.logger).Log("msg", "Call to DescribeVpcEndpoints failed", "region", c.region, "err", err)
240265
exporterMetrics.IncrementErrors()
241266
return
242267
}
243-
quota := len(descVpcEndpoints.VpcEndpoints)
244-
ch <- prometheus.MustNewConstMetric(c.e.InterfaceVpcEndpointsPerVpcUsage, prometheus.GaugeValue, float64(quota), *c.region, *vpc.VpcId)
268+
numEndpoints += len(vpcEndpoints)
269+
270+
ch <- prometheus.MustNewConstMetric(c.e.InterfaceVpcEndpointsPerVpcUsage, prometheus.GaugeValue, float64(numEndpoints), *c.region, *vpc.VpcId)
245271
}
246272

247273
func (c *VPCCollector) collectRoutesTablesPerVpcQuota(ch chan<- prometheus.Metric) {
@@ -257,18 +283,22 @@ func (c *VPCCollector) collectRoutesTablesPerVpcQuota(ch chan<- prometheus.Metri
257283
func (c *VPCCollector) collectRoutesTablesPerVpcUsage(ch chan<- prometheus.Metric, vpc *ec2.Vpc) {
258284
ctx, cancelFunc := context.WithTimeout(context.Background(), c.e.timeout)
259285
defer cancelFunc()
260-
descRouteTables, err := c.ec2.DescribeRouteTablesWithContext(ctx, &ec2.DescribeRouteTablesInput{
286+
var routeTables []*ec2.RouteTable
287+
input := &ec2.DescribeRouteTablesInput{
261288
Filters: []*ec2.Filter{{
262289
Name: aws.String("vpc-id"),
263290
Values: []*string{vpc.VpcId},
264-
}},
291+
}}}
292+
err := c.ec2.DescribeRouteTablesPagesWithContext(ctx, input, func(page *ec2.DescribeRouteTablesOutput, lastPage bool) bool {
293+
routeTables = append(routeTables, page.RouteTables...)
294+
return !lastPage
265295
})
266296
if err != nil {
267297
level.Error(c.e.logger).Log("msg", "Call to DescribeRouteTables failed", "region", c.region, "err", err)
268298
exporterMetrics.IncrementErrors()
269299
return
270300
}
271-
quota := len(descRouteTables.RouteTables)
301+
quota := len(routeTables)
272302
ch <- prometheus.MustNewConstMetric(c.e.RouteTablesPerVpcUsage, prometheus.GaugeValue, float64(quota), *c.region, *vpc.VpcId)
273303
}
274304

@@ -285,18 +315,28 @@ func (c *VPCCollector) collectIPv4BlocksPerVpcQuota(ch chan<- prometheus.Metric)
285315
func (c *VPCCollector) collectIPv4BlocksPerVpcUsage(ch chan<- prometheus.Metric, vpc *ec2.Vpc) {
286316
ctx, cancelFunc := context.WithTimeout(context.Background(), c.e.timeout)
287317
defer cancelFunc()
288-
descVpcs, err := c.ec2.DescribeVpcsWithContext(ctx, &ec2.DescribeVpcsInput{
318+
input := &ec2.DescribeVpcsInput{
289319
VpcIds: []*string{vpc.VpcId},
320+
}
321+
var unexpectedNumberOfVpcs error
322+
var cidrBlockAssociations []*ec2.VpcCidrBlockAssociation
323+
err := c.ec2.DescribeVpcsPagesWithContext(ctx, input, func(page *ec2.DescribeVpcsOutput, lastPage bool) bool {
324+
if len(page.Vpcs) != 1 {
325+
unexpectedNumberOfVpcs = errors.New("Unexpected number of vpcs received")
326+
return false
327+
}
328+
cidrBlockAssociations = append(cidrBlockAssociations, page.Vpcs[0].CidrBlockAssociationSet...)
329+
return !lastPage
290330
})
291331
if err != nil {
292332
level.Error(c.e.logger).Log("msg", "Call to DescribeVpcs failed", "region", c.region, "err", err)
293333
exporterMetrics.IncrementErrors()
294334
return
295335
}
296-
if len(descVpcs.Vpcs) != 1 {
336+
if unexpectedNumberOfVpcs != nil {
297337
level.Error(c.e.logger).Log("msg", "Unexpected numbers of VPCs (!= 1) returned", "region", c.region, "vpcId", vpc.VpcId)
298338
}
299-
quota := len(descVpcs.Vpcs[0].CidrBlockAssociationSet)
339+
quota := len(cidrBlockAssociations)
300340
ch <- prometheus.MustNewConstMetric(c.e.IPv4BlocksPerVpcUsage, prometheus.GaugeValue, float64(quota), *c.region, *vpc.VpcId)
301341
}
302342

0 commit comments

Comments
 (0)