Quellcode durchsuchen

fix cloudwatch ec2_instance_attribute (#9718)

* fix cloudwatch ec2_instance_attribute

* add test

* minor fix
Mitsuhiro Tanda vor 8 Jahren
Ursprung
Commit
52e1c4113b

+ 2 - 0
pkg/tsdb/cloudwatch/cloudwatch.go

@@ -17,6 +17,7 @@ import (
 	"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/ec2/ec2iface"
 	"github.com/grafana/grafana/pkg/components/null"
 	"github.com/grafana/grafana/pkg/components/simplejson"
 	"github.com/grafana/grafana/pkg/metrics"
@@ -24,6 +25,7 @@ import (
 
 type CloudWatchExecutor struct {
 	*models.DataSource
+	ec2Svc ec2iface.EC2API
 }
 
 type DatasourceInfo struct {

+ 19 - 16
pkg/tsdb/cloudwatch/metric_find_query.go

@@ -185,6 +185,18 @@ func (e *CloudWatchExecutor) executeMetricFindQuery(ctx context.Context, queryCo
 		data, err = e.handleGetEbsVolumeIds(ctx, parameters, queryContext)
 		break
 	case "ec2_instance_attribute":
+		region := parameters.Get("region").MustString()
+		dsInfo := e.getDsInfo(region)
+		cfg, err := e.getAwsConfig(dsInfo)
+		if err != nil {
+			return nil, errors.New("Failed to call ec2:DescribeInstances")
+		}
+		sess, err := session.NewSession(cfg)
+		if err != nil {
+			return nil, errors.New("Failed to call ec2:DescribeInstances")
+		}
+		e.ec2Svc = ec2.New(sess, cfg)
+
 		data, err = e.handleGetEc2InstanceAttribute(ctx, parameters, queryContext)
 		break
 	}
@@ -375,14 +387,16 @@ func (e *CloudWatchExecutor) handleGetEc2InstanceAttribute(ctx context.Context,
 
 	var filters []*ec2.Filter
 	for k, v := range filterJson {
-		if vv, ok := v.([]string); ok {
-			var vvvv []*string
+		if vv, ok := v.([]interface{}); ok {
+			var vvvvv []*string
 			for _, vvv := range vv {
-				vvvv = append(vvvv, &vvv)
+				if vvvv, ok := vvv.(string); ok {
+					vvvvv = append(vvvvv, &vvvv)
+				}
 			}
 			filters = append(filters, &ec2.Filter{
 				Name:   aws.String(k),
-				Values: vvvv,
+				Values: vvvvv,
 			})
 		}
 	}
@@ -469,24 +483,13 @@ func (e *CloudWatchExecutor) cloudwatchListMetrics(region string, namespace stri
 }
 
 func (e *CloudWatchExecutor) ec2DescribeInstances(region string, filters []*ec2.Filter, instanceIds []*string) (*ec2.DescribeInstancesOutput, error) {
-	dsInfo := e.getDsInfo(region)
-	cfg, err := e.getAwsConfig(dsInfo)
-	if err != nil {
-		return nil, errors.New("Failed to call ec2:DescribeInstances")
-	}
-	sess, err := session.NewSession(cfg)
-	if err != nil {
-		return nil, errors.New("Failed to call ec2:DescribeInstances")
-	}
-	svc := ec2.New(sess, cfg)
-
 	params := &ec2.DescribeInstancesInput{
 		Filters:     filters,
 		InstanceIds: instanceIds,
 	}
 
 	var resp ec2.DescribeInstancesOutput
-	err = svc.DescribeInstancesPages(params,
+	err := e.ec2Svc.DescribeInstancesPages(params,
 		func(page *ec2.DescribeInstancesOutput, lastPage bool) bool {
 			reservations, _ := awsutil.ValuesAtPath(page, "Reservations")
 			for _, reservation := range reservations {

+ 48 - 0
pkg/tsdb/cloudwatch/metric_find_query_test.go

@@ -1,13 +1,28 @@
 package cloudwatch
 
 import (
+	"context"
 	"testing"
 
 	"github.com/aws/aws-sdk-go/aws"
 	"github.com/aws/aws-sdk-go/service/cloudwatch"
+	"github.com/aws/aws-sdk-go/service/ec2"
+	"github.com/aws/aws-sdk-go/service/ec2/ec2iface"
+	"github.com/grafana/grafana/pkg/components/simplejson"
+	"github.com/grafana/grafana/pkg/tsdb"
 	. "github.com/smartystreets/goconvey/convey"
 )
 
+type mockedEc2 struct {
+	ec2iface.EC2API
+	Resp ec2.DescribeInstancesOutput
+}
+
+func (m mockedEc2) DescribeInstancesPages(in *ec2.DescribeInstancesInput, fn func(*ec2.DescribeInstancesOutput, bool) bool) error {
+	fn(&m.Resp, true)
+	return nil
+}
+
 func TestCloudWatchMetrics(t *testing.T) {
 
 	Convey("When calling getMetricsForCustomMetrics", t, func() {
@@ -66,4 +81,37 @@ func TestCloudWatchMetrics(t *testing.T) {
 		})
 	})
 
+	Convey("When calling handleGetEc2InstanceAttribute", t, func() {
+		executor := &CloudWatchExecutor{
+			ec2Svc: mockedEc2{Resp: ec2.DescribeInstancesOutput{
+				Reservations: []*ec2.Reservation{
+					{
+						Instances: []*ec2.Instance{
+							{
+								InstanceId: aws.String("i-12345678"),
+								Tags: []*ec2.Tag{
+									{
+										Key:   aws.String("Environment"),
+										Value: aws.String("production"),
+									},
+								},
+							},
+						},
+					},
+				},
+			}},
+		}
+
+		json := simplejson.New()
+		json.Set("region", "us-east-1")
+		json.Set("attributeName", "InstanceId")
+		filters := make(map[string]interface{})
+		filters["tag:Environment"] = []string{"production"}
+		json.Set("filters", filters)
+		result, _ := executor.handleGetEc2InstanceAttribute(context.Background(), json, &tsdb.TsdbQuery{})
+
+		Convey("Should equal production InstanceId", func() {
+			So(result[0].Text, ShouldEqual, "i-12345678")
+		})
+	})
 }