diff --git a/conf/defaults.ini b/conf/defaults.ini
index eac091fec67..b274ffbcf0f 100644
--- a/conf/defaults.ini
+++ b/conf/defaults.ini
@@ -515,6 +515,9 @@ allowed_auth_providers = default,keys,credentials
# If true, assume role will be enabled for all AWS authentication providers that are specified in aws_auth_providers
assume_role_enabled = true
+# Specify max no of pages to be returned by the ListMetricPages API
+list_metrics_page_limit = 500
+
#################################### SMTP / Emailing #####################
[smtp]
enabled = false
diff --git a/docs/sources/administration/configuration.md b/docs/sources/administration/configuration.md
index dd444b1803b..35d36113880 100644
--- a/docs/sources/administration/configuration.md
+++ b/docs/sources/administration/configuration.md
@@ -788,6 +788,10 @@ Set to `false` to disable AWS authentication from using an assumed role with tem
If this option is disabled, the **Assume Role** and the **External Id** field are removed from the AWS data source configuration page. If the plugin is configured using provisioning, it is possible to use an assumed role as long as `assume_role_enabled` is set to `true`.
+### list_metrics_page_limit
+
+Use the [List Metrics API](https://docs.aws.amazon.com/AmazonCloudWatch/latest/APIReference/API_ListMetrics.html) option to load metrics for custom namespaces in the CloudWatch data source. By default, the page limit is 500.
+
## [smtp]
diff --git a/docs/sources/datasources/cloudwatch.md b/docs/sources/datasources/cloudwatch.md
index c0f2f634232..607419d9c4d 100644
--- a/docs/sources/datasources/cloudwatch.md
+++ b/docs/sources/datasources/cloudwatch.md
@@ -300,7 +300,7 @@ Filters syntax:
Example `ec2_instance_attribute()` query
```javascript
-ec2_instance_attribute(us-east-1, InstanceId, { "tag:Environment": ["production"] });
+ec2_instance_attribute(us - east - 1, InstanceId, { 'tag:Environment': ['production'] });
```
### Selecting attributes
@@ -341,7 +341,7 @@ Tags can be selected by prepending the tag name with `Tags.`
Example `ec2_instance_attribute()` query
```javascript
-ec2_instance_attribute(us-east-1, Tags.Name, { "tag:Team": ["sysops"] });
+ec2_instance_attribute(us - east - 1, Tags.Name, { 'tag:Team': ['sysops'] });
```
## Using json format template variables
@@ -385,6 +385,10 @@ Specify which authentication providers are allowed for the CloudWatch data sourc
Allows you to disable `assume role (ARN)` in the CloudWatch data source. By default, assume role (ARN) is enabled for OSS Grafana.
+### list_metrics_page_limit
+
+When a custom namespace is specified in the query editor, the [List Metrics API](https://docs.aws.amazon.com/AmazonCloudWatch/latest/APIReference/API_ListMetrics.html) is used to populate the _Metrics_ field and the _Dimension_ fields. The API is paginated and returns up to 500 results per page. The CloudWatch data source also limits the number of pages to 500. However, you can change this limit using the `list_metrics_page_limit` variable in the [grafana configuration file](https://grafana.com/docs/grafana/latest/administration/configuration/#aws).
+
## Configure the data source with provisioning
It's now possible to configure data sources using config files with Grafana's provisioning system. You can read more about how it works and all the settings you can set for data sources on the [provisioning docs page]({{< relref "../administration/provisioning/#datasources" >}})
diff --git a/go.sum b/go.sum
index 7ea16abf572..fefb8915f28 100644
--- a/go.sum
+++ b/go.sum
@@ -42,6 +42,7 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
+cloud.google.com/go/storage v1.13.0/go.mod h1:pqFyBUK3zZqMIIU5+8NaZq6/Ma3ClgUg9Hv5jfuJnvo=
cloud.google.com/go/storage v1.14.0 h1:6RRlFMv1omScs6iq2hfE3IvgE+l6RfJPampq8UZc5TU=
cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo=
code.cloudfoundry.org/bytefmt v0.0.0-20200131002437-cf55d5288a48/go.mod h1:wN/zk7mhREp/oviagqUXY3EwuHhWyOvAdsn5Y4CzOrc=
@@ -183,6 +184,7 @@ github.com/aws/aws-sdk-go v1.33.12/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZve
github.com/aws/aws-sdk-go v1.34.9/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
github.com/aws/aws-sdk-go v1.35.5/go.mod h1:tlPOdRjfxPBpNIwqDj61rmsnA85v9jc0Ps9+muhnW+k=
github.com/aws/aws-sdk-go v1.35.30/go.mod h1:tlPOdRjfxPBpNIwqDj61rmsnA85v9jc0Ps9+muhnW+k=
+github.com/aws/aws-sdk-go v1.37.25/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
github.com/aws/aws-sdk-go v1.37.26 h1:D9Qvyjlr6xFR0CspZ0imdASc5Y1WE/Sgyte4l+cUp44=
github.com/aws/aws-sdk-go v1.37.26/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
@@ -1716,6 +1718,7 @@ golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4Iltr
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
+golang.org/x/oauth2 v0.0.0-20210113205817-d3ed898aa8a3/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99 h1:5vD4XjIc0X5+kHZjx4UecYdjA6mJo+XXNoaW0EjU5Os=
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -1825,6 +1828,7 @@ golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20201214210602-f9fddec55a1e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073 h1:8qxJSnu+7dRq6upnbntrmriWByIakBuct5OM/MdQC1M=
golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
@@ -1977,6 +1981,7 @@ google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz513
google.golang.org/api v0.32.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE=
+google.golang.org/api v0.38.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
google.golang.org/api v0.40.0 h1:uWrpz12dpVPn7cojP82mk02XDgTJLDPc2KbVTxrWb4A=
google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
@@ -2040,6 +2045,7 @@ google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6D
google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20210203152818-3206188e46ba/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210226172003-ab064af71705 h1:PYBmACG+YEv8uQPW0r1kJj8tR+gkF0UWq7iFdUezwEw=
google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
diff --git a/pkg/setting/setting.go b/pkg/setting/setting.go
index 57e2e7784c2..05a12bb2c22 100644
--- a/pkg/setting/setting.go
+++ b/pkg/setting/setting.go
@@ -275,6 +275,7 @@ type Cfg struct {
// AWS Plugin Auth
AWSAllowedAuthProviders []string
AWSAssumeRoleEnabled bool
+ AWSListMetricsPageLimit int
// Auth proxy settings
AuthProxyEnabled bool
@@ -944,6 +945,7 @@ func (cfg *Cfg) readAWSConfig() {
cfg.AWSAllowedAuthProviders = append(cfg.AWSAllowedAuthProviders, authProvider)
}
}
+ cfg.AWSListMetricsPageLimit = awsPluginSec.Key("list_metrics_page_limit").MustInt(500)
}
func (cfg *Cfg) readSessionConfig() {
diff --git a/pkg/tsdb/cloudwatch/log_actions_test.go b/pkg/tsdb/cloudwatch/log_actions_test.go
index 89ff0aafa6e..f8546fc1a7a 100644
--- a/pkg/tsdb/cloudwatch/log_actions_test.go
+++ b/pkg/tsdb/cloudwatch/log_actions_test.go
@@ -169,6 +169,7 @@ func TestQuery_GetLogGroupFields(t *testing.T) {
}
const refID = "A"
+
executor := newExecutor(nil, newTestConfig())
resp, err := executor.DataQuery(context.Background(), fakeDataSource(), plugins.DataQuery{
Queries: []plugins.DataSubQuery{
diff --git a/pkg/tsdb/cloudwatch/metric_find_query.go b/pkg/tsdb/cloudwatch/metric_find_query.go
index dd1a14653d5..5026e629129 100644
--- a/pkg/tsdb/cloudwatch/metric_find_query.go
+++ b/pkg/tsdb/cloudwatch/metric_find_query.go
@@ -462,14 +462,21 @@ func (e *cloudWatchExecutor) handleGetDimensionValues(ctx context.Context, param
}
}
- metrics, err := e.cloudwatchListMetrics(region, namespace, metricName, dimensions)
+ params := &cloudwatch.ListMetricsInput{
+ Namespace: aws.String(namespace),
+ Dimensions: dimensions,
+ }
+ if metricName != "" {
+ params.MetricName = aws.String(metricName)
+ }
+ metrics, err := e.listMetrics(region, params)
if err != nil {
return nil, err
}
result := make([]suggestData, 0)
dupCheck := make(map[string]bool)
- for _, metric := range metrics.Metrics {
+ for _, metric := range metrics {
for _, dim := range metric.Dimensions {
if *dim.Name == dimensionKey {
if _, exists := dupCheck[*dim.Value]; exists {
@@ -631,36 +638,29 @@ func (e *cloudWatchExecutor) handleGetResourceArns(ctx context.Context, paramete
return result, nil
}
-func (e *cloudWatchExecutor) cloudwatchListMetrics(region string, namespace string, metricName string,
- dimensions []*cloudwatch.DimensionFilter) (*cloudwatch.ListMetricsOutput, error) {
- svc, err := e.getCWClient(region)
+func (e *cloudWatchExecutor) listMetrics(region string, params *cloudwatch.ListMetricsInput) ([]*cloudwatch.Metric, error) {
+ client, err := e.getCWClient(region)
if err != nil {
return nil, err
}
- params := &cloudwatch.ListMetricsInput{
- Namespace: aws.String(namespace),
- Dimensions: dimensions,
- }
+ plog.Debug("Listing metrics pages")
+ cloudWatchMetrics := []*cloudwatch.Metric{}
- if metricName != "" {
- params.MetricName = aws.String(metricName)
- }
-
- var resp cloudwatch.ListMetricsOutput
- if err := svc.ListMetricsPages(params,
- func(page *cloudwatch.ListMetricsOutput, lastPage bool) bool {
- metrics.MAwsCloudWatchListMetrics.Inc()
- metrics, _ := awsutil.ValuesAtPath(page, "Metrics")
+ pageNum := 0
+ err = client.ListMetricsPages(params, func(page *cloudwatch.ListMetricsOutput, lastPage bool) bool {
+ pageNum++
+ metrics.MAwsCloudWatchListMetrics.Inc()
+ metrics, err := awsutil.ValuesAtPath(page, "Metrics")
+ if err == nil {
for _, metric := range metrics {
- resp.Metrics = append(resp.Metrics, metric.(*cloudwatch.Metric))
+ cloudWatchMetrics = append(cloudWatchMetrics, metric.(*cloudwatch.Metric))
}
- return !lastPage
- }); err != nil {
- return nil, fmt.Errorf("failed to call cloudwatch:ListMetrics: %w", err)
- }
+ }
+ return !lastPage && pageNum < e.cfg.AWSListMetricsPageLimit
+ })
- return &resp, nil
+ return cloudWatchMetrics, err
}
func (e *cloudWatchExecutor) ec2DescribeInstances(region string, filters []*ec2.Filter, instanceIds []*string) (*ec2.DescribeInstancesOutput, error) {
@@ -709,34 +709,6 @@ func (e *cloudWatchExecutor) resourceGroupsGetResources(region string, filters [
return &resp, nil
}
-func (e *cloudWatchExecutor) getAllMetrics(region, namespace string) (cloudwatch.ListMetricsOutput, error) {
- client, err := e.getCWClient(region)
- if err != nil {
- return cloudwatch.ListMetricsOutput{}, err
- }
-
- params := &cloudwatch.ListMetricsInput{
- Namespace: aws.String(namespace),
- }
-
- plog.Debug("Listing metrics pages")
- var resp cloudwatch.ListMetricsOutput
- err = client.ListMetricsPages(params, func(page *cloudwatch.ListMetricsOutput, lastPage bool) bool {
- metrics.MAwsCloudWatchListMetrics.Inc()
- metrics, err := awsutil.ValuesAtPath(page, "Metrics")
- if err != nil {
- return !lastPage
- }
-
- for _, metric := range metrics {
- resp.Metrics = append(resp.Metrics, metric.(*cloudwatch.Metric))
- }
- return !lastPage
- })
-
- return resp, err
-}
-
var metricsCacheLock sync.Mutex
func (e *cloudWatchExecutor) getMetricsForCustomMetrics(region, namespace string) ([]string, error) {
@@ -760,7 +732,10 @@ func (e *cloudWatchExecutor) getMetricsForCustomMetrics(region, namespace string
if customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region][namespace].Expire.After(time.Now()) {
return customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region][namespace].Cache, nil
}
- result, err := e.getAllMetrics(region, namespace)
+ metrics, err := e.listMetrics(region, &cloudwatch.ListMetricsInput{
+ Namespace: aws.String(namespace),
+ })
+
if err != nil {
return []string{}, err
}
@@ -768,7 +743,7 @@ func (e *cloudWatchExecutor) getMetricsForCustomMetrics(region, namespace string
customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region][namespace].Cache = make([]string, 0)
customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region][namespace].Expire = time.Now().Add(5 * time.Minute)
- for _, metric := range result.Metrics {
+ for _, metric := range metrics {
if isDuplicate(customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region][namespace].Cache, *metric.MetricName) {
continue
}
@@ -801,14 +776,15 @@ func (e *cloudWatchExecutor) getDimensionsForCustomMetrics(region, namespace str
if customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region][namespace].Expire.After(time.Now()) {
return customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region][namespace].Cache, nil
}
- result, err := e.getAllMetrics(region, namespace)
+
+ metrics, err := e.listMetrics(region, &cloudwatch.ListMetricsInput{Namespace: aws.String(namespace)})
if err != nil {
return []string{}, err
}
customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region][namespace].Cache = make([]string, 0)
customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region][namespace].Expire = time.Now().Add(5 * time.Minute)
- for _, metric := range result.Metrics {
+ for _, metric := range metrics {
for _, dimension := range metric.Dimensions {
if isDuplicate(customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region][namespace].Cache, *dimension.Name) {
continue
diff --git a/pkg/tsdb/cloudwatch/metric_find_query_test.go b/pkg/tsdb/cloudwatch/metric_find_query_test.go
index 66958ae0579..e9918504c30 100644
--- a/pkg/tsdb/cloudwatch/metric_find_query_test.go
+++ b/pkg/tsdb/cloudwatch/metric_find_query_test.go
@@ -15,6 +15,7 @@ import (
"github.com/aws/aws-sdk-go/service/resourcegroupstaggingapi/resourcegroupstaggingapiiface"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/plugins"
+ "github.com/grafana/grafana/pkg/setting"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@@ -499,3 +500,50 @@ func TestQuery_ResourceARNs(t *testing.T) {
}, resp)
})
}
+
+func TestQuery_ListMetricsPagination(t *testing.T) {
+ origNewCWClient := NewCWClient
+ t.Cleanup(func() {
+ NewCWClient = origNewCWClient
+ })
+
+ var client FakeCWClient
+
+ NewCWClient = func(sess *session.Session) cloudwatchiface.CloudWatchAPI {
+ return client
+ }
+
+ metrics := []*cloudwatch.Metric{
+ {MetricName: aws.String("Test_MetricName1")},
+ {MetricName: aws.String("Test_MetricName2")},
+ {MetricName: aws.String("Test_MetricName3")},
+ {MetricName: aws.String("Test_MetricName4")},
+ {MetricName: aws.String("Test_MetricName5")},
+ {MetricName: aws.String("Test_MetricName6")},
+ {MetricName: aws.String("Test_MetricName7")},
+ {MetricName: aws.String("Test_MetricName8")},
+ {MetricName: aws.String("Test_MetricName9")},
+ {MetricName: aws.String("Test_MetricName10")},
+ }
+
+ t.Run("List Metrics and page limit is reached", func(t *testing.T) {
+ client = FakeCWClient{Metrics: metrics, MetricsPerPage: 2}
+ executor := newExecutor(nil, &setting.Cfg{AWSListMetricsPageLimit: 3, AWSAllowedAuthProviders: []string{"default"}, AWSAssumeRoleEnabled: true})
+ executor.DataSource = fakeDataSource()
+ response, err := executor.listMetrics("default", &cloudwatch.ListMetricsInput{})
+ require.NoError(t, err)
+
+ expectedMetrics := client.MetricsPerPage * executor.cfg.AWSListMetricsPageLimit
+ assert.Equal(t, expectedMetrics, len(response))
+ })
+
+ t.Run("List Metrics and page limit is not reached", func(t *testing.T) {
+ client = FakeCWClient{Metrics: metrics, MetricsPerPage: 2}
+ executor := newExecutor(nil, &setting.Cfg{AWSListMetricsPageLimit: 1000, AWSAllowedAuthProviders: []string{"default"}, AWSAssumeRoleEnabled: true})
+ executor.DataSource = fakeDataSource()
+ response, err := executor.listMetrics("default", &cloudwatch.ListMetricsInput{})
+ require.NoError(t, err)
+
+ assert.Equal(t, len(metrics), len(response))
+ })
+}
diff --git a/pkg/tsdb/cloudwatch/test_utils.go b/pkg/tsdb/cloudwatch/test_utils.go
index 8f5725a4e90..7ceb36f8448 100644
--- a/pkg/tsdb/cloudwatch/test_utils.go
+++ b/pkg/tsdb/cloudwatch/test_utils.go
@@ -79,12 +79,24 @@ type FakeCWClient struct {
cloudwatchiface.CloudWatchAPI
Metrics []*cloudwatch.Metric
+
+ MetricsPerPage int
}
func (c FakeCWClient) ListMetricsPages(input *cloudwatch.ListMetricsInput, fn func(*cloudwatch.ListMetricsOutput, bool) bool) error {
- fn(&cloudwatch.ListMetricsOutput{
- Metrics: c.Metrics,
- }, true)
+ if c.MetricsPerPage == 0 {
+ c.MetricsPerPage = 1000
+ }
+ chunks := chunkSlice(c.Metrics, c.MetricsPerPage)
+
+ for i, metrics := range chunks {
+ response := fn(&cloudwatch.ListMetricsOutput{
+ Metrics: metrics,
+ }, i+1 == len(chunks))
+ if !response {
+ break
+ }
+ }
return nil
}
@@ -147,6 +159,23 @@ func (c fakeRGTAClient) GetResourcesPages(in *resourcegroupstaggingapi.GetResour
return nil
}
+func chunkSlice(slice []*cloudwatch.Metric, chunkSize int) [][]*cloudwatch.Metric {
+ var chunks [][]*cloudwatch.Metric
+ for {
+ if len(slice) == 0 {
+ break
+ }
+ if len(slice) < chunkSize {
+ chunkSize = len(slice)
+ }
+
+ chunks = append(chunks, slice[0:chunkSize])
+ slice = slice[chunkSize:]
+ }
+
+ return chunks
+}
+
func newTestConfig() *setting.Cfg {
- return &setting.Cfg{AWSAllowedAuthProviders: []string{"default"}, AWSAssumeRoleEnabled: true}
+ return &setting.Cfg{AWSAllowedAuthProviders: []string{"default"}, AWSAssumeRoleEnabled: true, AWSListMetricsPageLimit: 1000}
}