mirror of
https://github.com/grafana/grafana.git
synced 2025-02-14 17:43:35 -06:00
251 lines
9.1 KiB
Go
251 lines
9.1 KiB
Go
package cloudwatch
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/aws/aws-sdk-go/aws"
|
|
awsrequest "github.com/aws/aws-sdk-go/aws/request"
|
|
"github.com/aws/aws-sdk-go/aws/session"
|
|
"github.com/aws/aws-sdk-go/service/cloudwatch"
|
|
"github.com/aws/aws-sdk-go/service/cloudwatch/cloudwatchiface"
|
|
"github.com/aws/aws-sdk-go/service/cloudwatchlogs"
|
|
"github.com/aws/aws-sdk-go/service/cloudwatchlogs/cloudwatchlogsiface"
|
|
"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/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestNewInstanceSettings(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
settings backend.DataSourceInstanceSettings
|
|
expectedDS datasourceInfo
|
|
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: datasourceInfo{
|
|
profile: "foo",
|
|
region: "us-east2",
|
|
assumeRoleARN: "role",
|
|
externalID: "id",
|
|
endpoint: "bar",
|
|
namespace: "ns",
|
|
authType: awsds.AuthTypeKeys,
|
|
accessKey: "A123",
|
|
secretKey: "secret",
|
|
},
|
|
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 datasourceInfo, d2 datasourceInfo) bool {
|
|
return d1.profile == d2.profile &&
|
|
d1.region == d2.region &&
|
|
d1.authType == d2.authType &&
|
|
d1.assumeRoleARN == d2.assumeRoleARN &&
|
|
d1.externalID == d2.externalID &&
|
|
d1.namespace == d2.namespace &&
|
|
d1.endpoint == d2.endpoint &&
|
|
d1.accessKey == d2.accessKey &&
|
|
d1.secretKey == d2.secretKey &&
|
|
d1.datasourceID == d2.datasourceID
|
|
})
|
|
if !cmp.Equal(model.(datasourceInfo), tt.expectedDS, datasourceComparer) {
|
|
t.Errorf("Unexpected result. Expecting\n%v \nGot:\n%v", model, tt.expectedDS)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func Test_CheckHealth(t *testing.T) {
|
|
origNewCWClient := NewCWClient
|
|
origNewCWLogsClient := NewCWLogsClient
|
|
t.Cleanup(func() {
|
|
NewCWClient = origNewCWClient
|
|
NewCWLogsClient = origNewCWLogsClient
|
|
})
|
|
|
|
var client fakeCheckHealthClient
|
|
NewCWClient = func(sess *session.Session) cloudwatchiface.CloudWatchAPI {
|
|
return client
|
|
}
|
|
NewCWLogsClient = func(sess *session.Session) cloudwatchlogsiface.CloudWatchLogsAPI {
|
|
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 datasourceInfo{}, 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{
|
|
describeLogGroupsWithContext: func(ctx aws.Context, input *cloudwatchlogs.DescribeLogGroupsInput,
|
|
options ...awsrequest.Option) (*cloudwatchlogs.DescribeLogGroupsOutput, error) {
|
|
return nil, fmt.Errorf("some logs query error")
|
|
}}
|
|
im := datasource.NewInstanceManager(func(s backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
|
|
return datasourceInfo{}, 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 datasourceInfo{}, 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 datasourceInfo{}, 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 Test_executeLogAlertQuery(t *testing.T) {
|
|
origNewCWClient := NewCWClient
|
|
t.Cleanup(func() {
|
|
NewCWClient = origNewCWClient
|
|
})
|
|
|
|
var cli fakeCWLogsClient
|
|
NewCWLogsClient = func(sess *session.Session) cloudwatchlogsiface.CloudWatchLogsAPI {
|
|
return &cli
|
|
}
|
|
|
|
t.Run("getCWLogsClient is called with region from input JSON", func(t *testing.T) {
|
|
cli = fakeCWLogsClient{queryResults: cloudwatchlogs.GetQueryResultsOutput{Status: aws.String("Complete")}}
|
|
im := datasource.NewInstanceManager(func(s backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
|
|
return datasourceInfo{}, nil
|
|
})
|
|
sess := fakeSessionCache{}
|
|
executor := newExecutor(im, newTestConfig(), &sess, featuremgmt.WithFeatures())
|
|
|
|
_, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{
|
|
Headers: map[string]string{"FromAlert": "some value"},
|
|
PluginContext: backend.PluginContext{DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}},
|
|
Queries: []backend.DataQuery{
|
|
{
|
|
TimeRange: backend.TimeRange{From: time.Unix(0, 0), To: time.Unix(1, 0)},
|
|
JSON: json.RawMessage(`{
|
|
"queryMode": "Logs",
|
|
"region": "some region"
|
|
}`),
|
|
},
|
|
},
|
|
})
|
|
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, []string{"some region"}, sess.calledRegions)
|
|
})
|
|
|
|
t.Run("getCWLogsClient is called with region from instance manager when region is default", func(t *testing.T) {
|
|
cli = fakeCWLogsClient{queryResults: cloudwatchlogs.GetQueryResultsOutput{Status: aws.String("Complete")}}
|
|
im := datasource.NewInstanceManager(func(s backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
|
|
return datasourceInfo{region: "instance manager's region"}, nil
|
|
})
|
|
sess := fakeSessionCache{}
|
|
|
|
executor := newExecutor(im, newTestConfig(), &sess, featuremgmt.WithFeatures())
|
|
_, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{
|
|
Headers: map[string]string{"FromAlert": "some value"},
|
|
PluginContext: backend.PluginContext{DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}},
|
|
Queries: []backend.DataQuery{
|
|
{
|
|
TimeRange: backend.TimeRange{From: time.Unix(0, 0), To: time.Unix(1, 0)},
|
|
JSON: json.RawMessage(`{
|
|
"queryMode": "Logs",
|
|
"region": "default"
|
|
}`),
|
|
},
|
|
},
|
|
})
|
|
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, []string{"instance manager's region"}, sess.calledRegions)
|
|
})
|
|
}
|