plugins.go 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. package plugins
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "os"
  6. "path"
  7. "path/filepath"
  8. "strings"
  9. "github.com/grafana/grafana/pkg/log"
  10. "github.com/grafana/grafana/pkg/models"
  11. "github.com/grafana/grafana/pkg/setting"
  12. )
  13. var (
  14. DataSources map[string]DataSourcePlugin
  15. Panels map[string]PanelPlugin
  16. ExternalPlugins map[string]ExternalPlugin
  17. StaticRoutes []*StaticRootConfig
  18. Bundles map[string]PluginBundle
  19. )
  20. type PluginScanner struct {
  21. pluginPath string
  22. errors []error
  23. }
  24. func Init() error {
  25. DataSources = make(map[string]DataSourcePlugin)
  26. ExternalPlugins = make(map[string]ExternalPlugin)
  27. StaticRoutes = make([]*StaticRootConfig, 0)
  28. Panels = make(map[string]PanelPlugin)
  29. Bundles = make(map[string]PluginBundle)
  30. scan(path.Join(setting.StaticRootPath, "app/plugins"))
  31. checkExternalPluginPaths()
  32. checkDependencies()
  33. return nil
  34. }
  35. func checkDependencies() {
  36. for bundleType, bundle := range Bundles {
  37. for _, reqPanel := range bundle.PanelPlugins {
  38. if _, ok := Panels[reqPanel]; !ok {
  39. log.Fatal(4, "Bundle %s requires Panel type %s, but it is not present.", bundleType, reqPanel)
  40. }
  41. }
  42. for _, reqDataSource := range bundle.DatasourcePlugins {
  43. if _, ok := DataSources[reqDataSource]; !ok {
  44. log.Fatal(4, "Bundle %s requires DataSource type %s, but it is not present.", bundleType, reqDataSource)
  45. }
  46. }
  47. for _, reqExtPlugin := range bundle.ExternalPlugins {
  48. if _, ok := ExternalPlugins[reqExtPlugin]; !ok {
  49. log.Fatal(4, "Bundle %s requires DataSource type %s, but it is not present.", bundleType, reqExtPlugin)
  50. }
  51. }
  52. }
  53. }
  54. func checkExternalPluginPaths() error {
  55. for _, section := range setting.Cfg.Sections() {
  56. if strings.HasPrefix(section.Name(), "plugin.") {
  57. path := section.Key("path").String()
  58. if path != "" {
  59. log.Info("Plugin: Scaning dir %s", path)
  60. scan(path)
  61. }
  62. }
  63. }
  64. return nil
  65. }
  66. func scan(pluginDir string) error {
  67. scanner := &PluginScanner{
  68. pluginPath: pluginDir,
  69. }
  70. if err := filepath.Walk(pluginDir, scanner.walker); err != nil {
  71. return err
  72. }
  73. if len(scanner.errors) > 0 {
  74. return errors.New("Some plugins failed to load")
  75. }
  76. return nil
  77. }
  78. func (scanner *PluginScanner) walker(currentPath string, f os.FileInfo, err error) error {
  79. if err != nil {
  80. return err
  81. }
  82. if f.IsDir() {
  83. return nil
  84. }
  85. if f.Name() == "plugin.json" {
  86. err := scanner.loadPluginJson(currentPath)
  87. if err != nil {
  88. log.Error(3, "Failed to load plugin json file: %v, err: %v", currentPath, err)
  89. scanner.errors = append(scanner.errors, err)
  90. }
  91. }
  92. return nil
  93. }
  94. func addStaticRoot(staticRootConfig *StaticRootConfig, currentDir string) {
  95. if staticRootConfig != nil {
  96. staticRootConfig.Path = path.Join(currentDir, staticRootConfig.Path)
  97. StaticRoutes = append(StaticRoutes, staticRootConfig)
  98. }
  99. }
  100. func (scanner *PluginScanner) loadPluginJson(pluginJsonFilePath string) error {
  101. currentDir := filepath.Dir(pluginJsonFilePath)
  102. reader, err := os.Open(pluginJsonFilePath)
  103. if err != nil {
  104. return err
  105. }
  106. defer reader.Close()
  107. jsonParser := json.NewDecoder(reader)
  108. pluginJson := make(map[string]interface{})
  109. if err := jsonParser.Decode(&pluginJson); err != nil {
  110. return err
  111. }
  112. pluginType, exists := pluginJson["pluginType"]
  113. if !exists {
  114. return errors.New("Did not find pluginType property in plugin.json")
  115. }
  116. if pluginType == "datasource" {
  117. p := DataSourcePlugin{}
  118. reader.Seek(0, 0)
  119. if err := jsonParser.Decode(&p); err != nil {
  120. return err
  121. }
  122. if p.Type == "" {
  123. return errors.New("Did not find type property in plugin.json")
  124. }
  125. DataSources[p.Type] = p
  126. addStaticRoot(p.StaticRootConfig, currentDir)
  127. }
  128. if pluginType == "panel" {
  129. p := PanelPlugin{}
  130. reader.Seek(0, 0)
  131. if err := jsonParser.Decode(&p); err != nil {
  132. return err
  133. }
  134. if p.Type == "" {
  135. return errors.New("Did not find type property in plugin.json")
  136. }
  137. Panels[p.Type] = p
  138. addStaticRoot(p.StaticRootConfig, currentDir)
  139. }
  140. if pluginType == "external" {
  141. p := ExternalPlugin{}
  142. reader.Seek(0, 0)
  143. if err := jsonParser.Decode(&p); err != nil {
  144. return err
  145. }
  146. if p.Type == "" {
  147. return errors.New("Did not find type property in plugin.json")
  148. }
  149. ExternalPlugins[p.Type] = p
  150. addStaticRoot(p.StaticRootConfig, currentDir)
  151. }
  152. if pluginType == "bundle" {
  153. p := PluginBundle{}
  154. reader.Seek(0, 0)
  155. if err := jsonParser.Decode(&p); err != nil {
  156. return err
  157. }
  158. if p.Type == "" {
  159. return errors.New("Did not find type property in plugin.json")
  160. }
  161. Bundles[p.Type] = p
  162. }
  163. return nil
  164. }
  165. func GetEnabledPlugins(orgBundles []*models.PluginBundle) EnabledPlugins {
  166. enabledPlugins := NewEnabledPlugins()
  167. orgBundlesMap := make(map[string]*models.PluginBundle)
  168. for _, orgBundle := range orgBundles {
  169. orgBundlesMap[orgBundle.Type] = orgBundle
  170. }
  171. for bundleType, bundle := range Bundles {
  172. enabled := bundle.Enabled
  173. // check if the bundle is stored in the DB.
  174. if b, ok := orgBundlesMap[bundleType]; ok {
  175. enabled = b.Enabled
  176. }
  177. if enabled {
  178. for _, d := range bundle.DatasourcePlugins {
  179. if ds, ok := DataSources[d]; ok {
  180. enabledPlugins.DataSourcePlugins[d] = &ds
  181. }
  182. }
  183. for _, p := range bundle.PanelPlugins {
  184. if panel, ok := Panels[p]; ok {
  185. enabledPlugins.PanelPlugins = append(enabledPlugins.PanelPlugins, &panel)
  186. }
  187. }
  188. for _, e := range bundle.ExternalPlugins {
  189. if external, ok := ExternalPlugins[e]; ok {
  190. enabledPlugins.ExternalPlugins = append(enabledPlugins.ExternalPlugins, &external)
  191. }
  192. }
  193. }
  194. }
  195. return enabledPlugins
  196. }