install_command.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. package commands
  2. import (
  3. "archive/zip"
  4. "bytes"
  5. "errors"
  6. "fmt"
  7. "github.com/grafana/grafana/pkg/cmd/grafana-cli/log"
  8. m "github.com/grafana/grafana/pkg/cmd/grafana-cli/models"
  9. s "github.com/grafana/grafana/pkg/cmd/grafana-cli/services"
  10. "io"
  11. "io/ioutil"
  12. "net/http"
  13. "os"
  14. "path"
  15. "regexp"
  16. )
  17. func validateInput(c CommandLine, pluginFolder string) error {
  18. arg := c.Args().First()
  19. if arg == "" {
  20. return errors.New("please specify plugin to install")
  21. }
  22. pluginDir := c.GlobalString("path")
  23. if pluginDir == "" {
  24. return errors.New("missing path flag")
  25. }
  26. fileInfo, err := os.Stat(pluginDir)
  27. if err != nil {
  28. if err = os.MkdirAll(pluginDir, os.ModePerm); err != nil {
  29. return errors.New("path is not a directory")
  30. }
  31. return nil
  32. }
  33. if !fileInfo.IsDir() {
  34. return errors.New("path is not a directory")
  35. }
  36. return nil
  37. }
  38. func installCommand(c CommandLine) error {
  39. pluginFolder := c.GlobalString("path")
  40. if err := validateInput(c, pluginFolder); err != nil {
  41. return err
  42. }
  43. pluginToInstall := c.Args().First()
  44. version := c.Args().Get(1)
  45. if version == "" {
  46. log.Infof("version: latest\n")
  47. } else {
  48. log.Infof("version: %v\n", version)
  49. }
  50. return InstallPlugin(pluginToInstall, version, c)
  51. }
  52. func InstallPlugin(pluginName, version string, c CommandLine) error {
  53. plugin, err := s.GetPlugin(pluginName, c.GlobalString("repo"))
  54. pluginFolder := c.GlobalString("path")
  55. if err != nil {
  56. return err
  57. }
  58. v, err := SelectVersion(plugin, version)
  59. if err != nil {
  60. return err
  61. }
  62. if version == "" {
  63. version = v.Version
  64. }
  65. downloadURL := fmt.Sprintf("%s/%s/versions/%s/download",
  66. c.GlobalString("repo"),
  67. pluginName,
  68. version)
  69. log.Infof("installing %v @ %v\n", plugin.Id, version)
  70. log.Infof("from url: %v\n", downloadURL)
  71. log.Infof("into: %v\n", pluginFolder)
  72. err = downloadFile(plugin.Id, pluginFolder, downloadURL)
  73. if err != nil {
  74. return err
  75. }
  76. log.Infof("Installed %v successfully ✔\n", plugin.Id)
  77. /* Enable once we need support for downloading depedencies
  78. res, _ := s.ReadPlugin(pluginFolder, pluginName)
  79. for _, v := range res.Dependency.Plugins {
  80. InstallPlugin(v.Id, version, c)
  81. log.Infof("Installed dependency: %v ✔\n", v.Id)
  82. }
  83. */
  84. return err
  85. }
  86. func SelectVersion(plugin m.Plugin, version string) (m.Version, error) {
  87. if version == "" {
  88. return plugin.Versions[0], nil
  89. }
  90. for _, v := range plugin.Versions {
  91. if v.Version == version {
  92. return v, nil
  93. }
  94. }
  95. return m.Version{}, errors.New("Could not find the version your looking for")
  96. }
  97. func RemoveGitBuildFromName(pluginName, filename string) string {
  98. r := regexp.MustCompile("^[a-zA-Z0-9_.-]*/")
  99. return r.ReplaceAllString(filename, pluginName+"/")
  100. }
  101. var retryCount = 0
  102. func downloadFile(pluginName, filePath, url string) (err error) {
  103. defer func() {
  104. if r := recover(); r != nil {
  105. retryCount++
  106. if retryCount == 1 {
  107. log.Debug("\nFailed downloading. Will retry once.\n")
  108. downloadFile(pluginName, filePath, url)
  109. } else {
  110. panic(r)
  111. }
  112. }
  113. }()
  114. resp, err := http.Get(url)
  115. if err != nil {
  116. return err
  117. }
  118. defer resp.Body.Close()
  119. body, err := ioutil.ReadAll(resp.Body)
  120. if err != nil {
  121. return err
  122. }
  123. r, err := zip.NewReader(bytes.NewReader(body), resp.ContentLength)
  124. if err != nil {
  125. return err
  126. }
  127. for _, zf := range r.File {
  128. newFile := path.Join(filePath, RemoveGitBuildFromName(pluginName, zf.Name))
  129. if zf.FileInfo().IsDir() {
  130. os.Mkdir(newFile, 0777)
  131. } else {
  132. dst, err := os.Create(newFile)
  133. if err != nil {
  134. log.Errorf("%v", err)
  135. }
  136. defer dst.Close()
  137. src, err := zf.Open()
  138. if err != nil {
  139. log.Errorf("%v", err)
  140. }
  141. defer src.Close()
  142. io.Copy(dst, src)
  143. }
  144. }
  145. return nil
  146. }