mirror of
https://github.com/komodorio/helm-dashboard.git
synced 2026-03-24 11:48:04 +00:00
Check for newer version available (#47)
* Add helm version requirement notes * Check for newer version and offer upgrade * fix lint
This commit is contained in:
2
go.mod
2
go.mod
@@ -4,10 +4,10 @@ go 1.18
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/gin-gonic/gin v1.8.1
|
github.com/gin-gonic/gin v1.8.1
|
||||||
|
github.com/hashicorp/go-version v1.6.0
|
||||||
github.com/hexops/gotextdiff v1.0.3
|
github.com/hexops/gotextdiff v1.0.3
|
||||||
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8
|
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8
|
||||||
github.com/sirupsen/logrus v1.9.0
|
github.com/sirupsen/logrus v1.9.0
|
||||||
github.com/toqueteos/webbrowser v1.2.0
|
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
helm.sh/helm/v3 v3.9.4
|
helm.sh/helm/v3 v3.9.4
|
||||||
k8s.io/apimachinery v0.25.0-alpha.2
|
k8s.io/apimachinery v0.25.0-alpha.2
|
||||||
|
|||||||
4
go.sum
4
go.sum
@@ -31,6 +31,8 @@ github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN
|
|||||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
|
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
|
||||||
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
|
github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek=
|
||||||
|
github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||||
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
|
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
|
||||||
github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
|
github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
|
||||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||||
@@ -78,8 +80,6 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
|||||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
|
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
|
||||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
github.com/toqueteos/webbrowser v1.2.0 h1:tVP/gpK69Fx+qMJKsLE7TD8LuGWPnEV71wBN9rrstGQ=
|
|
||||||
github.com/toqueteos/webbrowser v1.2.0/go.mod h1:XWoZq4cyp9WeUeak7w7LXRUQf1F1ATJMir8RTqb4ayM=
|
|
||||||
github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M=
|
github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M=
|
||||||
github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0=
|
github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0=
|
||||||
github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY=
|
github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY=
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ func contextSetter(data *subproc.DataLayer) gin.HandlerFunc {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRouter(abortWeb utils.ControlChan, data *subproc.DataLayer, version string) *gin.Engine {
|
func NewRouter(abortWeb utils.ControlChan, data *subproc.DataLayer) *gin.Engine {
|
||||||
var api *gin.Engine
|
var api *gin.Engine
|
||||||
if os.Getenv("DEBUG") == "" {
|
if os.Getenv("DEBUG") == "" {
|
||||||
api = gin.New()
|
api = gin.New()
|
||||||
@@ -58,12 +58,12 @@ func NewRouter(abortWeb utils.ControlChan, data *subproc.DataLayer, version stri
|
|||||||
api.Use(errorHandler)
|
api.Use(errorHandler)
|
||||||
|
|
||||||
configureStatic(api)
|
configureStatic(api)
|
||||||
configureRoutes(abortWeb, data, api, version)
|
configureRoutes(abortWeb, data, api)
|
||||||
|
|
||||||
return api
|
return api
|
||||||
}
|
}
|
||||||
|
|
||||||
func configureRoutes(abortWeb utils.ControlChan, data *subproc.DataLayer, api *gin.Engine, version string) {
|
func configureRoutes(abortWeb utils.ControlChan, data *subproc.DataLayer, api *gin.Engine) {
|
||||||
// server shutdown handler
|
// server shutdown handler
|
||||||
api.DELETE("/", func(c *gin.Context) {
|
api.DELETE("/", func(c *gin.Context) {
|
||||||
abortWeb <- struct{}{}
|
abortWeb <- struct{}{}
|
||||||
@@ -71,7 +71,7 @@ func configureRoutes(abortWeb utils.ControlChan, data *subproc.DataLayer, api *g
|
|||||||
})
|
})
|
||||||
|
|
||||||
api.GET("/status", func(c *gin.Context) {
|
api.GET("/status", func(c *gin.Context) {
|
||||||
c.String(http.StatusOK, version)
|
c.IndentedJSON(http.StatusOK, data.VersionInfo)
|
||||||
})
|
})
|
||||||
|
|
||||||
configureHelms(api.Group("/api/helm"), data)
|
configureHelms(api.Group("/api/helm"), data)
|
||||||
|
|||||||
@@ -2,13 +2,16 @@ package dashboard
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/json"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/hashicorp/go-version"
|
||||||
"github.com/komodorio/helm-dashboard/pkg/dashboard/scanners"
|
"github.com/komodorio/helm-dashboard/pkg/dashboard/scanners"
|
||||||
"github.com/komodorio/helm-dashboard/pkg/dashboard/subproc"
|
"github.com/komodorio/helm-dashboard/pkg/dashboard/subproc"
|
||||||
"github.com/komodorio/helm-dashboard/pkg/dashboard/utils"
|
"github.com/komodorio/helm-dashboard/pkg/dashboard/utils"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func StartServer(version string) (string, utils.ControlChan) {
|
func StartServer(version string) (string, utils.ControlChan) {
|
||||||
@@ -19,6 +22,9 @@ func StartServer(version string) (string, utils.ControlChan) {
|
|||||||
os.Exit(1) // TODO: propagate error instead?
|
os.Exit(1) // TODO: propagate error instead?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data.VersionInfo = &subproc.VersionInfo{CurVer: version}
|
||||||
|
go checkUpgrade(data.VersionInfo)
|
||||||
|
|
||||||
discoverScanners(&data)
|
discoverScanners(&data)
|
||||||
|
|
||||||
address := os.Getenv("HD_BIND")
|
address := os.Getenv("HD_BIND")
|
||||||
@@ -33,7 +39,7 @@ func StartServer(version string) (string, utils.ControlChan) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
abort := make(utils.ControlChan)
|
abort := make(utils.ControlChan)
|
||||||
api := NewRouter(abort, &data, version)
|
api := NewRouter(abort, &data)
|
||||||
done := startBackgroundServer(address, api, abort)
|
done := startBackgroundServer(address, api, abort)
|
||||||
|
|
||||||
return "http://" + address, done
|
return "http://" + address, done
|
||||||
@@ -75,3 +81,44 @@ func discoverScanners(data *subproc.DataLayer) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func checkUpgrade(d *subproc.VersionInfo) {
|
||||||
|
url := "https://api.github.com/repos/komodorio/helm-dashboard/releases/latest"
|
||||||
|
type GHRelease struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var myClient = &http.Client{Timeout: 5 * time.Second}
|
||||||
|
r, err := myClient.Get(url)
|
||||||
|
if err != nil {
|
||||||
|
log.Warnf("Failed to check for new version: %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer r.Body.Close()
|
||||||
|
|
||||||
|
target := new(GHRelease)
|
||||||
|
err = json.NewDecoder(r.Body).Decode(target)
|
||||||
|
if err != nil {
|
||||||
|
log.Warnf("Failed to decode new release version: %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
d.LatestVer = target.Name
|
||||||
|
|
||||||
|
v1, err := version.NewVersion(d.CurVer)
|
||||||
|
if err != nil {
|
||||||
|
log.Warnf("Failed to parse version: %s", err)
|
||||||
|
v1 = &version.Version{}
|
||||||
|
}
|
||||||
|
|
||||||
|
v2, err := version.NewVersion(d.LatestVer)
|
||||||
|
if err != nil {
|
||||||
|
log.Warnf("Failed to parse version: %s", err)
|
||||||
|
} else {
|
||||||
|
if v1.LessThan(v2) {
|
||||||
|
log.Warnf("Newer Helm Dashboard version is available: %s", d.LatestVer)
|
||||||
|
log.Warnf("Upgrade instructions: https://github.com/komodorio/helm-dashboard#installing")
|
||||||
|
} else {
|
||||||
|
log.Debugf("Got latest version from GH: %s", d.LatestVer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,8 +5,8 @@
|
|||||||
})(window,document,'script','https://www.datadoghq-browser-agent.com/datadog-rum-v4.js','DD_RUM')
|
})(window,document,'script','https://www.datadoghq-browser-agent.com/datadog-rum-v4.js','DD_RUM')
|
||||||
DD_RUM.onReady(function() {
|
DD_RUM.onReady(function() {
|
||||||
const xhr = new XMLHttpRequest();
|
const xhr = new XMLHttpRequest();
|
||||||
xhr.onreadystatechange = function() {
|
xhr.onload = function() {
|
||||||
const version = xhr.responseText;
|
const version = JSON.parse(xhr.responseText).VerCur;
|
||||||
if (xhr.readyState === XMLHttpRequest.DONE && version!=="dev") {
|
if (xhr.readyState === XMLHttpRequest.DONE && version!=="dev") {
|
||||||
DD_RUM.init({
|
DD_RUM.init({
|
||||||
clientToken: 'pub16d64cd1c00cf073ce85af914333bf72',
|
clientToken: 'pub16d64cd1c00cf073ce85af914333bf72',
|
||||||
|
|||||||
@@ -54,8 +54,11 @@
|
|||||||
<a class="nav-link px-3 section-repo">Repository</a>
|
<a class="nav-link px-3 section-repo">Repository</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item dropdown">
|
<li class="nav-item dropdown">
|
||||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown"
|
<a class="nav-link dropdown-toggle" role="button" data-bs-toggle="dropdown"
|
||||||
aria-expanded="false">
|
aria-expanded="false">
|
||||||
|
<span class="position-absolute top-50 start-0 translate-middle p-1 bg-danger border border-light rounded-circle new-version-pill display-none">
|
||||||
|
<span class="visually-hidden">New version</span>
|
||||||
|
</span>
|
||||||
Help
|
Help
|
||||||
</a>
|
</a>
|
||||||
<ul class="dropdown-menu fs-80">
|
<ul class="dropdown-menu fs-80">
|
||||||
@@ -67,6 +70,13 @@
|
|||||||
<hr class="dropdown-divider">
|
<hr class="dropdown-divider">
|
||||||
</li>
|
</li>
|
||||||
<li><a class="dropdown-item disabled" href="#">Version <span id="toolVersion"></span></a></li>
|
<li><a class="dropdown-item disabled" href="#">Version <span id="toolVersion"></span></a></li>
|
||||||
|
<li class="">
|
||||||
|
<a class="dropdown-item position-relative" href="https://github.com/komodorio/helm-dashboard#installing" target="_blank">
|
||||||
|
<span class="position-absolute top-50 start-0 translate-middle p-1 bg-danger border border-light rounded-circle new-version-pill display-none">
|
||||||
|
<span class="visually-hidden">New version</span>
|
||||||
|
</span>
|
||||||
|
Upgrade to <span id="toolVersionUpgrade"></span>
|
||||||
|
</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ $(function () {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
$.get("/status").fail(function (xhr) {
|
$.getJSON("/status").fail(function (xhr) {
|
||||||
reportError("Failed to get tool version", xhr)
|
reportError("Failed to get tool version", xhr)
|
||||||
}).done(function (data) {
|
}).done(function (data) {
|
||||||
fillToolVersion(data)
|
fillToolVersion(data)
|
||||||
@@ -51,18 +51,20 @@ function initView() {
|
|||||||
$("#topNav ul a").click(function () {
|
$("#topNav ul a").click(function () {
|
||||||
const self = $(this)
|
const self = $(this)
|
||||||
|
|
||||||
|
if (self.hasClass("section-repo")) {
|
||||||
|
setHashParam("section", "repository")
|
||||||
|
} else if (self.hasClass("section-installed")) {
|
||||||
|
setHashParam("section", null)
|
||||||
|
} else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
$("#topNav ul a").removeClass("active")
|
$("#topNav ul a").removeClass("active")
|
||||||
|
|
||||||
const ctx = getHashParam("context")
|
const ctx = getHashParam("context")
|
||||||
setHashParam(null, null)
|
setHashParam(null, null)
|
||||||
setHashParam("context", ctx)
|
setHashParam("context", ctx)
|
||||||
|
|
||||||
if (self.hasClass("section-repo")) {
|
|
||||||
setHashParam("section", "repository")
|
|
||||||
} else {
|
|
||||||
setHashParam("section", null)
|
|
||||||
}
|
|
||||||
|
|
||||||
initView()
|
initView()
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -192,6 +194,14 @@ $(".bi-power").click(function () {
|
|||||||
})
|
})
|
||||||
|
|
||||||
function isNewerVersion(oldVer, newVer) {
|
function isNewerVersion(oldVer, newVer) {
|
||||||
|
if (oldVer && oldVer[0] === 'v') {
|
||||||
|
oldVer = oldVer.substring(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newVer && newVer[0] === 'v') {
|
||||||
|
newVer = newVer.substring(1)
|
||||||
|
}
|
||||||
|
|
||||||
const oldParts = oldVer.split('.')
|
const oldParts = oldVer.split('.')
|
||||||
const newParts = newVer.split('.')
|
const newParts = newVer.split('.')
|
||||||
for (let i = 0; i < newParts.length; i++) {
|
for (let i = 0; i < newParts.length; i++) {
|
||||||
@@ -204,5 +214,9 @@ function isNewerVersion(oldVer, newVer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function fillToolVersion(data) {
|
function fillToolVersion(data) {
|
||||||
$("#toolVersion").append($('<a>' + data + '</a>'))
|
$("#toolVersion").text(data.CurVer)
|
||||||
|
if (isNewerVersion(data.CurVer, data.LatestVer)) {
|
||||||
|
$("#toolVersionUpgrade").text(data.LatestVer)
|
||||||
|
$(".new-version-pill").show()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -25,6 +25,12 @@ type DataLayer struct {
|
|||||||
Helm string
|
Helm string
|
||||||
Kubectl string
|
Kubectl string
|
||||||
Scanners []Scanner
|
Scanners []Scanner
|
||||||
|
VersionInfo *VersionInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
type VersionInfo struct {
|
||||||
|
CurVer string
|
||||||
|
LatestVer string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *DataLayer) runCommand(cmd ...string) (string, error) {
|
func (d *DataLayer) runCommand(cmd ...string) (string, error) {
|
||||||
|
|||||||
Reference in New Issue
Block a user