cloudwatch.go 4.5 KB

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