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