|
|
@@ -17,7 +17,6 @@ import (
|
|
|
"github.com/aws/aws-sdk-go/service/cloudwatch"
|
|
|
"github.com/aws/aws-sdk-go/service/ec2"
|
|
|
"github.com/aws/aws-sdk-go/service/sts"
|
|
|
- "github.com/grafana/grafana/pkg/log"
|
|
|
"github.com/grafana/grafana/pkg/metrics"
|
|
|
"github.com/grafana/grafana/pkg/middleware"
|
|
|
m "github.com/grafana/grafana/pkg/models"
|
|
|
@@ -90,7 +89,7 @@ type cache struct {
|
|
|
var awsCredentialCache map[string]cache = make(map[string]cache)
|
|
|
var credentialCacheLock sync.RWMutex
|
|
|
|
|
|
-func getCredentials(dsInfo *datasourceInfo) *credentials.Credentials {
|
|
|
+func getCredentials(dsInfo *datasourceInfo) (*credentials.Credentials, error) {
|
|
|
cacheKey := dsInfo.Profile + ":" + dsInfo.AssumeRoleArn
|
|
|
credentialCacheLock.RLock()
|
|
|
if _, ok := awsCredentialCache[cacheKey]; ok {
|
|
|
@@ -98,7 +97,7 @@ func getCredentials(dsInfo *datasourceInfo) *credentials.Credentials {
|
|
|
(*awsCredentialCache[cacheKey].expiration).After(time.Now().UTC()) {
|
|
|
result := awsCredentialCache[cacheKey].credential
|
|
|
credentialCacheLock.RUnlock()
|
|
|
- return result
|
|
|
+ return result, nil
|
|
|
}
|
|
|
}
|
|
|
credentialCacheLock.RUnlock()
|
|
|
@@ -130,8 +129,7 @@ func getCredentials(dsInfo *datasourceInfo) *credentials.Credentials {
|
|
|
svc := sts.New(session.New(stsConfig), stsConfig)
|
|
|
resp, err := svc.AssumeRole(params)
|
|
|
if err != nil {
|
|
|
- // ignore
|
|
|
- log.Error(3, "CloudWatch: Failed to assume role", err)
|
|
|
+ return nil, err
|
|
|
}
|
|
|
if resp.Credentials != nil {
|
|
|
accessKeyId = *resp.Credentials.AccessKeyId
|
|
|
@@ -165,19 +163,28 @@ func getCredentials(dsInfo *datasourceInfo) *credentials.Credentials {
|
|
|
}
|
|
|
credentialCacheLock.Unlock()
|
|
|
|
|
|
- return creds
|
|
|
+ return creds, nil
|
|
|
}
|
|
|
|
|
|
-func getAwsConfig(req *cwRequest) *aws.Config {
|
|
|
+func getAwsConfig(req *cwRequest) (*aws.Config, error) {
|
|
|
+ creds, err := getCredentials(req.GetDatasourceInfo())
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+
|
|
|
cfg := &aws.Config{
|
|
|
Region: aws.String(req.Region),
|
|
|
- Credentials: getCredentials(req.GetDatasourceInfo()),
|
|
|
+ Credentials: creds,
|
|
|
}
|
|
|
- return cfg
|
|
|
+ return cfg, nil
|
|
|
}
|
|
|
|
|
|
func handleGetMetricStatistics(req *cwRequest, c *middleware.Context) {
|
|
|
- cfg := getAwsConfig(req)
|
|
|
+ cfg, err := getAwsConfig(req)
|
|
|
+ if err != nil {
|
|
|
+ c.JsonApiErr(500, "Unable to call AWS API", err)
|
|
|
+ return
|
|
|
+ }
|
|
|
svc := cloudwatch.New(session.New(cfg), cfg)
|
|
|
|
|
|
reqParam := &struct {
|
|
|
@@ -220,7 +227,11 @@ func handleGetMetricStatistics(req *cwRequest, c *middleware.Context) {
|
|
|
}
|
|
|
|
|
|
func handleListMetrics(req *cwRequest, c *middleware.Context) {
|
|
|
- cfg := getAwsConfig(req)
|
|
|
+ cfg, err := getAwsConfig(req)
|
|
|
+ if err != nil {
|
|
|
+ c.JsonApiErr(500, "Unable to call AWS API", err)
|
|
|
+ return
|
|
|
+ }
|
|
|
svc := cloudwatch.New(session.New(cfg), cfg)
|
|
|
|
|
|
reqParam := &struct {
|
|
|
@@ -239,7 +250,7 @@ func handleListMetrics(req *cwRequest, c *middleware.Context) {
|
|
|
}
|
|
|
|
|
|
var resp cloudwatch.ListMetricsOutput
|
|
|
- err := svc.ListMetricsPages(params,
|
|
|
+ err = svc.ListMetricsPages(params,
|
|
|
func(page *cloudwatch.ListMetricsOutput, lastPage bool) bool {
|
|
|
metrics.M_Aws_CloudWatch_ListMetrics.Inc(1)
|
|
|
metrics, _ := awsutil.ValuesAtPath(page, "Metrics")
|
|
|
@@ -257,7 +268,11 @@ func handleListMetrics(req *cwRequest, c *middleware.Context) {
|
|
|
}
|
|
|
|
|
|
func handleDescribeAlarms(req *cwRequest, c *middleware.Context) {
|
|
|
- cfg := getAwsConfig(req)
|
|
|
+ cfg, err := getAwsConfig(req)
|
|
|
+ if err != nil {
|
|
|
+ c.JsonApiErr(500, "Unable to call AWS API", err)
|
|
|
+ return
|
|
|
+ }
|
|
|
svc := cloudwatch.New(session.New(cfg), cfg)
|
|
|
|
|
|
reqParam := &struct {
|
|
|
@@ -296,7 +311,11 @@ func handleDescribeAlarms(req *cwRequest, c *middleware.Context) {
|
|
|
}
|
|
|
|
|
|
func handleDescribeAlarmsForMetric(req *cwRequest, c *middleware.Context) {
|
|
|
- cfg := getAwsConfig(req)
|
|
|
+ cfg, err := getAwsConfig(req)
|
|
|
+ if err != nil {
|
|
|
+ c.JsonApiErr(500, "Unable to call AWS API", err)
|
|
|
+ return
|
|
|
+ }
|
|
|
svc := cloudwatch.New(session.New(cfg), cfg)
|
|
|
|
|
|
reqParam := &struct {
|
|
|
@@ -336,7 +355,11 @@ func handleDescribeAlarmsForMetric(req *cwRequest, c *middleware.Context) {
|
|
|
}
|
|
|
|
|
|
func handleDescribeAlarmHistory(req *cwRequest, c *middleware.Context) {
|
|
|
- cfg := getAwsConfig(req)
|
|
|
+ cfg, err := getAwsConfig(req)
|
|
|
+ if err != nil {
|
|
|
+ c.JsonApiErr(500, "Unable to call AWS API", err)
|
|
|
+ return
|
|
|
+ }
|
|
|
svc := cloudwatch.New(session.New(cfg), cfg)
|
|
|
|
|
|
reqParam := &struct {
|
|
|
@@ -368,7 +391,11 @@ func handleDescribeAlarmHistory(req *cwRequest, c *middleware.Context) {
|
|
|
}
|
|
|
|
|
|
func handleDescribeInstances(req *cwRequest, c *middleware.Context) {
|
|
|
- cfg := getAwsConfig(req)
|
|
|
+ cfg, err := getAwsConfig(req)
|
|
|
+ if err != nil {
|
|
|
+ c.JsonApiErr(500, "Unable to call AWS API", err)
|
|
|
+ return
|
|
|
+ }
|
|
|
svc := ec2.New(session.New(cfg), cfg)
|
|
|
|
|
|
reqParam := &struct {
|
|
|
@@ -388,7 +415,7 @@ func handleDescribeInstances(req *cwRequest, c *middleware.Context) {
|
|
|
}
|
|
|
|
|
|
var resp ec2.DescribeInstancesOutput
|
|
|
- err := svc.DescribeInstancesPages(params,
|
|
|
+ err = svc.DescribeInstancesPages(params,
|
|
|
func(page *ec2.DescribeInstancesOutput, lastPage bool) bool {
|
|
|
reservations, _ := awsutil.ValuesAtPath(page, "Reservations")
|
|
|
for _, reservation := range reservations {
|