ceremonyclient/client/cmd/update.go

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)
}