From 7722cad9a90fb907fbcdacb471b2b8201ef2fa49 Mon Sep 17 00:00:00 2001 From: Dipankar Das <65275144+dipankardas011@users.noreply.github.com> Date: Fri, 2 Aug 2024 00:24:59 +0530 Subject: [PATCH 1/6] added the sub command left to add the logic Signed-off-by: Dipankar Das <65275144+dipankardas011@users.noreply.github.com> --- cli/cmd/upgrade.go | 31 +++++++++++++++++++++++++++++++ cli/cmd/version.go | 13 +------------ 2 files changed, 32 insertions(+), 12 deletions(-) create mode 100644 cli/cmd/upgrade.go diff --git a/cli/cmd/upgrade.go b/cli/cmd/upgrade.go new file mode 100644 index 0000000..f41d377 --- /dev/null +++ b/cli/cmd/upgrade.go @@ -0,0 +1,31 @@ +package cmd + +import ( + "os" + + "github.com/ksctl/cli/logger" + "github.com/ksctl/ksctl/pkg/types" + + "github.com/spf13/cobra" +) + +var selfUpdate = &cobra.Command{ + Use: "self-update", + Short: "update the ksctl cli", + Long: "setups up update for ksctl cli", + Run: func(cmd *cobra.Command, args []string) { + verbosity, _ := cmd.Flags().GetInt("verbose") + var log types.LoggerFactory = logger.NewLogger(verbosity, os.Stdout) + + newVer := "TODO" + + log.Success(ctx, "Updated Ksctl cli", "previousVer", Version, "newVer", newVer) + }, +} + +func init() { + RootCmd.AddCommand(selfUpdate) + storageFlag(selfUpdate) + + selfUpdate.Flags().BoolP("verbose", "v", true, "for verbose output") +} diff --git a/cli/cmd/version.go b/cli/cmd/version.go index 8896e96..5875aaf 100644 --- a/cli/cmd/version.go +++ b/cli/cmd/version.go @@ -17,15 +17,6 @@ const ( | <\__ \ (__| |_| | |_|\_\___/\___|\__|_| -` - - v1_0Ksctl = ` - __ __ .__ -| | __ ______ ____ _/ |_ | | -| |/ / / ___/_/ ___\\ __\| | -| < \___ \ \ \___ | | | |__ -|__|_ \/____ > \___ >|__| |____/ - \/ \/ \/ ` v2_0Ksctl = ` @@ -48,9 +39,7 @@ var versionCmd = &cobra.Command{ Short: "Print the version number of ksctl", Run: func(cmd *cobra.Command, args []string) { - fmt.Println(v0_1Ksctl) - - color.HiGreen(v1_0Ksctl) + color.HiGreen(v0_1Ksctl) x := strings.Split(v2_0Ksctl, "\n") From 7ed88ec6e8c40eef5540407ce3426dbd61ab748e Mon Sep 17 00:00:00 2001 From: Dipankar Das <65275144+dipankardas011@users.noreply.github.com> Date: Fri, 2 Aug 2024 07:39:16 +0530 Subject: [PATCH 2/6] updated the table logging Signed-off-by: Dipankar Das <65275144+dipankardas011@users.noreply.github.com> --- logger/general_logging.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/logger/general_logging.go b/logger/general_logging.go index fcd9f00..0957c42 100644 --- a/logger/general_logging.go +++ b/logger/general_logging.go @@ -193,7 +193,10 @@ func (l *GeneralLog) Table(ctx context.Context, op consts.LogClusterDetail, data ) } + println() tbl.Print() + println() + println() } else if op == consts.LoggingInfoCluster { a, err := json.MarshalIndent(data[0], "", " ") if err != nil { From 52f1d04fddd1b484a5d5791e16592e770d315cd9 Mon Sep 17 00:00:00 2001 From: Dipankar Das <65275144+dipankardas011@users.noreply.github.com> Date: Fri, 2 Aug 2024 08:08:35 +0530 Subject: [PATCH 3/6] added releases fetch and filting Signed-off-by: Dipankar Das <65275144+dipankardas011@users.noreply.github.com> --- cli/cmd/upgrade.go | 67 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 66 insertions(+), 1 deletion(-) diff --git a/cli/cmd/upgrade.go b/cli/cmd/upgrade.go index f41d377..7f7b375 100644 --- a/cli/cmd/upgrade.go +++ b/cli/cmd/upgrade.go @@ -1,14 +1,61 @@ package cmd import ( + "encoding/json" + "net/http" "os" + "regexp" "github.com/ksctl/cli/logger" "github.com/ksctl/ksctl/pkg/types" + "github.com/pterm/pterm" "github.com/spf13/cobra" ) +func fetchLatestVersion() ([]string, error) { + + type Release struct { + TagName string `json:"tag_name"` + } + + resp, err := http.Get("https://api.github.com/repos/ksctl/cli/releases") + if err != nil { + return nil, err + } + defer resp.Body.Close() + + var _releases []Release + if err := json.NewDecoder(resp.Body).Decode(&_releases); err != nil { + return nil, err + } + + var releases []string + rcRegex := regexp.MustCompile(`.*-rc[0-9]+$`) + for _, release := range _releases { + if rcRegex.MatchString(release.TagName) { + continue + } + releases = append(releases, release.TagName) + } + + return releases, nil +} + +func filterToUpgradeableVersions(versions []string) []string { + var upgradeableVersions []string + for _, version := range versions { + if version > Version { + upgradeableVersions = append(upgradeableVersions, version) + } + } + return upgradeableVersions +} + +func update(version string) error { + return nil +} + var selfUpdate = &cobra.Command{ Use: "self-update", Short: "update the ksctl cli", @@ -17,7 +64,25 @@ var selfUpdate = &cobra.Command{ verbosity, _ := cmd.Flags().GetInt("verbose") var log types.LoggerFactory = logger.NewLogger(verbosity, os.Stdout) - newVer := "TODO" + // if Version == "dev" { + // log.Error("Cannot update a dev version of ksctl") + // os.Exit(1) + // } + + vers, err := fetchLatestVersion() + if err != nil { + log.Error("Failed to fetch latest version", "error", err) + os.Exit(1) + } + vers = filterToUpgradeableVersions(vers) + + log.Print(ctx, "Available versions to update") + selectedOption, _ := pterm.DefaultInteractiveSelect.WithOptions(vers).Show() + + newVer := selectedOption + + if err := update(newVer); err != nil { + } log.Success(ctx, "Updated Ksctl cli", "previousVer", Version, "newVer", newVer) }, From 37d2707b9b04792b28356327ced09ce11e1add0f Mon Sep 17 00:00:00 2001 From: Dipankar Das <65275144+dipankardas011@users.noreply.github.com> Date: Fri, 2 Aug 2024 08:19:19 +0530 Subject: [PATCH 4/6] added initial work on download of artifacts Signed-off-by: Dipankar Das <65275144+dipankardas011@users.noreply.github.com> --- cli/cmd/upgrade.go | 78 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 71 insertions(+), 7 deletions(-) diff --git a/cli/cmd/upgrade.go b/cli/cmd/upgrade.go index 7f7b375..1775303 100644 --- a/cli/cmd/upgrade.go +++ b/cli/cmd/upgrade.go @@ -1,13 +1,16 @@ package cmd import ( + "crypto/sha256" + "encoding/hex" "encoding/json" + "fmt" + "io" "net/http" "os" "regexp" + "runtime" - "github.com/ksctl/cli/logger" - "github.com/ksctl/ksctl/pkg/types" "github.com/pterm/pterm" "github.com/spf13/cobra" @@ -52,7 +55,66 @@ func filterToUpgradeableVersions(versions []string) []string { return upgradeableVersions } +func downloadFile(url, localFilename string) error { + fmt.Printf("Downloading %s to %s\n", url, localFilename) + resp, err := http.Get(url) + if err != nil { + return err + } + defer resp.Body.Close() + + out, err := os.Create(localFilename) + if err != nil { + return err + } + defer out.Close() + + _, err = io.Copy(out, resp.Body) + return err +} +func verifyChecksum(filePath, expectedChecksum string) (bool, error) { + file, err := os.Open(filePath) + if err != nil { + return false, err + } + defer file.Close() + + hash := sha256.New() + if _, err := io.Copy(hash, file); err != nil { + return false, err + } + + calculatedChecksum := hex.EncodeToString(hash.Sum(nil)) + return calculatedChecksum == expectedChecksum, nil +} + +func getOsArch() (string, error) { + arch := runtime.GOARCH + + if arch != "amd64" && arch != "arm64" { + return "", logCli.NewError(ctx, "Unsupported architecture") + } + return arch, nil +} + +func getOs() (string, error) { + os := runtime.GOOS + + if os != "linux" && os != "darwin" { + return "", logCli.NewError(ctx, "Unsupported OS", "message", "will provide support for windows based OS soon") + } + return os, nil +} + func update(version string) error { + os, err := getOs() + if err != nil { + return err + } + arch, err := getOsArch() + if err != nil { + return err + } return nil } @@ -61,30 +123,32 @@ var selfUpdate = &cobra.Command{ Short: "update the ksctl cli", Long: "setups up update for ksctl cli", Run: func(cmd *cobra.Command, args []string) { - verbosity, _ := cmd.Flags().GetInt("verbose") - var log types.LoggerFactory = logger.NewLogger(verbosity, os.Stdout) // if Version == "dev" { // log.Error("Cannot update a dev version of ksctl") // os.Exit(1) // } + logCli.Warn(ctx, "Currently no migrations are supported", "Message", "Please help us by creating a PR to support migrations. Thank you!") + vers, err := fetchLatestVersion() if err != nil { - log.Error("Failed to fetch latest version", "error", err) + logCli.Error("Failed to fetch latest version", "error", err) os.Exit(1) } vers = filterToUpgradeableVersions(vers) - log.Print(ctx, "Available versions to update") + logCli.Print(ctx, "Available versions to update") selectedOption, _ := pterm.DefaultInteractiveSelect.WithOptions(vers).Show() newVer := selectedOption if err := update(newVer); err != nil { + logCli.Error("Failed to update ksctl cli", "error", err) + os.Exit(1) } - log.Success(ctx, "Updated Ksctl cli", "previousVer", Version, "newVer", newVer) + logCli.Success(ctx, "Updated Ksctl cli", "previousVer", Version, "newVer", newVer) }, } From 10ba5fdacbf9dc6fa558e83f4c255b7371764931 Mon Sep 17 00:00:00 2001 From: Dipankar Das <65275144+dipankardas011@users.noreply.github.com> Date: Fri, 2 Aug 2024 08:38:19 +0530 Subject: [PATCH 5/6] added download and verify checksum done Signed-off-by: Dipankar Das <65275144+dipankardas011@users.noreply.github.com> --- cli/cmd/upgrade.go | 70 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 66 insertions(+), 4 deletions(-) diff --git a/cli/cmd/upgrade.go b/cli/cmd/upgrade.go index 1775303..e11e03d 100644 --- a/cli/cmd/upgrade.go +++ b/cli/cmd/upgrade.go @@ -6,10 +6,12 @@ import ( "encoding/json" "fmt" "io" + "log" "net/http" "os" "regexp" "runtime" + "strings" "github.com/pterm/pterm" @@ -18,6 +20,8 @@ import ( func fetchLatestVersion() ([]string, error) { + log.Print(ctx, "Fetching available versions") + type Release struct { TagName string `json:"tag_name"` } @@ -56,7 +60,8 @@ func filterToUpgradeableVersions(versions []string) []string { } func downloadFile(url, localFilename string) error { - fmt.Printf("Downloading %s to %s\n", url, localFilename) + logCli.Print(ctx, "Downloading file", "url", url, "localFilename", localFilename) + resp, err := http.Get(url) if err != nil { return err @@ -72,7 +77,26 @@ func downloadFile(url, localFilename string) error { _, err = io.Copy(out, resp.Body) return err } -func verifyChecksum(filePath, expectedChecksum string) (bool, error) { +func verifyChecksum(filePath, checksumfileLoc string) (bool, error) { + logCli.Print(ctx, "Verifying checksum", "file", filePath, "checksumfile", checksumfileLoc) + + rawChecksum, err := os.ReadFile(checksumfileLoc) + if err != nil { + return false, err + } + checksums := strings.Split(string(rawChecksum), "\n") + + var expectedChecksum string = "LOL" + for _, line := range checksums { + if strings.Contains(line, filePath) { + expectedChecksum = strings.Fields(line)[0] + break + } + } + if expectedChecksum == "LOL" { + return false, logCli.NewError(ctx, "Checksum not found in checksum file") + } + file, err := os.Open(filePath) if err != nil { return false, err @@ -107,14 +131,52 @@ func getOs() (string, error) { } func update(version string) error { - os, err := getOs() + osName, err := getOs() if err != nil { return err } - arch, err := getOsArch() + archName, err := getOsArch() if err != nil { return err } + + logCli.Print(ctx, "Delected System", "OS", osName, "Arch", archName) + downloadURLBase := fmt.Sprintf("https://github.com/ksctl/cli/releases/download/%s", version) + tarFile := fmt.Sprintf("ksctl-cli_%s_%s_%s.tar.gz", version[1:], osName, archName) + checksumFile := fmt.Sprintf("ksctl-cli_%s_checksums.txt", version[1:]) + + tarUri := fmt.Sprintf("%s/%s", downloadURLBase, tarFile) + checksumUri := fmt.Sprintf("%s/%s", downloadURLBase, checksumFile) + + defer func() { + if err := os.Remove(checksumFile); err != nil { + logCli.Error("Failed to remove checksum file", "error", err) + } + + if err := os.Remove(tarFile); err != nil { + logCli.Error("Failed to remove checksum file", "error", err) + } + }() + + if err := downloadFile(tarUri, tarFile); err != nil { + return err + } + + if err := downloadFile(checksumUri, checksumFile); err != nil { + return err + } + + match, err := verifyChecksum(tarFile, checksumFile) + if err != nil { + logCli.Error("Failed to verify checksum", "error", err) + os.Exit(1) + } + if !match { + logCli.Error("Checksum verification failed") + os.Exit(1) + } + logCli.Success(ctx, "Checksum verification successful") + return nil } From 697bf3ef7edf2608a0ced59d7884a2a935dd2ea4 Mon Sep 17 00:00:00 2001 From: Dipankar Das <65275144+dipankardas011@users.noreply.github.com> Date: Fri, 2 Aug 2024 09:22:50 +0530 Subject: [PATCH 6/6] done with update from ksctl cli Signed-off-by: Dipankar Das <65275144+dipankardas011@users.noreply.github.com> --- cli/cmd/upgrade.go | 80 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 69 insertions(+), 11 deletions(-) diff --git a/cli/cmd/upgrade.go b/cli/cmd/upgrade.go index e11e03d..8d352de 100644 --- a/cli/cmd/upgrade.go +++ b/cli/cmd/upgrade.go @@ -1,14 +1,17 @@ package cmd import ( + "archive/tar" + "compress/gzip" "crypto/sha256" "encoding/hex" "encoding/json" "fmt" "io" - "log" "net/http" "os" + "os/exec" + "path/filepath" "regexp" "runtime" "strings" @@ -20,7 +23,7 @@ import ( func fetchLatestVersion() ([]string, error) { - log.Print(ctx, "Fetching available versions") + logCli.Print(ctx, "Fetching available versions") type Release struct { TagName string `json:"tag_name"` @@ -149,6 +152,7 @@ func update(version string) error { checksumUri := fmt.Sprintf("%s/%s", downloadURLBase, checksumFile) defer func() { + logCli.Print(ctx, "Cleaning up") if err := os.Remove(checksumFile); err != nil { logCli.Error("Failed to remove checksum file", "error", err) } @@ -168,15 +172,68 @@ func update(version string) error { match, err := verifyChecksum(tarFile, checksumFile) if err != nil { - logCli.Error("Failed to verify checksum", "error", err) - os.Exit(1) + return logCli.NewError(ctx, "Failed to verify checksum", "error", err) } if !match { - logCli.Error("Checksum verification failed") - os.Exit(1) + return logCli.NewError(ctx, "Checksum verification failed") } logCli.Success(ctx, "Checksum verification successful") + tempDir, err := os.MkdirTemp("", "ksctl-update") + if err != nil { + return logCli.NewError(ctx, "Failed to create temp dir", "error", err) + } + file, err := os.Open(tarFile) + if err != nil { + return logCli.NewError(ctx, "Failed to open tar file", "error", err) + } + defer file.Close() + + gzr, err := gzip.NewReader(file) + if err != nil { + return logCli.NewError(ctx, "Failed to read gzip file", "error", err) + } + defer gzr.Close() + tr := tar.NewReader(gzr) + for { + header, err := tr.Next() + if err == io.EOF { + break + } + if err != nil { + return logCli.NewError(ctx, "Failed to read tar file", "error", err) + } + if header.Name == "ksctl" { + outFile, err := os.Create(filepath.Join(tempDir, "ksctl")) + if err != nil { + return logCli.NewError(ctx, "Failed to create ksctl binary", "error", err) + } + defer outFile.Close() + + if _, err := io.Copy(outFile, tr); err != nil { + return logCli.NewError(ctx, "Failed to copy ksctl binary", "error", err) + } + break + } + } + + logCli.Print(ctx, "Making ksctl executable...") + if err := os.Chmod(filepath.Join(tempDir, "ksctl"), 0550); err != nil { + return logCli.NewError(ctx, "Failed to make ksctl executable", "error", err) + } + + logCli.Print(ctx, "Moving ksctl to /usr/local/bin (requires sudo)...") + cmd := exec.Command("sudo", "mv", "-v", filepath.Join(tempDir, "ksctl"), "/usr/local/bin/ksctl") + err = cmd.Run() + if err != nil { + return logCli.NewError(ctx, "Failed to move ksctl to /usr/local/bin", "error", err) + } + + _, err = exec.LookPath("ksctl") + if err != nil { + return logCli.NewError(ctx, "Failed to find ksctl in PATH", "error", err) + } + return nil } @@ -186,12 +243,12 @@ var selfUpdate = &cobra.Command{ Long: "setups up update for ksctl cli", Run: func(cmd *cobra.Command, args []string) { - // if Version == "dev" { - // log.Error("Cannot update a dev version of ksctl") - // os.Exit(1) - // } + if Version == "dev" { + logCli.Error("Cannot update dev version", "msg", "Please use a stable version to update") + os.Exit(1) + } - logCli.Warn(ctx, "Currently no migrations are supported", "Message", "Please help us by creating a PR to support migrations. Thank you!") + logCli.Warn(ctx, "Currently no migrations are supported", "msg", "Please help us by creating a PR to support migrations. Thank you!") vers, err := fetchLatestVersion() if err != nil { @@ -211,6 +268,7 @@ var selfUpdate = &cobra.Command{ } logCli.Success(ctx, "Updated Ksctl cli", "previousVer", Version, "newVer", newVer) + logCli.Note(ctx, "Please restart your terminal to use the updated version") }, }