diff --git a/pkg/api/api.go b/pkg/api/api.go index e15c08b770c..0915bbd678d 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -171,7 +171,6 @@ func Register(r *macaron.Macaron) { r.Put("/:id", bind(m.UpdateDataSourceCommand{}), UpdateDataSource) r.Delete("/:id", DeleteDataSource) r.Get("/:id", wrap(GetDataSourceById)) - r.Get("/plugins", GetDataSourcePlugins) }, reqOrgAdmin) r.Group("/datasources/name/:name", func() { diff --git a/pkg/api/datasources.go b/pkg/api/datasources.go index 8c57438dfb5..a156d10f098 100644 --- a/pkg/api/datasources.go +++ b/pkg/api/datasources.go @@ -6,7 +6,6 @@ import ( //"github.com/grafana/grafana/pkg/log" "github.com/grafana/grafana/pkg/middleware" m "github.com/grafana/grafana/pkg/models" - "github.com/grafana/grafana/pkg/plugins" "github.com/grafana/grafana/pkg/util" ) @@ -100,24 +99,6 @@ func UpdateDataSource(c *middleware.Context, cmd m.UpdateDataSourceCommand) { c.JsonOK("Datasource updated") } -func GetDataSourcePlugins(c *middleware.Context) { - dsList := make(map[string]*plugins.DataSourcePlugin) - - if enabledPlugins, err := plugins.GetEnabledPlugins(c.OrgId); err != nil { - c.JsonApiErr(500, "Failed to get org apps", err) - return - } else { - - for key, value := range enabledPlugins.DataSources { - if !value.BuiltIn { - dsList[key] = value - } - } - - c.JSON(200, dsList) - } -} - // Get /api/datasources/name/:name func GetDataSourceByName(c *middleware.Context) Response { query := m.GetDataSourceByNameQuery{Name: c.Params(":name"), OrgId: c.OrgId} diff --git a/pkg/api/dtos/plugins.go b/pkg/api/dtos/plugins.go index 20b976af122..61b149d73e4 100644 --- a/pkg/api/dtos/plugins.go +++ b/pkg/api/dtos/plugins.go @@ -5,23 +5,23 @@ import "github.com/grafana/grafana/pkg/plugins" type PluginSetting struct { Name string `json:"name"` Type string `json:"type"` - PluginId string `json:"pluginId"` + Id string `json:"id"` Enabled bool `json:"enabled"` Pinned bool `json:"pinned"` Module string `json:"module"` BaseUrl string `json:"baseUrl"` Info *plugins.PluginInfo `json:"info"` Pages []*plugins.AppPluginPage `json:"pages"` - Includes []*plugins.AppIncludeInfo `json:"includes"` + Includes []*plugins.PluginInclude `json:"includes"` Dependencies *plugins.PluginDependencies `json:"dependencies"` JsonData map[string]interface{} `json:"jsonData"` } type PluginListItem struct { - Name string `json:"name"` - Type string `json:"type"` - PluginId string `json:"pluginId"` - Enabled bool `json:"enabled"` - Pinned bool `json:"pinned"` - Info *plugins.PluginInfo `json:"info"` + Name string `json:"name"` + Type string `json:"type"` + Id string `json:"id"` + Enabled bool `json:"enabled"` + Pinned bool `json:"pinned"` + Info *plugins.PluginInfo `json:"info"` } diff --git a/pkg/api/plugin_setting.go b/pkg/api/plugin_setting.go index ff9e3413e40..1ceecdfac18 100644 --- a/pkg/api/plugin_setting.go +++ b/pkg/api/plugin_setting.go @@ -9,6 +9,10 @@ import ( ) func GetPluginList(c *middleware.Context) Response { + typeFilter := c.Query("type") + enabledFilter := c.Query("enabled") + embeddedFilter := c.Query("embedded") + pluginSettingsMap, err := plugins.GetPluginSettings(c.OrgId) if err != nil { @@ -17,16 +21,21 @@ func GetPluginList(c *middleware.Context) Response { result := make([]*dtos.PluginListItem, 0) for _, pluginDef := range plugins.Plugins { - // filter out plugin components - if pluginDef.IncludedInAppId != "" { + // filter out app sub plugins + if embeddedFilter == "0" && pluginDef.IncludedInAppId != "" { + continue + } + + // filter on type + if typeFilter != "" && typeFilter != pluginDef.Type { continue } listItem := &dtos.PluginListItem{ - PluginId: pluginDef.Id, - Name: pluginDef.Name, - Type: pluginDef.Type, - Info: &pluginDef.Info, + Id: pluginDef.Id, + Name: pluginDef.Name, + Type: pluginDef.Type, + Info: &pluginDef.Info, } if pluginSetting, exists := pluginSettingsMap[pluginDef.Id]; exists { @@ -34,6 +43,11 @@ func GetPluginList(c *middleware.Context) Response { listItem.Pinned = pluginSetting.Pinned } + // filter out disabled + if enabledFilter == "1" && !listItem.Enabled { + continue + } + result = append(result, listItem) } @@ -46,19 +60,20 @@ func GetPluginSettingById(c *middleware.Context) Response { if def, exists := plugins.Plugins[pluginId]; !exists { return ApiError(404, "Plugin not found, no installed plugin with that id", nil) } else { + dto := &dtos.PluginSetting{ Type: def.Type, - PluginId: def.Id, + Id: def.Id, Name: def.Name, Info: &def.Info, Dependencies: &def.Dependencies, + Includes: def.Includes, + BaseUrl: def.BaseUrl, + Module: def.Module, } if app, exists := plugins.Apps[pluginId]; exists { dto.Pages = app.Pages - dto.Includes = app.Includes - dto.BaseUrl = app.BaseUrl - dto.Module = app.Module } query := m.GetPluginSettingByIdQuery{PluginId: pluginId, OrgId: c.OrgId} diff --git a/pkg/models/plugin_setting.go b/pkg/models/plugin_setting.go index 777f4599241..d030c125ba9 100644 --- a/pkg/models/plugin_setting.go +++ b/pkg/models/plugin_setting.go @@ -61,7 +61,14 @@ func (cmd *UpdatePluginSettingCmd) GetEncryptedJsonData() SecureJsonData { // QUERIES type GetPluginSettingsQuery struct { OrgId int64 - Result []*PluginSetting + Result []*PluginSettingInfoDTO +} + +type PluginSettingInfoDTO struct { + OrgId int64 + PluginId string + Enabled bool + Pinned bool } type GetPluginSettingByIdQuery struct { diff --git a/pkg/plugins/app_plugin.go b/pkg/plugins/app_plugin.go index ac7ef8948b0..7fc170784f3 100644 --- a/pkg/plugins/app_plugin.go +++ b/pkg/plugins/app_plugin.go @@ -21,20 +21,13 @@ type AppPluginCss struct { Dark string `json:"dark"` } -type AppIncludeInfo struct { - Name string `json:"name"` - Type string `json:"type"` - Id string `json:"id"` -} - type AppPlugin struct { FrontendPluginBase - Pages []*AppPluginPage `json:"pages"` - Routes []*AppPluginRoute `json:"routes"` - Includes []*AppIncludeInfo `json:"-"` + Pages []*AppPluginPage `json:"pages"` + Routes []*AppPluginRoute `json:"routes"` - Pinned bool `json:"-"` - Enabled bool `json:"-"` + FoundChildPlugins []*PluginInclude `json:"-"` + Pinned bool `json:"-"` } type AppPluginRoute struct { @@ -71,7 +64,7 @@ func (app *AppPlugin) initApp() { for _, panel := range Panels { if strings.HasPrefix(panel.PluginDir, app.PluginDir) { panel.setPathsBasedOnApp(app) - app.Includes = append(app.Includes, &AppIncludeInfo{ + app.FoundChildPlugins = append(app.FoundChildPlugins, &PluginInclude{ Name: panel.Name, Id: panel.Id, Type: panel.Type, @@ -83,7 +76,7 @@ func (app *AppPlugin) initApp() { for _, ds := range DataSources { if strings.HasPrefix(ds.PluginDir, app.PluginDir) { ds.setPathsBasedOnApp(app) - app.Includes = append(app.Includes, &AppIncludeInfo{ + app.FoundChildPlugins = append(app.FoundChildPlugins, &PluginInclude{ Name: ds.Name, Id: ds.Id, Type: ds.Type, diff --git a/pkg/plugins/datasource_plugin.go b/pkg/plugins/datasource_plugin.go index ecffb87b8db..b8c79f22998 100644 --- a/pkg/plugins/datasource_plugin.go +++ b/pkg/plugins/datasource_plugin.go @@ -4,12 +4,11 @@ import "encoding/json" type DataSourcePlugin struct { FrontendPluginBase - DefaultMatchFormat string `json:"defaultMatchFormat"` - Annotations bool `json:"annotations"` - Metrics bool `json:"metrics"` - BuiltIn bool `json:"builtIn"` - Mixed bool `json:"mixed"` - App string `json:"app"` + Annotations bool `json:"annotations"` + Metrics bool `json:"metrics"` + BuiltIn bool `json:"builtIn"` + Mixed bool `json:"mixed"` + App string `json:"app"` } func (p *DataSourcePlugin) Load(decoder *json.Decoder, pluginDir string) error { diff --git a/pkg/plugins/frontend_plugin.go b/pkg/plugins/frontend_plugin.go index dac59e9b9ba..aab3f851f60 100644 --- a/pkg/plugins/frontend_plugin.go +++ b/pkg/plugins/frontend_plugin.go @@ -11,10 +11,6 @@ import ( type FrontendPluginBase struct { PluginBase - Module string `json:"module"` - BaseUrl string `json:"baseUrl"` - StaticRoot string `json:"staticRoot"` - StaticRootAbs string `json:"-"` } func (fp *FrontendPluginBase) initFrontendPlugin() { diff --git a/pkg/plugins/models.go b/pkg/plugins/models.go index 298ca817b5c..0addaac9bb7 100644 --- a/pkg/plugins/models.go +++ b/pkg/plugins/models.go @@ -14,11 +14,16 @@ type PluginLoader interface { } type PluginBase struct { - Type string `json:"type"` - Name string `json:"name"` - Id string `json:"id"` - Info PluginInfo `json:"info"` - Dependencies PluginDependencies `json:"dependencies"` + Type string `json:"type"` + Name string `json:"name"` + Id string `json:"id"` + Info PluginInfo `json:"info"` + Dependencies PluginDependencies `json:"dependencies"` + Includes []*PluginInclude `json:"includes"` + Module string `json:"module"` + BaseUrl string `json:"baseUrl"` + StaticRoot string `json:"staticRoot"` + StaticRootAbs string `json:"-"` IncludedInAppId string `json:"-"` PluginDir string `json:"-"` @@ -51,6 +56,13 @@ type PluginDependencies struct { Plugins []PluginDependencyItem `json:"plugins"` } +type PluginInclude struct { + Name string `json:"name"` + Path string `json:"path"` + Type string `json:"type"` + Id string `json:"id"` +} + type PluginDependencyItem struct { Type string `json:"type"` Id string `json:"id"` diff --git a/pkg/plugins/queries.go b/pkg/plugins/queries.go index b3cc92bf7d1..b930c9575a3 100644 --- a/pkg/plugins/queries.go +++ b/pkg/plugins/queries.go @@ -5,61 +5,71 @@ import ( m "github.com/grafana/grafana/pkg/models" ) -func GetPluginSettings(orgId int64) (map[string]*m.PluginSetting, error) { +func GetPluginSettings(orgId int64) (map[string]*m.PluginSettingInfoDTO, error) { query := m.GetPluginSettingsQuery{OrgId: orgId} if err := bus.Dispatch(&query); err != nil { return nil, err } - pluginMap := make(map[string]*m.PluginSetting) + pluginMap := make(map[string]*m.PluginSettingInfoDTO) for _, plug := range query.Result { pluginMap[plug.PluginId] = plug } + for _, pluginDef := range Plugins { + // ignore entries that exists + if _, ok := pluginMap[pluginDef.Id]; ok { + continue + } + + // default to enabled true + opt := &m.PluginSettingInfoDTO{Enabled: true} + + // if it's included in app check app settings + if pluginDef.IncludedInAppId != "" { + // app componets are by default disabled + opt.Enabled = false + + if appSettings, ok := pluginMap[pluginDef.IncludedInAppId]; ok { + opt.Enabled = appSettings.Enabled + } + } + + pluginMap[pluginDef.Id] = opt + } + return pluginMap, nil } func GetEnabledPlugins(orgId int64) (*EnabledPlugins, error) { enabledPlugins := NewEnabledPlugins() - orgPlugins, err := GetPluginSettings(orgId) + pluginSettingMap, err := GetPluginSettings(orgId) if err != nil { return nil, err } - enabledApps := make(map[string]bool) + isPluginEnabled := func(pluginId string) bool { + _, ok := pluginSettingMap[pluginId] + return ok + } for pluginId, app := range Apps { - - if b, ok := orgPlugins[pluginId]; ok { - app.Enabled = b.Enabled + if b, ok := pluginSettingMap[pluginId]; ok { app.Pinned = b.Pinned - } - - if app.Enabled { - enabledApps[pluginId] = true enabledPlugins.Apps = append(enabledPlugins.Apps, app) } } - isPluginEnabled := func(appId string) bool { - if appId == "" { - return true - } - - _, ok := enabledApps[appId] - return ok - } - // add all plugins that are not part of an App. for dsId, ds := range DataSources { - if isPluginEnabled(ds.IncludedInAppId) { + if isPluginEnabled(ds.Id) { enabledPlugins.DataSources[dsId] = ds } } for _, panel := range Panels { - if isPluginEnabled(panel.IncludedInAppId) { + if isPluginEnabled(panel.Id) { enabledPlugins.Panels = append(enabledPlugins.Panels, panel) } } diff --git a/pkg/services/sqlstore/plugin_setting.go b/pkg/services/sqlstore/plugin_setting.go index 53f4857d9b6..b3285e905cf 100644 --- a/pkg/services/sqlstore/plugin_setting.go +++ b/pkg/services/sqlstore/plugin_setting.go @@ -16,9 +16,12 @@ func init() { } func GetPluginSettings(query *m.GetPluginSettingsQuery) error { - sess := x.Where("org_id=?", query.OrgId) + sql := `SELECT org_id, plugin_id, enabled, pinned + FROM plugin_setting + WHERE org_id=?` - query.Result = make([]*m.PluginSetting, 0) + sess := x.Sql(sql, query.OrgId) + query.Result = make([]*m.PluginSettingInfoDTO, 0) return sess.Find(&query.Result) } diff --git a/public/app/features/dashboard/import_list/import_list.ts b/public/app/features/dashboard/import_list/import_list.ts index f229e56d425..1d3aa42611b 100644 --- a/public/app/features/dashboard/import_list/import_list.ts +++ b/public/app/features/dashboard/import_list/import_list.ts @@ -26,7 +26,10 @@ export class DashImportListCtrl { } var template = ` - + `; export function dashboardImportList() { diff --git a/public/app/features/datasources/edit_ctrl.js b/public/app/features/datasources/edit_ctrl.js index cbb3cfdd4c5..062cec6e5e9 100644 --- a/public/app/features/datasources/edit_ctrl.js +++ b/public/app/features/datasources/edit_ctrl.js @@ -40,7 +40,7 @@ function (angular, _, config) { return $q.when(null); } - return backendSrv.get('/api/datasources/plugins').then(function(plugins) { + return backendSrv.get('/api/org/plugins', {enabled: 1, type: 'datasource'}).then(function(plugins) { datasourceTypes = plugins; $scope.types = plugins; }); @@ -55,7 +55,9 @@ function (angular, _, config) { }; $scope.typeChanged = function() { - $scope.datasourceMeta = $scope.types[$scope.current.type]; + return backendSrv.get('/api/org/plugins/' + $scope.current.type + '/settings').then(function(pluginInfo) { + $scope.datasourceMeta = pluginInfo; + }); }; $scope.updateFrontendSettings = function() { diff --git a/public/app/features/datasources/partials/edit.html b/public/app/features/datasources/partials/edit.html index facddc498c9..005efab49d3 100644 --- a/public/app/features/datasources/partials/edit.html +++ b/public/app/features/datasources/partials/edit.html @@ -27,34 +27,36 @@ icon="icon-gf icon-gf-datasources">
Type
- +
+ - - - - - + + + + -
-
Testing....
-
Test results
-
-
{{testing.title}}
-
-
+
+
Testing....
+
Test results
+
+
{{testing.title}}
+
+
-
- - - - Cancel -
+ + +
+ + + + Cancel +
diff --git a/public/app/features/plugins/edit_ctrl.ts b/public/app/features/plugins/edit_ctrl.ts index 2c060c230de..f8e7c96792c 100644 --- a/public/app/features/plugins/edit_ctrl.ts +++ b/public/app/features/plugins/edit_ctrl.ts @@ -72,8 +72,6 @@ export class PluginEditCtrl { // Perform the core update procedure chain = chain.then(function() { var updateCmd = _.extend({ - pluginId: self.model.pluginId, - orgId: self.model.orgId, enabled: self.model.enabled, pinned: self.model.pinned, jsonData: self.model.jsonData, diff --git a/public/app/features/plugins/partials/edit.html b/public/app/features/plugins/partials/edit.html index 14e75cea15f..9bb9ebfdbaf 100644 --- a/public/app/features/plugins/partials/edit.html +++ b/public/app/features/plugins/partials/edit.html @@ -48,7 +48,7 @@ -
+
@@ -70,7 +70,7 @@
  • - {{page.name}} + {{page.name}}
  • diff --git a/public/app/features/plugins/partials/list.html b/public/app/features/plugins/partials/list.html index 2b2f9741be0..b00c280c43f 100644 --- a/public/app/features/plugins/partials/list.html +++ b/public/app/features/plugins/partials/list.html @@ -18,7 +18,7 @@ - + {{plugin.name}} @@ -30,7 +30,7 @@ Pinned - + Edit diff --git a/public/app/plugins/datasource/graphite/plugin.json b/public/app/plugins/datasource/graphite/plugin.json index d2836b2a107..b079ec320f2 100644 --- a/public/app/plugins/datasource/graphite/plugin.json +++ b/public/app/plugins/datasource/graphite/plugin.json @@ -3,7 +3,10 @@ "type": "datasource", "id": "graphite", - "defaultMatchFormat": "glob", + "includes": [ + {"type": "dashboard", "name": "Carbon Stats", "path": "dashboards/carbon_stats.json"} + ], + "metrics": true, "annotations": true }