feat: restart to apply update, privileged helper, rollback
This commit is contained in:
1 parent
70460e4170
commit
54e8fd5fed
63 files changed
+8635
-164
No files matched your search
@@ -0,0 +1,138 @@
|
||||
package update
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrNeedsLinux = errors.New("Browser updates need Linux with systemd.")
|
||||
ErrNeedsSystemd = errors.New("Browser updates need systemd, which this machine is not running.")
|
||||
ErrNeedsRoot = errors.New("Run this command as root, for example with sudo.")
|
||||
ErrServiceNotFound = errors.New("Could not find the RenewCMS service. Pass --service, --binary and --data-dir.")
|
||||
ErrDataDirNotFound = errors.New("Could not find the data directory. Pass --data-dir.")
|
||||
ErrInvalidPort = errors.New("The port must be a number between 1 and 65535.")
|
||||
)
|
||||
|
||||
const (
|
||||
OSLinux = "linux"
|
||||
pathUnitDescription = "Watch for a RenewCMS restart request"
|
||||
)
|
||||
|
||||
type ServiceDescription struct {
|
||||
Name string
|
||||
BinaryPath string
|
||||
DataDir string
|
||||
EnvironmentFile string
|
||||
}
|
||||
|
||||
type InstallOptions struct {
|
||||
Service string
|
||||
Binary string
|
||||
DataDir string
|
||||
Port string
|
||||
}
|
||||
|
||||
type MachineProbe interface {
|
||||
OS() string
|
||||
SystemdRunning() bool
|
||||
IsRoot() bool
|
||||
}
|
||||
|
||||
type ServiceLocator interface {
|
||||
Locate(name string) (ServiceDescription, bool)
|
||||
PortFromEnvironmentFile(path string) (string, bool)
|
||||
}
|
||||
|
||||
type UnitWriter interface {
|
||||
Write(name string, content string) error
|
||||
Remove(name string) (bool, error)
|
||||
}
|
||||
|
||||
type UnitManager interface {
|
||||
DaemonReload() error
|
||||
EnableNow(unit string) error
|
||||
DisableNow(unit string) error
|
||||
}
|
||||
|
||||
type HelperStatusWriter interface {
|
||||
Write(dataDir string, status HelperStatus) error
|
||||
Remove(dataDir string) (bool, error)
|
||||
}
|
||||
|
||||
func CheckInstallEnvironment(probe MachineProbe) error {
|
||||
if probe.OS() != OSLinux {
|
||||
return ErrNeedsLinux
|
||||
}
|
||||
if !probe.SystemdRunning() {
|
||||
return ErrNeedsSystemd
|
||||
}
|
||||
if !probe.IsRoot() {
|
||||
return ErrNeedsRoot
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func ValidatePort(port string) error {
|
||||
number, err := strconv.Atoi(port)
|
||||
if err != nil || number < 1 || number > 65535 {
|
||||
return ErrInvalidPort
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func RenderPathUnit(layout HelperLayout) string {
|
||||
lines := []string{
|
||||
"[Unit]",
|
||||
"Description=" + pathUnitDescription,
|
||||
"",
|
||||
"[Path]",
|
||||
"PathExists=" + layout.RestartRequestPath(),
|
||||
"Unit=" + ServiceUnitName,
|
||||
"",
|
||||
"[Install]",
|
||||
"WantedBy=multi-user.target",
|
||||
"",
|
||||
}
|
||||
return strings.Join(lines, "\n")
|
||||
}
|
||||
|
||||
func RenderServiceUnit(options InstallOptions) string {
|
||||
command := []string{
|
||||
quoteUnitArgument(options.Binary),
|
||||
"apply-update",
|
||||
"--service", quoteUnitArgument(options.Service),
|
||||
"--binary", quoteUnitArgument(options.Binary),
|
||||
"--data-dir", quoteUnitArgument(options.DataDir),
|
||||
"--port", options.Port,
|
||||
}
|
||||
lines := []string{
|
||||
"[Unit]",
|
||||
"Description=RenewCMS update helper",
|
||||
"",
|
||||
"[Service]",
|
||||
"Type=oneshot",
|
||||
"User=root",
|
||||
"ExecStart=" + strings.Join(command, " "),
|
||||
"",
|
||||
}
|
||||
return strings.Join(lines, "\n")
|
||||
}
|
||||
|
||||
var unitArgumentEscaper = strings.NewReplacer(
|
||||
`\`, `\\`,
|
||||
`"`, `\"`,
|
||||
`%`, `%%`,
|
||||
`$`, `$$`,
|
||||
"\n", `\n`,
|
||||
"\r", `\r`,
|
||||
"\t", `\t`,
|
||||
)
|
||||
|
||||
func quoteUnitArgument(value string) string {
|
||||
if !strings.ContainsAny(value, " \t\r\n\"'\\%$;") {
|
||||
return value
|
||||
}
|
||||
return `"` + unitArgumentEscaper.Replace(value) + `"`
|
||||
}
|
||||
Reference in new issue
Block a user