/
check.go
146 lines (112 loc) · 3.97 KB
/
check.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
// (C) Copyright 2019 Hewlett Packard Enterprise Development LP.
package update
import (
"fmt"
"os"
"runtime"
"strings"
gover "github.com/hashicorp/go-version"
"github.com/sirupsen/logrus"
)
// CheckResponse is a response for a Check request.
type CheckResponse struct {
// Remote repo has a newer version than the running version
UpdateAvailable bool
// Latest version available in remote repository
RemoteVersion string
// Messagse about the latest updated
Message string
// URL where the update can be downloaded
URL string
// If the download has been signed, this is the public key
// that can be used to verify the signature
PublicKey []byte
// SHA265 Has of the download that can be used to validate
// the integrity of the file after it was downloaded
CheckSum []byte
}
type remoteResponse struct {
version *gover.Version
message string
updateURL string
publicKey []byte
checkSum []byte
}
type source interface {
validate() error
get() (*remoteResponse, error)
}
// EnvDisableUpdateCheck is an environmental variable to disable remote
// http request to check if a newer version of the CLI is available
const EnvDisableUpdateCheck = "HPECLI_DISABLE_UPDATE_CHECK"
// json file that describes the latest release version. Should be updated when new versions are published
// can alternatively change to using github tags once we real releases
const versionHost = "raw.githubusercontent.com"
const versionPath = "/HewlettPackard/hpecli/master/site/published-version.json"
var versionURL = fmt.Sprintf("https://%s%s", versionHost, versionPath)
var cacheResponse *CheckResponse
// CheckForUpdate returns data about the availability of an updated version of the CLI
func CheckForUpdate(localVersion string) (*CheckResponse, error) {
logrus.Debug("Local version is: " + localVersion)
logrus.Debug("Checking for a newer version at: " + versionURL)
res, err := checkUpdate(&jsonSource{url: versionURL}, localVersion)
if err != nil {
logrus.Debug("Unable to determine if a new version of the CLI is available")
logrus.Debugf("Error: %v", err)
return &CheckResponse{}, err
}
logrus.Debugf("%#v", res)
return res, nil
}
// Check fetches last version information from its source
// and compares with target and return result (CheckResponse).
func checkUpdate(s source, lVersion string) (*CheckResponse, error) {
// don't check if env var is setup to skip
if os.Getenv(EnvDisableUpdateCheck) != "" {
logrus.Debugf("%s set. Not performing remote check", EnvDisableUpdateCheck)
return &CheckResponse{}, nil
}
// Since the CLI is a short-lived process cache a copy and
// return the cached copy if we have already retrieved the
// results this session.
if cacheResponse != nil {
logrus.Debug("cacheResponse present. Not making additional remote check")
return cacheResponse, nil
}
localVersion, err := gover.NewVersion(lVersion)
if err != nil {
return nil, fmt.Errorf("failed to parse %s, %s", lVersion, err.Error())
}
if err = s.validate(); err != nil {
return nil, err
}
resp, err := s.get()
if err != nil {
return nil, err
}
var updateAvailable bool
// If target > current, then update is available
if resp.version.GreaterThan(localVersion) {
updateAvailable = true
}
// retrieve GOOS from runtime GO variables
logrus.Debugf("Detected operating system: %v", runtime.GOOS)
// Substitute {{$GOOS}} with osenv in updateURL
resp.updateURL = strings.Replace(resp.updateURL, "{{$GOOS}}", runtime.GOOS, 1)
// Windows uses a .exe filename while linux and MacOs don't
var dotexe string = ""
if runtime.GOOS == "windows" {
dotexe = ".exe"
}
// Substitute {{$EXE}} with dotexe in updateURL
resp.updateURL = strings.Replace(resp.updateURL, "{{$EXE}}", dotexe, 1)
cacheResponse = &CheckResponse{
UpdateAvailable: updateAvailable,
RemoteVersion: resp.version.String(),
Message: resp.message,
URL: resp.updateURL,
PublicKey: resp.publicKey,
CheckSum: resp.checkSum,
}
return cacheResponse, nil
}