Sfoglia il codice sorgente

cloudwatch: add support for defining AWS profile for CloudWatch datasource

Add support for defining AWS profile for CloudWatch datasource to support
pulling information from multiple different AWS accounts to single dashboard.

With this change, it is possible to define multiple AWS credentials in
~/.aws/credentials file and connect different data sources to different
AWS accounts.
Jari Sukanen 10 anni fa
parent
commit
23599814a3

+ 27 - 6
pkg/api/cloudwatch/cloudwatch.go

@@ -7,6 +7,8 @@ import (
 	"time"
 	"time"
 
 
 	"github.com/aws/aws-sdk-go/aws"
 	"github.com/aws/aws-sdk-go/aws"
+	"github.com/aws/aws-sdk-go/aws/credentials"
+	"github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds"
 	"github.com/aws/aws-sdk-go/service/cloudwatch"
 	"github.com/aws/aws-sdk-go/service/cloudwatch"
 	"github.com/aws/aws-sdk-go/service/ec2"
 	"github.com/aws/aws-sdk-go/service/ec2"
 	"github.com/grafana/grafana/pkg/middleware"
 	"github.com/grafana/grafana/pkg/middleware"
@@ -17,9 +19,10 @@ type actionHandler func(*cwRequest, *middleware.Context)
 var actionHandlers map[string]actionHandler
 var actionHandlers map[string]actionHandler
 
 
 type cwRequest struct {
 type cwRequest struct {
-	Region string `json:"region"`
-	Action string `json:"action"`
-	Body   []byte `json:"-"`
+	Region  string `json:"region"`
+	Profile string `json:"profile"`
+	Action  string `json:"action"`
+	Body    []byte `json:"-"`
 }
 }
 
 
 func init() {
 func init() {
@@ -35,7 +38,16 @@ func init() {
 }
 }
 
 
 func handleGetMetricStatistics(req *cwRequest, c *middleware.Context) {
 func handleGetMetricStatistics(req *cwRequest, c *middleware.Context) {
-	svc := cloudwatch.New(&aws.Config{Region: aws.String(req.Region)})
+	creds := credentials.NewChainCredentials(
+		[]credentials.Provider{
+			&credentials.EnvProvider{},
+			&credentials.SharedCredentialsProvider{Filename: "", Profile: req.Profile},
+			&ec2rolecreds.EC2RoleProvider{ExpiryWindow: 5 * time.Minute},
+		})
+	svc := cloudwatch.New(&aws.Config{
+		Region:      aws.String(req.Region),
+		Credentials: creds,
+	})
 
 
 	reqParam := &struct {
 	reqParam := &struct {
 		Parameters struct {
 		Parameters struct {
@@ -70,7 +82,17 @@ func handleGetMetricStatistics(req *cwRequest, c *middleware.Context) {
 }
 }
 
 
 func handleListMetrics(req *cwRequest, c *middleware.Context) {
 func handleListMetrics(req *cwRequest, c *middleware.Context) {
-	svc := cloudwatch.New(&aws.Config{Region: aws.String(req.Region)})
+	creds := credentials.NewChainCredentials(
+		[]credentials.Provider{
+			&credentials.EnvProvider{},
+			&credentials.SharedCredentialsProvider{Filename: "", Profile: req.Profile},
+			&ec2rolecreds.EC2RoleProvider{ExpiryWindow: 5 * time.Minute},
+		})
+	svc := cloudwatch.New(&aws.Config{
+		Region:      aws.String(req.Region),
+		Credentials: creds,
+	})
+
 	reqParam := &struct {
 	reqParam := &struct {
 		Parameters struct {
 		Parameters struct {
 			Namespace  string                        `json:"namespace"`
 			Namespace  string                        `json:"namespace"`
@@ -78,7 +100,6 @@ func handleListMetrics(req *cwRequest, c *middleware.Context) {
 			Dimensions []*cloudwatch.DimensionFilter `json:"dimensions"`
 			Dimensions []*cloudwatch.DimensionFilter `json:"dimensions"`
 		} `json:"parameters"`
 		} `json:"parameters"`
 	}{}
 	}{}
-
 	json.Unmarshal(req.Body, reqParam)
 	json.Unmarshal(req.Body, reqParam)
 
 
 	params := &cloudwatch.ListMetricsInput{
 	params := &cloudwatch.ListMetricsInput{

+ 3 - 0
public/app/plugins/datasource/cloudwatch/datasource.js

@@ -18,6 +18,7 @@ function (angular, _) {
       this.supportMetrics = true;
       this.supportMetrics = true;
       this.proxyUrl = datasource.url;
       this.proxyUrl = datasource.url;
       this.defaultRegion = datasource.jsonData.defaultRegion;
       this.defaultRegion = datasource.jsonData.defaultRegion;
+      this.profile = datasource.jsonData.profile;
     }
     }
 
 
     CloudWatchDatasource.prototype.query = function(options) {
     CloudWatchDatasource.prototype.query = function(options) {
@@ -73,6 +74,7 @@ function (angular, _) {
     CloudWatchDatasource.prototype.performTimeSeriesQuery = function(query, start, end) {
     CloudWatchDatasource.prototype.performTimeSeriesQuery = function(query, start, end) {
       return this.awsRequest({
       return this.awsRequest({
         region: query.region,
         region: query.region,
+        profile: this.profile,
         action: 'GetMetricStatistics',
         action: 'GetMetricStatistics',
         parameters:  {
         parameters:  {
           namespace: query.namespace,
           namespace: query.namespace,
@@ -115,6 +117,7 @@ function (angular, _) {
     CloudWatchDatasource.prototype.getDimensionValues = function(region, namespace, metricName, dimensions) {
     CloudWatchDatasource.prototype.getDimensionValues = function(region, namespace, metricName, dimensions) {
       var request = {
       var request = {
         region: templateSrv.replace(region),
         region: templateSrv.replace(region),
+        profile: this.profile,
         action: 'ListMetrics',
         action: 'ListMetrics',
         parameters: {
         parameters: {
           namespace: templateSrv.replace(namespace),
           namespace: templateSrv.replace(namespace),

+ 11 - 0
public/app/plugins/datasource/cloudwatch/partials/config.html

@@ -12,6 +12,17 @@
   </ul>
   </ul>
   <div class="clearfix"></div>
   <div class="clearfix"></div>
 </div>
 </div>
+<div class="tight-form last">
+  <ul class="tight-form-list">
+    <li class="tight-form-item" style="width: 160px">
+      AWS Profile
+    </li>
+    <li>
+      <input type="text" class="tight-form-input input-xlarge" ng-model='current.jsonData.profile' placeholder="default" required></input>
+    </li>
+  </ul>
+  <div class="clearfix"></div>
+</div>
 
 
 <!-- <div class="tight&#45;form" ng&#45;show="current.jsonData.access === 'direct'"> -->
 <!-- <div class="tight&#45;form" ng&#45;show="current.jsonData.access === 'direct'"> -->
 <!--   <ul class="tight&#45;form&#45;list"> -->
 <!--   <ul class="tight&#45;form&#45;list"> -->