mirror of
https://github.com/QuilibriumNetwork/ceremonyclient.git
synced 2026-02-22 02:47:26 +08:00
* 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>
297 lines
8.2 KiB
Go
297 lines
8.2 KiB
Go
package node
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"runtime"
|
|
"strings"
|
|
|
|
"github.com/spf13/cobra"
|
|
)
|
|
|
|
// autoUpdateCmd represents the command to setup automatic updates
|
|
var autoUpdateCmd = &cobra.Command{
|
|
Use: "auto-update [enable|disable|status]",
|
|
Short: "Setup automatic update checks",
|
|
Long: `Setup, remove, or check status of a cron job to automatically check for Quilibrium node updates every 10 minutes.
|
|
|
|
This command will create, remove, or check a cron entry that runs 'qclient node update' every 10 minutes
|
|
to check for and apply any available updates.
|
|
|
|
Example:
|
|
# Setup automatic update checks
|
|
qclient node auto-update enable
|
|
|
|
# Remove automatic update checks
|
|
qclient node auto-update disable
|
|
|
|
# Check if automatic update is enabled
|
|
qclient node auto-update status`,
|
|
Run: func(cmd *cobra.Command, args []string) {
|
|
if len(args) != 1 || (args[0] != "enable" && args[0] != "disable" && args[0] != "status") {
|
|
fmt.Fprintf(os.Stderr, "Error: must specify 'enable', 'disable', or 'status'\n")
|
|
cmd.Help()
|
|
return
|
|
}
|
|
|
|
if args[0] == "enable" {
|
|
setupCronJob()
|
|
} else if args[0] == "disable" {
|
|
removeCronJob()
|
|
} else if args[0] == "status" {
|
|
checkAutoUpdateStatus()
|
|
}
|
|
},
|
|
}
|
|
|
|
func init() {
|
|
NodeCmd.AddCommand(autoUpdateCmd)
|
|
}
|
|
|
|
func setupCronJob() {
|
|
// Get full path to qclient executable
|
|
qclientPath, err := exec.LookPath("qclient")
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "Error: qclient executable not found in PATH: %v\n", err)
|
|
fmt.Fprintf(os.Stderr, "Please ensure qclient is properly installed and in your PATH (use 'sudo qclient link')\n")
|
|
return
|
|
}
|
|
|
|
// Absolute path for qclient
|
|
qclientAbsPath, err := filepath.Abs(qclientPath)
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "Error getting absolute path for qclient: %v\n", err)
|
|
return
|
|
}
|
|
|
|
// OS-specific setup
|
|
if runtime.GOOS == "darwin" || runtime.GOOS == "linux" {
|
|
setupUnixCron(qclientAbsPath)
|
|
} else {
|
|
fmt.Fprintf(os.Stderr, "Error: auto-update is only supported on macOS and Linux\n")
|
|
return
|
|
}
|
|
}
|
|
|
|
func removeCronJob() {
|
|
// OS-specific removal
|
|
if runtime.GOOS == "darwin" || runtime.GOOS == "linux" {
|
|
removeUnixCron()
|
|
} else {
|
|
fmt.Fprintf(os.Stderr, "Error: auto-update is only supported on macOS and Linux\n")
|
|
return
|
|
}
|
|
}
|
|
|
|
func isCrontabInstalled() bool {
|
|
// Check if crontab is installed
|
|
_, err := exec.LookPath("crontab")
|
|
return err == nil
|
|
}
|
|
|
|
func installCrontab() {
|
|
fmt.Fprintf(os.Stdout, "Installing cron package...\n")
|
|
// Install crontab
|
|
updateCmd := exec.Command("sudo", "apt-get", "update")
|
|
updateCmd.Stdout = nil
|
|
updateCmd.Stderr = nil
|
|
if err := updateCmd.Run(); err != nil {
|
|
fmt.Fprintf(os.Stderr, "Error updating package lists: %v\n", err)
|
|
return
|
|
}
|
|
|
|
installCmd := exec.Command("sudo", "apt-get", "install", "-y", "cron")
|
|
installCmd.Stdout = nil
|
|
installCmd.Stderr = nil
|
|
if err := installCmd.Run(); err != nil {
|
|
fmt.Fprintf(os.Stderr, "Error installing cron package: %v\n", err)
|
|
return
|
|
}
|
|
|
|
// verify crontab is installed
|
|
if isCrontabInstalled() {
|
|
fmt.Fprintf(os.Stdout, "Cron package installed\n")
|
|
} else {
|
|
fmt.Fprintf(os.Stderr, "Error: cron package not installed\n")
|
|
os.Exit(1)
|
|
}
|
|
}
|
|
|
|
func setupUnixCron(qclientPath string) {
|
|
if !isCrontabInstalled() {
|
|
fmt.Fprintf(os.Stdout, "Crontab command not found, attempting to install cron package...\n")
|
|
installCrontab()
|
|
}
|
|
|
|
fmt.Fprintf(os.Stdout, "Setting up cron job...\n")
|
|
// Create cron expression: run every 10 minutes
|
|
cronExpression := fmt.Sprintf("*/10 * * * * %s node update > /dev/null 2>&1", qclientPath)
|
|
|
|
// Check existing crontab
|
|
checkCmd := exec.Command("crontab", "-l")
|
|
checkOutput, err := checkCmd.CombinedOutput()
|
|
|
|
var currentCrontab string
|
|
if err != nil {
|
|
// If there's no crontab yet, this is fine, start with empty crontab
|
|
currentCrontab = ""
|
|
} else {
|
|
currentCrontab = string(checkOutput)
|
|
}
|
|
|
|
// Check if our update command is already in crontab
|
|
if strings.Contains(currentCrontab, "### qclient-auto-update") {
|
|
fmt.Fprintf(os.Stdout, "Automatic update check is already configured in crontab\n")
|
|
return
|
|
}
|
|
|
|
// Add new cron entry with indicators
|
|
newCrontab := currentCrontab
|
|
if strings.TrimSpace(newCrontab) != "" && !strings.HasSuffix(newCrontab, "\n") {
|
|
newCrontab += "\n"
|
|
}
|
|
newCrontab += "### qclient-auto-update\n" +
|
|
cronExpression + "\n" +
|
|
"### end-qclient-auto-update\n"
|
|
|
|
// Write to temporary file
|
|
tempFile, err := os.CreateTemp("", "qclient-crontab")
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "Error creating temporary file: %v\n", err)
|
|
return
|
|
}
|
|
defer os.Remove(tempFile.Name())
|
|
|
|
if _, err := tempFile.WriteString(newCrontab); err != nil {
|
|
fmt.Fprintf(os.Stderr, "Error writing to temporary file: %v\n", err)
|
|
return
|
|
}
|
|
tempFile.Close()
|
|
|
|
// Install new crontab
|
|
installCmd := exec.Command("crontab", tempFile.Name())
|
|
if err := installCmd.Run(); err != nil {
|
|
fmt.Fprintf(os.Stderr, "Error installing crontab: %v\n", err)
|
|
return
|
|
}
|
|
|
|
fmt.Fprintf(os.Stdout, "Successfully configured cron job to check for updates every 10 minutes\n")
|
|
fmt.Fprintf(os.Stdout, "Added: %s\n", cronExpression)
|
|
}
|
|
|
|
func removeUnixCron() {
|
|
if !isCrontabInstalled() {
|
|
fmt.Fprintf(os.Stderr, "Error: crontab command not found\n")
|
|
return
|
|
}
|
|
|
|
fmt.Fprintf(os.Stdout, "Removing auto-update cron job...\n")
|
|
|
|
// Check existing crontab
|
|
checkCmd := exec.Command("crontab", "-l")
|
|
checkOutput, err := checkCmd.CombinedOutput()
|
|
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "Error checking existing crontab: %v\n", err)
|
|
return
|
|
}
|
|
|
|
currentCrontab := string(checkOutput)
|
|
|
|
// No crontab or doesn't contain our section
|
|
if currentCrontab == "" || !strings.Contains(currentCrontab, "### qclient-auto-update") {
|
|
fmt.Fprintf(os.Stdout, "No auto-update job found in crontab\n")
|
|
return
|
|
}
|
|
|
|
// Remove our section
|
|
startMarker := "### qclient-auto-update"
|
|
endMarker := "### end-qclient-auto-update"
|
|
|
|
startIdx := strings.Index(currentCrontab, startMarker)
|
|
endIdx := strings.Index(currentCrontab, endMarker)
|
|
|
|
var newCrontab string
|
|
if startIdx >= 0 && endIdx >= 0 {
|
|
endIdx += len(endMarker)
|
|
// Remove the section including markers
|
|
newCrontab = currentCrontab[:startIdx] + currentCrontab[endIdx:]
|
|
} else {
|
|
newCrontab = currentCrontab
|
|
}
|
|
|
|
// Clean up any leftover double newlines
|
|
newCrontab = strings.ReplaceAll(newCrontab, "\n\n\n", "\n\n")
|
|
if strings.TrimSpace(newCrontab) != "" && !strings.HasSuffix(newCrontab, "\n") {
|
|
newCrontab += "\n"
|
|
}
|
|
|
|
// Write to temporary file
|
|
tempFile, err := os.CreateTemp("", "qclient-crontab")
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "Error creating temporary file: %v\n", err)
|
|
return
|
|
}
|
|
defer os.Remove(tempFile.Name())
|
|
|
|
if _, err := tempFile.WriteString(newCrontab); err != nil {
|
|
fmt.Fprintf(os.Stderr, "Error writing to temporary file: %v\n", err)
|
|
return
|
|
}
|
|
tempFile.Close()
|
|
|
|
// Install new crontab
|
|
installCmd := exec.Command("crontab", tempFile.Name())
|
|
if err := installCmd.Run(); err != nil {
|
|
fmt.Fprintf(os.Stderr, "Error updating crontab: %v\n", err)
|
|
return
|
|
}
|
|
|
|
fmt.Fprintf(os.Stdout, "Successfully removed auto-update cron job\n")
|
|
}
|
|
|
|
func checkAutoUpdateStatus() {
|
|
if !isCrontabInstalled() {
|
|
fmt.Fprintf(os.Stderr, "Error: crontab command not found\n")
|
|
fmt.Fprintf(os.Stdout, "Auto-update is not enabled (crontab not installed)\n")
|
|
return
|
|
}
|
|
|
|
// Check existing crontab
|
|
checkCmd := exec.Command("crontab", "-l")
|
|
checkOutput, err := checkCmd.CombinedOutput()
|
|
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stdout, "Auto-update is not enabled (no crontab found)\n")
|
|
return
|
|
}
|
|
|
|
currentCrontab := string(checkOutput)
|
|
|
|
if strings.Contains(currentCrontab, "### qclient-auto-update") {
|
|
// Extract the cron expression
|
|
startMarker := "### qclient-auto-update"
|
|
endMarker := "### end-qclient-auto-update"
|
|
|
|
startIdx := strings.Index(currentCrontab, startMarker) + len(startMarker)
|
|
endIdx := strings.Index(currentCrontab, endMarker)
|
|
|
|
if startIdx >= 0 && endIdx >= 0 {
|
|
cronSection := currentCrontab[startIdx:endIdx]
|
|
cronLines := strings.Split(strings.TrimSpace(cronSection), "\n")
|
|
if len(cronLines) > 0 {
|
|
fmt.Fprintf(os.Stdout, "Auto-update is enabled.")
|
|
fmt.Fprintf(os.Stdout, "The installed schedule is: %s\n", strings.TrimSpace(cronLines[0]))
|
|
} else {
|
|
fmt.Fprintf(os.Stdout, "Auto-update is enabled\n")
|
|
}
|
|
} else {
|
|
fmt.Fprintf(os.Stdout, "Auto-update is enabled\n")
|
|
}
|
|
} else {
|
|
fmt.Fprintf(os.Stdout, "Auto-update is not enabled\n")
|
|
}
|
|
}
|