Cloudwatch: Refactor metrics resource request (#57424)

* refactor metrics request

* Update pkg/tsdb/cloudwatch/routes/dimension_keys_test.go

Co-authored-by: Shirley <4163034+fridgepoet@users.noreply.github.com>

* return metric struct value intead of pointer

* make it possible to test hard coded metrics service

* test all paths in route

* fix broken test

* fix one more broken test

* add integration test

Co-authored-by: Shirley <4163034+fridgepoet@users.noreply.github.com>
This commit is contained in:
Erik Sundell
2022-10-25 14:00:54 +02:00
committed by GitHub
co-authored by Shirley
parent 53d7404e2b
commit 4c654ddb76
21 changed files with 458 additions and 91 deletions
@@ -0,0 +1,43 @@
package services
import (
"fmt"
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/constants"
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/models"
)
var GetHardCodedDimensionKeysByNamespace = func(namespace string) ([]string, error) {
var dimensionKeys []string
exists := false
if dimensionKeys, exists = constants.NamespaceDimensionKeysMap[namespace]; !exists {
return nil, fmt.Errorf("unable to find dimensions for namespace '%q'", namespace)
}
return dimensionKeys, nil
}
var GetHardCodedMetricsByNamespace = func(namespace string) ([]models.Metric, error) {
response := []models.Metric{}
exists := false
var metrics []string
if metrics, exists = constants.NamespaceMetricsMap[namespace]; !exists {
return nil, fmt.Errorf("unable to find metrics for namespace '%q'", namespace)
}
for _, metric := range metrics {
response = append(response, models.Metric{Namespace: namespace, Name: metric})
}
return response, nil
}
var GetAllHardCodedMetrics = func() []models.Metric {
response := []models.Metric{}
for namespace, metrics := range constants.NamespaceMetricsMap {
for _, metric := range metrics {
response = append(response, models.Metric{Namespace: namespace, Name: metric})
}
}
return response
}
@@ -0,0 +1,39 @@
package services
import (
"testing"
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/models"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestHardcodedMetrics_GetHardCodedDimensionKeysByNamespace(t *testing.T) {
t.Run("Should return an error in case namespace doesnt exist in map", func(t *testing.T) {
resp, err := GetHardCodedDimensionKeysByNamespace("unknownNamespace")
require.Error(t, err)
assert.Nil(t, resp)
assert.Equal(t, err.Error(), "unable to find dimensions for namespace '\"unknownNamespace\"'")
})
t.Run("Should return keys if namespace exist", func(t *testing.T) {
resp, err := GetHardCodedDimensionKeysByNamespace("AWS/EC2")
require.NoError(t, err)
assert.Equal(t, []string{"AutoScalingGroupName", "ImageId", "InstanceId", "InstanceType"}, resp)
})
}
func TestHardcodedMetrics_GetHardCodedMetricsByNamespace(t *testing.T) {
t.Run("Should return an error in case namespace doesnt exist in map", func(t *testing.T) {
resp, err := GetHardCodedMetricsByNamespace("unknownNamespace")
require.Error(t, err)
assert.Nil(t, resp)
assert.Equal(t, err.Error(), "unable to find metrics for namespace '\"unknownNamespace\"'")
})
t.Run("Should return metrics if namespace exist", func(t *testing.T) {
resp, err := GetHardCodedMetricsByNamespace("AWS/IoTAnalytics")
require.NoError(t, err)
assert.Equal(t, []models.Metric{{Name: "ActionExecution", Namespace: "AWS/IoTAnalytics"}, {Name: "ActivityExecutionError", Namespace: "AWS/IoTAnalytics"}, {Name: "IncomingMessages", Namespace: "AWS/IoTAnalytics"}}, resp)
})
}
+19 -10
View File
@@ -6,7 +6,6 @@ import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/cloudwatch"
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/constants"
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/models"
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/models/request"
)
@@ -19,15 +18,6 @@ func NewListMetricsService(metricsClient models.MetricsClientProvider) models.Li
return &ListMetricsService{metricsClient}
}
func (*ListMetricsService) GetHardCodedDimensionKeysByNamespace(namespace string) ([]string, error) {
var dimensionKeys []string
exists := false
if dimensionKeys, exists = constants.NamespaceDimensionKeysMap[namespace]; !exists {
return nil, fmt.Errorf("unable to find dimensions for namespace '%q'", namespace)
}
return dimensionKeys, nil
}
func (l *ListMetricsService) GetDimensionKeysByDimensionFilter(r *request.DimensionKeysRequest) ([]string, error) {
input := &cloudwatch.ListMetricsInput{}
if r.Namespace != "" {
@@ -126,6 +116,25 @@ func (l *ListMetricsService) GetDimensionKeysByNamespace(namespace string) ([]st
return dimensionKeys, nil
}
func (l *ListMetricsService) GetMetricsByNamespace(namespace string) ([]models.Metric, error) {
metrics, err := l.ListMetricsWithPageLimit(&cloudwatch.ListMetricsInput{Namespace: aws.String(namespace)})
if err != nil {
return nil, err
}
response := []models.Metric{}
dupCheck := make(map[string]struct{})
for _, metric := range metrics {
if _, exists := dupCheck[*metric.MetricName]; exists {
continue
}
dupCheck[*metric.MetricName] = struct{}{}
response = append(response, models.Metric{Name: *metric.MetricName, Namespace: *metric.Namespace})
}
return response, nil
}
func setDimensionFilter(input *cloudwatch.ListMetricsInput, dimensionFilter []*request.Dimension) {
for _, dimension := range dimensionFilter {
df := &cloudwatch.DimensionFilter{
@@ -41,23 +41,6 @@ var metricResponse = []*cloudwatch.Metric{
},
}
func TestListMetricsService_GetHardCodedDimensionKeysByNamespace(t *testing.T) {
t.Run("Should return an error in case namespace doesnt exist in map", func(t *testing.T) {
listMetricsService := NewListMetricsService(&mocks.FakeMetricsClient{})
resp, err := listMetricsService.GetHardCodedDimensionKeysByNamespace("unknownNamespace")
require.Error(t, err)
assert.Nil(t, resp)
assert.Equal(t, err.Error(), "unable to find dimensions for namespace '\"unknownNamespace\"'")
})
t.Run("Should return keys if namespace exist", func(t *testing.T) {
listMetricsService := NewListMetricsService(&mocks.FakeMetricsClient{})
resp, err := listMetricsService.GetHardCodedDimensionKeysByNamespace("AWS/EC2")
require.NoError(t, err)
assert.Equal(t, []string{"AutoScalingGroupName", "ImageId", "InstanceId", "InstanceType"}, resp)
})
}
func TestListMetricsService_GetDimensionKeysByDimensionFilter(t *testing.T) {
t.Run("Should filter out duplicates and keys matching dimension filter keys", func(t *testing.T) {
fakeMetricsClient := &mocks.FakeMetricsClient{}