install_command_test.go 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. package commands
  2. import (
  3. "fmt"
  4. "io/ioutil"
  5. "os"
  6. "runtime"
  7. "testing"
  8. "github.com/grafana/grafana/pkg/cmd/grafana-cli/commands/commandstest"
  9. "github.com/grafana/grafana/pkg/cmd/grafana-cli/models"
  10. "github.com/grafana/grafana/pkg/cmd/grafana-cli/utils"
  11. . "github.com/smartystreets/goconvey/convey"
  12. "github.com/stretchr/testify/assert"
  13. )
  14. func TestFoldernameReplacement(t *testing.T) {
  15. Convey("path containing git commit path", t, func() {
  16. pluginName := "datasource-plugin-kairosdb"
  17. paths := map[string]string{
  18. "datasource-plugin-kairosdb-cc4a3965ef5d3eb1ae0ee4f93e9e78ec7db69e64/": "datasource-plugin-kairosdb/",
  19. "datasource-plugin-kairosdb-cc4a3965ef5d3eb1ae0ee4f93e9e78ec7db69e64/README.md": "datasource-plugin-kairosdb/README.md",
  20. "datasource-plugin-kairosdb-cc4a3965ef5d3eb1ae0ee4f93e9e78ec7db69e64/partials/": "datasource-plugin-kairosdb/partials/",
  21. "datasource-plugin-kairosdb-cc4a3965ef5d3eb1ae0ee4f93e9e78ec7db69e64/partials/config.html": "datasource-plugin-kairosdb/partials/config.html",
  22. }
  23. Convey("should be replaced with plugin name", func() {
  24. for k, v := range paths {
  25. So(RemoveGitBuildFromName(pluginName, k), ShouldEqual, v)
  26. }
  27. })
  28. })
  29. Convey("path containing git commit path", t, func() {
  30. pluginName := "app-example"
  31. paths := map[string]string{
  32. "app-plugin-example-3c28f65ac6fb7f1e234b0364b97081d836495439/": "app-example/",
  33. }
  34. Convey("should be replaced with plugin name", func() {
  35. for k, v := range paths {
  36. So(RemoveGitBuildFromName(pluginName, k), ShouldEqual, v)
  37. }
  38. })
  39. })
  40. }
  41. func TestExtractFiles(t *testing.T) {
  42. t.Run("Should preserve file permissions for plugin backend binaries for linux and darwin", func(t *testing.T) {
  43. pluginDir, del := setupFakePluginsDir(t)
  44. defer del()
  45. body, err := ioutil.ReadFile("testdata/grafana-simple-json-datasource-ec18fa4da8096a952608a7e4c7782b4260b41bcf.zip")
  46. assert.Nil(t, err)
  47. err = extractFiles(body, "grafana-simple-json-datasource", pluginDir, false)
  48. assert.Nil(t, err)
  49. //File in zip has permissions 755
  50. fileInfo, err := os.Stat(pluginDir + "/grafana-simple-json-datasource/simple-plugin_darwin_amd64")
  51. assert.Nil(t, err)
  52. assert.Equal(t, "-rwxr-xr-x", fileInfo.Mode().String())
  53. //File in zip has permission 755
  54. fileInfo, err = os.Stat(pluginDir + "/grafana-simple-json-datasource/simple-plugin_linux_amd64")
  55. assert.Nil(t, err)
  56. assert.Equal(t, "-rwxr-xr-x", fileInfo.Mode().String())
  57. //File in zip has permission 644
  58. fileInfo, err = os.Stat(pluginDir + "/grafana-simple-json-datasource/simple-plugin_windows_amd64.exe")
  59. assert.Nil(t, err)
  60. assert.Equal(t, "-rw-r--r--", fileInfo.Mode().String())
  61. //File in zip has permission 755
  62. fileInfo, err = os.Stat(pluginDir + "/grafana-simple-json-datasource/non-plugin-binary")
  63. assert.Nil(t, err)
  64. assert.Equal(t, "-rwxr-xr-x", fileInfo.Mode().String())
  65. })
  66. t.Run("Should ignore symlinks if not allowed", func(t *testing.T) {
  67. pluginDir, del := setupFakePluginsDir(t)
  68. defer del()
  69. body, err := ioutil.ReadFile("testdata/plugin-with-symlink.zip")
  70. assert.Nil(t, err)
  71. err = extractFiles(body, "plugin-with-symlink", pluginDir, false)
  72. assert.Nil(t, err)
  73. _, err = os.Stat(pluginDir + "/plugin-with-symlink/text.txt")
  74. assert.Nil(t, err)
  75. _, err = os.Stat(pluginDir + "/plugin-with-symlink/symlink_to_txt")
  76. assert.NotNil(t, err)
  77. })
  78. t.Run("Should extract symlinks if allowed", func(t *testing.T) {
  79. pluginDir, del := setupFakePluginsDir(t)
  80. defer del()
  81. body, err := ioutil.ReadFile("testdata/plugin-with-symlink.zip")
  82. assert.Nil(t, err)
  83. err = extractFiles(body, "plugin-with-symlink", pluginDir, true)
  84. assert.Nil(t, err)
  85. _, err = os.Stat(pluginDir + "/plugin-with-symlink/symlink_to_txt")
  86. assert.Nil(t, err)
  87. fmt.Println(err)
  88. })
  89. }
  90. func TestInstallPluginCommand(t *testing.T) {
  91. pluginDir, del := setupFakePluginsDir(t)
  92. defer del()
  93. cmd := setupPluginInstallCmd(t, pluginDir)
  94. err := InstallPlugin("test-plugin-panel", "", cmd)
  95. assert.Nil(t, err)
  96. }
  97. func TestIsPathSafe(t *testing.T) {
  98. t.Run("Should be true on nested destinations", func(t *testing.T) {
  99. assert.True(t, isPathSafe("dest", "/test/path"))
  100. assert.True(t, isPathSafe("dest/one", "/test/path"))
  101. assert.True(t, isPathSafe("../path/dest/one", "/test/path"))
  102. })
  103. t.Run("Should be false on destinations outside of path", func(t *testing.T) {
  104. assert.False(t, isPathSafe("../dest", "/test/path"))
  105. assert.False(t, isPathSafe("../../", "/test/path"))
  106. assert.False(t, isPathSafe("../../test", "/test/path"))
  107. })
  108. }
  109. func setupPluginInstallCmd(t *testing.T, pluginDir string) utils.CommandLine {
  110. cmd := &commandstest.FakeCommandLine{
  111. GlobalFlags: &commandstest.FakeFlagger{Data: map[string]interface{}{
  112. "pluginsDir": pluginDir,
  113. }},
  114. }
  115. client := &commandstest.FakeGrafanaComClient{}
  116. client.GetPluginFunc = func(pluginId, repoUrl string) (models.Plugin, error) {
  117. assert.Equal(t, "test-plugin-panel", pluginId)
  118. plugin := models.Plugin{
  119. Id: "test-plugin-panel",
  120. Category: "",
  121. Versions: []models.Version{
  122. {
  123. Commit: "commit",
  124. Url: "url",
  125. Version: "1.0.0",
  126. Arch: map[string]models.ArchMeta{
  127. fmt.Sprintf("%s-%s", runtime.GOOS, runtime.GOARCH): {
  128. Md5: "test",
  129. },
  130. },
  131. },
  132. },
  133. }
  134. return plugin, nil
  135. }
  136. client.DownloadFileFunc = func(pluginName, filePath, url string, checksum string) (content []byte, err error) {
  137. assert.Equal(t, "test-plugin-panel", pluginName)
  138. assert.Equal(t, "/test-plugin-panel/versions/1.0.0/download", url)
  139. assert.Equal(t, "test", checksum)
  140. body, err := ioutil.ReadFile("testdata/grafana-simple-json-datasource-ec18fa4da8096a952608a7e4c7782b4260b41bcf.zip")
  141. assert.Nil(t, err)
  142. return body, nil
  143. }
  144. cmd.Client = client
  145. return cmd
  146. }
  147. func setupFakePluginsDir(t *testing.T) (string, func()) {
  148. dirname := "testdata/fake-plugins-dir"
  149. err := os.RemoveAll(dirname)
  150. assert.Nil(t, err)
  151. err = os.MkdirAll(dirname, 0774)
  152. assert.Nil(t, err)
  153. return dirname, func() {
  154. err = os.RemoveAll(dirname)
  155. assert.Nil(t, err)
  156. }
  157. }