Files
steampipe/task/version_checker.go
Binaek Sarkar 9a0c660547 sorts plugin updates alphabetically. Closes #339 (#348)
* removing unused code

* correcting comment and removing redundant declaration

* sort plugins by name in notification

* review changes
2021-04-08 09:47:44 +01:00

149 lines
3.9 KiB
Go

package task
import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/url"
"os"
"github.com/fatih/color"
SemVer "github.com/hashicorp/go-version"
"github.com/olekukonko/tablewriter"
"github.com/spf13/viper"
"github.com/turbot/steampipe/constants"
"github.com/turbot/steampipe/utils"
"github.com/turbot/steampipe/version"
)
// the current version of the Steampipe CLI application
var currentVersion = version.String()
type versionCheckResponse struct {
NewVersion string `json:"latest_version,omitempty"` // `json:"current_version"`
DownloadURL string `json:"download_url,omitempty"` // `json:"download_url"`
ChangelogURL string `json:"html,omitempty"` // `json:"changelog_url"`
Alerts []*string `json:"alerts,omitempty"`
}
// VersionChecker :: the version checker struct composition container.
// This MUST not be instantiated manually. Use `CreateVersionChecker` instead
type versionChecker struct {
checkResult *versionCheckResponse // a channel to store the HTTP response
signature string // flags whether update check should be done
}
// check if there is a new version
func checkSteampipeVersion(id string) {
if !viper.GetBool(constants.ArgUpdateCheck) {
return
}
v := new(versionChecker)
v.signature = id
v.GetVersionResp()
v.Notify()
}
// GetVersionResp :: Communicates with the Turbot Artifacts Server retrieves
// the latest released version
func (c *versionChecker) GetVersionResp() {
c.doCheckRequest()
}
// Notify :: Notifies the user if a new version is available
func (c *versionChecker) Notify() {
info := c.checkResult
if info == nil {
return
}
if info.NewVersion == "" {
return
}
newVersion, err := SemVer.NewVersion(info.NewVersion)
if err != nil {
return
}
currentVersion, err := SemVer.NewVersion(currentVersion)
if err != nil {
fmt.Println(fmt.Errorf("there's something wrong with the Current Version"))
fmt.Println(err)
}
if newVersion.GreaterThan(currentVersion) {
displayUpdateNotification(info, currentVersion, newVersion)
}
}
func displayUpdateNotification(info *versionCheckResponse, currentVersion *SemVer.Version, newVersion *SemVer.Version) {
var downloadURLColor = color.New(color.FgYellow)
var notificationLines = [][]string{
{""},
{fmt.Sprintf("A new version of Steampipe is available! %s → %s", constants.Bold(currentVersion), constants.Bold(newVersion))},
{fmt.Sprintf("You can update by downloading from %s", downloadURLColor.Sprint("https://steampipe.io/downloads"))},
{""},
}
table := tablewriter.NewWriter(os.Stdout)
table.SetHeader([]string{}) // no headers please
table.SetAlignment(tablewriter.ALIGN_LEFT) // we align to the left
table.SetAutoWrapText(false) // let's not wrap the text
table.SetBorder(true) // there needs to be a border to give the dialog feel
table.AppendBulk(notificationLines) // Add Bulk Data
fmt.Println()
table.Render()
fmt.Println()
}
func (c *versionChecker) doCheckRequest() {
payload := utils.BuildRequestPayload(c.signature, map[string]interface{}{})
sendRequestTo := c.versionCheckURL()
resp, err := utils.SendRequest(c.signature, "POST", sendRequestTo, payload)
if err != nil {
return
}
bodyBytes, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
bodyString := string(bodyBytes)
defer resp.Body.Close()
if resp.StatusCode == 204 {
return
}
if resp.StatusCode != 200 {
log.Printf("[DEBUG] Unknown response during version check: %d\n", resp.StatusCode)
return
}
c.checkResult = c.decodeResult(bodyString)
}
func (c *versionChecker) decodeResult(body string) *versionCheckResponse {
var result versionCheckResponse
if err := json.Unmarshal([]byte(body), &result); err != nil {
return nil
}
return &result
}
func (c *versionChecker) versionCheckURL() url.URL {
var u url.URL
//https://hub.steampipe.io/api/cli/version/latest
u.Scheme = "https"
u.Host = "hub.steampipe.io"
u.Path = "api/cli/version/latest"
return u
}