Develop #3
57
main.go
57
main.go
@@ -1,9 +1,11 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"katenary/cmd"
|
"katenary/cmd"
|
||||||
"katenary/generator/writers"
|
"katenary/generator/writers"
|
||||||
"katenary/helm"
|
"katenary/helm"
|
||||||
|
"katenary/update"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
@@ -92,10 +94,57 @@ func main() {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
rootCmd.AddCommand(versionCmd)
|
// Update the binary to the latest version
|
||||||
rootCmd.AddCommand(convertCmd)
|
updateCmd := &cobra.Command{
|
||||||
rootCmd.AddCommand(showLabelsCmd)
|
Use: "upgrade",
|
||||||
|
Short: "Upgrade katenary to the latest version if available",
|
||||||
|
Run: func(c *cobra.Command, args []string) {
|
||||||
|
version, assets, err := update.CheckLatestVersion()
|
||||||
|
if err != nil {
|
||||||
|
c.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.Println("Updating to version: " + version)
|
||||||
|
err = update.DownloadLatestVersion(assets)
|
||||||
|
if err != nil {
|
||||||
|
c.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.Println("Update completed")
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
rootCmd.Execute()
|
rootCmd.AddCommand(
|
||||||
|
versionCmd,
|
||||||
|
convertCmd,
|
||||||
|
showLabelsCmd,
|
||||||
|
updateCmd,
|
||||||
|
)
|
||||||
|
|
||||||
|
// in parallel, check if the current katenary version is the latest
|
||||||
|
ch := make(chan string)
|
||||||
|
go func() {
|
||||||
|
version, _, err := update.CheckLatestVersion()
|
||||||
|
if err != nil {
|
||||||
|
ch <- ""
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if cmd.Version != version {
|
||||||
|
ch <- fmt.Sprintf("\x1b[33mNew version available: " +
|
||||||
|
version +
|
||||||
|
" - to auto upgrade katenary, you can execute: katenary upgrade\x1b[0m\n")
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
// Execute the command
|
||||||
|
finalize := make(chan error)
|
||||||
|
go func() {
|
||||||
|
finalize <- rootCmd.Execute()
|
||||||
|
}()
|
||||||
|
|
||||||
|
// Wait for both goroutines to finish
|
||||||
|
if err := <-finalize; err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
fmt.Print(<-ch)
|
||||||
}
|
}
|
||||||
|
127
update/main.go
Normal file
127
update/main.go
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
package update
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"katenary/cmd"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"runtime"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var exe, _ = os.Executable()
|
||||||
|
|
||||||
|
// Asset is a github asset from release url.
|
||||||
|
type Asset struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
URL string `json:"browser_download_url"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckLatestVersion check katenary latest version from release and propose to download it
|
||||||
|
func CheckLatestVersion() (string, []Asset, error) {
|
||||||
|
|
||||||
|
githuburl := "https://api.github.com/repos/metal3d/katenary/releases/latest"
|
||||||
|
// Create a HTTP client with 1s timeout
|
||||||
|
client := &http.Client{
|
||||||
|
Timeout: time.Second * 1,
|
||||||
|
}
|
||||||
|
// Create a request
|
||||||
|
req, err := http.NewRequest("GET", githuburl, nil)
|
||||||
|
if err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send the request via a client
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
// Get tag_name from the json response
|
||||||
|
var release = struct {
|
||||||
|
TagName string `json:"tag_name"`
|
||||||
|
Assets []Asset `json:"assets"`
|
||||||
|
}{}
|
||||||
|
err = json.NewDecoder(resp.Body).Decode(&release)
|
||||||
|
if err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if release.TagName == "" {
|
||||||
|
return "", nil, errors.New("No release found")
|
||||||
|
}
|
||||||
|
|
||||||
|
if cmd.Version == release.TagName {
|
||||||
|
fmt.Println("You are using the latest version")
|
||||||
|
return "", nil, errors.New("You are using the latest version")
|
||||||
|
}
|
||||||
|
|
||||||
|
return release.TagName, release.Assets, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func DownloadLatestVersion(assets []Asset) error {
|
||||||
|
// Download the latest version
|
||||||
|
fmt.Println("Downloading the latest version...")
|
||||||
|
|
||||||
|
// ok, replace this from the current version to the latest version
|
||||||
|
err := os.Rename(exe, exe+".old")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Download the latest version for the current OS
|
||||||
|
for _, asset := range assets {
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "windows":
|
||||||
|
if asset.Name == "katenary.exe" {
|
||||||
|
err = DownloadFile(asset.URL, exe)
|
||||||
|
}
|
||||||
|
case "linux":
|
||||||
|
switch runtime.GOARCH {
|
||||||
|
case "amd64":
|
||||||
|
if asset.Name == "katenary-linux-amd64" {
|
||||||
|
err = DownloadFile(asset.URL, exe)
|
||||||
|
}
|
||||||
|
case "arm64":
|
||||||
|
if asset.Name == "katenary-linux-arm64" {
|
||||||
|
err = DownloadFile(asset.URL, exe)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case "darwin":
|
||||||
|
if asset.Name == "katenary-darwin" {
|
||||||
|
err = DownloadFile(asset.URL, exe)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
fmt.Println("Unsupported OS")
|
||||||
|
err = errors.New("Unsupported OS")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err == nil {
|
||||||
|
// remove the old version
|
||||||
|
os.Remove(exe + ".old")
|
||||||
|
} else {
|
||||||
|
// restore the old version
|
||||||
|
os.Rename(exe+".old", exe)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func DownloadFile(url, exe string) error {
|
||||||
|
// Download the url binary to exe path
|
||||||
|
resp, err := http.Get(url)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
fp, err := os.OpenFile(exe, os.O_WRONLY|os.O_CREATE, 0755)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer fp.Close()
|
||||||
|
_, err = io.Copy(fp, resp.Body)
|
||||||
|
return err
|
||||||
|
}
|
36
update/update_test.go
Normal file
36
update/update_test.go
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
package update
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"katenary/cmd"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestDownloadLatestRelease(t *testing.T) {
|
||||||
|
|
||||||
|
// Change the cmd.Version to "v0.0.0" to test the fallback to the latest release
|
||||||
|
cmd.Version = "v0.0.0"
|
||||||
|
|
||||||
|
// change "exe" to /tmp/test-katenary
|
||||||
|
exe = "/tmp/test-katenary"
|
||||||
|
|
||||||
|
// Now call the CheckLatestVersion function
|
||||||
|
version, assets, err := CheckLatestVersion()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Error: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("Version found", version)
|
||||||
|
|
||||||
|
// Touch exe binary
|
||||||
|
f, _ := os.OpenFile(exe, os.O_RDONLY|os.O_CREATE, 0755)
|
||||||
|
f.Write(nil)
|
||||||
|
f.Close()
|
||||||
|
|
||||||
|
err = DownloadLatestVersion(assets)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Error: %s", err)
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user