diff --git a/pkg/tsdb/cloudwatch/get_metric_data_executor_test.go b/pkg/tsdb/cloudwatch/get_metric_data_executor_test.go index dc9c3893077..4312fa4f364 100644 --- a/pkg/tsdb/cloudwatch/get_metric_data_executor_test.go +++ b/pkg/tsdb/cloudwatch/get_metric_data_executor_test.go @@ -5,41 +5,27 @@ import ( "testing" "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/request" "github.com/aws/aws-sdk-go/service/cloudwatch" - "github.com/aws/aws-sdk-go/service/cloudwatch/cloudwatchiface" + "github.com/grafana/grafana/pkg/tsdb/cloudwatch/mocks" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" ) -type cloudWatchFakeClient struct { - cloudwatchiface.CloudWatchAPI - - counterForGetMetricDataWithContext int -} - -func (client *cloudWatchFakeClient) GetMetricDataWithContext(ctx aws.Context, input *cloudwatch.GetMetricDataInput, opts ...request.Option) (*cloudwatch.GetMetricDataOutput, error) { - nextToken := "next" - res := []*cloudwatch.MetricDataResult{{ - Values: []*float64{aws.Float64(12.3), aws.Float64(23.5)}, - }} - if client.counterForGetMetricDataWithContext == 0 { - nextToken = "" - res = []*cloudwatch.MetricDataResult{{ - Values: []*float64{aws.Float64(100)}, - }} - } - client.counterForGetMetricDataWithContext-- - return &cloudwatch.GetMetricDataOutput{ - MetricDataResults: res, - NextToken: aws.String(nextToken), - }, nil -} - func TestGetMetricDataExecutorTest(t *testing.T) { executor := &cloudWatchExecutor{} inputs := &cloudwatch.GetMetricDataInput{MetricDataQueries: []*cloudwatch.MetricDataQuery{}} - res, err := executor.executeRequest(context.Background(), &cloudWatchFakeClient{counterForGetMetricDataWithContext: 1}, inputs) + mockMetricClient := &mocks.MetricsAPI{} + mockMetricClient.On("GetMetricDataWithContext", mock.Anything, mock.Anything, mock.Anything).Return( + &cloudwatch.GetMetricDataOutput{ + MetricDataResults: []*cloudwatch.MetricDataResult{{Values: []*float64{aws.Float64(12.3), aws.Float64(23.5)}}}, + NextToken: aws.String("next"), + }, nil).Once() + mockMetricClient.On("GetMetricDataWithContext", mock.Anything, mock.Anything, mock.Anything).Return( + &cloudwatch.GetMetricDataOutput{ + MetricDataResults: []*cloudwatch.MetricDataResult{{Values: []*float64{aws.Float64(100)}}}, + }, nil).Once() + res, err := executor.executeRequest(context.Background(), mockMetricClient, inputs) require.NoError(t, err) require.Len(t, res, 2) require.Len(t, res[0].MetricDataResults[0].Values, 2) diff --git a/pkg/tsdb/cloudwatch/mocks/cloudwatch_metric_api.go b/pkg/tsdb/cloudwatch/mocks/cloudwatch_metric_api.go index 656c775fb1a..8508f6e5697 100644 --- a/pkg/tsdb/cloudwatch/mocks/cloudwatch_metric_api.go +++ b/pkg/tsdb/cloudwatch/mocks/cloudwatch_metric_api.go @@ -10,18 +10,9 @@ import ( type FakeMetricsAPI struct { cloudwatchiface.CloudWatchAPI - cloudwatch.GetMetricDataOutput Metrics []*cloudwatch.Metric MetricsPerPage int - - CallsGetMetricDataWithContext []*cloudwatch.GetMetricDataInput -} - -func (c *FakeMetricsAPI) GetMetricDataWithContext(ctx aws.Context, input *cloudwatch.GetMetricDataInput, opts ...request.Option) (*cloudwatch.GetMetricDataOutput, error) { - c.CallsGetMetricDataWithContext = append(c.CallsGetMetricDataWithContext, input) - - return &c.GetMetricDataOutput, nil } func (c *FakeMetricsAPI) ListMetricsPages(input *cloudwatch.ListMetricsInput, fn func(*cloudwatch.ListMetricsOutput, bool) bool) error { @@ -58,12 +49,12 @@ func chunkSlice(slice []*cloudwatch.Metric, chunkSize int) [][]*cloudwatch.Metri return chunks } -type MetricsClient struct { +type MetricsAPI struct { cloudwatchiface.CloudWatchAPI mock.Mock } -func (m *MetricsClient) GetMetricDataWithContext(ctx aws.Context, input *cloudwatch.GetMetricDataInput, opts ...request.Option) (*cloudwatch.GetMetricDataOutput, error) { +func (m *MetricsAPI) GetMetricDataWithContext(ctx aws.Context, input *cloudwatch.GetMetricDataInput, opts ...request.Option) (*cloudwatch.GetMetricDataOutput, error) { args := m.Called(ctx, input, opts) return args.Get(0).(*cloudwatch.GetMetricDataOutput), args.Error(1) diff --git a/pkg/tsdb/cloudwatch/time_series_query_test.go b/pkg/tsdb/cloudwatch/time_series_query_test.go index 1e1b7dd0b37..c978120662f 100644 --- a/pkg/tsdb/cloudwatch/time_series_query_test.go +++ b/pkg/tsdb/cloudwatch/time_series_query_test.go @@ -32,28 +32,22 @@ func TestTimeSeriesQuery(t *testing.T) { t.Cleanup(func() { NewCWClient = origNewCWClient }) - var api mocks.FakeMetricsAPI + var api mocks.MetricsAPI NewCWClient = func(sess *session.Session) cloudwatchiface.CloudWatchAPI { return &api } t.Run("Custom metrics", func(t *testing.T) { - api = mocks.FakeMetricsAPI{ - CloudWatchAPI: nil, - GetMetricDataOutput: cloudwatch.GetMetricDataOutput{ - NextToken: nil, - Messages: []*cloudwatch.MessageData{}, - MetricDataResults: []*cloudwatch.MetricDataResult{ - { - StatusCode: aws.String("Complete"), Id: aws.String("a"), Label: aws.String("NetworkOut"), Values: []*float64{aws.Float64(1.0)}, Timestamps: []*time.Time{&now}, - }, - { - StatusCode: aws.String("Complete"), Id: aws.String("b"), Label: aws.String("NetworkIn"), Values: []*float64{aws.Float64(1.0)}, Timestamps: []*time.Time{&now}, - }, + api = mocks.MetricsAPI{} + api.On("GetMetricDataWithContext", mock.Anything, mock.Anything, mock.Anything).Return(&cloudwatch.GetMetricDataOutput{ + MetricDataResults: []*cloudwatch.MetricDataResult{ + { + StatusCode: aws.String("Complete"), Id: aws.String("a"), Label: aws.String("NetworkOut"), Values: []*float64{aws.Float64(1.0)}, Timestamps: []*time.Time{&now}, }, - }, - } + { + StatusCode: aws.String("Complete"), Id: aws.String("b"), Label: aws.String("NetworkIn"), Values: []*float64{aws.Float64(1.0)}, Timestamps: []*time.Time{&now}, + }}}, nil) im := datasource.NewInstanceManager(func(s backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) { return DataSource{Settings: &models.CloudWatchSettings{}}, nil @@ -150,7 +144,7 @@ func Test_executeTimeSeriesQuery_getCWClient_is_called_once_per_region_and_GetMe NewCWClient = origNewCWClient }) - var mockMetricClient mocks.MetricsClient + var mockMetricClient mocks.MetricsAPI NewCWClient = func(sess *session.Session) cloudwatchiface.CloudWatchAPI { return &mockMetricClient } @@ -164,7 +158,7 @@ func Test_executeTimeSeriesQuery_getCWClient_is_called_once_per_region_and_GetMe mockSessionCache.On("GetSession", mock.MatchedBy( func(config awsds.SessionConfig) bool { return config.Settings.Region == "us-east-1" })). // region from queries is asserted here Return(&session.Session{Config: &aws.Config{}}, nil).Once() - mockMetricClient = mocks.MetricsClient{} + mockMetricClient = mocks.MetricsAPI{} mockMetricClient.On("GetMetricDataWithContext", mock.Anything, mock.Anything, mock.Anything).Return(nil, nil) executor := newExecutor(im, newTestConfig(), mockSessionCache, featuremgmt.WithFeatures()) @@ -215,7 +209,7 @@ func Test_executeTimeSeriesQuery_getCWClient_is_called_once_per_region_and_GetMe sessionCache.On("GetSession", mock.MatchedBy( func(config awsds.SessionConfig) bool { return config.Settings.Region == "us-east-2" })). Return(&session.Session{Config: &aws.Config{}}, nil, nil).Once() - mockMetricClient = mocks.MetricsClient{} + mockMetricClient = mocks.MetricsAPI{} mockMetricClient.On("GetMetricDataWithContext", mock.Anything, mock.Anything, mock.Anything).Return(nil, nil) executor := newExecutor(im, newTestConfig(), sessionCache, featuremgmt.WithFeatures()) @@ -341,7 +335,7 @@ func Test_QueryData_timeSeriesQuery_GetMetricDataWithContext(t *testing.T) { NewCWClient = origNewCWClient }) - var api mocks.FakeMetricsAPI + var api mocks.MetricsAPI NewCWClient = func(sess *session.Session) cloudwatchiface.CloudWatchAPI { return &api @@ -352,7 +346,8 @@ func Test_QueryData_timeSeriesQuery_GetMetricDataWithContext(t *testing.T) { }) t.Run("passes query label as GetMetricData label when dynamic labels feature toggle is enabled", func(t *testing.T) { - api = mocks.FakeMetricsAPI{} + api = mocks.MetricsAPI{} + api.On("GetMetricDataWithContext", mock.Anything, mock.Anything, mock.Anything).Return(&cloudwatch.GetMetricDataOutput{}, nil) executor := newExecutor(im, newTestConfig(), &fakeSessionCache{}, featuremgmt.WithFeatures(featuremgmt.FlagCloudWatchDynamicLabels)) query := newTestQuery(t, queryParameters{ Label: aws.String("${PROP('Period')} some words ${PROP('Dim.InstanceId')}"), @@ -373,11 +368,12 @@ func Test_QueryData_timeSeriesQuery_GetMetricDataWithContext(t *testing.T) { }) assert.NoError(t, err) - require.Len(t, api.CallsGetMetricDataWithContext, 1) - require.Len(t, api.CallsGetMetricDataWithContext[0].MetricDataQueries, 1) - require.NotNil(t, api.CallsGetMetricDataWithContext[0].MetricDataQueries[0].Label) - - assert.Equal(t, "${PROP('Period')} some words ${PROP('Dim.InstanceId')}", *api.CallsGetMetricDataWithContext[0].MetricDataQueries[0].Label) + require.Len(t, api.Calls, 1) + getMetricDataInput, ok := api.Calls[0].Arguments.Get(1).(*cloudwatch.GetMetricDataInput) + require.True(t, ok) + require.Len(t, getMetricDataInput.MetricDataQueries, 1) + require.NotNil(t, getMetricDataInput.MetricDataQueries[0].Label) + assert.Equal(t, "${PROP('Period')} some words ${PROP('Dim.InstanceId')}", *getMetricDataInput.MetricDataQueries[0].Label) }) testCases := map[string]struct { @@ -399,7 +395,8 @@ func Test_QueryData_timeSeriesQuery_GetMetricDataWithContext(t *testing.T) { for name, tc := range testCases { t.Run(name, func(t *testing.T) { - api = mocks.FakeMetricsAPI{} + api = mocks.MetricsAPI{} + api.On("GetMetricDataWithContext", mock.Anything, mock.Anything, mock.Anything).Return(&cloudwatch.GetMetricDataOutput{}, nil) executor := newExecutor(im, newTestConfig(), &fakeSessionCache{}, tc.feature) _, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{ @@ -417,10 +414,12 @@ func Test_QueryData_timeSeriesQuery_GetMetricDataWithContext(t *testing.T) { }) assert.NoError(t, err) - require.Len(t, api.CallsGetMetricDataWithContext, 1) - require.Len(t, api.CallsGetMetricDataWithContext[0].MetricDataQueries, 1) - - assert.Nil(t, api.CallsGetMetricDataWithContext[0].MetricDataQueries[0].Label) + assert.NoError(t, err) + require.Len(t, api.Calls, 1) + getMetricDataInput, ok := api.Calls[0].Arguments.Get(1).(*cloudwatch.GetMetricDataInput) + require.True(t, ok) + require.Len(t, getMetricDataInput.MetricDataQueries, 1) + require.Nil(t, getMetricDataInput.MetricDataQueries[0].Label) }) } } @@ -430,21 +429,20 @@ func Test_QueryData_response_data_frame_names(t *testing.T) { t.Cleanup(func() { NewCWClient = origNewCWClient }) - var api mocks.FakeMetricsAPI + var api mocks.MetricsAPI NewCWClient = func(sess *session.Session) cloudwatchiface.CloudWatchAPI { return &api } labelFromGetMetricData := "some label" - api = mocks.FakeMetricsAPI{ - GetMetricDataOutput: cloudwatch.GetMetricDataOutput{ + api.On("GetMetricDataWithContext", mock.Anything, mock.Anything, mock.Anything). + Return(&cloudwatch.GetMetricDataOutput{ MetricDataResults: []*cloudwatch.MetricDataResult{ {StatusCode: aws.String("Complete"), Id: aws.String(queryId), Label: aws.String(labelFromGetMetricData), Values: []*float64{aws.Float64(1.0)}, Timestamps: []*time.Time{{}}}, - }, - }, - } + }}, nil) + im := datasource.NewInstanceManager(func(s backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) { return DataSource{Settings: &models.CloudWatchSettings{}}, nil })