tech(cloudwatch): refactoring
This commit is contained in:
@@ -33,6 +33,30 @@ type cwRequest struct {
|
||||
DataSource *m.DataSource
|
||||
}
|
||||
|
||||
type datasourceInfo struct {
|
||||
Profile string
|
||||
Region string
|
||||
AssumeRoleArn string
|
||||
Namespace string
|
||||
|
||||
AccessKey string
|
||||
SecretKey string
|
||||
}
|
||||
|
||||
func (req *cwRequest) GetDatasourceInfo() *datasourceInfo {
|
||||
assumeRoleArn := req.DataSource.JsonData.Get("assumeRoleArn").MustString()
|
||||
accessKey := req.DataSource.JsonData.Get("accessKey").MustString()
|
||||
secretKey := req.DataSource.JsonData.Get("secretKey").MustString()
|
||||
|
||||
return &datasourceInfo{
|
||||
AssumeRoleArn: assumeRoleArn,
|
||||
Region: req.Region,
|
||||
Profile: req.DataSource.Database,
|
||||
AccessKey: accessKey,
|
||||
SecretKey: secretKey,
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
actionHandlers = map[string]actionHandler{
|
||||
"GetMetricStatistics": handleGetMetricStatistics,
|
||||
@@ -53,21 +77,11 @@ type cache struct {
|
||||
expiration *time.Time
|
||||
}
|
||||
|
||||
type CloudwatchDatasource struct {
|
||||
Profile string
|
||||
Region string
|
||||
AssumeRoleArn string
|
||||
Namespace string
|
||||
|
||||
AccessKey string
|
||||
SecretKey string
|
||||
}
|
||||
|
||||
var awsCredentialCache map[string]cache = make(map[string]cache)
|
||||
var credentialCacheLock sync.RWMutex
|
||||
|
||||
func getCredentials(cwDatasource *CloudwatchDatasource) *credentials.Credentials {
|
||||
cacheKey := cwDatasource.Profile + ":" + cwDatasource.AssumeRoleArn
|
||||
func getCredentials(dsInfo *datasourceInfo) *credentials.Credentials {
|
||||
cacheKey := dsInfo.Profile + ":" + dsInfo.AssumeRoleArn
|
||||
credentialCacheLock.RLock()
|
||||
if _, ok := awsCredentialCache[cacheKey]; ok {
|
||||
if awsCredentialCache[cacheKey].expiration != nil &&
|
||||
@@ -84,9 +98,9 @@ func getCredentials(cwDatasource *CloudwatchDatasource) *credentials.Credentials
|
||||
sessionToken := ""
|
||||
var expiration *time.Time
|
||||
expiration = nil
|
||||
if strings.Index(cwDatasource.AssumeRoleArn, "arn:aws:iam:") == 0 {
|
||||
if strings.Index(dsInfo.AssumeRoleArn, "arn:aws:iam:") == 0 {
|
||||
params := &sts.AssumeRoleInput{
|
||||
RoleArn: aws.String(cwDatasource.AssumeRoleArn),
|
||||
RoleArn: aws.String(dsInfo.AssumeRoleArn),
|
||||
RoleSessionName: aws.String("GrafanaSession"),
|
||||
DurationSeconds: aws.Int64(900),
|
||||
}
|
||||
@@ -95,11 +109,11 @@ func getCredentials(cwDatasource *CloudwatchDatasource) *credentials.Credentials
|
||||
stsCreds := credentials.NewChainCredentials(
|
||||
[]credentials.Provider{
|
||||
&credentials.EnvProvider{},
|
||||
&credentials.SharedCredentialsProvider{Filename: "", Profile: cwDatasource.Profile},
|
||||
&credentials.SharedCredentialsProvider{Filename: "", Profile: dsInfo.Profile},
|
||||
&ec2rolecreds.EC2RoleProvider{Client: ec2metadata.New(stsSess), ExpiryWindow: 5 * time.Minute},
|
||||
})
|
||||
stsConfig := &aws.Config{
|
||||
Region: aws.String(cwDatasource.Region),
|
||||
Region: aws.String(dsInfo.Region),
|
||||
Credentials: stsCreds,
|
||||
}
|
||||
|
||||
@@ -127,10 +141,10 @@ func getCredentials(cwDatasource *CloudwatchDatasource) *credentials.Credentials
|
||||
}},
|
||||
&credentials.EnvProvider{},
|
||||
&credentials.StaticProvider{Value: credentials.Value{
|
||||
AccessKeyID: cwDatasource.AccessKey,
|
||||
SecretAccessKey: cwDatasource.SecretKey,
|
||||
AccessKeyID: dsInfo.AccessKey,
|
||||
SecretAccessKey: dsInfo.SecretKey,
|
||||
}},
|
||||
&credentials.SharedCredentialsProvider{Filename: "", Profile: cwDatasource.Profile},
|
||||
&credentials.SharedCredentialsProvider{Filename: "", Profile: dsInfo.Profile},
|
||||
&ec2rolecreds.EC2RoleProvider{Client: ec2metadata.New(sess), ExpiryWindow: 5 * time.Minute},
|
||||
})
|
||||
|
||||
@@ -145,19 +159,9 @@ func getCredentials(cwDatasource *CloudwatchDatasource) *credentials.Credentials
|
||||
}
|
||||
|
||||
func getAwsConfig(req *cwRequest) *aws.Config {
|
||||
assumeRoleArn := req.DataSource.JsonData.Get("assumeRoleArn").MustString()
|
||||
accessKey := req.DataSource.JsonData.Get("accessKey").MustString()
|
||||
secretKey := req.DataSource.JsonData.Get("secretKey").MustString()
|
||||
|
||||
cfg := &aws.Config{
|
||||
Region: aws.String(req.Region),
|
||||
Credentials: getCredentials(&CloudwatchDatasource{
|
||||
AccessKey: accessKey,
|
||||
SecretKey: secretKey,
|
||||
Region: req.Region,
|
||||
Profile: req.DataSource.Database,
|
||||
AssumeRoleArn: assumeRoleArn,
|
||||
}),
|
||||
Region: aws.String(req.Region),
|
||||
Credentials: getCredentials(req.GetDatasourceInfo()),
|
||||
}
|
||||
return cfg
|
||||
}
|
||||
|
||||
@@ -192,18 +192,23 @@ func handleGetMetrics(req *cwRequest, c *middleware.Context) {
|
||||
}
|
||||
} else {
|
||||
var err error
|
||||
assumeRoleArn := req.DataSource.JsonData.Get("assumeRoleArn").MustString()
|
||||
accessKey := req.DataSource.JsonData.Get("accessKey").MustString()
|
||||
secretKey := req.DataSource.JsonData.Get("secretKey").MustString()
|
||||
/*
|
||||
assumeRoleArn := req.DataSource.JsonData.Get("assumeRoleArn").MustString()
|
||||
accessKey := req.DataSource.JsonData.Get("accessKey").MustString()
|
||||
secretKey := req.DataSource.JsonData.Get("secretKey").MustString()
|
||||
|
||||
cwData := &CloudwatchDatasource{
|
||||
AssumeRoleArn: assumeRoleArn,
|
||||
Region: req.Region,
|
||||
Namespace: reqParam.Parameters.Namespace,
|
||||
Profile: req.DataSource.Database,
|
||||
AccessKey: accessKey,
|
||||
SecretKey: secretKey,
|
||||
}
|
||||
cwData := &datasourceInfo{
|
||||
AssumeRoleArn: assumeRoleArn,
|
||||
Region: req.Region,
|
||||
Namespace: reqParam.Parameters.Namespace,
|
||||
Profile: req.DataSource.Database,
|
||||
AccessKey: accessKey,
|
||||
SecretKey: secretKey,
|
||||
}
|
||||
*/
|
||||
|
||||
cwData := req.GetDatasourceInfo()
|
||||
cwData.Namespace = reqParam.Parameters.Namespace
|
||||
|
||||
if namespaceMetrics, err = getMetricsForCustomMetrics(cwData, getAllMetrics); err != nil {
|
||||
c.JsonApiErr(500, "Unable to call AWS API", err)
|
||||
@@ -242,7 +247,7 @@ func handleGetDimensions(req *cwRequest, c *middleware.Context) {
|
||||
accessKey := req.DataSource.JsonData.Get("accessKey").MustString()
|
||||
secretKey := req.DataSource.JsonData.Get("secretKey").MustString()
|
||||
|
||||
cwDatasource := &CloudwatchDatasource{
|
||||
cwDatasource := &datasourceInfo{
|
||||
Region: req.Region,
|
||||
Namespace: reqParam.Parameters.Namespace,
|
||||
Profile: req.DataSource.Database,
|
||||
@@ -265,7 +270,7 @@ func handleGetDimensions(req *cwRequest, c *middleware.Context) {
|
||||
c.JSON(200, result)
|
||||
}
|
||||
|
||||
func getAllMetrics(cwData *CloudwatchDatasource) (cloudwatch.ListMetricsOutput, error) {
|
||||
func getAllMetrics(cwData *datasourceInfo) (cloudwatch.ListMetricsOutput, error) {
|
||||
cfg := &aws.Config{
|
||||
Region: aws.String(cwData.Region),
|
||||
Credentials: getCredentials(cwData),
|
||||
@@ -295,8 +300,8 @@ func getAllMetrics(cwData *CloudwatchDatasource) (cloudwatch.ListMetricsOutput,
|
||||
|
||||
var metricsCacheLock sync.Mutex
|
||||
|
||||
func getMetricsForCustomMetrics(cwDatasource *CloudwatchDatasource, getAllMetrics func(*CloudwatchDatasource) (cloudwatch.ListMetricsOutput, error)) ([]string, error) {
|
||||
result, err := getAllMetrics(cwDatasource)
|
||||
func getMetricsForCustomMetrics(dsInfo *datasourceInfo, getAllMetrics func(*datasourceInfo) (cloudwatch.ListMetricsOutput, error)) ([]string, error) {
|
||||
result, err := getAllMetrics(dsInfo)
|
||||
if err != nil {
|
||||
return []string{}, err
|
||||
}
|
||||
@@ -304,37 +309,37 @@ func getMetricsForCustomMetrics(cwDatasource *CloudwatchDatasource, getAllMetric
|
||||
metricsCacheLock.Lock()
|
||||
defer metricsCacheLock.Unlock()
|
||||
|
||||
if _, ok := customMetricsMetricsMap[cwDatasource.Profile]; !ok {
|
||||
customMetricsMetricsMap[cwDatasource.Profile] = make(map[string]map[string]*CustomMetricsCache)
|
||||
if _, ok := customMetricsMetricsMap[dsInfo.Profile]; !ok {
|
||||
customMetricsMetricsMap[dsInfo.Profile] = make(map[string]map[string]*CustomMetricsCache)
|
||||
}
|
||||
if _, ok := customMetricsMetricsMap[cwDatasource.Profile][cwDatasource.Region]; !ok {
|
||||
customMetricsMetricsMap[cwDatasource.Profile][cwDatasource.Region] = make(map[string]*CustomMetricsCache)
|
||||
if _, ok := customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region]; !ok {
|
||||
customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region] = make(map[string]*CustomMetricsCache)
|
||||
}
|
||||
if _, ok := customMetricsMetricsMap[cwDatasource.Profile][cwDatasource.Region][cwDatasource.Namespace]; !ok {
|
||||
customMetricsMetricsMap[cwDatasource.Profile][cwDatasource.Region][cwDatasource.Namespace] = &CustomMetricsCache{}
|
||||
customMetricsMetricsMap[cwDatasource.Profile][cwDatasource.Region][cwDatasource.Namespace].Cache = make([]string, 0)
|
||||
if _, ok := customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace]; !ok {
|
||||
customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace] = &CustomMetricsCache{}
|
||||
customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Cache = make([]string, 0)
|
||||
}
|
||||
|
||||
if customMetricsMetricsMap[cwDatasource.Profile][cwDatasource.Region][cwDatasource.Namespace].Expire.After(time.Now()) {
|
||||
return customMetricsMetricsMap[cwDatasource.Profile][cwDatasource.Region][cwDatasource.Namespace].Cache, nil
|
||||
if customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Expire.After(time.Now()) {
|
||||
return customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Cache, nil
|
||||
}
|
||||
customMetricsMetricsMap[cwDatasource.Profile][cwDatasource.Region][cwDatasource.Namespace].Cache = make([]string, 0)
|
||||
customMetricsMetricsMap[cwDatasource.Profile][cwDatasource.Region][cwDatasource.Namespace].Expire = time.Now().Add(5 * time.Minute)
|
||||
customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Cache = make([]string, 0)
|
||||
customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Expire = time.Now().Add(5 * time.Minute)
|
||||
|
||||
for _, metric := range result.Metrics {
|
||||
if isDuplicate(customMetricsMetricsMap[cwDatasource.Profile][cwDatasource.Region][cwDatasource.Namespace].Cache, *metric.MetricName) {
|
||||
if isDuplicate(customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Cache, *metric.MetricName) {
|
||||
continue
|
||||
}
|
||||
customMetricsMetricsMap[cwDatasource.Profile][cwDatasource.Region][cwDatasource.Namespace].Cache = append(customMetricsMetricsMap[cwDatasource.Profile][cwDatasource.Region][cwDatasource.Namespace].Cache, *metric.MetricName)
|
||||
customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Cache = append(customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Cache, *metric.MetricName)
|
||||
}
|
||||
|
||||
return customMetricsMetricsMap[cwDatasource.Profile][cwDatasource.Region][cwDatasource.Namespace].Cache, nil
|
||||
return customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Cache, nil
|
||||
}
|
||||
|
||||
var dimensionsCacheLock sync.Mutex
|
||||
|
||||
func getDimensionsForCustomMetrics(cwDatasource *CloudwatchDatasource, getAllMetrics func(*CloudwatchDatasource) (cloudwatch.ListMetricsOutput, error)) ([]string, error) {
|
||||
result, err := getAllMetrics(cwDatasource)
|
||||
func getDimensionsForCustomMetrics(dsInfo *datasourceInfo, getAllMetrics func(*datasourceInfo) (cloudwatch.ListMetricsOutput, error)) ([]string, error) {
|
||||
result, err := getAllMetrics(dsInfo)
|
||||
if err != nil {
|
||||
return []string{}, err
|
||||
}
|
||||
@@ -342,33 +347,33 @@ func getDimensionsForCustomMetrics(cwDatasource *CloudwatchDatasource, getAllMet
|
||||
dimensionsCacheLock.Lock()
|
||||
defer dimensionsCacheLock.Unlock()
|
||||
|
||||
if _, ok := customMetricsDimensionsMap[cwDatasource.Profile]; !ok {
|
||||
customMetricsDimensionsMap[cwDatasource.Profile] = make(map[string]map[string]*CustomMetricsCache)
|
||||
if _, ok := customMetricsDimensionsMap[dsInfo.Profile]; !ok {
|
||||
customMetricsDimensionsMap[dsInfo.Profile] = make(map[string]map[string]*CustomMetricsCache)
|
||||
}
|
||||
if _, ok := customMetricsDimensionsMap[cwDatasource.Profile][cwDatasource.Region]; !ok {
|
||||
customMetricsDimensionsMap[cwDatasource.Profile][cwDatasource.Region] = make(map[string]*CustomMetricsCache)
|
||||
if _, ok := customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region]; !ok {
|
||||
customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region] = make(map[string]*CustomMetricsCache)
|
||||
}
|
||||
if _, ok := customMetricsDimensionsMap[cwDatasource.Profile][cwDatasource.Region][cwDatasource.Namespace]; !ok {
|
||||
customMetricsDimensionsMap[cwDatasource.Profile][cwDatasource.Region][cwDatasource.Namespace] = &CustomMetricsCache{}
|
||||
customMetricsDimensionsMap[cwDatasource.Profile][cwDatasource.Region][cwDatasource.Namespace].Cache = make([]string, 0)
|
||||
if _, ok := customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace]; !ok {
|
||||
customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace] = &CustomMetricsCache{}
|
||||
customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Cache = make([]string, 0)
|
||||
}
|
||||
|
||||
if customMetricsDimensionsMap[cwDatasource.Profile][cwDatasource.Region][cwDatasource.Namespace].Expire.After(time.Now()) {
|
||||
return customMetricsDimensionsMap[cwDatasource.Profile][cwDatasource.Region][cwDatasource.Namespace].Cache, nil
|
||||
if customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Expire.After(time.Now()) {
|
||||
return customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Cache, nil
|
||||
}
|
||||
customMetricsDimensionsMap[cwDatasource.Profile][cwDatasource.Region][cwDatasource.Namespace].Cache = make([]string, 0)
|
||||
customMetricsDimensionsMap[cwDatasource.Profile][cwDatasource.Region][cwDatasource.Namespace].Expire = time.Now().Add(5 * time.Minute)
|
||||
customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Cache = make([]string, 0)
|
||||
customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Expire = time.Now().Add(5 * time.Minute)
|
||||
|
||||
for _, metric := range result.Metrics {
|
||||
for _, dimension := range metric.Dimensions {
|
||||
if isDuplicate(customMetricsDimensionsMap[cwDatasource.Profile][cwDatasource.Region][cwDatasource.Namespace].Cache, *dimension.Name) {
|
||||
if isDuplicate(customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Cache, *dimension.Name) {
|
||||
continue
|
||||
}
|
||||
customMetricsDimensionsMap[cwDatasource.Profile][cwDatasource.Region][cwDatasource.Namespace].Cache = append(customMetricsDimensionsMap[cwDatasource.Profile][cwDatasource.Region][cwDatasource.Namespace].Cache, *dimension.Name)
|
||||
customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Cache = append(customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Cache, *dimension.Name)
|
||||
}
|
||||
}
|
||||
|
||||
return customMetricsDimensionsMap[cwDatasource.Profile][cwDatasource.Region][cwDatasource.Namespace].Cache, nil
|
||||
return customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Cache, nil
|
||||
}
|
||||
|
||||
func isDuplicate(nameList []string, target string) bool {
|
||||
|
||||
@@ -11,13 +11,13 @@ import (
|
||||
func TestCloudWatchMetrics(t *testing.T) {
|
||||
|
||||
Convey("When calling getMetricsForCustomMetrics", t, func() {
|
||||
dsInfo := &CloudwatchDatasource{
|
||||
dsInfo := &datasourceInfo{
|
||||
Region: "us-east-1",
|
||||
Namespace: "Foo",
|
||||
Profile: "default",
|
||||
AssumeRoleArn: "",
|
||||
}
|
||||
f := func(dsInfo *CloudwatchDatasource) (cloudwatch.ListMetricsOutput, error) {
|
||||
f := func(dsInfo *datasourceInfo) (cloudwatch.ListMetricsOutput, error) {
|
||||
return cloudwatch.ListMetricsOutput{
|
||||
Metrics: []*cloudwatch.Metric{
|
||||
{
|
||||
@@ -39,13 +39,13 @@ func TestCloudWatchMetrics(t *testing.T) {
|
||||
})
|
||||
|
||||
Convey("When calling getDimensionsForCustomMetrics", t, func() {
|
||||
dsInfo := &CloudwatchDatasource{
|
||||
dsInfo := &datasourceInfo{
|
||||
Region: "us-east-1",
|
||||
Namespace: "Foo",
|
||||
Profile: "default",
|
||||
AssumeRoleArn: "",
|
||||
}
|
||||
f := func(dsInfo *CloudwatchDatasource) (cloudwatch.ListMetricsOutput, error) {
|
||||
f := func(dsInfo *datasourceInfo) (cloudwatch.ListMetricsOutput, error) {
|
||||
return cloudwatch.ListMetricsOutput{
|
||||
Metrics: []*cloudwatch.Metric{
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user