mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
feat(apps): auto update dashboard dashboards, #5529
This commit is contained in:
parent
4545b4d323
commit
b62f1f00cd
@ -20,6 +20,7 @@ type PluginSetting struct {
|
||||
Pinned bool
|
||||
JsonData map[string]interface{}
|
||||
SecureJsonData SecureJsonData
|
||||
PluginVersion string
|
||||
|
||||
Created time.Time
|
||||
Updated time.Time
|
||||
@ -44,11 +45,19 @@ type UpdatePluginSettingCmd struct {
|
||||
Pinned bool `json:"pinned"`
|
||||
JsonData map[string]interface{} `json:"jsonData"`
|
||||
SecureJsonData map[string]string `json:"secureJsonData"`
|
||||
PluginVersion string `json:"version"`
|
||||
|
||||
PluginId string `json:"-"`
|
||||
OrgId int64 `json:"-"`
|
||||
}
|
||||
|
||||
// specific command, will only update version
|
||||
type UpdatePluginSettingVersionCmd struct {
|
||||
PluginVersion string
|
||||
PluginId string `json:"-"`
|
||||
OrgId int64 `json:"-"`
|
||||
}
|
||||
|
||||
func (cmd *UpdatePluginSettingCmd) GetEncryptedJsonData() SecureJsonData {
|
||||
encrypted := make(SecureJsonData)
|
||||
for key, data := range cmd.SecureJsonData {
|
||||
@ -65,10 +74,11 @@ type GetPluginSettingsQuery struct {
|
||||
}
|
||||
|
||||
type PluginSettingInfoDTO struct {
|
||||
OrgId int64
|
||||
PluginId string
|
||||
Enabled bool
|
||||
Pinned bool
|
||||
OrgId int64
|
||||
PluginId string
|
||||
Enabled bool
|
||||
Pinned bool
|
||||
PluginVersion string
|
||||
}
|
||||
|
||||
type GetPluginSettingByIdQuery struct {
|
||||
|
88
pkg/plugins/dashboards_updater.go
Normal file
88
pkg/plugins/dashboards_updater.go
Normal file
@ -0,0 +1,88 @@
|
||||
package plugins
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
m "github.com/grafana/grafana/pkg/models"
|
||||
)
|
||||
|
||||
func updateAppDashboards() {
|
||||
time.Sleep(time.Second * 1)
|
||||
|
||||
plog.Debug("Looking for App Dashboard Updates")
|
||||
|
||||
query := m.GetPluginSettingsQuery{OrgId: 0}
|
||||
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
plog.Error("Failed to get all plugin settings", "error", err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, pluginSetting := range query.Result {
|
||||
if appDef, exist := Apps[pluginSetting.PluginId]; exist {
|
||||
if appDef.Info.Version != pluginSetting.PluginVersion {
|
||||
handleAppPluginUpdated(appDef, pluginSetting.OrgId)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func autoUpdateAppDashboard(pluginDashInfo *PluginDashboardInfoDTO, orgId int64) error {
|
||||
if dash, err := loadPluginDashboard(pluginDashInfo.PluginId, pluginDashInfo.Path); err != nil {
|
||||
return err
|
||||
} else {
|
||||
plog.Info("Auto updating App dashboard", "dashboard", dash.Title, "newRev", pluginDashInfo.Revision, "oldRev", pluginDashInfo.ImportedRevision)
|
||||
updateCmd := ImportDashboardCommand{
|
||||
OrgId: orgId,
|
||||
PluginId: pluginDashInfo.PluginId,
|
||||
Overwrite: true,
|
||||
Dashboard: dash.Data,
|
||||
UserId: 0,
|
||||
Path: pluginDashInfo.Path,
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(&updateCmd); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func handleAppPluginUpdated(appDef *AppPlugin, orgId int64) {
|
||||
plog.Info("App update detected", "pluginId", appDef.Id)
|
||||
|
||||
// Get plugin dashboards
|
||||
if dashboards, err := GetPluginDashboards(orgId, appDef.Id); err != nil {
|
||||
plog.Error("Failed to load app dashboards", "error", err)
|
||||
return
|
||||
} else {
|
||||
// Update dashboards with updated revisions
|
||||
for _, dash := range dashboards {
|
||||
if dash.ImportedRevision != dash.Revision {
|
||||
if err := autoUpdateAppDashboard(dash, orgId); err != nil {
|
||||
plog.Error("Failed to auto update app dashboard", "pluginId", appDef.Id, "error", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// update version in plugin_setting table to mark that we have processed the update
|
||||
query := m.GetPluginSettingByIdQuery{PluginId: appDef.Id, OrgId: orgId}
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
plog.Error("Failed to read plugin setting by id", "error", err)
|
||||
return
|
||||
}
|
||||
|
||||
appSetting := query.Result
|
||||
cmd := m.UpdatePluginSettingVersionCmd{
|
||||
OrgId: appSetting.OrgId,
|
||||
PluginId: appSetting.PluginId,
|
||||
PluginVersion: appDef.Info.Version,
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
plog.Error("Failed to update plugin setting version", "error", err)
|
||||
}
|
||||
}
|
@ -77,6 +77,8 @@ func Init() error {
|
||||
}
|
||||
|
||||
go StartPluginUpdateChecker()
|
||||
go updateAppDashboards()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -26,4 +26,10 @@ func addAppSettingsMigration(mg *Migrator) {
|
||||
|
||||
//------- indexes ------------------
|
||||
addTableIndicesMigrations(mg, "v1", pluginSettingTable)
|
||||
|
||||
// add column to store installed version
|
||||
mg.AddMigration("Add column plugin_version to plugin_settings", NewAddColumnMigration(pluginSettingTable, &Column{
|
||||
Name: "plugin_version", Type: DB_NVarchar, Nullable: true, Length: 50,
|
||||
}))
|
||||
|
||||
}
|
||||
|
@ -13,14 +13,20 @@ func init() {
|
||||
bus.AddHandler("sql", GetPluginSettings)
|
||||
bus.AddHandler("sql", GetPluginSettingById)
|
||||
bus.AddHandler("sql", UpdatePluginSetting)
|
||||
bus.AddHandler("sql", UpdatePluginSettingVersion)
|
||||
}
|
||||
|
||||
func GetPluginSettings(query *m.GetPluginSettingsQuery) error {
|
||||
sql := `SELECT org_id, plugin_id, enabled, pinned
|
||||
FROM plugin_setting
|
||||
WHERE org_id=?`
|
||||
sql := `SELECT org_id, plugin_id, enabled, pinned, plugin_version
|
||||
FROM plugin_setting `
|
||||
params := make([]interface{}, 0)
|
||||
|
||||
sess := x.Sql(sql, query.OrgId)
|
||||
if query.OrgId != 0 {
|
||||
sql += "WHERE org_id=?"
|
||||
params = append(params, query.OrgId)
|
||||
}
|
||||
|
||||
sess := x.Sql(sql, params...)
|
||||
query.Result = make([]*m.PluginSettingInfoDTO, 0)
|
||||
return sess.Find(&query.Result)
|
||||
}
|
||||
@ -51,6 +57,7 @@ func UpdatePluginSetting(cmd *m.UpdatePluginSettingCmd) error {
|
||||
Enabled: cmd.Enabled,
|
||||
Pinned: cmd.Pinned,
|
||||
JsonData: cmd.JsonData,
|
||||
PluginVersion: cmd.PluginVersion,
|
||||
SecureJsonData: cmd.GetEncryptedJsonData(),
|
||||
Created: time.Now(),
|
||||
Updated: time.Now(),
|
||||
@ -65,8 +72,18 @@ func UpdatePluginSetting(cmd *m.UpdatePluginSettingCmd) error {
|
||||
pluginSetting.Enabled = cmd.Enabled
|
||||
pluginSetting.JsonData = cmd.JsonData
|
||||
pluginSetting.Pinned = cmd.Pinned
|
||||
pluginSetting.PluginVersion = cmd.PluginVersion
|
||||
_, err = sess.Id(pluginSetting.Id).Update(&pluginSetting)
|
||||
return err
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func UpdatePluginSettingVersion(cmd *m.UpdatePluginSettingVersionCmd) error {
|
||||
return inTransaction2(func(sess *session) error {
|
||||
|
||||
_, err := sess.Exec("UPDATE plugin_setting SET plugin_version=? WHERE org_id=? AND plugin_id=?", cmd.PluginVersion, cmd.OrgId, cmd.PluginId)
|
||||
return err
|
||||
|
||||
})
|
||||
}
|
||||
|
@ -14,10 +14,9 @@
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
v{{dash.revision}}
|
||||
<span ng-if="dash.installed">
|
||||
(Imported v{{dash.importedRevision}})
|
||||
<span>
|
||||
<span ng-if="dash.imported" bs-tooltip='"Imported revision:" + dash.importedRevision'>
|
||||
Revision: {{dash.revision}}
|
||||
<span>
|
||||
</td>
|
||||
<td style="text-align: right">
|
||||
<button class="btn btn-secondary" ng-click="ctrl.import(dash, false)" ng-show="!dash.imported">
|
||||
|
Loading…
Reference in New Issue
Block a user