diff --git a/conf/defaults.ini b/conf/defaults.ini index 851c88efc7c..6f63891d1ee 100644 --- a/conf/defaults.ini +++ b/conf/defaults.ini @@ -111,6 +111,13 @@ gc_interval_time = 86400 # Change this option to false to disable reporting. reporting_enabled = true +# Set to false to disable all checks to https://grafana.net +# for new vesions (grafana itself and plugins), check is used +# in some UI views to notify that grafana or plugin update exists +# This option does not cause any auto updates, nor send any information +# only a GET request to http://grafana.net to get latest versions +check_for_updates = true + # Google Analytics universal tracking code, only enabled if you specify an id here google_analytics_ua_id = diff --git a/conf/sample.ini b/conf/sample.ini index b875cbda093..4ab923c1376 100644 --- a/conf/sample.ini +++ b/conf/sample.ini @@ -100,6 +100,13 @@ # Change this option to false to disable reporting. ;reporting_enabled = true +# Set to false to disable all checks to https://grafana.net +# for new vesions (grafana itself and plugins), check is used +# in some UI views to notify that grafana or plugin update exists +# This option does not cause any auto updates, nor send any information +# only a GET request to http://grafana.net to get latest versions +check_for_updates = true + # Google Analytics universal tracking code, only enabled if you specify an id here ;google_analytics_ua_id = diff --git a/latest.json b/latest.json index 79eb42a8527..6bb5ba3e411 100644 --- a/latest.json +++ b/latest.json @@ -1,3 +1,4 @@ { - "version": "2.1.1" + "stable": "2.6.0", + "testing": "3.0.0-beta1" } diff --git a/pkg/api/dtos/plugins.go b/pkg/api/dtos/plugins.go index 53c911c10fa..ba34b851c08 100644 --- a/pkg/api/dtos/plugins.go +++ b/pkg/api/dtos/plugins.go @@ -18,12 +18,14 @@ type PluginSetting struct { } type PluginListItem struct { - 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"` + 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"` + LastesVersion string `json:"latestVersion"` + HasUpdate bool `json:"hasUpdate"` } type PluginList []PluginListItem diff --git a/pkg/plugins/models.go b/pkg/plugins/models.go index 30f794285e1..6b62847ed45 100644 --- a/pkg/plugins/models.go +++ b/pkg/plugins/models.go @@ -44,6 +44,9 @@ type PluginBase struct { PluginDir string `json:"-"` DefaultNavUrl string `json:"-"` + GrafanaNetVersion string `json:"-"` + GrafanaNetHasUpdate bool `json:"-"` + // cache for readme file contents Readme []byte `json:"-"` } diff --git a/pkg/plugins/plugins.go b/pkg/plugins/plugins.go index 0d69d5745b9..a6fc2d60b78 100644 --- a/pkg/plugins/plugins.go +++ b/pkg/plugins/plugins.go @@ -22,6 +22,9 @@ var ( Apps map[string]*AppPlugin Plugins map[string]*PluginBase PluginTypes map[string]interface{} + + GrafanaLatestVersion string + GrafanaHasUpdate bool ) type PluginScanner struct { @@ -70,6 +73,7 @@ func Init() error { app.initApp() } + StartPluginUpdateChecker() return nil } diff --git a/pkg/plugins/update_checker.go b/pkg/plugins/update_checker.go new file mode 100644 index 00000000000..7e8025d2987 --- /dev/null +++ b/pkg/plugins/update_checker.go @@ -0,0 +1,109 @@ +package plugins + +import ( + "encoding/json" + "io/ioutil" + "net/http" + "strings" + "time" + + "github.com/grafana/grafana/pkg/log" + "github.com/grafana/grafana/pkg/setting" +) + +type GrafanaNetPlugins struct { + Plugins []GrafanaNetPlugin `json:"plugins"` +} + +type GrafanaNetPlugin struct { + Id string `json:"id"` + Versions []GrafanaNetPluginVersion `json:"versions"` +} + +type GrafanaNetPluginVersion struct { + Version string `json:"version"` +} + +type GithubLatest struct { + Stable string `json:"stable"` + Testing string `json:"testing"` +} + +func StartPluginUpdateChecker() { + if !setting.CheckForUpdates { + return + } + + ticker := time.NewTicker(time.Second * 24) + for { + select { + case <-ticker.C: + checkForUpdates() + } + } +} + +func checkForUpdates() { + log.Trace("Checking for updates") + + client := http.Client{Timeout: time.Duration(5 * time.Second)} + resp, err := client.Get("https://grafana.net/api/plugins/repo?grafanaVersion=" + setting.BuildVersion) + + if err != nil { + log.Trace("Failed to get plugins repo from grafana.net, %v", err.Error()) + return + } + + defer resp.Body.Close() + + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + log.Trace("Update check failed, reading response from grafana.net, %v", err.Error()) + return + } + + var data GrafanaNetPlugins + err = json.Unmarshal(body, &data) + if err != nil { + log.Trace("Failed to unmarshal plugin repo, reading response from grafana.net, %v", err.Error()) + return + } + + for _, plug := range Plugins { + for _, gplug := range data.Plugins { + if gplug.Id == plug.Id { + if len(gplug.Versions) > 0 { + plug.GrafanaNetVersion = gplug.Versions[0].Version + plug.GrafanaNetHasUpdate = plug.Info.Version != plug.GrafanaNetVersion + } + } + } + } + + resp2, err := client.Get("https://raw.githubusercontent.com/grafana/grafana/master/latest.json") + if err != nil { + log.Trace("Failed to get lates.json repo from github: %v", err.Error()) + return + } + + defer resp2.Body.Close() + body, err = ioutil.ReadAll(resp2.Body) + if err != nil { + log.Trace("Update check failed, reading response from github.net, %v", err.Error()) + return + } + + var githubLatest GithubLatest + err = json.Unmarshal(body, &githubLatest) + if err != nil { + log.Trace("Failed to unmarshal github latest, reading response from github: %v", err.Error()) + return + } + + if strings.Contains(setting.BuildVersion, "-") { + GrafanaLatestVersion = githubLatest.Testing + } else { + GrafanaLatestVersion = githubLatest.Stable + GrafanaHasUpdate = githubLatest.Stable != setting.BuildVersion + } +} diff --git a/pkg/setting/setting.go b/pkg/setting/setting.go index b8e8d7f7fcf..2d1bad945eb 100644 --- a/pkg/setting/setting.go +++ b/pkg/setting/setting.go @@ -124,6 +124,7 @@ var ( appliedEnvOverrides []string ReportingEnabled bool + CheckForUpdates bool GoogleAnalyticsId string GoogleTagManagerId string @@ -475,6 +476,7 @@ func NewConfigContext(args *CommandLineArgs) error { analytics := Cfg.Section("analytics") ReportingEnabled = analytics.Key("reporting_enabled").MustBool(true) + CheckForUpdates = analytics.Key("check_for_updates").MustBool(true) GoogleAnalyticsId = analytics.Key("google_analytics_ua_id").String() GoogleTagManagerId = analytics.Key("google_tag_manager_id").String()