services.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. package services
  2. import (
  3. "crypto/tls"
  4. "encoding/json"
  5. "errors"
  6. "fmt"
  7. "io/ioutil"
  8. "net"
  9. "net/http"
  10. "net/url"
  11. "path"
  12. "time"
  13. "github.com/grafana/grafana/pkg/cmd/grafana-cli/logger"
  14. m "github.com/grafana/grafana/pkg/cmd/grafana-cli/models"
  15. )
  16. var (
  17. IoHelper m.IoUtil = IoUtilImp{}
  18. HttpClient http.Client
  19. grafanaVersion string
  20. )
  21. func Init(version string, skipTLSVerify bool) {
  22. grafanaVersion = version
  23. tr := &http.Transport{
  24. Proxy: http.ProxyFromEnvironment,
  25. DialContext: (&net.Dialer{
  26. Timeout: 30 * time.Second,
  27. KeepAlive: 30 * time.Second,
  28. DualStack: true,
  29. }).DialContext,
  30. MaxIdleConns: 100,
  31. IdleConnTimeout: 90 * time.Second,
  32. TLSHandshakeTimeout: 10 * time.Second,
  33. ExpectContinueTimeout: 1 * time.Second,
  34. TLSClientConfig: &tls.Config{
  35. InsecureSkipVerify: skipTLSVerify,
  36. },
  37. }
  38. HttpClient = http.Client{
  39. Timeout: time.Duration(10 * time.Second),
  40. Transport: tr,
  41. }
  42. }
  43. func ListAllPlugins(repoUrl string) (m.PluginRepo, error) {
  44. body, err := sendRequest(repoUrl, "repo")
  45. if err != nil {
  46. logger.Info("Failed to send request", "error", err)
  47. return m.PluginRepo{}, fmt.Errorf("Failed to send request. error: %v", err)
  48. }
  49. if err != nil {
  50. return m.PluginRepo{}, err
  51. }
  52. var data m.PluginRepo
  53. err = json.Unmarshal(body, &data)
  54. if err != nil {
  55. logger.Info("Failed to unmarshal graphite response error: %v", err)
  56. return m.PluginRepo{}, err
  57. }
  58. return data, nil
  59. }
  60. func ReadPlugin(pluginDir, pluginName string) (m.InstalledPlugin, error) {
  61. distPluginDataPath := path.Join(pluginDir, pluginName, "dist", "plugin.json")
  62. var data []byte
  63. var err error
  64. data, err = IoHelper.ReadFile(distPluginDataPath)
  65. if err != nil {
  66. pluginDataPath := path.Join(pluginDir, pluginName, "plugin.json")
  67. data, err = IoHelper.ReadFile(pluginDataPath)
  68. if err != nil {
  69. return m.InstalledPlugin{}, errors.New("Could not find dist/plugin.json or plugin.json on " + pluginName + " in " + pluginDir)
  70. }
  71. }
  72. res := m.InstalledPlugin{}
  73. json.Unmarshal(data, &res)
  74. if res.Info.Version == "" {
  75. res.Info.Version = "0.0.0"
  76. }
  77. if res.Id == "" {
  78. return m.InstalledPlugin{}, errors.New("could not find plugin " + pluginName + " in " + pluginDir)
  79. }
  80. return res, nil
  81. }
  82. func GetLocalPlugins(pluginDir string) []m.InstalledPlugin {
  83. result := make([]m.InstalledPlugin, 0)
  84. files, _ := IoHelper.ReadDir(pluginDir)
  85. for _, f := range files {
  86. res, err := ReadPlugin(pluginDir, f.Name())
  87. if err == nil {
  88. result = append(result, res)
  89. }
  90. }
  91. return result
  92. }
  93. func RemoveInstalledPlugin(pluginPath, pluginName string) error {
  94. logger.Infof("Removing plugin: %v\n", pluginName)
  95. pluginDir := path.Join(pluginPath, pluginName)
  96. _, err := IoHelper.Stat(pluginDir)
  97. if err != nil {
  98. return err
  99. }
  100. return IoHelper.RemoveAll(pluginDir)
  101. }
  102. func GetPlugin(pluginId, repoUrl string) (m.Plugin, error) {
  103. body, err := sendRequest(repoUrl, "repo", pluginId)
  104. if err != nil {
  105. logger.Info("Failed to send request", "error", err)
  106. return m.Plugin{}, fmt.Errorf("Failed to send request. error: %v", err)
  107. }
  108. if err != nil {
  109. return m.Plugin{}, err
  110. }
  111. var data m.Plugin
  112. err = json.Unmarshal(body, &data)
  113. if err != nil {
  114. logger.Info("Failed to unmarshal graphite response error: %v", err)
  115. return m.Plugin{}, err
  116. }
  117. return data, nil
  118. }
  119. func sendRequest(repoUrl string, subPaths ...string) ([]byte, error) {
  120. u, _ := url.Parse(repoUrl)
  121. for _, v := range subPaths {
  122. u.Path = path.Join(u.Path, v)
  123. }
  124. req, err := http.NewRequest(http.MethodGet, u.String(), nil)
  125. req.Header.Set("grafana-version", grafanaVersion)
  126. req.Header.Set("User-Agent", "grafana "+grafanaVersion)
  127. if err != nil {
  128. return []byte{}, err
  129. }
  130. res, err := HttpClient.Do(req)
  131. if err != nil {
  132. return []byte{}, err
  133. }
  134. if res.StatusCode/100 != 2 {
  135. return []byte{}, fmt.Errorf("Api returned invalid status: %s", res.Status)
  136. }
  137. body, err := ioutil.ReadAll(res.Body)
  138. defer res.Body.Close()
  139. return body, err
  140. }