mirror of https://github.com/minio/minio.git
mainUpdate: refactor to handle quiet flag properly (#3744)
This commit is contained in:
parent
c6e76160ad
commit
602dac8773
|
@ -145,14 +145,13 @@ func checkMainSyntax(c *cli.Context) {
|
||||||
func checkUpdate() {
|
func checkUpdate() {
|
||||||
// Do not print update messages, if quiet flag is set.
|
// Do not print update messages, if quiet flag is set.
|
||||||
if !globalQuiet {
|
if !globalQuiet {
|
||||||
updateMsg, _, err := getReleaseUpdate(minioUpdateStableURL, 1*time.Second)
|
older, downloadURL, err := getUpdateInfo(1 * time.Second)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Ignore any errors during getReleaseUpdate(), possibly
|
// Its OK to ignore any errors during getUpdateInfo() here.
|
||||||
// because of network errors.
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if updateMsg.Update {
|
if older > time.Duration(0) {
|
||||||
console.Println(updateMsg)
|
console.Println(colorizeUpdateMessage(downloadURL, older))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Minio Cloud Storage, (C) 2015 Minio, Inc.
|
* Minio Cloud Storage, (C) 2015, 2016, 2017 Minio, Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -18,7 +18,7 @@ package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
@ -36,7 +36,16 @@ var updateCmd = cli.Command{
|
||||||
Name: "update",
|
Name: "update",
|
||||||
Usage: "Check for a new software update.",
|
Usage: "Check for a new software update.",
|
||||||
Action: mainUpdate,
|
Action: mainUpdate,
|
||||||
Flags: globalFlags,
|
Flags: []cli.Flag{
|
||||||
|
cli.BoolFlag{
|
||||||
|
Name: "help, h",
|
||||||
|
Usage: "Show this help.",
|
||||||
|
},
|
||||||
|
cli.BoolFlag{
|
||||||
|
Name: "quiet",
|
||||||
|
Usage: "Disable any update messages.",
|
||||||
|
},
|
||||||
|
},
|
||||||
CustomHelpTemplate: `Name:
|
CustomHelpTemplate: `Name:
|
||||||
minio {{.Name}} - {{.Usage}}
|
minio {{.Name}} - {{.Usage}}
|
||||||
|
|
||||||
|
@ -46,238 +55,215 @@ USAGE:
|
||||||
FLAGS:
|
FLAGS:
|
||||||
{{range .Flags}}{{.}}
|
{{range .Flags}}{{.}}
|
||||||
{{end}}
|
{{end}}
|
||||||
EXAMPLES:
|
EXIT STATUS:
|
||||||
1. Check for any new official release.
|
0 - You are already running the most recent version.
|
||||||
$ minio {{.Name}}
|
1 - New update is available.
|
||||||
`,
|
-1 - Error in getting update information.
|
||||||
|
|
||||||
|
VERSION:
|
||||||
|
` + Version + `{{"\n"}}`,
|
||||||
}
|
}
|
||||||
|
|
||||||
// update URL endpoints.
|
const releaseTagTimeLayout = "2006-01-02T15-04-05Z"
|
||||||
const (
|
|
||||||
minioUpdateStableURL = "https://dl.minio.io/server/minio/release"
|
|
||||||
)
|
|
||||||
|
|
||||||
// updateMessage container to hold update messages.
|
const minioReleaseURL = "https://dl.minio.io/server/minio/release/" + runtime.GOOS + "-" + runtime.GOARCH + "/"
|
||||||
type updateMessage struct {
|
|
||||||
Update bool `json:"update"`
|
|
||||||
Download string `json:"downloadURL"`
|
|
||||||
NewerThan time.Duration `json:"newerThan"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// String colorized update message.
|
func getCurrentReleaseTime(minioVersion, minioBinaryPath string) (releaseTime time.Time, err error) {
|
||||||
func (u updateMessage) String() string {
|
if releaseTime, err = time.Parse(time.RFC3339, minioVersion); err == nil {
|
||||||
if !u.Update {
|
return releaseTime, err
|
||||||
updateMessage := color.New(color.FgGreen, color.Bold).SprintfFunc()
|
|
||||||
return updateMessage("You are already running the most recent version of ‘minio’.")
|
|
||||||
}
|
}
|
||||||
msg := colorizeUpdateMessage(u.Download, u.NewerThan)
|
|
||||||
return msg
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseReleaseData(data string) (time.Time, error) {
|
// Looks like version is minio non-standard, we use minio binary's ModTime as release time.
|
||||||
releaseStr := strings.Fields(data)
|
fi, err := os.Stat(minioBinaryPath)
|
||||||
if len(releaseStr) < 2 {
|
|
||||||
return time.Time{}, errors.New("Update data malformed")
|
|
||||||
}
|
|
||||||
releaseDate := releaseStr[1]
|
|
||||||
releaseDateSplits := strings.SplitN(releaseDate, ".", 3)
|
|
||||||
if len(releaseDateSplits) < 3 {
|
|
||||||
return time.Time{}, (errors.New("Update data malformed"))
|
|
||||||
}
|
|
||||||
if releaseDateSplits[0] != globalMinioDefaultOwnerID {
|
|
||||||
return time.Time{}, (errors.New("Update data malformed, missing minio tag"))
|
|
||||||
}
|
|
||||||
// "OFFICIAL" tag is still kept for backward compatibility.
|
|
||||||
// We should remove this for the next release.
|
|
||||||
if releaseDateSplits[1] != "RELEASE" && releaseDateSplits[1] != "OFFICIAL" {
|
|
||||||
return time.Time{}, (errors.New("Update data malformed, missing RELEASE tag"))
|
|
||||||
}
|
|
||||||
dateSplits := strings.SplitN(releaseDateSplits[2], "T", 2)
|
|
||||||
if len(dateSplits) < 2 {
|
|
||||||
return time.Time{}, (errors.New("Update data malformed, not in modified RFC3359 form"))
|
|
||||||
}
|
|
||||||
dateSplits[1] = strings.Replace(dateSplits[1], "-", ":", -1)
|
|
||||||
date := strings.Join(dateSplits, "T")
|
|
||||||
|
|
||||||
parsedDate, err := time.Parse(time.RFC3339, date)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return time.Time{}, err
|
err = fmt.Errorf("Unable to get ModTime of %s. %s", minioBinaryPath, err)
|
||||||
}
|
|
||||||
return parsedDate, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// User Agent should always following the below style.
|
|
||||||
// Please open an issue to discuss any new changes here.
|
|
||||||
//
|
|
||||||
// Minio (OS; ARCH) APP/VER APP/VER
|
|
||||||
var (
|
|
||||||
userAgentSuffix = "Minio/" + Version + " " + "Minio/" + ReleaseTag + " " + "Minio/" + CommitID
|
|
||||||
)
|
|
||||||
|
|
||||||
// Check if the operating system is a docker container.
|
|
||||||
func isDocker() bool {
|
|
||||||
cgroup, err := ioutil.ReadFile("/proc/self/cgroup")
|
|
||||||
if err != nil && !os.IsNotExist(err) {
|
|
||||||
errorIf(err, "Unable to read `cgroup` file.")
|
|
||||||
}
|
|
||||||
|
|
||||||
return bytes.Contains(cgroup, []byte("docker"))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if the minio server binary was built with source.
|
|
||||||
func isSourceBuild() bool {
|
|
||||||
return Version == goGetTag
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fetch the current version of the Minio server binary.
|
|
||||||
func getCurrentMinioVersion() (current time.Time, err error) {
|
|
||||||
// For development builds we check for binary modTime
|
|
||||||
// to validate against latest minio server release.
|
|
||||||
if Version != goGetTag {
|
|
||||||
// Parse current minio version into RFC3339.
|
|
||||||
current, err = time.Parse(time.RFC3339, Version)
|
|
||||||
if err != nil {
|
|
||||||
return time.Time{}, err
|
|
||||||
}
|
|
||||||
return current, nil
|
|
||||||
} // else {
|
|
||||||
// For all development builds through `go get`.
|
|
||||||
// fall back to looking for version of the build
|
|
||||||
// date of the binary itself.
|
|
||||||
var fi os.FileInfo
|
|
||||||
fi, err = os.Stat(os.Args[0])
|
|
||||||
if err != nil {
|
|
||||||
return time.Time{}, err
|
|
||||||
}
|
|
||||||
return fi.ModTime(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// verify updates for releases.
|
|
||||||
func getReleaseUpdate(updateURL string, duration time.Duration) (updateMsg updateMessage, errMsg string, err error) {
|
|
||||||
// Construct a new update url.
|
|
||||||
newUpdateURLPrefix := updateURL + "/" + runtime.GOOS + "-" + runtime.GOARCH
|
|
||||||
newUpdateURL := newUpdateURLPrefix + "/minio.shasum"
|
|
||||||
|
|
||||||
// Get the downloadURL.
|
|
||||||
var downloadURL string
|
|
||||||
if isDocker() {
|
|
||||||
downloadURL = "docker pull minio/minio"
|
|
||||||
} else {
|
} else {
|
||||||
switch runtime.GOOS {
|
releaseTime = fi.ModTime().UTC()
|
||||||
case globalWindowsOSName:
|
|
||||||
// For windows.
|
|
||||||
downloadURL = newUpdateURLPrefix + "/minio.exe"
|
|
||||||
default:
|
|
||||||
// For all other operating systems.
|
|
||||||
downloadURL = newUpdateURLPrefix + "/minio"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize update message.
|
return releaseTime, err
|
||||||
updateMsg = updateMessage{
|
}
|
||||||
Download: downloadURL,
|
|
||||||
|
// GetCurrentReleaseTime - returns this process's release time. If it is official minio version,
|
||||||
|
// parsed version is returned else minio binary's mod time is returned.
|
||||||
|
func GetCurrentReleaseTime() (releaseTime time.Time, err error) {
|
||||||
|
return getCurrentReleaseTime(Version, os.Args[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDocker(cgroupFile string) (bool, error) {
|
||||||
|
cgroup, err := ioutil.ReadFile(cgroupFile)
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
err = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Instantiate a new client with 3 sec timeout.
|
return bytes.Contains(cgroup, []byte("docker")), err
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsDocker - returns if the environment is docker or not.
|
||||||
|
func IsDocker() bool {
|
||||||
|
found, err := isDocker("/proc/self/cgroup")
|
||||||
|
if err != nil {
|
||||||
|
console.Fatalf("Error in docker check: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return found
|
||||||
|
}
|
||||||
|
|
||||||
|
func isSourceBuild(minioVersion string) bool {
|
||||||
|
_, err := time.Parse(time.RFC3339, minioVersion)
|
||||||
|
return err != nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsSourceBuild - returns if this binary is made from source or not.
|
||||||
|
func IsSourceBuild() bool {
|
||||||
|
return isSourceBuild(Version)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DO NOT CHANGE USER AGENT STYLE.
|
||||||
|
// The style should be
|
||||||
|
// Minio (<OS>; <ARCH>[; docker][; source]) Minio/<VERSION> Minio/<RELEASE-TAG> Minio/<COMMIT-ID>
|
||||||
|
//
|
||||||
|
// For any change here should be discussed by openning an issue at https://github.com/minio/minio/issues.
|
||||||
|
func getUserAgent() string {
|
||||||
|
userAgent := "Minio (" + runtime.GOOS + "; " + runtime.GOARCH
|
||||||
|
if IsDocker() {
|
||||||
|
userAgent += "; docker"
|
||||||
|
}
|
||||||
|
if IsSourceBuild() {
|
||||||
|
userAgent += "; source"
|
||||||
|
}
|
||||||
|
userAgent += ") " + " Minio/" + Version + " Minio/" + ReleaseTag + " Minio/" + CommitID
|
||||||
|
|
||||||
|
return userAgent
|
||||||
|
}
|
||||||
|
|
||||||
|
func downloadReleaseData(releaseChecksumURL string, timeout time.Duration) (data string, err error) {
|
||||||
|
req, err := http.NewRequest("GET", releaseChecksumURL, nil)
|
||||||
|
if err != nil {
|
||||||
|
return data, err
|
||||||
|
}
|
||||||
|
req.Header.Set("User-Agent", getUserAgent())
|
||||||
|
|
||||||
client := &http.Client{
|
client := &http.Client{
|
||||||
Timeout: duration,
|
Timeout: timeout,
|
||||||
}
|
}
|
||||||
|
|
||||||
current, err := getCurrentMinioVersion()
|
|
||||||
if err != nil {
|
|
||||||
errMsg = "Unable to fetch the current version of Minio server."
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize new request.
|
|
||||||
req, err := http.NewRequest("GET", newUpdateURL, nil)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
userAgentPrefix := func() string {
|
|
||||||
prefix := "Minio (" + runtime.GOOS + "; " + runtime.GOARCH
|
|
||||||
// if its a source build.
|
|
||||||
if isSourceBuild() {
|
|
||||||
if isDocker() {
|
|
||||||
prefix = prefix + "; " + "docker; source) "
|
|
||||||
} else {
|
|
||||||
prefix = prefix + "; " + "source) "
|
|
||||||
}
|
|
||||||
return prefix
|
|
||||||
} // else { not source.
|
|
||||||
if isDocker() {
|
|
||||||
prefix = prefix + "; " + "docker) "
|
|
||||||
} else {
|
|
||||||
prefix = prefix + ") "
|
|
||||||
}
|
|
||||||
return prefix
|
|
||||||
}()
|
|
||||||
|
|
||||||
// Set user agent.
|
|
||||||
req.Header.Set("User-Agent", userAgentPrefix+" "+userAgentSuffix)
|
|
||||||
|
|
||||||
// Fetch new update.
|
|
||||||
resp, err := client.Do(req)
|
resp, err := client.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return data, err
|
||||||
|
}
|
||||||
|
if resp == nil {
|
||||||
|
return data, fmt.Errorf("No response from server to download URL %s", releaseChecksumURL)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify if we have a valid http response i.e http.StatusOK.
|
if resp.StatusCode != http.StatusOK {
|
||||||
if resp != nil {
|
return data, fmt.Errorf("Error downloading URL %s. Response: %v", releaseChecksumURL, resp.Status)
|
||||||
if resp.StatusCode != http.StatusOK {
|
}
|
||||||
errMsg = "Failed to retrieve update notice."
|
|
||||||
err = errors.New("http status : " + resp.Status)
|
dataBytes, err := ioutil.ReadAll(resp.Body)
|
||||||
return
|
if err != nil {
|
||||||
|
return data, fmt.Errorf("Error reading response. %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
data = string(dataBytes)
|
||||||
|
return data, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DownloadReleaseData - downloads release data from minio official server.
|
||||||
|
func DownloadReleaseData(timeout time.Duration) (data string, err error) {
|
||||||
|
return downloadReleaseData(minioReleaseURL+"minio.shasum", timeout)
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseReleaseData(data string) (releaseTime time.Time, err error) {
|
||||||
|
fields := strings.Fields(data)
|
||||||
|
if len(fields) != 2 {
|
||||||
|
err = fmt.Errorf("Unknown release data `%s`", data)
|
||||||
|
return releaseTime, err
|
||||||
|
}
|
||||||
|
|
||||||
|
releaseInfo := fields[1]
|
||||||
|
if fields = strings.Split(releaseInfo, "."); len(fields) != 3 {
|
||||||
|
err = fmt.Errorf("Unknown release information `%s`", releaseInfo)
|
||||||
|
return releaseTime, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !(fields[0] == "minio" && fields[1] == "RELEASE") {
|
||||||
|
err = fmt.Errorf("Unknown release '%s'", releaseInfo)
|
||||||
|
return releaseTime, err
|
||||||
|
}
|
||||||
|
|
||||||
|
releaseTime, err = time.Parse(releaseTagTimeLayout, fields[2])
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("Unknown release time format. %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return releaseTime, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func getLatestReleaseTime(timeout time.Duration) (releaseTime time.Time, err error) {
|
||||||
|
data, err := DownloadReleaseData(timeout)
|
||||||
|
if err != nil {
|
||||||
|
return releaseTime, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return parseReleaseData(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getDownloadURL() (downloadURL string) {
|
||||||
|
if IsDocker() {
|
||||||
|
return "docker pull minio/minio"
|
||||||
|
}
|
||||||
|
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
return minioReleaseURL + "minio.exe"
|
||||||
|
}
|
||||||
|
|
||||||
|
return minioReleaseURL + "minio"
|
||||||
|
}
|
||||||
|
|
||||||
|
func getUpdateInfo(timeout time.Duration) (older time.Duration, downloadURL string, err error) {
|
||||||
|
currentReleaseTime, err := GetCurrentReleaseTime()
|
||||||
|
if err != nil {
|
||||||
|
return older, downloadURL, err
|
||||||
|
}
|
||||||
|
|
||||||
|
latestReleaseTime, err := getLatestReleaseTime(timeout)
|
||||||
|
if err != nil {
|
||||||
|
return older, downloadURL, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if latestReleaseTime.After(currentReleaseTime) {
|
||||||
|
older = latestReleaseTime.Sub(currentReleaseTime)
|
||||||
|
downloadURL = getDownloadURL()
|
||||||
|
}
|
||||||
|
|
||||||
|
return older, downloadURL, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func mainUpdate(ctx *cli.Context) {
|
||||||
|
if len(ctx.Args()) != 0 {
|
||||||
|
cli.ShowCommandHelpAndExit(ctx, "update", -1)
|
||||||
|
}
|
||||||
|
|
||||||
|
quiet := ctx.Bool("quiet") || ctx.GlobalBool("quiet")
|
||||||
|
quietPrintln := func(args ...interface{}) {
|
||||||
|
if !quiet {
|
||||||
|
console.Println(args...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read the response body.
|
older, downloadURL, err := getUpdateInfo(10 * time.Second)
|
||||||
updateBody, err := ioutil.ReadAll(resp.Body)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errMsg = "Failed to retrieve update notice. Please try again later."
|
quietPrintln(err)
|
||||||
return
|
os.Exit(-1)
|
||||||
}
|
}
|
||||||
|
|
||||||
errMsg = "Failed to retrieve update notice. Please try again later. Please report this issue at https://github.com/minio/minio/issues"
|
if older != time.Duration(0) {
|
||||||
|
quietPrintln(colorizeUpdateMessage(downloadURL, older))
|
||||||
// Parse the date if its valid.
|
os.Exit(1)
|
||||||
latest, err := parseReleaseData(string(updateBody))
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify if the date is not zero.
|
colorSprintf := color.New(color.FgGreen, color.Bold).SprintfFunc()
|
||||||
if latest.IsZero() {
|
quietPrintln(colorSprintf("You are already running the most recent version of ‘minio’."))
|
||||||
err = errors.New("Release date cannot be zero. Please report this issue at https://github.com/minio/minio/issues")
|
os.Exit(0)
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Is the update latest?.
|
|
||||||
if latest.After(current) {
|
|
||||||
updateMsg.Update = true
|
|
||||||
updateMsg.NewerThan = latest.Sub(current)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return update message.
|
|
||||||
return updateMsg, "", nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// main entry point for update command.
|
|
||||||
func mainUpdate(ctx *cli.Context) {
|
|
||||||
// Initialization routine, such as config loading, enable logging, ..
|
|
||||||
minioInit(ctx)
|
|
||||||
|
|
||||||
if globalQuiet {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for update.
|
|
||||||
var updateMsg updateMessage
|
|
||||||
var errMsg string
|
|
||||||
var err error
|
|
||||||
var secs = time.Second * 3
|
|
||||||
updateMsg, errMsg, err = getReleaseUpdate(minioUpdateStableURL, secs)
|
|
||||||
fatalIf(err, errMsg)
|
|
||||||
console.Println(updateMsg)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,109 +0,0 @@
|
||||||
// +build linux darwin dragonfly freebsd netbsd openbsd
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Minio Cloud Storage, (C) 2016 Minio, Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package cmd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"net/http/httptest"
|
|
||||||
"reflect"
|
|
||||||
"runtime"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Validate when release versions are properly set.
|
|
||||||
func TestReleaseUpdateVersion(t *testing.T) {
|
|
||||||
Version = "2016-10-06T00:08:32Z"
|
|
||||||
ReleaseTag = "RELEASE.2016-10-06T00-08-32Z"
|
|
||||||
CommitID = "d1c38ba8f0b3aecdf9b932c087dd65c21eebac33"
|
|
||||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
fmt.Fprintln(w, "fbe246edbd382902db9a4035df7dce8cb441357d minio.RELEASE.2016-10-07T01-16-39Z")
|
|
||||||
}))
|
|
||||||
userAgentSuffix = "Minio/" + Version + " " + "Minio/" + ReleaseTag + " " + "Minio/" + CommitID
|
|
||||||
defer ts.Close()
|
|
||||||
testCases := []struct {
|
|
||||||
updateURL string
|
|
||||||
updateMsg updateMessage
|
|
||||||
errMsg string
|
|
||||||
shouldPass bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
updateURL: ts.URL,
|
|
||||||
updateMsg: updateMessage{
|
|
||||||
Download: ts.URL + "/" + runtime.GOOS + "-" + runtime.GOARCH + "/minio",
|
|
||||||
Update: true,
|
|
||||||
NewerThan: 90487000000000,
|
|
||||||
},
|
|
||||||
errMsg: "",
|
|
||||||
shouldPass: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validates all the errors reported.
|
|
||||||
for i, testCase := range testCases {
|
|
||||||
updateMsg, errMsg, err := getReleaseUpdate(testCase.updateURL, time.Second*1)
|
|
||||||
if testCase.shouldPass && err != nil {
|
|
||||||
t.Errorf("Test %d: Unable to fetch release update %s", i+1, err)
|
|
||||||
}
|
|
||||||
if errMsg != testCase.errMsg {
|
|
||||||
t.Errorf("Test %d: Expected %s, got %s", i+1, testCase.errMsg, errMsg)
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(updateMsg, testCase.updateMsg) {
|
|
||||||
t.Errorf("Test %d: Expected %#v, got %#v", i+1, testCase.updateMsg, updateMsg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestReleaseUpdate(t *testing.T) {
|
|
||||||
Version = "DEVELOPMENT.GOGET"
|
|
||||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
fmt.Fprintln(w, "Hello, client")
|
|
||||||
}))
|
|
||||||
defer ts.Close()
|
|
||||||
testCases := []struct {
|
|
||||||
updateURL string
|
|
||||||
updateMsg updateMessage
|
|
||||||
errMsg string
|
|
||||||
shouldPass bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
updateURL: ts.URL,
|
|
||||||
updateMsg: updateMessage{
|
|
||||||
Download: ts.URL + "/" + runtime.GOOS + "-" + runtime.GOARCH + "/minio",
|
|
||||||
},
|
|
||||||
errMsg: "Failed to retrieve update notice. Please try again later. Please report this issue at https://github.com/minio/minio/issues",
|
|
||||||
shouldPass: false,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validates all the errors reported.
|
|
||||||
for i, testCase := range testCases {
|
|
||||||
updateMsg, errMsg, err := getReleaseUpdate(testCase.updateURL, time.Second*1)
|
|
||||||
if testCase.shouldPass && err != nil {
|
|
||||||
t.Errorf("Test %d: Unable to fetch release update %s", i+1, err)
|
|
||||||
}
|
|
||||||
if errMsg != testCase.errMsg {
|
|
||||||
t.Errorf("Test %d: Expected %s, got %s", i+1, testCase.errMsg, errMsg)
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(updateMsg, testCase.updateMsg) {
|
|
||||||
t.Errorf("Test %d: Expected %#v, got %#v", i+1, testCase.updateMsg, updateMsg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,275 @@
|
||||||
|
/*
|
||||||
|
* Minio Cloud Storage, (C) 2017 Minio, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"os"
|
||||||
|
"runtime"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGetCurrentReleaseTime(t *testing.T) {
|
||||||
|
minioVersion1 := time.Now().UTC().Format(time.RFC3339)
|
||||||
|
releaseTime1, _ := time.Parse(time.RFC3339, minioVersion1)
|
||||||
|
|
||||||
|
minioVersion2 := "DEVELOPMENT.GOGET"
|
||||||
|
tmpfile, err := ioutil.TempFile("", "get-current-release-time-testcase")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Unable to create temporary file. %s", err)
|
||||||
|
}
|
||||||
|
defer os.Remove(tmpfile.Name())
|
||||||
|
minioBinaryPath2 := tmpfile.Name()
|
||||||
|
fi, err := tmpfile.Stat()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Unable to get temporary file info. %s", err)
|
||||||
|
}
|
||||||
|
if err = tmpfile.Close(); err != nil {
|
||||||
|
t.Fatalf("Unable to create temporary file. %s", err)
|
||||||
|
}
|
||||||
|
releaseTime2 := fi.ModTime().UTC()
|
||||||
|
|
||||||
|
errorMessage1 := "Unable to get ModTime of . stat : no such file or directory"
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
errorMessage1 = "Unable to get ModTime of . Lstat : The system cannot find the path specified."
|
||||||
|
}
|
||||||
|
|
||||||
|
errorMessage2 := "Unable to get ModTime of non-existing-file. stat non-existing-file: no such file or directory"
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
errorMessage2 = "Unable to get ModTime of non-existing-file. GetFileAttributesEx non-existing-file: The system cannot find the file specified."
|
||||||
|
}
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
minioVersion string
|
||||||
|
minioBinaryPath string
|
||||||
|
expectedResult time.Time
|
||||||
|
expectedErr error
|
||||||
|
}{
|
||||||
|
{minioVersion1, "", releaseTime1, nil},
|
||||||
|
{minioVersion1, minioBinaryPath2, releaseTime1, nil},
|
||||||
|
{minioVersion2, minioBinaryPath2, releaseTime2, nil},
|
||||||
|
{"junk", minioBinaryPath2, releaseTime2, nil},
|
||||||
|
{"3.2.0", minioBinaryPath2, releaseTime2, nil},
|
||||||
|
{minioVersion2, "", time.Time{}, fmt.Errorf(errorMessage1)},
|
||||||
|
{"junk", "non-existing-file", time.Time{}, fmt.Errorf(errorMessage2)},
|
||||||
|
{"3.2.0", "non-existing-file", time.Time{}, fmt.Errorf(errorMessage2)},
|
||||||
|
}
|
||||||
|
|
||||||
|
if runtime.GOOS == "linux" {
|
||||||
|
testCases = append(testCases, struct {
|
||||||
|
minioVersion string
|
||||||
|
minioBinaryPath string
|
||||||
|
expectedResult time.Time
|
||||||
|
expectedErr error
|
||||||
|
}{"3.2a", "/proc/1/cwd", time.Time{}, fmt.Errorf("Unable to get ModTime of /proc/1/cwd. stat /proc/1/cwd: permission denied")})
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, testCase := range testCases {
|
||||||
|
result, err := getCurrentReleaseTime(testCase.minioVersion, testCase.minioBinaryPath)
|
||||||
|
if testCase.expectedErr == nil {
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("error: expected: %v, got: %v", testCase.expectedErr, err)
|
||||||
|
}
|
||||||
|
} else if err == nil {
|
||||||
|
t.Fatalf("error: expected: %v, got: %v", testCase.expectedErr, err)
|
||||||
|
} else if testCase.expectedErr.Error() != err.Error() {
|
||||||
|
t.Fatalf("error: expected: %v, got: %v", testCase.expectedErr, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !testCase.expectedResult.Equal(result) {
|
||||||
|
t.Fatalf("result: expected: %v, got: %v", testCase.expectedResult, result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIsDocker(t *testing.T) {
|
||||||
|
createTempFile := func(content string) string {
|
||||||
|
tmpfile, err := ioutil.TempFile("", "isdocker-testcase")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Unable to create temporary file. %s", err)
|
||||||
|
}
|
||||||
|
if _, err = tmpfile.Write([]byte(content)); err != nil {
|
||||||
|
t.Fatalf("Unable to create temporary file. %s", err)
|
||||||
|
}
|
||||||
|
if err = tmpfile.Close(); err != nil {
|
||||||
|
t.Fatalf("Unable to create temporary file. %s", err)
|
||||||
|
}
|
||||||
|
return tmpfile.Name()
|
||||||
|
}
|
||||||
|
|
||||||
|
filename1 := createTempFile(`11:pids:/user.slice/user-1000.slice/user@1000.service
|
||||||
|
10:blkio:/
|
||||||
|
9:hugetlb:/
|
||||||
|
8:perf_event:/
|
||||||
|
7:cpuset:/
|
||||||
|
6:devices:/user.slice
|
||||||
|
5:net_cls,net_prio:/
|
||||||
|
4:cpu,cpuacct:/
|
||||||
|
3:memory:/user/bala/0
|
||||||
|
2:freezer:/user/bala/0
|
||||||
|
1:name=systemd:/user.slice/user-1000.slice/user@1000.service/gnome-terminal-server.service
|
||||||
|
`)
|
||||||
|
defer os.Remove(filename1)
|
||||||
|
filename2 := createTempFile(`14:name=systemd:/docker/d5eb950884d828237f60f624ff575a1a7a4daa28a8d4d750040527ed9545e727
|
||||||
|
13:pids:/docker/d5eb950884d828237f60f624ff575a1a7a4daa28a8d4d750040527ed9545e727
|
||||||
|
12:hugetlb:/docker/d5eb950884d828237f60f624ff575a1a7a4daa28a8d4d750040527ed9545e727
|
||||||
|
11:net_prio:/docker/d5eb950884d828237f60f624ff575a1a7a4daa28a8d4d750040527ed9545e727
|
||||||
|
10:perf_event:/docker/d5eb950884d828237f60f624ff575a1a7a4daa28a8d4d750040527ed9545e727
|
||||||
|
9:net_cls:/docker/d5eb950884d828237f60f624ff575a1a7a4daa28a8d4d750040527ed9545e727
|
||||||
|
8:freezer:/docker/d5eb950884d828237f60f624ff575a1a7a4daa28a8d4d750040527ed9545e727
|
||||||
|
7:devices:/docker/d5eb950884d828237f60f624ff575a1a7a4daa28a8d4d750040527ed9545e727
|
||||||
|
6:memory:/docker/d5eb950884d828237f60f624ff575a1a7a4daa28a8d4d750040527ed9545e727
|
||||||
|
5:blkio:/docker/d5eb950884d828237f60f624ff575a1a7a4daa28a8d4d750040527ed9545e727
|
||||||
|
4:cpuacct:/docker/d5eb950884d828237f60f624ff575a1a7a4daa28a8d4d750040527ed9545e727
|
||||||
|
3:cpu:/docker/d5eb950884d828237f60f624ff575a1a7a4daa28a8d4d750040527ed9545e727
|
||||||
|
2:cpuset:/docker/d5eb950884d828237f60f624ff575a1a7a4daa28a8d4d750040527ed9545e727
|
||||||
|
1:name=openrc:/docker
|
||||||
|
`)
|
||||||
|
defer os.Remove(filename2)
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
filename string
|
||||||
|
expectedResult bool
|
||||||
|
expectedErr error
|
||||||
|
}{
|
||||||
|
{"", false, nil},
|
||||||
|
{"/tmp/non-existing-file", false, nil},
|
||||||
|
{filename1, false, nil},
|
||||||
|
{filename2, true, nil},
|
||||||
|
}
|
||||||
|
|
||||||
|
if runtime.GOOS == "linux" {
|
||||||
|
testCases = append(testCases, struct {
|
||||||
|
filename string
|
||||||
|
expectedResult bool
|
||||||
|
expectedErr error
|
||||||
|
}{"/proc/1/cwd", false, fmt.Errorf("open /proc/1/cwd: permission denied")})
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, testCase := range testCases {
|
||||||
|
result, err := isDocker(testCase.filename)
|
||||||
|
if testCase.expectedErr == nil {
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("error: expected: %v, got: %v", testCase.expectedErr, err)
|
||||||
|
}
|
||||||
|
} else if err == nil {
|
||||||
|
t.Fatalf("error: expected: %v, got: %v", testCase.expectedErr, err)
|
||||||
|
} else if testCase.expectedErr.Error() != err.Error() {
|
||||||
|
t.Fatalf("error: expected: %v, got: %v", testCase.expectedErr, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if testCase.expectedResult != result {
|
||||||
|
t.Fatalf("result: expected: %v, got: %v", testCase.expectedResult, result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIsSourceBuild(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
minioVersion string
|
||||||
|
expectedResult bool
|
||||||
|
}{
|
||||||
|
{time.Now().UTC().Format(time.RFC3339), false},
|
||||||
|
{"DEVELOPMENT.GOGET", true},
|
||||||
|
{"junk", true},
|
||||||
|
{"3.2.4", true},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, testCase := range testCases {
|
||||||
|
result := isSourceBuild(testCase.minioVersion)
|
||||||
|
if testCase.expectedResult != result {
|
||||||
|
t.Fatalf("expected: %v, got: %v", testCase.expectedResult, result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDownloadReleaseData(t *testing.T) {
|
||||||
|
httpServer1 := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}))
|
||||||
|
defer httpServer1.Close()
|
||||||
|
httpServer2 := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
fmt.Fprintln(w, "fbe246edbd382902db9a4035df7dce8cb441357d minio.RELEASE.2016-10-07T01-16-39Z")
|
||||||
|
}))
|
||||||
|
defer httpServer2.Close()
|
||||||
|
httpServer3 := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
http.Error(w, "", http.StatusNotFound)
|
||||||
|
}))
|
||||||
|
defer httpServer3.Close()
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
releaseChecksumURL string
|
||||||
|
expectedResult string
|
||||||
|
expectedErr error
|
||||||
|
}{
|
||||||
|
{httpServer1.URL, "", nil},
|
||||||
|
{httpServer2.URL, "fbe246edbd382902db9a4035df7dce8cb441357d minio.RELEASE.2016-10-07T01-16-39Z\n", nil},
|
||||||
|
{httpServer3.URL, "", fmt.Errorf("Error downloading URL " + httpServer3.URL + ". Response: 404 Not Found")},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, testCase := range testCases {
|
||||||
|
result, err := downloadReleaseData(testCase.releaseChecksumURL, 1*time.Second)
|
||||||
|
if testCase.expectedErr == nil {
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("error: expected: %v, got: %v", testCase.expectedErr, err)
|
||||||
|
}
|
||||||
|
} else if err == nil {
|
||||||
|
t.Fatalf("error: expected: %v, got: %v", testCase.expectedErr, err)
|
||||||
|
} else if testCase.expectedErr.Error() != err.Error() {
|
||||||
|
t.Fatalf("error: expected: %v, got: %v", testCase.expectedErr, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if testCase.expectedResult != result {
|
||||||
|
t.Fatalf("result: expected: %v, got: %v", testCase.expectedResult, result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParseReleaseData(t *testing.T) {
|
||||||
|
releaseTime, _ := time.Parse(releaseTagTimeLayout, "2016-10-07T01-16-39Z")
|
||||||
|
testCases := []struct {
|
||||||
|
data string
|
||||||
|
expectedResult time.Time
|
||||||
|
expectedErr error
|
||||||
|
}{
|
||||||
|
{"more than two fields", time.Time{}, fmt.Errorf("Unknown release data `more than two fields`")},
|
||||||
|
{"more than", time.Time{}, fmt.Errorf("Unknown release information `than`")},
|
||||||
|
{"more than.two.fields", time.Time{}, fmt.Errorf("Unknown release 'than.two.fields'")},
|
||||||
|
{"more minio.RELEASE.fields", time.Time{}, fmt.Errorf(`Unknown release time format. parsing time "fields" as "2006-01-02T15-04-05Z": cannot parse "fields" as "2006"`)},
|
||||||
|
{"more minio.RELEASE.2016-10-07T01-16-39Z", releaseTime, nil},
|
||||||
|
{"fbe246edbd382902db9a4035df7dce8cb441357d minio.RELEASE.2016-10-07T01-16-39Z\n", releaseTime, nil},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, testCase := range testCases {
|
||||||
|
result, err := parseReleaseData(testCase.data)
|
||||||
|
if testCase.expectedErr == nil {
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("error: expected: %v, got: %v", testCase.expectedErr, err)
|
||||||
|
}
|
||||||
|
} else if err == nil {
|
||||||
|
t.Fatalf("error: expected: %v, got: %v", testCase.expectedErr, err)
|
||||||
|
} else if testCase.expectedErr.Error() != err.Error() {
|
||||||
|
t.Fatalf("error: expected: %v, got: %v", testCase.expectedErr, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !testCase.expectedResult.Equal(result) {
|
||||||
|
t.Fatalf("result: expected: %v, got: %v", testCase.expectedResult, result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,109 +0,0 @@
|
||||||
// +build windows
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Minio Cloud Storage, (C) 2016 Minio, Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package cmd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"net/http/httptest"
|
|
||||||
"reflect"
|
|
||||||
"runtime"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Validate when release versions are properly set.
|
|
||||||
func TestReleaseUpdateVersion(t *testing.T) {
|
|
||||||
Version = "2016-10-06T00:08:32Z"
|
|
||||||
ReleaseTag = "RELEASE.2016-10-06T00-08-32Z"
|
|
||||||
CommitID = "d1c38ba8f0b3aecdf9b932c087dd65c21eebac33"
|
|
||||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
fmt.Fprintln(w, "fbe246edbd382902db9a4035df7dce8cb441357d minio.RELEASE.2016-10-07T01-16-39Z")
|
|
||||||
}))
|
|
||||||
userAgentSuffix = "Minio/" + Version + " " + "Minio/" + ReleaseTag + " " + "Minio/" + CommitID
|
|
||||||
defer ts.Close()
|
|
||||||
testCases := []struct {
|
|
||||||
updateURL string
|
|
||||||
updateMsg updateMessage
|
|
||||||
errMsg string
|
|
||||||
shouldPass bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
updateURL: ts.URL,
|
|
||||||
updateMsg: updateMessage{
|
|
||||||
Download: ts.URL + "/" + runtime.GOOS + "-" + runtime.GOARCH + "/minio.exe",
|
|
||||||
Update: true,
|
|
||||||
NewerThan: 90487000000000,
|
|
||||||
},
|
|
||||||
errMsg: "",
|
|
||||||
shouldPass: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validates all the errors reported.
|
|
||||||
for i, testCase := range testCases {
|
|
||||||
updateMsg, errMsg, err := getReleaseUpdate(testCase.updateURL, time.Second*1)
|
|
||||||
if testCase.shouldPass && err != nil {
|
|
||||||
t.Errorf("Test %d: Unable to fetch release update %s", i+1, err)
|
|
||||||
}
|
|
||||||
if errMsg != testCase.errMsg {
|
|
||||||
t.Errorf("Test %d: Expected %s, got %s", i+1, testCase.errMsg, errMsg)
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(updateMsg, testCase.updateMsg) {
|
|
||||||
t.Errorf("Test %d: Expected %#v, got %#v", i+1, testCase.updateMsg, updateMsg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestReleaseUpdate(t *testing.T) {
|
|
||||||
Version = "DEVELOPMENT.GOGET"
|
|
||||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
fmt.Fprintln(w, "Hello, client")
|
|
||||||
}))
|
|
||||||
defer ts.Close()
|
|
||||||
testCases := []struct {
|
|
||||||
updateURL string
|
|
||||||
updateMsg updateMessage
|
|
||||||
errMsg string
|
|
||||||
shouldPass bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
updateURL: ts.URL,
|
|
||||||
updateMsg: updateMessage{
|
|
||||||
Download: ts.URL + "/" + runtime.GOOS + "-" + runtime.GOARCH + "/minio.exe",
|
|
||||||
},
|
|
||||||
errMsg: "Failed to retrieve update notice. Please try again later. Please report this issue at https://github.com/minio/minio/issues",
|
|
||||||
shouldPass: false,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validates all the errors reported.
|
|
||||||
for i, testCase := range testCases {
|
|
||||||
updateMsg, errMsg, err := getReleaseUpdate(testCase.updateURL, time.Second*1)
|
|
||||||
if testCase.shouldPass && err != nil {
|
|
||||||
t.Errorf("Test %d: Unable to fetch release update %s", i+1, err)
|
|
||||||
}
|
|
||||||
if errMsg != testCase.errMsg {
|
|
||||||
t.Errorf("Test %d: Expected %s, got %s", i+1, testCase.errMsg, errMsg)
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(updateMsg, testCase.updateMsg) {
|
|
||||||
t.Errorf("Test %d: Expected %#v, got %#v", i+1, testCase.updateMsg, updateMsg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -24,12 +24,11 @@ import (
|
||||||
|
|
||||||
// Tests update notifier string builder.
|
// Tests update notifier string builder.
|
||||||
func TestUpdateNotifier(t *testing.T) {
|
func TestUpdateNotifier(t *testing.T) {
|
||||||
updateMsg := minioUpdateStableURL
|
colorUpdateMsg := colorizeUpdateMessage(minioReleaseURL, time.Duration(72*time.Hour))
|
||||||
colorUpdateMsg := colorizeUpdateMessage(updateMsg, time.Duration(72*time.Hour))
|
if !strings.Contains(colorUpdateMsg, "minutes") {
|
||||||
if strings.Index(colorUpdateMsg, "minutes") == -1 {
|
|
||||||
t.Fatal("Duration string not found in colorized update message", colorUpdateMsg)
|
t.Fatal("Duration string not found in colorized update message", colorUpdateMsg)
|
||||||
}
|
}
|
||||||
if strings.Index(colorUpdateMsg, updateMsg) == -1 {
|
if !strings.Contains(colorUpdateMsg, minioReleaseURL) {
|
||||||
t.Fatal("Update message not found in colorized update message", updateMsg)
|
t.Fatal("Update message not found in colorized update message", minioReleaseURL)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue