|
|
|
|
@ -1,7 +1,6 @@ |
|
|
|
|
package cloudwatch |
|
|
|
|
|
|
|
|
|
import ( |
|
|
|
|
"context" |
|
|
|
|
"errors" |
|
|
|
|
"fmt" |
|
|
|
|
"reflect" |
|
|
|
|
@ -37,30 +36,30 @@ var customMetricsDimensionsMap = make(map[string]map[string]map[string]*customMe |
|
|
|
|
|
|
|
|
|
var regionCache sync.Map |
|
|
|
|
|
|
|
|
|
func (e *cloudWatchExecutor) executeMetricFindQuery(ctx context.Context, model *simplejson.Json, query backend.DataQuery, pluginCtx backend.PluginContext) (*backend.QueryDataResponse, error) { |
|
|
|
|
func (e *cloudWatchExecutor) executeMetricFindQuery(pluginCtx backend.PluginContext, model *simplejson.Json, query backend.DataQuery) (*backend.QueryDataResponse, error) { |
|
|
|
|
subType := model.Get("subtype").MustString() |
|
|
|
|
|
|
|
|
|
var data []suggestData |
|
|
|
|
var err error |
|
|
|
|
switch subType { |
|
|
|
|
case "regions": |
|
|
|
|
data, err = e.handleGetRegions(ctx, model, pluginCtx) |
|
|
|
|
data, err = e.handleGetRegions(pluginCtx) |
|
|
|
|
case "namespaces": |
|
|
|
|
data, err = e.handleGetNamespaces(ctx, model, pluginCtx) |
|
|
|
|
data, err = e.handleGetNamespaces(pluginCtx) |
|
|
|
|
case "metrics": |
|
|
|
|
data, err = e.handleGetMetrics(ctx, model, pluginCtx) |
|
|
|
|
data, err = e.handleGetMetrics(pluginCtx, model) |
|
|
|
|
case "all_metrics": |
|
|
|
|
data, err = e.handleGetAllMetrics(ctx, model, pluginCtx) |
|
|
|
|
data, err = e.handleGetAllMetrics() |
|
|
|
|
case "dimension_keys": |
|
|
|
|
data, err = e.handleGetDimensions(ctx, model, pluginCtx) |
|
|
|
|
data, err = e.handleGetDimensions(pluginCtx, model) |
|
|
|
|
case "dimension_values": |
|
|
|
|
data, err = e.handleGetDimensionValues(ctx, model, pluginCtx) |
|
|
|
|
data, err = e.handleGetDimensionValues(pluginCtx, model) |
|
|
|
|
case "ebs_volume_ids": |
|
|
|
|
data, err = e.handleGetEbsVolumeIds(ctx, model, pluginCtx) |
|
|
|
|
data, err = e.handleGetEbsVolumeIds(pluginCtx, model) |
|
|
|
|
case "ec2_instance_attribute": |
|
|
|
|
data, err = e.handleGetEc2InstanceAttribute(ctx, model, pluginCtx) |
|
|
|
|
data, err = e.handleGetEc2InstanceAttribute(pluginCtx, model) |
|
|
|
|
case "resource_arns": |
|
|
|
|
data, err = e.handleGetResourceArns(ctx, model, pluginCtx) |
|
|
|
|
data, err = e.handleGetResourceArns(pluginCtx, model) |
|
|
|
|
} |
|
|
|
|
if err != nil { |
|
|
|
|
return nil, err |
|
|
|
|
@ -108,8 +107,7 @@ func parseMultiSelectValue(input string) []string { |
|
|
|
|
|
|
|
|
|
// Whenever this list is updated, the frontend list should also be updated.
|
|
|
|
|
// Please update the region list in public/app/plugins/datasource/cloudwatch/partials/config.html
|
|
|
|
|
func (e *cloudWatchExecutor) handleGetRegions(ctx context.Context, parameters *simplejson.Json, |
|
|
|
|
pluginCtx backend.PluginContext) ([]suggestData, error) { |
|
|
|
|
func (e *cloudWatchExecutor) handleGetRegions(pluginCtx backend.PluginContext) ([]suggestData, error) { |
|
|
|
|
dsInfo, err := e.getDSInfo(pluginCtx) |
|
|
|
|
if err != nil { |
|
|
|
|
return nil, err |
|
|
|
|
@ -122,7 +120,7 @@ func (e *cloudWatchExecutor) handleGetRegions(ctx context.Context, parameters *s |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
client, err := e.getEC2Client(defaultRegion, pluginCtx) |
|
|
|
|
client, err := e.getEC2Client(pluginCtx, defaultRegion) |
|
|
|
|
if err != nil { |
|
|
|
|
return nil, err |
|
|
|
|
} |
|
|
|
|
@ -158,7 +156,7 @@ func (e *cloudWatchExecutor) handleGetRegions(ctx context.Context, parameters *s |
|
|
|
|
return result, nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (e *cloudWatchExecutor) handleGetNamespaces(ctx context.Context, parameters *simplejson.Json, pluginCtx backend.PluginContext) ([]suggestData, error) { |
|
|
|
|
func (e *cloudWatchExecutor) handleGetNamespaces(pluginCtx backend.PluginContext) ([]suggestData, error) { |
|
|
|
|
var keys []string |
|
|
|
|
for key := range metricsMap { |
|
|
|
|
keys = append(keys, key) |
|
|
|
|
@ -183,7 +181,7 @@ func (e *cloudWatchExecutor) handleGetNamespaces(ctx context.Context, parameters |
|
|
|
|
return result, nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (e *cloudWatchExecutor) handleGetMetrics(ctx context.Context, parameters *simplejson.Json, pluginCtx backend.PluginContext) ([]suggestData, error) { |
|
|
|
|
func (e *cloudWatchExecutor) handleGetMetrics(pluginCtx backend.PluginContext, parameters *simplejson.Json) ([]suggestData, error) { |
|
|
|
|
region := parameters.Get("region").MustString() |
|
|
|
|
namespace := parameters.Get("namespace").MustString() |
|
|
|
|
|
|
|
|
|
@ -210,7 +208,7 @@ func (e *cloudWatchExecutor) handleGetMetrics(ctx context.Context, parameters *s |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// handleGetAllMetrics returns a slice of suggestData structs with metric and its namespace
|
|
|
|
|
func (e *cloudWatchExecutor) handleGetAllMetrics(ctx context.Context, parameters *simplejson.Json, pluginCtx backend.PluginContext) ([]suggestData, error) { |
|
|
|
|
func (e *cloudWatchExecutor) handleGetAllMetrics() ([]suggestData, error) { |
|
|
|
|
result := make([]suggestData, 0) |
|
|
|
|
for namespace, metrics := range metricsMap { |
|
|
|
|
for _, metric := range metrics { |
|
|
|
|
@ -224,7 +222,7 @@ func (e *cloudWatchExecutor) handleGetAllMetrics(ctx context.Context, parameters |
|
|
|
|
// handleGetDimensions returns a slice of suggestData structs with dimension keys.
|
|
|
|
|
// If a dimension filters parameter is specified, a new api call to list metrics will be issued to load dimension keys for the given filter.
|
|
|
|
|
// If no dimension filter is specified, dimension keys will be retrieved from the hard coded map in this file.
|
|
|
|
|
func (e *cloudWatchExecutor) handleGetDimensions(ctx context.Context, parameters *simplejson.Json, pluginCtx backend.PluginContext) ([]suggestData, error) { |
|
|
|
|
func (e *cloudWatchExecutor) handleGetDimensions(pluginCtx backend.PluginContext, parameters *simplejson.Json) ([]suggestData, error) { |
|
|
|
|
region := parameters.Get("region").MustString() |
|
|
|
|
namespace := parameters.Get("namespace").MustString() |
|
|
|
|
metricName := parameters.Get("metricName").MustString("") |
|
|
|
|
@ -266,7 +264,8 @@ func (e *cloudWatchExecutor) handleGetDimensions(ctx context.Context, parameters |
|
|
|
|
input.MetricName = aws.String(metricName) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
metrics, err := e.listMetrics(region, input, pluginCtx) |
|
|
|
|
metrics, err := e.listMetrics(pluginCtx, |
|
|
|
|
region, input) |
|
|
|
|
|
|
|
|
|
if err != nil { |
|
|
|
|
return nil, errutil.Wrap("unable to call AWS API", err) |
|
|
|
|
@ -312,7 +311,7 @@ func (e *cloudWatchExecutor) handleGetDimensions(ctx context.Context, parameters |
|
|
|
|
|
|
|
|
|
// handleGetDimensionValues returns a slice of suggestData structs with dimension values.
|
|
|
|
|
// A call to the list metrics api is issued to retrieve the dimension values. All parameters are used as input args to the list metrics call.
|
|
|
|
|
func (e *cloudWatchExecutor) handleGetDimensionValues(ctx context.Context, parameters *simplejson.Json, pluginCtx backend.PluginContext) ([]suggestData, error) { |
|
|
|
|
func (e *cloudWatchExecutor) handleGetDimensionValues(pluginCtx backend.PluginContext, parameters *simplejson.Json) ([]suggestData, error) { |
|
|
|
|
region := parameters.Get("region").MustString() |
|
|
|
|
namespace := parameters.Get("namespace").MustString() |
|
|
|
|
metricName := parameters.Get("metricName").MustString() |
|
|
|
|
@ -350,7 +349,7 @@ func (e *cloudWatchExecutor) handleGetDimensionValues(ctx context.Context, param |
|
|
|
|
if metricName != "" { |
|
|
|
|
params.MetricName = aws.String(metricName) |
|
|
|
|
} |
|
|
|
|
metrics, err := e.listMetrics(region, params, pluginCtx) |
|
|
|
|
metrics, err := e.listMetrics(pluginCtx, region, params) |
|
|
|
|
if err != nil { |
|
|
|
|
return nil, err |
|
|
|
|
} |
|
|
|
|
@ -377,13 +376,12 @@ func (e *cloudWatchExecutor) handleGetDimensionValues(ctx context.Context, param |
|
|
|
|
return result, nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (e *cloudWatchExecutor) handleGetEbsVolumeIds(ctx context.Context, parameters *simplejson.Json, |
|
|
|
|
pluginCtx backend.PluginContext) ([]suggestData, error) { |
|
|
|
|
func (e *cloudWatchExecutor) handleGetEbsVolumeIds(pluginCtx backend.PluginContext, parameters *simplejson.Json) ([]suggestData, error) { |
|
|
|
|
region := parameters.Get("region").MustString() |
|
|
|
|
instanceId := parameters.Get("instanceId").MustString() |
|
|
|
|
|
|
|
|
|
instanceIds := aws.StringSlice(parseMultiSelectValue(instanceId)) |
|
|
|
|
instances, err := e.ec2DescribeInstances(region, nil, instanceIds, pluginCtx) |
|
|
|
|
instances, err := e.ec2DescribeInstances(pluginCtx, region, nil, instanceIds) |
|
|
|
|
if err != nil { |
|
|
|
|
return nil, err |
|
|
|
|
} |
|
|
|
|
@ -400,8 +398,7 @@ func (e *cloudWatchExecutor) handleGetEbsVolumeIds(ctx context.Context, paramete |
|
|
|
|
return result, nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (e *cloudWatchExecutor) handleGetEc2InstanceAttribute(ctx context.Context, parameters *simplejson.Json, |
|
|
|
|
pluginCtx backend.PluginContext) ([]suggestData, error) { |
|
|
|
|
func (e *cloudWatchExecutor) handleGetEc2InstanceAttribute(pluginCtx backend.PluginContext, parameters *simplejson.Json) ([]suggestData, error) { |
|
|
|
|
region := parameters.Get("region").MustString() |
|
|
|
|
attributeName := parameters.Get("attributeName").MustString() |
|
|
|
|
filterJson := parameters.Get("filters").MustMap() |
|
|
|
|
@ -422,7 +419,7 @@ func (e *cloudWatchExecutor) handleGetEc2InstanceAttribute(ctx context.Context, |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
instances, err := e.ec2DescribeInstances(region, filters, nil, pluginCtx) |
|
|
|
|
instances, err := e.ec2DescribeInstances(pluginCtx, region, filters, nil) |
|
|
|
|
if err != nil { |
|
|
|
|
return nil, err |
|
|
|
|
} |
|
|
|
|
@ -480,8 +477,7 @@ func (e *cloudWatchExecutor) handleGetEc2InstanceAttribute(ctx context.Context, |
|
|
|
|
return result, nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (e *cloudWatchExecutor) handleGetResourceArns(ctx context.Context, parameters *simplejson.Json, |
|
|
|
|
pluginCtx backend.PluginContext) ([]suggestData, error) { |
|
|
|
|
func (e *cloudWatchExecutor) handleGetResourceArns(pluginCtx backend.PluginContext, parameters *simplejson.Json) ([]suggestData, error) { |
|
|
|
|
region := parameters.Get("region").MustString() |
|
|
|
|
resourceType := parameters.Get("resourceType").MustString() |
|
|
|
|
filterJson := parameters.Get("tags").MustMap() |
|
|
|
|
@ -505,7 +501,7 @@ func (e *cloudWatchExecutor) handleGetResourceArns(ctx context.Context, paramete |
|
|
|
|
var resourceTypes []*string |
|
|
|
|
resourceTypes = append(resourceTypes, &resourceType) |
|
|
|
|
|
|
|
|
|
resources, err := e.resourceGroupsGetResources(region, filters, resourceTypes, pluginCtx) |
|
|
|
|
resources, err := e.resourceGroupsGetResources(pluginCtx, region, filters, resourceTypes) |
|
|
|
|
if err != nil { |
|
|
|
|
return nil, err |
|
|
|
|
} |
|
|
|
|
@ -519,8 +515,8 @@ func (e *cloudWatchExecutor) handleGetResourceArns(ctx context.Context, paramete |
|
|
|
|
return result, nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (e *cloudWatchExecutor) listMetrics(region string, params *cloudwatch.ListMetricsInput, pluginCtx backend.PluginContext) ([]*cloudwatch.Metric, error) { |
|
|
|
|
client, err := e.getCWClient(region, pluginCtx) |
|
|
|
|
func (e *cloudWatchExecutor) listMetrics(pluginCtx backend.PluginContext, region string, params *cloudwatch.ListMetricsInput) ([]*cloudwatch.Metric, error) { |
|
|
|
|
client, err := e.getCWClient(pluginCtx, region) |
|
|
|
|
if err != nil { |
|
|
|
|
return nil, err |
|
|
|
|
} |
|
|
|
|
@ -544,13 +540,13 @@ func (e *cloudWatchExecutor) listMetrics(region string, params *cloudwatch.ListM |
|
|
|
|
return cloudWatchMetrics, err |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (e *cloudWatchExecutor) ec2DescribeInstances(region string, filters []*ec2.Filter, instanceIds []*string, pluginCtx backend.PluginContext) (*ec2.DescribeInstancesOutput, error) { |
|
|
|
|
func (e *cloudWatchExecutor) ec2DescribeInstances(pluginCtx backend.PluginContext, region string, filters []*ec2.Filter, instanceIds []*string) (*ec2.DescribeInstancesOutput, error) { |
|
|
|
|
params := &ec2.DescribeInstancesInput{ |
|
|
|
|
Filters: filters, |
|
|
|
|
InstanceIds: instanceIds, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
client, err := e.getEC2Client(region, pluginCtx) |
|
|
|
|
client, err := e.getEC2Client(pluginCtx, region) |
|
|
|
|
if err != nil { |
|
|
|
|
return nil, err |
|
|
|
|
} |
|
|
|
|
@ -566,14 +562,14 @@ func (e *cloudWatchExecutor) ec2DescribeInstances(region string, filters []*ec2. |
|
|
|
|
return &resp, nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (e *cloudWatchExecutor) resourceGroupsGetResources(region string, filters []*resourcegroupstaggingapi.TagFilter, |
|
|
|
|
resourceTypes []*string, pluginCtx backend.PluginContext) (*resourcegroupstaggingapi.GetResourcesOutput, error) { |
|
|
|
|
func (e *cloudWatchExecutor) resourceGroupsGetResources(pluginCtx backend.PluginContext, region string, filters []*resourcegroupstaggingapi.TagFilter, |
|
|
|
|
resourceTypes []*string) (*resourcegroupstaggingapi.GetResourcesOutput, error) { |
|
|
|
|
params := &resourcegroupstaggingapi.GetResourcesInput{ |
|
|
|
|
ResourceTypeFilters: resourceTypes, |
|
|
|
|
TagFilters: filters, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
client, err := e.getRGTAClient(region, pluginCtx) |
|
|
|
|
client, err := e.getRGTAClient(pluginCtx, region) |
|
|
|
|
if err != nil { |
|
|
|
|
return nil, err |
|
|
|
|
} |
|
|
|
|
@ -616,9 +612,9 @@ func (e *cloudWatchExecutor) getMetricsForCustomMetrics(region, namespace string |
|
|
|
|
if customMetricsMetricsMap[dsInfo.profile][dsInfo.region][namespace].Expire.After(time.Now()) { |
|
|
|
|
return customMetricsMetricsMap[dsInfo.profile][dsInfo.region][namespace].Cache, nil |
|
|
|
|
} |
|
|
|
|
metrics, err := e.listMetrics(region, &cloudwatch.ListMetricsInput{ |
|
|
|
|
metrics, err := e.listMetrics(pluginCtx, region, &cloudwatch.ListMetricsInput{ |
|
|
|
|
Namespace: aws.String(namespace), |
|
|
|
|
}, pluginCtx) |
|
|
|
|
}) |
|
|
|
|
if err != nil { |
|
|
|
|
return []string{}, err |
|
|
|
|
} |
|
|
|
|
@ -662,7 +658,7 @@ func (e *cloudWatchExecutor) getDimensionsForCustomMetrics(region, namespace str |
|
|
|
|
if customMetricsDimensionsMap[dsInfo.profile][dsInfo.region][namespace].Expire.After(time.Now()) { |
|
|
|
|
return customMetricsDimensionsMap[dsInfo.profile][dsInfo.region][namespace].Cache, nil |
|
|
|
|
} |
|
|
|
|
metrics, err := e.listMetrics(region, &cloudwatch.ListMetricsInput{Namespace: aws.String(namespace)}, pluginCtx) |
|
|
|
|
metrics, err := e.listMetrics(pluginCtx, region, &cloudwatch.ListMetricsInput{Namespace: aws.String(namespace)}) |
|
|
|
|
if err != nil { |
|
|
|
|
return []string{}, err |
|
|
|
|
} |
|
|
|
|
|