Bläddra i källkod

re-implement ebs_volume_ids()

Mitsuhiro Tanda 8 år sedan
förälder
incheckning
cf23734d7d

+ 68 - 0
pkg/tsdb/cloudwatch/metric_find_query.go

@@ -12,6 +12,7 @@ import (
 	"github.com/aws/aws-sdk-go/aws/awsutil"
 	"github.com/aws/aws-sdk-go/aws/awsutil"
 	"github.com/aws/aws-sdk-go/aws/session"
 	"github.com/aws/aws-sdk-go/aws/session"
 	"github.com/aws/aws-sdk-go/service/cloudwatch"
 	"github.com/aws/aws-sdk-go/service/cloudwatch"
+	"github.com/aws/aws-sdk-go/service/ec2"
 	cwapi "github.com/grafana/grafana/pkg/api/cloudwatch"
 	cwapi "github.com/grafana/grafana/pkg/api/cloudwatch"
 	"github.com/grafana/grafana/pkg/components/simplejson"
 	"github.com/grafana/grafana/pkg/components/simplejson"
 	"github.com/grafana/grafana/pkg/metrics"
 	"github.com/grafana/grafana/pkg/metrics"
@@ -174,6 +175,9 @@ func (e *CloudWatchExecutor) executeMetricFindQuery(ctx context.Context, queries
 	case "dimension_keys":
 	case "dimension_keys":
 		data, err = e.handleGetDimensions(ctx, parameters, queryContext)
 		data, err = e.handleGetDimensions(ctx, parameters, queryContext)
 		break
 		break
+	case "ebs_volume_ids":
+		data, err = e.handleGetEbsVolumeIds(ctx, parameters, queryContext)
+		break
 	}
 	}
 	if err != nil {
 	if err != nil {
 		queryResult.Error = err
 		queryResult.Error = err
@@ -320,6 +324,70 @@ func (e *CloudWatchExecutor) handleGetDimensions(ctx context.Context, parameters
 	return result, nil
 	return result, nil
 }
 }
 
 
+func (e *CloudWatchExecutor) handleGetEbsVolumeIds(ctx context.Context, parameters *simplejson.Json, queryContext *tsdb.QueryContext) ([]suggestData, error) {
+	region := parameters.Get("region").MustString()
+	instanceId := parameters.Get("instanceId").MustString()
+
+	instanceIds := []*string{aws.String(instanceId)}
+	instances, err := e.ec2DescribeInstances(region, nil, instanceIds)
+	if err != nil {
+		return nil, err
+	}
+
+	result := make([]suggestData, 0)
+	for _, mapping := range instances.Reservations[0].Instances[0].BlockDeviceMappings {
+		result = append(result, suggestData{Text: *mapping.Ebs.VolumeId, Value: *mapping.Ebs.VolumeId})
+	}
+
+	return result, nil
+}
+
+func getAwsConfig(dsInfo *cwapi.DatasourceInfo) (*aws.Config, error) {
+	creds, err := cwapi.GetCredentials(dsInfo)
+	if err != nil {
+		return nil, err
+	}
+
+	cfg := &aws.Config{
+		Region:      aws.String(dsInfo.Region),
+		Credentials: creds,
+	}
+	return cfg, nil
+}
+
+func (e *CloudWatchExecutor) ec2DescribeInstances(region string, filters []*ec2.Filter, instanceIds []*string) (*ec2.DescribeInstancesOutput, error) {
+	dsInfo := e.getDsInfo(region)
+	cfg, err := getAwsConfig(dsInfo)
+	if err != nil {
+		return nil, errors.New("Failed to call describe instances")
+	}
+	sess, err := session.NewSession(cfg)
+	if err != nil {
+		return nil, errors.New("Failed to call describe instances")
+	}
+	svc := ec2.New(sess, cfg)
+
+	params := &ec2.DescribeInstancesInput{
+		Filters:     filters,
+		InstanceIds: instanceIds,
+	}
+
+	var resp ec2.DescribeInstancesOutput
+	err = svc.DescribeInstancesPages(params,
+		func(page *ec2.DescribeInstancesOutput, lastPage bool) bool {
+			reservations, _ := awsutil.ValuesAtPath(page, "Reservations")
+			for _, reservation := range reservations {
+				resp.Reservations = append(resp.Reservations, reservation.(*ec2.Reservation))
+			}
+			return !lastPage
+		})
+	if err != nil {
+		return nil, errors.New("Failed to call describe instances")
+	}
+
+	return &resp, nil
+}
+
 func getAllMetrics(cwData *cwapi.DatasourceInfo) (cloudwatch.ListMetricsOutput, error) {
 func getAllMetrics(cwData *cwapi.DatasourceInfo) (cloudwatch.ListMetricsOutput, error) {
 	creds, err := cwapi.GetCredentials(cwData)
 	creds, err := cwapi.GetCredentials(cwData)
 	if err != nil {
 	if err != nil {

+ 23 - 11
public/app/plugins/datasource/cloudwatch/datasource.js

@@ -248,6 +248,28 @@ function (angular, _, moment, dateMath, kbn, templatingVariable, CloudWatchAnnot
       });
       });
     };
     };
 
 
+    this.getEbsVolumeIds = function(region, instanceId) {
+      var range = timeSrv.timeRange();
+      return backendSrv.post('/api/tsdb/query', {
+        from: range.from,
+        to: range.to,
+        queries: [
+          {
+            refId: 'metricFindQuery',
+            intervalMs: 1, // dummy
+            maxDataPoints: 1, // dummy
+            datasourceId: this.instanceSettings.id,
+            type: 'metricFindQuery',
+            subtype: 'ebs_volume_ids',
+            parameters: {
+              region: region,
+              instanceId: instanceId
+            }
+          }
+        ]
+      }).then(function (r) { return transformSuggestDataFromTable(r); });
+    };
+
     this.performEC2DescribeInstances = function(region, filters, instanceIds) {
     this.performEC2DescribeInstances = function(region, filters, instanceIds) {
       return this.awsRequest({
       return this.awsRequest({
         region: region,
         region: region,
@@ -301,17 +323,7 @@ function (angular, _, moment, dateMath, kbn, templatingVariable, CloudWatchAnnot
       if (ebsVolumeIdsQuery) {
       if (ebsVolumeIdsQuery) {
         region = templateSrv.replace(ebsVolumeIdsQuery[1]);
         region = templateSrv.replace(ebsVolumeIdsQuery[1]);
         var instanceId = templateSrv.replace(ebsVolumeIdsQuery[2]);
         var instanceId = templateSrv.replace(ebsVolumeIdsQuery[2]);
-        var instanceIds = [
-          instanceId
-        ];
-
-        return this.performEC2DescribeInstances(region, [], instanceIds).then(function(result) {
-          var volumeIds = _.map(result.Reservations[0].Instances[0].BlockDeviceMappings, function(mapping) {
-            return mapping.Ebs.VolumeId;
-          });
-
-          return transformSuggestData(volumeIds);
-        });
+        return this.getEbsVolumeIds(region, instanceId);
       }
       }
 
 
       var ec2InstanceAttributeQuery = query.match(/^ec2_instance_attribute\(([^,]+?),\s?([^,]+?),\s?(.+?)\)/);
       var ec2InstanceAttributeQuery = query.match(/^ec2_instance_attribute\(([^,]+?),\s?([^,]+?),\s?(.+?)\)/);