mirror of
https://github.com/grafana/grafana.git
synced 2024-11-29 04:04:00 -06:00
6309d3fae6
Co-authored-by: Shirley <4163034+fridgepoet@users.noreply.github.com> Co-authored-by: Isabella Siu <Isabella.siu@grafana.com>
253 lines
9.3 KiB
Go
253 lines
9.3 KiB
Go
package cloudwatch
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"testing"
|
|
|
|
"github.com/aws/aws-sdk-go/aws"
|
|
"github.com/aws/aws-sdk-go/aws/session"
|
|
"github.com/aws/aws-sdk-go/service/cloudwatch"
|
|
"github.com/aws/aws-sdk-go/service/cloudwatchlogs"
|
|
"github.com/google/go-cmp/cmp"
|
|
"github.com/grafana/grafana-aws-sdk/pkg/awsds"
|
|
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
|
"github.com/grafana/grafana-plugin-sdk-go/backend/datasource"
|
|
"github.com/grafana/grafana-plugin-sdk-go/backend/instancemgmt"
|
|
"github.com/grafana/grafana/pkg/infra/httpclient"
|
|
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
|
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/mocks"
|
|
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/models"
|
|
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/utils"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/mock"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestNewInstanceSettings(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
settings backend.DataSourceInstanceSettings
|
|
expectedDS DataSource
|
|
Err require.ErrorAssertionFunc
|
|
}{
|
|
{
|
|
name: "creates a request",
|
|
settings: backend.DataSourceInstanceSettings{
|
|
JSONData: []byte(`{
|
|
"profile": "foo",
|
|
"defaultRegion": "us-east2",
|
|
"assumeRoleArn": "role",
|
|
"externalId": "id",
|
|
"endpoint": "bar",
|
|
"customMetricsNamespaces": "ns",
|
|
"authType": "keys"
|
|
}`),
|
|
DecryptedSecureJSONData: map[string]string{
|
|
"accessKey": "A123",
|
|
"secretKey": "secret",
|
|
},
|
|
},
|
|
expectedDS: DataSource{
|
|
Settings: models.CloudWatchSettings{
|
|
AWSDatasourceSettings: awsds.AWSDatasourceSettings{
|
|
Profile: "foo",
|
|
Region: "us-east2",
|
|
AssumeRoleARN: "role",
|
|
ExternalID: "id",
|
|
Endpoint: "bar",
|
|
AuthType: awsds.AuthTypeKeys,
|
|
AccessKey: "A123",
|
|
SecretKey: "secret",
|
|
},
|
|
Namespace: "ns",
|
|
},
|
|
},
|
|
Err: require.NoError,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
f := NewInstanceSettings(httpclient.NewProvider())
|
|
model, err := f(tt.settings)
|
|
tt.Err(t, err)
|
|
datasourceComparer := cmp.Comparer(func(d1 DataSource, d2 DataSource) bool {
|
|
return d1.Settings.Profile == d2.Settings.Profile &&
|
|
d1.Settings.Region == d2.Settings.Region &&
|
|
d1.Settings.AuthType == d2.Settings.AuthType &&
|
|
d1.Settings.AssumeRoleARN == d2.Settings.AssumeRoleARN &&
|
|
d1.Settings.ExternalID == d2.Settings.ExternalID &&
|
|
d1.Settings.Namespace == d2.Settings.Namespace &&
|
|
d1.Settings.Endpoint == d2.Settings.Endpoint &&
|
|
d1.Settings.AccessKey == d2.Settings.AccessKey &&
|
|
d1.Settings.SecretKey == d2.Settings.SecretKey
|
|
})
|
|
if !cmp.Equal(model.(DataSource), tt.expectedDS, datasourceComparer) {
|
|
t.Errorf("Unexpected result. Expecting\n%v \nGot:\n%v", model, tt.expectedDS)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func Test_CheckHealth(t *testing.T) {
|
|
origNewMetricsAPI := NewMetricsAPI
|
|
origNewCWLogsClient := NewCWLogsClient
|
|
origNewLogsAPI := NewLogsAPI
|
|
t.Cleanup(func() {
|
|
NewMetricsAPI = origNewMetricsAPI
|
|
NewCWLogsClient = origNewCWLogsClient
|
|
NewLogsAPI = origNewLogsAPI
|
|
})
|
|
|
|
var client fakeCheckHealthClient
|
|
NewMetricsAPI = func(sess *session.Session) models.CloudWatchMetricsAPIProvider {
|
|
return client
|
|
}
|
|
NewLogsAPI = func(sess *session.Session) models.CloudWatchLogsAPIProvider {
|
|
return client
|
|
}
|
|
|
|
t.Run("successfully query metrics and logs", func(t *testing.T) {
|
|
client = fakeCheckHealthClient{}
|
|
im := datasource.NewInstanceManager(func(s backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
|
|
return DataSource{Settings: models.CloudWatchSettings{}}, nil
|
|
})
|
|
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{}, featuremgmt.WithFeatures())
|
|
|
|
resp, err := executor.CheckHealth(context.Background(), &backend.CheckHealthRequest{
|
|
PluginContext: backend.PluginContext{DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}},
|
|
})
|
|
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, &backend.CheckHealthResult{
|
|
Status: backend.HealthStatusOk,
|
|
Message: "1. Successfully queried the CloudWatch metrics API.\n2. Successfully queried the CloudWatch logs API.",
|
|
}, resp)
|
|
})
|
|
|
|
t.Run("successfully queries metrics, fails during logs query", func(t *testing.T) {
|
|
client = fakeCheckHealthClient{
|
|
describeLogGroups: func(input *cloudwatchlogs.DescribeLogGroupsInput) (*cloudwatchlogs.DescribeLogGroupsOutput, error) {
|
|
return nil, fmt.Errorf("some logs query error")
|
|
}}
|
|
im := datasource.NewInstanceManager(func(s backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
|
|
return DataSource{Settings: models.CloudWatchSettings{}}, nil
|
|
})
|
|
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{}, featuremgmt.WithFeatures())
|
|
|
|
resp, err := executor.CheckHealth(context.Background(), &backend.CheckHealthRequest{
|
|
PluginContext: backend.PluginContext{DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}},
|
|
})
|
|
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, &backend.CheckHealthResult{
|
|
Status: backend.HealthStatusError,
|
|
Message: "1. Successfully queried the CloudWatch metrics API.\n2. CloudWatch logs query failed: some logs query error",
|
|
}, resp)
|
|
})
|
|
|
|
t.Run("successfully queries logs, fails during metrics query", func(t *testing.T) {
|
|
client = fakeCheckHealthClient{
|
|
listMetricsPages: func(input *cloudwatch.ListMetricsInput, fn func(*cloudwatch.ListMetricsOutput, bool) bool) error {
|
|
return fmt.Errorf("some list metrics error")
|
|
}}
|
|
im := datasource.NewInstanceManager(func(s backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
|
|
return DataSource{Settings: models.CloudWatchSettings{}}, nil
|
|
})
|
|
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{}, featuremgmt.WithFeatures())
|
|
|
|
resp, err := executor.CheckHealth(context.Background(), &backend.CheckHealthRequest{
|
|
PluginContext: backend.PluginContext{DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}},
|
|
})
|
|
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, &backend.CheckHealthResult{
|
|
Status: backend.HealthStatusError,
|
|
Message: "1. CloudWatch metrics query failed: some list metrics error\n2. Successfully queried the CloudWatch logs API.",
|
|
}, resp)
|
|
})
|
|
|
|
t.Run("fail to get clients", func(t *testing.T) {
|
|
client = fakeCheckHealthClient{}
|
|
im := datasource.NewInstanceManager(func(s backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
|
|
return DataSource{Settings: models.CloudWatchSettings{}}, nil
|
|
})
|
|
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{getSession: func(c awsds.SessionConfig) (*session.Session, error) {
|
|
return nil, fmt.Errorf("some sessions error")
|
|
}}, featuremgmt.WithFeatures())
|
|
|
|
resp, err := executor.CheckHealth(context.Background(), &backend.CheckHealthRequest{
|
|
PluginContext: backend.PluginContext{DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}},
|
|
})
|
|
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, &backend.CheckHealthResult{
|
|
Status: backend.HealthStatusError,
|
|
Message: "1. CloudWatch metrics query failed: some sessions error\n2. CloudWatch logs query failed: some sessions error",
|
|
}, resp)
|
|
})
|
|
}
|
|
|
|
func TestQuery_ResourceRequest_DescribeLogGroups_with_CrossAccountQuerying(t *testing.T) {
|
|
sender := &mockedCallResourceResponseSenderForOauth{}
|
|
origNewMetricsAPI := NewMetricsAPI
|
|
origNewOAMAPI := NewOAMAPI
|
|
origNewLogsAPI := NewLogsAPI
|
|
NewMetricsAPI = func(sess *session.Session) models.CloudWatchMetricsAPIProvider { return nil }
|
|
NewOAMAPI = func(sess *session.Session) models.OAMAPIProvider { return nil }
|
|
t.Cleanup(func() {
|
|
NewOAMAPI = origNewOAMAPI
|
|
NewMetricsAPI = origNewMetricsAPI
|
|
NewLogsAPI = origNewLogsAPI
|
|
})
|
|
|
|
var logsApi mocks.LogsAPI
|
|
NewLogsAPI = func(sess *session.Session) models.CloudWatchLogsAPIProvider {
|
|
return &logsApi
|
|
}
|
|
|
|
im := datasource.NewInstanceManager(func(s backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
|
|
return DataSource{Settings: models.CloudWatchSettings{}}, nil
|
|
})
|
|
|
|
t.Run("maps log group api response to resource response of log-groups", func(t *testing.T) {
|
|
logsApi = mocks.LogsAPI{}
|
|
logsApi.On("DescribeLogGroups", mock.Anything).Return(&cloudwatchlogs.DescribeLogGroupsOutput{
|
|
LogGroups: []*cloudwatchlogs.LogGroup{
|
|
{Arn: aws.String("arn:aws:logs:us-east-1:111:log-group:group_a"), LogGroupName: aws.String("group_a")},
|
|
},
|
|
}, nil)
|
|
req := &backend.CallResourceRequest{
|
|
Method: "GET",
|
|
Path: `/log-groups?logGroupPattern=some-pattern&accountId=some-account-id`,
|
|
PluginContext: backend.PluginContext{
|
|
DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{ID: 0},
|
|
PluginID: "cloudwatch",
|
|
},
|
|
}
|
|
|
|
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{}, featuremgmt.WithFeatures(featuremgmt.FlagCloudWatchCrossAccountQuerying))
|
|
err := executor.CallResource(context.Background(), req, sender)
|
|
assert.NoError(t, err)
|
|
|
|
assert.JSONEq(t, `[
|
|
{
|
|
"accountId":"111",
|
|
"value":{
|
|
"arn":"arn:aws:logs:us-east-1:111:log-group:group_a",
|
|
"name":"group_a"
|
|
}
|
|
}
|
|
]`, string(sender.Response.Body))
|
|
|
|
logsApi.AssertCalled(t, "DescribeLogGroups",
|
|
&cloudwatchlogs.DescribeLogGroupsInput{
|
|
AccountIdentifiers: []*string{utils.Pointer("some-account-id")},
|
|
IncludeLinkedAccounts: utils.Pointer(true),
|
|
Limit: utils.Pointer(int64(50)),
|
|
LogGroupNamePrefix: utils.Pointer("some-pattern"),
|
|
})
|
|
})
|
|
}
|