mirror of
https://github.com/fankes/beszel.git
synced 2025-10-19 01:39:34 +08:00
update project structure
- move agent to /agent - change /beszel to /src - update workflows and docker builds
This commit is contained in:
165
agent/update.go
Normal file
165
agent/update.go
Normal file
@@ -0,0 +1,165 @@
|
||||
package agent
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/henrygd/beszel/src/ghupdate"
|
||||
)
|
||||
|
||||
// restarter knows how to restart the beszel-agent service.
|
||||
type restarter interface {
|
||||
Restart() error
|
||||
}
|
||||
|
||||
type systemdRestarter struct{ cmd string }
|
||||
|
||||
func (s *systemdRestarter) Restart() error {
|
||||
// Only restart if the service is active
|
||||
if err := exec.Command(s.cmd, "is-active", "beszel-agent.service").Run(); err != nil {
|
||||
return nil
|
||||
}
|
||||
ghupdate.ColorPrint(ghupdate.ColorYellow, "Restarting beszel-agent.service via systemd…")
|
||||
return exec.Command(s.cmd, "restart", "beszel-agent.service").Run()
|
||||
}
|
||||
|
||||
type openRCRestarter struct{ cmd string }
|
||||
|
||||
func (o *openRCRestarter) Restart() error {
|
||||
if err := exec.Command(o.cmd, "status", "beszel-agent").Run(); err != nil {
|
||||
return nil
|
||||
}
|
||||
ghupdate.ColorPrint(ghupdate.ColorYellow, "Restarting beszel-agent via OpenRC…")
|
||||
return exec.Command(o.cmd, "restart", "beszel-agent").Run()
|
||||
}
|
||||
|
||||
type openWRTRestarter struct{ cmd string }
|
||||
|
||||
func (w *openWRTRestarter) Restart() error {
|
||||
if err := exec.Command(w.cmd, "running", "beszel-agent").Run(); err != nil {
|
||||
return nil
|
||||
}
|
||||
ghupdate.ColorPrint(ghupdate.ColorYellow, "Restarting beszel-agent via procd…")
|
||||
return exec.Command(w.cmd, "restart", "beszel-agent").Run()
|
||||
}
|
||||
|
||||
type freeBSDRestarter struct{ cmd string }
|
||||
|
||||
func (f *freeBSDRestarter) Restart() error {
|
||||
if err := exec.Command(f.cmd, "beszel-agent", "status").Run(); err != nil {
|
||||
return nil
|
||||
}
|
||||
ghupdate.ColorPrint(ghupdate.ColorYellow, "Restarting beszel-agent via FreeBSD rc…")
|
||||
return exec.Command(f.cmd, "beszel-agent", "restart").Run()
|
||||
}
|
||||
|
||||
func detectRestarter() restarter {
|
||||
if path, err := exec.LookPath("systemctl"); err == nil {
|
||||
return &systemdRestarter{cmd: path}
|
||||
}
|
||||
if path, err := exec.LookPath("rc-service"); err == nil {
|
||||
return &openRCRestarter{cmd: path}
|
||||
}
|
||||
if path, err := exec.LookPath("service"); err == nil {
|
||||
if runtime.GOOS == "freebsd" {
|
||||
return &freeBSDRestarter{cmd: path}
|
||||
}
|
||||
return &openWRTRestarter{cmd: path}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Update checks GitHub for a newer release of beszel-agent, applies it,
|
||||
// fixes SELinux context if needed, and restarts the service.
|
||||
func Update(useMirror bool) error {
|
||||
exePath, _ := os.Executable()
|
||||
|
||||
dataDir, err := getDataDir()
|
||||
if err != nil {
|
||||
dataDir = os.TempDir()
|
||||
}
|
||||
updated, err := ghupdate.Update(ghupdate.Config{
|
||||
ArchiveExecutable: "beszel-agent",
|
||||
DataDir: dataDir,
|
||||
UseMirror: useMirror,
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
if !updated {
|
||||
return nil
|
||||
}
|
||||
|
||||
// make sure the file is executable
|
||||
if err := os.Chmod(exePath, 0755); err != nil {
|
||||
ghupdate.ColorPrintf(ghupdate.ColorYellow, "Warning: failed to set executable permissions: %v", err)
|
||||
}
|
||||
// set ownership to beszel:beszel if possible
|
||||
if chownPath, err := exec.LookPath("chown"); err == nil {
|
||||
if err := exec.Command(chownPath, "beszel:beszel", exePath).Run(); err != nil {
|
||||
ghupdate.ColorPrintf(ghupdate.ColorYellow, "Warning: failed to set file ownership: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// 6) Fix SELinux context if necessary
|
||||
if err := handleSELinuxContext(exePath); err != nil {
|
||||
ghupdate.ColorPrintf(ghupdate.ColorYellow, "Warning: SELinux context handling: %v", err)
|
||||
}
|
||||
|
||||
// 7) Restart service if running under a recognised init system
|
||||
if r := detectRestarter(); r != nil {
|
||||
if err := r.Restart(); err != nil {
|
||||
ghupdate.ColorPrintf(ghupdate.ColorYellow, "Warning: failed to restart service: %v", err)
|
||||
ghupdate.ColorPrint(ghupdate.ColorYellow, "Please restart the service manually.")
|
||||
} else {
|
||||
ghupdate.ColorPrint(ghupdate.ColorGreen, "Service restarted successfully")
|
||||
}
|
||||
} else {
|
||||
ghupdate.ColorPrint(ghupdate.ColorYellow, "No supported init system detected; please restart manually if needed.")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// handleSELinuxContext restores or applies the correct SELinux label to the binary.
|
||||
func handleSELinuxContext(path string) error {
|
||||
out, err := exec.Command("getenforce").Output()
|
||||
if err != nil {
|
||||
// SELinux not enabled or getenforce not available
|
||||
return nil
|
||||
}
|
||||
state := strings.TrimSpace(string(out))
|
||||
if state == "Disabled" {
|
||||
return nil
|
||||
}
|
||||
|
||||
ghupdate.ColorPrint(ghupdate.ColorYellow, "SELinux is enabled; applying context…")
|
||||
var errs []string
|
||||
|
||||
// Try persistent context via semanage+restorecon
|
||||
if semanagePath, err := exec.LookPath("semanage"); err == nil {
|
||||
if err := exec.Command(semanagePath, "fcontext", "-a", "-t", "bin_t", path).Run(); err != nil {
|
||||
errs = append(errs, "semanage fcontext failed: "+err.Error())
|
||||
} else if restoreconPath, err := exec.LookPath("restorecon"); err == nil {
|
||||
if err := exec.Command(restoreconPath, "-v", path).Run(); err != nil {
|
||||
errs = append(errs, "restorecon failed: "+err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback to temporary context via chcon
|
||||
if chconPath, err := exec.LookPath("chcon"); err == nil {
|
||||
if err := exec.Command(chconPath, "-t", "bin_t", path).Run(); err != nil {
|
||||
errs = append(errs, "chcon failed: "+err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
if len(errs) > 0 {
|
||||
return fmt.Errorf("SELinux context errors: %s", strings.Join(errs, "; "))
|
||||
}
|
||||
return nil
|
||||
}
|
Reference in New Issue
Block a user