cloudwatch.go 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. package cloudwatch
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "io/ioutil"
  6. "time"
  7. "github.com/aws/aws-sdk-go/aws"
  8. "github.com/aws/aws-sdk-go/aws/credentials"
  9. "github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds"
  10. "github.com/aws/aws-sdk-go/service/cloudwatch"
  11. "github.com/aws/aws-sdk-go/service/ec2"
  12. "github.com/grafana/grafana/pkg/middleware"
  13. m "github.com/grafana/grafana/pkg/models"
  14. )
  15. type actionHandler func(*cwRequest, *middleware.Context)
  16. var actionHandlers map[string]actionHandler
  17. type cwRequest struct {
  18. Region string `json:"region"`
  19. Action string `json:"action"`
  20. Body []byte `json:"-"`
  21. DataSource *m.DataSource
  22. }
  23. func init() {
  24. actionHandlers = map[string]actionHandler{
  25. "GetMetricStatistics": handleGetMetricStatistics,
  26. "ListMetrics": handleListMetrics,
  27. "DescribeInstances": handleDescribeInstances,
  28. "__GetRegions": handleGetRegions,
  29. "__GetNamespaces": handleGetNamespaces,
  30. "__GetMetrics": handleGetMetrics,
  31. "__GetDimensions": handleGetDimensions,
  32. }
  33. }
  34. func handleGetMetricStatistics(req *cwRequest, c *middleware.Context) {
  35. creds := credentials.NewChainCredentials(
  36. []credentials.Provider{
  37. &credentials.EnvProvider{},
  38. &credentials.SharedCredentialsProvider{Filename: "", Profile: req.DataSource.Database},
  39. &ec2rolecreds.EC2RoleProvider{ExpiryWindow: 5 * time.Minute},
  40. })
  41. svc := cloudwatch.New(&aws.Config{
  42. Region: aws.String(req.Region),
  43. Credentials: creds,
  44. })
  45. reqParam := &struct {
  46. Parameters struct {
  47. Namespace string `json:"namespace"`
  48. MetricName string `json:"metricName"`
  49. Dimensions []*cloudwatch.Dimension `json:"dimensions"`
  50. Statistics []*string `json:"statistics"`
  51. StartTime int64 `json:"startTime"`
  52. EndTime int64 `json:"endTime"`
  53. Period int64 `json:"period"`
  54. } `json:"parameters"`
  55. }{}
  56. json.Unmarshal(req.Body, reqParam)
  57. params := &cloudwatch.GetMetricStatisticsInput{
  58. Namespace: aws.String(reqParam.Parameters.Namespace),
  59. MetricName: aws.String(reqParam.Parameters.MetricName),
  60. Dimensions: reqParam.Parameters.Dimensions,
  61. Statistics: reqParam.Parameters.Statistics,
  62. StartTime: aws.Time(time.Unix(reqParam.Parameters.StartTime, 0)),
  63. EndTime: aws.Time(time.Unix(reqParam.Parameters.EndTime, 0)),
  64. Period: aws.Int64(reqParam.Parameters.Period),
  65. }
  66. resp, err := svc.GetMetricStatistics(params)
  67. if err != nil {
  68. c.JsonApiErr(500, "Unable to call AWS API", err)
  69. return
  70. }
  71. c.JSON(200, resp)
  72. }
  73. func handleListMetrics(req *cwRequest, c *middleware.Context) {
  74. creds := credentials.NewChainCredentials(
  75. []credentials.Provider{
  76. &credentials.EnvProvider{},
  77. &credentials.SharedCredentialsProvider{Filename: "", Profile: req.DataSource.Database},
  78. &ec2rolecreds.EC2RoleProvider{ExpiryWindow: 5 * time.Minute},
  79. })
  80. svc := cloudwatch.New(&aws.Config{
  81. Region: aws.String(req.Region),
  82. Credentials: creds,
  83. })
  84. reqParam := &struct {
  85. Parameters struct {
  86. Namespace string `json:"namespace"`
  87. MetricName string `json:"metricName"`
  88. Dimensions []*cloudwatch.DimensionFilter `json:"dimensions"`
  89. } `json:"parameters"`
  90. }{}
  91. json.Unmarshal(req.Body, reqParam)
  92. params := &cloudwatch.ListMetricsInput{
  93. Namespace: aws.String(reqParam.Parameters.Namespace),
  94. MetricName: aws.String(reqParam.Parameters.MetricName),
  95. Dimensions: reqParam.Parameters.Dimensions,
  96. }
  97. resp, err := svc.ListMetrics(params)
  98. if err != nil {
  99. c.JsonApiErr(500, "Unable to call AWS API", err)
  100. return
  101. }
  102. c.JSON(200, resp)
  103. }
  104. func handleDescribeInstances(req *cwRequest, c *middleware.Context) {
  105. svc := ec2.New(&aws.Config{Region: aws.String(req.Region)})
  106. reqParam := &struct {
  107. Parameters struct {
  108. Filters []*ec2.Filter `json:"filters"`
  109. InstanceIds []*string `json:"instanceIds"`
  110. } `json:"parameters"`
  111. }{}
  112. json.Unmarshal(req.Body, reqParam)
  113. params := &ec2.DescribeInstancesInput{}
  114. if len(reqParam.Parameters.Filters) > 0 {
  115. params.Filters = reqParam.Parameters.Filters
  116. }
  117. if len(reqParam.Parameters.InstanceIds) > 0 {
  118. params.InstanceIds = reqParam.Parameters.InstanceIds
  119. }
  120. resp, err := svc.DescribeInstances(params)
  121. if err != nil {
  122. c.JsonApiErr(500, "Unable to call AWS API", err)
  123. return
  124. }
  125. c.JSON(200, resp)
  126. }
  127. func HandleRequest(c *middleware.Context, ds *m.DataSource) {
  128. var req cwRequest
  129. req.Body, _ = ioutil.ReadAll(c.Req.Request.Body)
  130. req.DataSource = ds
  131. json.Unmarshal(req.Body, &req)
  132. if handler, found := actionHandlers[req.Action]; !found {
  133. c.JsonApiErr(500, "Unexpected AWS Action", errors.New(req.Action))
  134. return
  135. } else {
  136. handler(&req, c)
  137. }
  138. }