diff --git a/vpc.go b/vpc.go index 8bafbcb..ac7b268 100644 --- a/vpc.go +++ b/vpc.go @@ -153,14 +153,17 @@ func (c *VPCCollector) collectVpcsPerRegionQuota(ch chan<- prometheus.Metric) { func (c *VPCCollector) collectVpcsPerRegionUsage(ch chan<- prometheus.Metric) { ctx, cancelFunc := context.WithTimeout(context.Background(), c.e.timeout) defer cancelFunc() - describeVpcsOutput, err := c.ec2.DescribeVpcsWithContext(ctx, &ec2.DescribeVpcsInput{}) + numVpcs := 0 + err := c.ec2.DescribeVpcsPagesWithContext(ctx, &ec2.DescribeVpcsInput{}, func(page *ec2.DescribeVpcsOutput, lastPage bool) bool { + numVpcs += len(page.Vpcs) + return !lastPage + }) if err != nil { level.Error(c.e.logger).Log("msg", "Call to DescribeVpcs failed", "region", c.region, "err", err) exporterMetrics.IncrementErrors() return } - usage := len(describeVpcsOutput.Vpcs) - ch <- prometheus.MustNewConstMetric(c.e.VpcsPerRegionUsage, prometheus.GaugeValue, float64(usage), *c.region) + ch <- prometheus.MustNewConstMetric(c.e.VpcsPerRegionUsage, prometheus.GaugeValue, float64(numVpcs), *c.region) } func (c *VPCCollector) collectSubnetsPerVpcQuota(ch chan<- prometheus.Metric) { @@ -176,19 +179,21 @@ func (c *VPCCollector) collectSubnetsPerVpcQuota(ch chan<- prometheus.Metric) { func (c *VPCCollector) collectSubnetsPerVpcUsage(ch chan<- prometheus.Metric, vpc *ec2.Vpc) { ctx, cancelFunc := context.WithTimeout(context.Background(), c.e.timeout) defer cancelFunc() - describeSubnetsOutput, err := c.ec2.DescribeSubnetsWithContext(ctx, &ec2.DescribeSubnetsInput{ - Filters: []*ec2.Filter{&ec2.Filter{ + numSubnets := 0 + err := c.ec2.DescribeSubnetsPagesWithContext(ctx, &ec2.DescribeSubnetsInput{ + Filters: []*ec2.Filter{{ Name: aws.String("vpc-id"), Values: []*string{vpc.VpcId}, - }}, + }}}, func(page *ec2.DescribeSubnetsOutput, lastPage bool) bool { + numSubnets += len(page.Subnets) + return !lastPage }) if err != nil { level.Error(c.e.logger).Log("msg", "Call to DescribeSubnets failed", "region", c.region, "err", err) exporterMetrics.IncrementErrors() return } - usage := len(describeSubnetsOutput.Subnets) - ch <- prometheus.MustNewConstMetric(c.e.SubnetsPerVpcUsage, prometheus.GaugeValue, float64(usage), *c.region, *vpc.VpcId) + ch <- prometheus.MustNewConstMetric(c.e.SubnetsPerVpcUsage, prometheus.GaugeValue, float64(numSubnets), *c.region, *vpc.VpcId) } func (c *VPCCollector) collectRoutesPerRouteTableQuota(ch chan<- prometheus.Metric) { @@ -204,15 +209,19 @@ func (c *VPCCollector) collectRoutesPerRouteTableQuota(ch chan<- prometheus.Metr func (c *VPCCollector) collectRoutesPerRouteTableUsage(ch chan<- prometheus.Metric, rtb *ec2.RouteTable) { ctx, cancelFunc := context.WithTimeout(context.Background(), c.e.timeout) defer cancelFunc() - descRouteTableOutput, err := c.ec2.DescribeRouteTablesWithContext(ctx, &ec2.DescribeRouteTablesInput{ + output, err := c.ec2.DescribeRouteTablesWithContext(ctx, &ec2.DescribeRouteTablesInput{ RouteTableIds: []*string{rtb.RouteTableId}, }) + if len(output.RouteTables) != 1 { + level.Error(c.e.logger).Log("msg", "Unexpected number of routetables (!= 1) returned from DescribeRouteTables") + return + } if err != nil { level.Error(c.e.logger).Log("msg", "Call to DescribeRouteTables failed", "region", c.region, "err", err) exporterMetrics.IncrementErrors() return } - quota := len(descRouteTableOutput.RouteTables) + quota := len(output.RouteTables[0].Routes) ch <- prometheus.MustNewConstMetric(c.e.RoutesPerRouteTableUsage, prometheus.GaugeValue, float64(quota), *c.region, *rtb.VpcId, *rtb.RouteTableId) } @@ -229,19 +238,22 @@ func (c *VPCCollector) collectInterfaceVpcEndpointsPerVpcQuota(ch chan<- prometh func (c *VPCCollector) collectInterfaceVpcEndpointsPerVpcUsage(ch chan<- prometheus.Metric, vpc *ec2.Vpc) { ctx, cancelFunc := context.WithTimeout(context.Background(), c.e.timeout) defer cancelFunc() - descVpcEndpoints, err := c.ec2.DescribeVpcEndpointsWithContext(ctx, &ec2.DescribeVpcEndpointsInput{ - Filters: []*ec2.Filter{{ - Name: aws.String("vpc-id"), - Values: []*string{vpc.VpcId}, - }}, + + numEndpoints := 0 + descEndpointsInput := &ec2.DescribeVpcEndpointsInput{ + Filters: []*ec2.Filter{{Name: aws.String("vpc-id"), Values: []*string{vpc.VpcId}}}, + } + err := c.ec2.DescribeVpcEndpointsPagesWithContext(ctx, descEndpointsInput, func(page *ec2.DescribeVpcEndpointsOutput, lastPage bool) bool { + numEndpoints += len(page.VpcEndpoints) + return !lastPage }) if err != nil { level.Error(c.e.logger).Log("msg", "Call to DescribeVpcEndpoints failed", "region", c.region, "err", err) exporterMetrics.IncrementErrors() return } - quota := len(descVpcEndpoints.VpcEndpoints) - ch <- prometheus.MustNewConstMetric(c.e.InterfaceVpcEndpointsPerVpcUsage, prometheus.GaugeValue, float64(quota), *c.region, *vpc.VpcId) + + ch <- prometheus.MustNewConstMetric(c.e.InterfaceVpcEndpointsPerVpcUsage, prometheus.GaugeValue, float64(numEndpoints), *c.region, *vpc.VpcId) } func (c *VPCCollector) collectRoutesTablesPerVpcQuota(ch chan<- prometheus.Metric) { @@ -257,19 +269,22 @@ func (c *VPCCollector) collectRoutesTablesPerVpcQuota(ch chan<- prometheus.Metri func (c *VPCCollector) collectRoutesTablesPerVpcUsage(ch chan<- prometheus.Metric, vpc *ec2.Vpc) { ctx, cancelFunc := context.WithTimeout(context.Background(), c.e.timeout) defer cancelFunc() - descRouteTables, err := c.ec2.DescribeRouteTablesWithContext(ctx, &ec2.DescribeRouteTablesInput{ + var numRouteTables int + input := &ec2.DescribeRouteTablesInput{ Filters: []*ec2.Filter{{ Name: aws.String("vpc-id"), Values: []*string{vpc.VpcId}, - }}, + }}} + err := c.ec2.DescribeRouteTablesPagesWithContext(ctx, input, func(page *ec2.DescribeRouteTablesOutput, lastPage bool) bool { + numRouteTables += len(page.RouteTables) + return !lastPage }) if err != nil { level.Error(c.e.logger).Log("msg", "Call to DescribeRouteTables failed", "region", c.region, "err", err) exporterMetrics.IncrementErrors() return } - quota := len(descRouteTables.RouteTables) - ch <- prometheus.MustNewConstMetric(c.e.RouteTablesPerVpcUsage, prometheus.GaugeValue, float64(quota), *c.region, *vpc.VpcId) + ch <- prometheus.MustNewConstMetric(c.e.RouteTablesPerVpcUsage, prometheus.GaugeValue, float64(numRouteTables), *c.region, *vpc.VpcId) } func (c *VPCCollector) collectIPv4BlocksPerVpcQuota(ch chan<- prometheus.Metric) { @@ -285,18 +300,19 @@ func (c *VPCCollector) collectIPv4BlocksPerVpcQuota(ch chan<- prometheus.Metric) func (c *VPCCollector) collectIPv4BlocksPerVpcUsage(ch chan<- prometheus.Metric, vpc *ec2.Vpc) { ctx, cancelFunc := context.WithTimeout(context.Background(), c.e.timeout) defer cancelFunc() - descVpcs, err := c.ec2.DescribeVpcsWithContext(ctx, &ec2.DescribeVpcsInput{ + input := &ec2.DescribeVpcsInput{ VpcIds: []*string{vpc.VpcId}, - }) + } + output, err := c.ec2.DescribeVpcsWithContext(ctx, input) if err != nil { level.Error(c.e.logger).Log("msg", "Call to DescribeVpcs failed", "region", c.region, "err", err) exporterMetrics.IncrementErrors() return } - if len(descVpcs.Vpcs) != 1 { + if len(output.Vpcs) != 1 { level.Error(c.e.logger).Log("msg", "Unexpected numbers of VPCs (!= 1) returned", "region", c.region, "vpcId", vpc.VpcId) } - quota := len(descVpcs.Vpcs[0].CidrBlockAssociationSet) + quota := len(output.Vpcs[0].CidrBlockAssociationSet) ch <- prometheus.MustNewConstMetric(c.e.IPv4BlocksPerVpcUsage, prometheus.GaugeValue, float64(quota), *c.region, *vpc.VpcId) }