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,175 @@
|
||||
package useCases
|
||||
|
||||
import (
|
||||
"RenewCMS/internal/domain/update"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type ManageBrowserUpdatesDependencies struct {
|
||||
Probe update.MachineProbe
|
||||
Locator update.ServiceLocator
|
||||
Units update.UnitWriter
|
||||
Manager update.UnitManager
|
||||
Status update.HelperStatusWriter
|
||||
Now func() time.Time
|
||||
}
|
||||
|
||||
type EnableBrowserUpdatesUseCase struct {
|
||||
dependencies ManageBrowserUpdatesDependencies
|
||||
}
|
||||
|
||||
type DisableBrowserUpdatesUseCase struct {
|
||||
dependencies ManageBrowserUpdatesDependencies
|
||||
}
|
||||
|
||||
func NewEnableBrowserUpdatesUseCase(dependencies ManageBrowserUpdatesDependencies) *EnableBrowserUpdatesUseCase {
|
||||
return &EnableBrowserUpdatesUseCase{dependencies: dependencies}
|
||||
}
|
||||
|
||||
func NewDisableBrowserUpdatesUseCase(dependencies ManageBrowserUpdatesDependencies) *DisableBrowserUpdatesUseCase {
|
||||
return &DisableBrowserUpdatesUseCase{dependencies: dependencies}
|
||||
}
|
||||
|
||||
func (e *EnableBrowserUpdatesUseCase) Enable(options update.InstallOptions) (string, error) {
|
||||
d := e.dependencies
|
||||
if err := update.CheckInstallEnvironment(d.Probe); err != nil {
|
||||
return "", err
|
||||
}
|
||||
resolved, err := e.resolve(options)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if err := e.install(resolved); err != nil {
|
||||
e.undo()
|
||||
return "", err
|
||||
}
|
||||
status := update.HelperStatus{
|
||||
Version: update.HelperStatusVersion,
|
||||
Service: resolved.Service,
|
||||
Binary: resolved.Binary,
|
||||
DataDir: resolved.DataDir,
|
||||
InstalledAt: d.Now().UTC(),
|
||||
}
|
||||
if err := d.Status.Write(resolved.DataDir, status); err != nil {
|
||||
e.undo()
|
||||
return "", err
|
||||
}
|
||||
return enabledMessage(resolved), nil
|
||||
}
|
||||
|
||||
func (e *EnableBrowserUpdatesUseCase) resolve(options update.InstallOptions) (update.InstallOptions, error) {
|
||||
service := firstNonEmpty(options.Service, update.DefaultService)
|
||||
description, found := e.dependencies.Locator.Locate(service)
|
||||
resolved := update.InstallOptions{
|
||||
Service: service,
|
||||
Binary: firstNonEmpty(options.Binary, description.BinaryPath),
|
||||
DataDir: firstNonEmpty(options.DataDir, description.DataDir),
|
||||
}
|
||||
if resolved.Binary == "" || (resolved.DataDir == "" && !found) {
|
||||
return resolved, update.ErrServiceNotFound
|
||||
}
|
||||
if resolved.DataDir == "" {
|
||||
return resolved, update.ErrDataDirNotFound
|
||||
}
|
||||
resolved.Port = e.port(options.Port, description)
|
||||
return resolved, update.ValidatePort(resolved.Port)
|
||||
}
|
||||
|
||||
func (e *EnableBrowserUpdatesUseCase) port(flag string, description update.ServiceDescription) string {
|
||||
if flag != "" {
|
||||
return flag
|
||||
}
|
||||
if port, found := e.dependencies.Locator.PortFromEnvironmentFile(description.EnvironmentFile); found {
|
||||
return port
|
||||
}
|
||||
return update.DefaultPort
|
||||
}
|
||||
|
||||
func (e *EnableBrowserUpdatesUseCase) install(options update.InstallOptions) error {
|
||||
d := e.dependencies
|
||||
layout := update.HelperLayout{DataDir: options.DataDir, BinaryPath: options.Binary}
|
||||
if err := d.Units.Write(update.ServiceUnitName, update.RenderServiceUnit(options)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := d.Units.Write(update.PathUnitName, update.RenderPathUnit(layout)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := d.Manager.DaemonReload(); err != nil {
|
||||
return err
|
||||
}
|
||||
return d.Manager.EnableNow(update.PathUnitName)
|
||||
}
|
||||
|
||||
func (e *EnableBrowserUpdatesUseCase) undo() {
|
||||
d := e.dependencies
|
||||
_ = d.Manager.DisableNow(update.PathUnitName)
|
||||
_, _ = d.Units.Remove(update.ServiceUnitName)
|
||||
_, _ = d.Units.Remove(update.PathUnitName)
|
||||
_ = d.Manager.DaemonReload()
|
||||
}
|
||||
|
||||
func enabledMessage(options update.InstallOptions) string {
|
||||
lines := []string{
|
||||
"Browser updates are enabled for " + options.Service + ".",
|
||||
"Installed " + update.PathUnitName + " and " + update.ServiceUnitName + " (port " + options.Port + ") and wrote " + update.HelperStatusFileName + " in " + options.DataDir + ".",
|
||||
"To undo it, run: renewcms disable-browser-updates",
|
||||
}
|
||||
return strings.Join(lines, "\n")
|
||||
}
|
||||
|
||||
func (u *DisableBrowserUpdatesUseCase) Disable(options update.InstallOptions) (string, error) {
|
||||
d := u.dependencies
|
||||
if d.Probe.OS() != update.OSLinux || !d.Probe.SystemdRunning() {
|
||||
return notEnabledMessage, nil
|
||||
}
|
||||
if err := update.CheckInstallEnvironment(d.Probe); err != nil {
|
||||
return "", err
|
||||
}
|
||||
dataDir := firstNonEmpty(options.DataDir, u.locatedDataDir(options.Service))
|
||||
|
||||
_ = d.Manager.DisableNow(update.PathUnitName)
|
||||
removed := u.removeUnits()
|
||||
if dataDir == "" {
|
||||
return "", update.ErrDataDirNotFound
|
||||
}
|
||||
statusRemoved, err := d.Status.Remove(dataDir)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if !removed && !statusRemoved {
|
||||
return notEnabledMessage, nil
|
||||
}
|
||||
if err := d.Manager.DaemonReload(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return disabledMessage, nil
|
||||
}
|
||||
|
||||
func (u *DisableBrowserUpdatesUseCase) locatedDataDir(service string) string {
|
||||
description, _ := u.dependencies.Locator.Locate(firstNonEmpty(service, update.DefaultService))
|
||||
return description.DataDir
|
||||
}
|
||||
|
||||
func (u *DisableBrowserUpdatesUseCase) removeUnits() bool {
|
||||
removedAny := false
|
||||
for _, name := range []string{update.PathUnitName, update.ServiceUnitName} {
|
||||
removed, err := u.dependencies.Units.Remove(name)
|
||||
removedAny = removedAny || (removed && err == nil)
|
||||
}
|
||||
return removedAny
|
||||
}
|
||||
|
||||
const (
|
||||
notEnabledMessage = "Browser updates were not enabled, nothing to remove."
|
||||
disabledMessage = "Browser updates are disabled. The restart request, the result, the staged files and the backups were left in place."
|
||||
)
|
||||
|
||||
func firstNonEmpty(values ...string) string {
|
||||
for _, value := range values {
|
||||
if value != "" {
|
||||
return value
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
Reference in new issue
Block a user