Selaa lähdekoodia

feat(apps): auto update dashboard dashboards, #5529

Torkel Ödegaard 9 vuotta sitten
vanhempi
commit
b62f1f00cd

+ 14 - 4
pkg/models/plugin_settings.go

@@ -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 - 0
pkg/plugins/dashboards_updater.go

@@ -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)
+	}
+}

+ 2 - 0
pkg/plugins/plugins.go

@@ -77,6 +77,8 @@ func Init() error {
 	}
 
 	go StartPluginUpdateChecker()
+	go updateAppDashboards()
+
 	return nil
 }
 

+ 6 - 0
pkg/services/sqlstore/migrations/plugin_setting.go

@@ -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,
+	}))
+
 }

+ 21 - 4
pkg/services/sqlstore/plugin_setting.go

@@ -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
+
+	})
+}

+ 3 - 4
public/app/features/plugins/import_list/import_list.html

@@ -14,10 +14,9 @@
 					</span>
 				</td>
 				<td>
-					v{{dash.revision}}
-					<span ng-if="dash.installed">
-						&nbsp;(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">