plugins.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. package plugins
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "os"
  6. "path"
  7. "path/filepath"
  8. "github.com/grafana/grafana/pkg/log"
  9. "github.com/grafana/grafana/pkg/models"
  10. "github.com/grafana/grafana/pkg/setting"
  11. )
  12. type PluginMeta struct {
  13. Type string `json:"type"`
  14. Name string `json:"name"`
  15. }
  16. type ExternalPluginRoute struct {
  17. Path string `json:"path"`
  18. Method string `json:"method"`
  19. ReqSignedIn bool `json:"req_signed_in"`
  20. ReqGrafanaAdmin bool `json:"req_grafana_admin"`
  21. ReqRole models.RoleType `json:"req_role"`
  22. Url string `json:"url"`
  23. }
  24. type ExternalPluginJs struct {
  25. Src string `json:"src"`
  26. }
  27. type ExternalPluginMenuItem struct {
  28. Text string `json:"text"`
  29. Icon string `json:"icon"`
  30. Href string `json:"href"`
  31. }
  32. type ExternalPluginCss struct {
  33. Href string `json:"href"`
  34. }
  35. type ExternalPluginSettings struct {
  36. Routes []*ExternalPluginRoute `json:"routes"`
  37. Js []*ExternalPluginJs `json:"js"`
  38. Css []*ExternalPluginCss `json:"css"`
  39. MenuItems []*ExternalPluginMenuItem `json:"menu_items"`
  40. }
  41. type ExternalPlugin struct {
  42. PluginType string `json:"pluginType"`
  43. Settings ExternalPluginSettings `json:"settings"`
  44. }
  45. var (
  46. DataSources map[string]interface{}
  47. ExternalPlugins []ExternalPlugin
  48. )
  49. type PluginScanner struct {
  50. pluginPath string
  51. errors []error
  52. }
  53. func Init() {
  54. scan(path.Join(setting.StaticRootPath, "app/plugins"))
  55. }
  56. func scan(pluginDir string) error {
  57. DataSources = make(map[string]interface{})
  58. ExternalPlugins = make([]ExternalPlugin, 0)
  59. scanner := &PluginScanner{
  60. pluginPath: pluginDir,
  61. }
  62. if err := filepath.Walk(pluginDir, scanner.walker); err != nil {
  63. return err
  64. }
  65. if len(scanner.errors) > 0 {
  66. return errors.New("Some plugins failed to load")
  67. }
  68. return nil
  69. }
  70. func (scanner *PluginScanner) walker(path string, f os.FileInfo, err error) error {
  71. if err != nil {
  72. return err
  73. }
  74. if f.IsDir() {
  75. return nil
  76. }
  77. if f.Name() == "plugin.json" {
  78. err := scanner.loadPluginJson(path)
  79. if err != nil {
  80. log.Error(3, "Failed to load plugin json file: %v, err: %v", path, err)
  81. scanner.errors = append(scanner.errors, err)
  82. }
  83. }
  84. return nil
  85. }
  86. func (scanner *PluginScanner) loadPluginJson(path string) error {
  87. reader, err := os.Open(path)
  88. if err != nil {
  89. return err
  90. }
  91. defer reader.Close()
  92. jsonParser := json.NewDecoder(reader)
  93. pluginJson := make(map[string]interface{})
  94. if err := jsonParser.Decode(&pluginJson); err != nil {
  95. return err
  96. }
  97. pluginType, exists := pluginJson["pluginType"]
  98. if !exists {
  99. return errors.New("Did not find pluginType property in plugin.json")
  100. }
  101. if pluginType == "datasource" {
  102. datasourceType, exists := pluginJson["type"]
  103. if !exists {
  104. return errors.New("Did not find type property in plugin.json")
  105. }
  106. DataSources[datasourceType.(string)] = pluginJson
  107. }
  108. if pluginType == "externalPlugin" {
  109. p := ExternalPlugin{}
  110. reader.Seek(0, 0)
  111. if err := jsonParser.Decode(&p); err != nil {
  112. return err
  113. }
  114. ExternalPlugins = append(ExternalPlugins, p)
  115. }
  116. return nil
  117. }