mirror of
https://github.com/grafana/grafana.git
synced 2025-02-20 11:48:34 -06:00
* first pass * add instance manager * fix tests * remove dead code * unexport fields * cleanup * remove ds instance from executor * cleanup * inline im * remove old func * get error working * unexport field * let fe do its magic * fix channel name * revert some tsdb changes * fix annotations * cleanup
214 lines
5.4 KiB
Go
214 lines
5.4 KiB
Go
package metrics
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/aws/aws-sdk-go/aws"
|
|
"github.com/aws/aws-sdk-go/aws/session"
|
|
"github.com/aws/aws-sdk-go/service/cloudwatch/cloudwatchiface"
|
|
"github.com/aws/aws-sdk-go/service/cloudwatchlogs/cloudwatchlogsiface"
|
|
"github.com/grafana/grafana-plugin-sdk-go/data"
|
|
"github.com/grafana/grafana/pkg/models"
|
|
"github.com/grafana/grafana/pkg/plugins"
|
|
"github.com/grafana/grafana/pkg/services/sqlstore"
|
|
"github.com/grafana/grafana/pkg/tests/testinfra"
|
|
"github.com/grafana/grafana/pkg/tsdb/cloudwatch"
|
|
|
|
cwapi "github.com/aws/aws-sdk-go/service/cloudwatch"
|
|
"github.com/grafana/grafana/pkg/api/dtos"
|
|
"github.com/grafana/grafana/pkg/components/simplejson"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestQueryCloudWatchMetrics(t *testing.T) {
|
|
grafDir, cfgPath := testinfra.CreateGrafDir(t)
|
|
sqlStore := setUpDatabase(t, grafDir)
|
|
addr := testinfra.StartGrafana(t, grafDir, cfgPath, sqlStore)
|
|
|
|
origNewCWClient := cloudwatch.NewCWClient
|
|
t.Cleanup(func() {
|
|
cloudwatch.NewCWClient = origNewCWClient
|
|
})
|
|
var client cloudwatch.FakeCWClient
|
|
cloudwatch.NewCWClient = func(sess *session.Session) cloudwatchiface.CloudWatchAPI {
|
|
return client
|
|
}
|
|
|
|
t.Run("Custom metrics", func(t *testing.T) {
|
|
client = cloudwatch.FakeCWClient{
|
|
Metrics: []*cwapi.Metric{
|
|
{
|
|
MetricName: aws.String("Test_MetricName"),
|
|
Dimensions: []*cwapi.Dimension{
|
|
{
|
|
Name: aws.String("Test_DimensionName"),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
req := dtos.MetricRequest{
|
|
Queries: []*simplejson.Json{
|
|
simplejson.NewFromAny(map[string]interface{}{
|
|
"type": "metricFindQuery",
|
|
"subtype": "metrics",
|
|
"region": "us-east-1",
|
|
"namespace": "custom",
|
|
"datasourceId": 1,
|
|
}),
|
|
},
|
|
}
|
|
result := makeCWRequest(t, req, addr)
|
|
|
|
dataFrames := plugins.NewDecodedDataFrames(data.Frames{
|
|
&data.Frame{
|
|
RefID: "A",
|
|
Fields: []*data.Field{
|
|
data.NewField("text", nil, []string{"Test_MetricName"}),
|
|
data.NewField("value", nil, []string{"Test_MetricName"}),
|
|
},
|
|
Meta: &data.FrameMeta{
|
|
Custom: map[string]interface{}{
|
|
"rowCount": float64(1),
|
|
},
|
|
},
|
|
},
|
|
})
|
|
|
|
// Have to call this so that dataFrames.encoded is non-nil, for the comparison
|
|
// In the future we should use gocmp instead and ignore this field
|
|
_, err := dataFrames.Encoded()
|
|
require.NoError(t, err)
|
|
|
|
assert.Equal(t, plugins.DataResponse{
|
|
Results: map[string]plugins.DataQueryResult{
|
|
"A": {
|
|
RefID: "A",
|
|
Dataframes: dataFrames,
|
|
},
|
|
},
|
|
}, result)
|
|
})
|
|
}
|
|
|
|
func TestQueryCloudWatchLogs(t *testing.T) {
|
|
grafDir, cfgPath := testinfra.CreateGrafDir(t)
|
|
sqlStore := setUpDatabase(t, grafDir)
|
|
addr := testinfra.StartGrafana(t, grafDir, cfgPath, sqlStore)
|
|
|
|
origNewCWLogsClient := cloudwatch.NewCWLogsClient
|
|
t.Cleanup(func() {
|
|
cloudwatch.NewCWLogsClient = origNewCWLogsClient
|
|
})
|
|
|
|
var client cloudwatch.FakeCWLogsClient
|
|
cloudwatch.NewCWLogsClient = func(sess *session.Session) cloudwatchlogsiface.CloudWatchLogsAPI {
|
|
return client
|
|
}
|
|
|
|
t.Run("Describe log groups", func(t *testing.T) {
|
|
client = cloudwatch.FakeCWLogsClient{}
|
|
|
|
req := dtos.MetricRequest{
|
|
Queries: []*simplejson.Json{
|
|
simplejson.NewFromAny(map[string]interface{}{
|
|
"type": "logAction",
|
|
"subtype": "DescribeLogGroups",
|
|
"region": "us-east-1",
|
|
"datasourceId": 1,
|
|
}),
|
|
},
|
|
}
|
|
tr := makeCWRequest(t, req, addr)
|
|
|
|
dataFrames := plugins.NewDecodedDataFrames(data.Frames{
|
|
&data.Frame{
|
|
Name: "logGroups",
|
|
RefID: "A",
|
|
Fields: []*data.Field{
|
|
data.NewField("logGroupName", nil, []*string{}),
|
|
},
|
|
Meta: &data.FrameMeta{
|
|
PreferredVisualization: "logs",
|
|
},
|
|
},
|
|
})
|
|
// Have to call this so that dataFrames.encoded is non-nil, for the comparison
|
|
// In the future we should use gocmp instead and ignore this field
|
|
_, err := dataFrames.Encoded()
|
|
require.NoError(t, err)
|
|
assert.Equal(t, plugins.DataResponse{
|
|
Results: map[string]plugins.DataQueryResult{
|
|
"A": {
|
|
RefID: "A",
|
|
Dataframes: dataFrames,
|
|
},
|
|
},
|
|
}, tr)
|
|
})
|
|
}
|
|
|
|
func makeCWRequest(t *testing.T, req dtos.MetricRequest, addr string) plugins.DataResponse {
|
|
t.Helper()
|
|
|
|
buf := bytes.Buffer{}
|
|
enc := json.NewEncoder(&buf)
|
|
err := enc.Encode(&req)
|
|
require.NoError(t, err)
|
|
u := fmt.Sprintf("http://%s/api/ds/query", addr)
|
|
t.Logf("Making POST request to %s", u)
|
|
// nolint:gosec
|
|
resp, err := http.Post(u, "application/json", &buf)
|
|
require.NoError(t, err)
|
|
require.NotNil(t, resp)
|
|
t.Cleanup(func() {
|
|
err := resp.Body.Close()
|
|
assert.NoError(t, err)
|
|
})
|
|
|
|
buf = bytes.Buffer{}
|
|
_, err = io.Copy(&buf, resp.Body)
|
|
require.NoError(t, err)
|
|
require.Equal(t, 200, resp.StatusCode)
|
|
|
|
var tr plugins.DataResponse
|
|
err = json.Unmarshal(buf.Bytes(), &tr)
|
|
require.NoError(t, err)
|
|
|
|
return tr
|
|
}
|
|
|
|
func setUpDatabase(t *testing.T, grafDir string) *sqlstore.SQLStore {
|
|
t.Helper()
|
|
|
|
sqlStore := testinfra.SetUpDatabase(t, grafDir)
|
|
err := sqlStore.WithDbSession(context.Background(), func(sess *sqlstore.DBSession) error {
|
|
_, err := sess.Insert(&models.DataSource{
|
|
Id: 1,
|
|
// This will be the ID of the main org
|
|
OrgId: 2,
|
|
Name: "Test",
|
|
Type: "cloudwatch",
|
|
Created: time.Now(),
|
|
Updated: time.Now(),
|
|
})
|
|
return err
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
// Make sure changes are synced with other goroutines
|
|
err = sqlStore.Sync()
|
|
require.NoError(t, err)
|
|
|
|
return sqlStore
|
|
}
|