cloudwatch.go 4.8 KB

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