Commit 8fba6dcb by Mitsuhiro Tanda

re-implement ec2_instance_attribute()

parent cf23734d
......@@ -3,6 +3,7 @@ package cloudwatch
import (
"context"
"errors"
"reflect"
"sort"
"strings"
"sync"
......@@ -178,6 +179,9 @@ func (e *CloudWatchExecutor) executeMetricFindQuery(ctx context.Context, queries
case "ebs_volume_ids":
data, err = e.handleGetEbsVolumeIds(ctx, parameters, queryContext)
break
case "ec2_instance_attribute":
data, err = e.handleGetEc2InstanceAttribute(ctx, parameters, queryContext)
break
}
if err != nil {
queryResult.Error = err
......@@ -342,6 +346,75 @@ func (e *CloudWatchExecutor) handleGetEbsVolumeIds(ctx context.Context, paramete
return result, nil
}
func (e *CloudWatchExecutor) handleGetEc2InstanceAttribute(ctx context.Context, parameters *simplejson.Json, queryContext *tsdb.QueryContext) ([]suggestData, error) {
region := parameters.Get("region").MustString()
attributeName := parameters.Get("attributeName").MustString()
filterJson := parameters.Get("filters").MustMap()
var filters []*ec2.Filter
for k, v := range filterJson {
if vv, ok := v.([]string); ok {
var vvvv []*string
for _, vvv := range vv {
vvvv = append(vvvv, &vvv)
}
filters = append(filters, &ec2.Filter{
Name: aws.String(k),
Values: vvvv,
})
}
}
instances, err := e.ec2DescribeInstances(region, filters, nil)
if err != nil {
return nil, err
}
result := make([]suggestData, 0)
dupCheck := make(map[string]bool)
for _, instance := range instances.Reservations[0].Instances {
tags := make(map[string]string)
for _, tag := range instance.Tags {
tags[*tag.Key] = *tag.Value
}
var data string
if strings.Index(attributeName, "Tags.") == 0 {
tagName := attributeName[5:]
data = tags[tagName]
} else {
attributePath := strings.Split(attributeName, ".")
v := reflect.ValueOf(instance)
for _, key := range attributePath {
if v.Kind() == reflect.Ptr {
v = v.Elem()
}
if v.Kind() != reflect.Struct {
return nil, errors.New("invalid attribute path")
}
v = v.FieldByName(key)
}
if attr, ok := v.Interface().(*string); ok {
data = *attr
} else {
return nil, errors.New("invalid attribute path")
}
}
if _, exists := dupCheck[data]; exists {
continue
}
dupCheck[data] = true
result = append(result, suggestData{Text: data, Value: data})
}
sort.Slice(result, func(i, j int) bool {
return result[i].Text < result[j].Text
})
return result, nil
}
func getAwsConfig(dsInfo *cwapi.DatasourceInfo) (*aws.Config, error) {
creds, err := cwapi.GetCredentials(dsInfo)
if err != nil {
......
......@@ -270,6 +270,29 @@ function (angular, _, moment, dateMath, kbn, templatingVariable, CloudWatchAnnot
}).then(function (r) { return transformSuggestDataFromTable(r); });
};
this.getEc2InstanceAttribute = function(region, attributeName, filters) {
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: 'ec2_instance_attribute',
parameters: {
region: region,
attributeName: attributeName,
filters: filters
}
}
]
}).then(function (r) { return transformSuggestDataFromTable(r); });
};
this.performEC2DescribeInstances = function(region, filters, instanceIds) {
return this.awsRequest({
region: region,
......@@ -283,12 +306,6 @@ function (angular, _, moment, dateMath, kbn, templatingVariable, CloudWatchAnnot
var namespace;
var metricName;
var transformSuggestData = function(suggestData) {
return _.map(suggestData, function(v) {
return { text: v };
});
};
var regionQuery = query.match(/^regions\(\)/);
if (regionQuery) {
return this.getRegions();
......@@ -329,33 +346,9 @@ function (angular, _, moment, dateMath, kbn, templatingVariable, CloudWatchAnnot
var ec2InstanceAttributeQuery = query.match(/^ec2_instance_attribute\(([^,]+?),\s?([^,]+?),\s?(.+?)\)/);
if (ec2InstanceAttributeQuery) {
region = templateSrv.replace(ec2InstanceAttributeQuery[1]);
var filterJson = JSON.parse(templateSrv.replace(ec2InstanceAttributeQuery[3]));
var filters = _.map(filterJson, function(values, name) {
return {
Name: name,
Values: values
};
});
var targetAttributeName = templateSrv.replace(ec2InstanceAttributeQuery[2]);
return this.performEC2DescribeInstances(region, filters, null).then(function(result) {
var attributes = _.chain(result.Reservations)
.map(function(reservations) {
return _.map(reservations.Instances, function(instance) {
var tags = {};
_.each(instance.Tags, function(tag) {
tags[tag.Key] = tag.Value;
});
instance.Tags = tags;
return instance;
});
})
.map(function(instances) {
return _.map(instances, targetAttributeName);
})
.flatten().uniq().sortBy().value();
return transformSuggestData(attributes);
});
var filterJson = JSON.parse(templateSrv.replace(ec2InstanceAttributeQuery[3]));
return this.getEc2InstanceAttribute(region, targetAttributeName, filterJson);
}
return $q.when([]);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment