Files
RenewCMS/internal/infrastructure/useCases/ManageBrowserUpdates.go
T

176 lines
5.3 KiB
Go

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