ceremonyclient/client/cmd/update.go
Tyler Sturos 9cfbdef12c
Feat/2.1 qclient refactor and node install (#429)
* initial auto-update

* working link, update, and testing docker container and scripts

* refactor packages/folders

* move files to proper folders

* fix typos

Closes #421

* optimize rpm imports

* optimize channel imports

* Refactor split command to allow testing of split operations

Closes #338

* modify split and test for folder changes

* remove alias

* fix docker warning about FROM and AS being in different letter case

Closes #422

* QClient Account Command

* Display transaction details and confirmation prompts for transfer and merge commands

* build qclient docker improvements

* update build args for mpfr.so.6

* update install and node commands

* remove NodeConfig check for qclient node commands

* udpate

* working node commands

* update commands

* move utils and rename package

---------

Co-authored-by: Vasyl Tretiakov <vasyl.tretiakov@gmail.com>
Co-authored-by: littleblackcloud <163544315+littleblackcloud@users.noreply.github.com>
Co-authored-by: 0xOzgur <29779769+0xOzgur@users.noreply.github.com>
Co-authored-by: Cassandra Heart <7929478+CassOnMars@users.noreply.github.com>
2025-04-11 21:43:20 -05:00

168 lines
5.0 KiB
Go

package cmd
import (
"fmt"
"os"
"path/filepath"
"runtime"
"strings"
"github.com/spf13/cobra"
"source.quilibrium.com/quilibrium/monorepo/client/utils"
"source.quilibrium.com/quilibrium/monorepo/node/config"
)
var (
osType = runtime.GOOS
arch = runtime.GOARCH
)
// updateCmd represents the command to update the Quilibrium client
var updateCmd = &cobra.Command{
Use: "update [version]",
Short: "Update Quilibrium client",
Long: `Update Quilibrium client to a specified version or the latest version.
If no version is specified, the latest version will be installed.
If the current version is already the latest version, the command will exit with a message.
Examples:
# Update to the latest version
qclient update
# Update to a specific version
qclient update 2.1.0`,
Args: cobra.RangeArgs(0, 1),
Run: func(cmd *cobra.Command, args []string) {
// Get system information and validate
localOsType, localArch, err := utils.GetSystemInfo()
if err != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
return
}
osType = localOsType
arch = localArch
// Determine version to install
version := determineVersion(args)
fmt.Fprintf(os.Stdout, "Updating Quilibrium client for %s-%s, version: %s\n", osType, arch, version)
// Update the client
updateClient(version)
},
}
func init() {
rootCmd.AddCommand(updateCmd)
}
// determineVersion gets the version to install from args or defaults to "latest"
func determineVersion(args []string) string {
if len(args) > 0 {
return args[0]
}
return "latest"
}
// updateClient handles the client update process
func updateClient(version string) {
currentVersion := config.GetVersionString()
// If version is "latest", get the latest version
if version == "latest" {
latestVersion, err := utils.GetLatestVersion(utils.ReleaseTypeQClient)
if err != nil {
fmt.Fprintf(os.Stderr, "Error getting latest version: %v\n", err)
return
}
version = latestVersion
fmt.Fprintf(os.Stdout, "Latest version: %s\n", version)
}
if version == currentVersion {
fmt.Fprintf(os.Stdout, "Already on version %s\n", currentVersion)
return
}
// Check if we need sudo privileges
if err := utils.CheckAndRequestSudo(fmt.Sprintf("Updating client at %s requires root privileges", utils.ClientInstallPath)); err != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
return
}
// Create version-specific installation directory
versionDir := filepath.Join(utils.ClientInstallPath, version)
if err := os.MkdirAll(versionDir, 0755); err != nil {
fmt.Fprintf(os.Stderr, "Error creating installation directory: %v\n", err)
return
}
// Create data directory
versionDataDir := filepath.Join(utils.ClientDataPath, version)
if err := os.MkdirAll(versionDataDir, 0755); err != nil {
fmt.Fprintf(os.Stderr, "Error creating data directory: %v\n", err)
return
}
// Construct the expected filename for the specified version
// Remove 'v' prefix if present for filename construction
versionWithoutV := strings.TrimPrefix(version, "v")
// Download the release directly
err := utils.DownloadRelease(utils.ReleaseTypeQClient, versionWithoutV)
if err != nil {
fmt.Fprintf(os.Stderr, "Error downloading version %s: %v\n", version, err)
fmt.Fprintf(os.Stderr, "The specified version %s does not exist for %s-%s\n", version, osType, arch)
// Clean up the created directories since installation failed
os.RemoveAll(versionDir)
os.RemoveAll(versionDataDir)
return
}
// Download signature files
if err := utils.DownloadReleaseSignatures(utils.ReleaseTypeQClient, versionWithoutV); err != nil {
fmt.Fprintf(os.Stderr, "Warning: Failed to download signature files: %v\n", err)
fmt.Fprintf(os.Stdout, "Continuing with installation...\n")
}
// Successfully downloaded the specific version
finishInstallation(version)
}
// finishInstallation completes the update process
func finishInstallation(version string) {
// Construct executable path
execPath := filepath.Join(utils.ClientDataPath, version, "qclient-"+version+"-"+osType+"-"+arch)
// Make the binary executable
if err := os.Chmod(execPath, 0755); err != nil {
fmt.Fprintf(os.Stderr, "Error making binary executable: %v\n", err)
return
}
// Create symlink to the new version
symlinkPath := utils.DefaultQClientSymlinkPath
// Check if we need sudo privileges for creating symlink in system directory
if strings.HasPrefix(symlinkPath, "/usr/") || strings.HasPrefix(symlinkPath, "/bin/") || strings.HasPrefix(symlinkPath, "/sbin/") {
if err := utils.CheckAndRequestSudo(fmt.Sprintf("Creating symlink at %s requires root privileges", symlinkPath)); err != nil {
fmt.Fprintf(os.Stderr, "Warning: Failed to get sudo privileges: %v\n", err)
return
}
}
// Create symlink
if err := utils.CreateSymlink(execPath, symlinkPath); err != nil {
fmt.Fprintf(os.Stderr, "Error creating symlink: %v\n", err)
return
}
fmt.Fprintf(os.Stdout, "Successfully updated qclient to version %s\n", version)
fmt.Fprintf(os.Stdout, "Executable: %s\n", execPath)
fmt.Fprintf(os.Stdout, "Symlink: %s\n", symlinkPath)
}