cloudwatch.go 5.2 KB

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