Files
ctrld/cmd/cli/commands_service_uninstall.go
T

140 lines
4.0 KiB
Go

package cli
import (
"fmt"
"net"
"os"
"path/filepath"
"github.com/spf13/cobra"
"github.com/Control-D-Inc/ctrld"
)
// Uninstall implements the logic from cmdUninstall.Run
func (sc *ServiceCommand) Uninstall(cmd *cobra.Command, args []string) error {
logger := mainLog.Load()
logger.Debug().Msg("Service uninstall command started")
readConfig(false)
v.Unmarshal(&cfg)
s, p, err := sc.initializeServiceManager()
if err != nil {
logger.Error().Err(err).Msg("Failed to initialize service manager")
return err
}
p.cfg = &cfg
if iface == "" {
iface = autoIface
}
p.preRun()
if ir := runningIface(s); ir != nil {
p.runningIface = ir.Name
p.requiredMultiNICsConfig = ir.All
}
if err := checkDeactivationPin(s, nil); isCheckDeactivationPinErr(err) {
logger.Error().Msg("Deactivation pin check failed")
os.Exit(deactivationPinInvalidExitCode)
}
logger.Debug().Msg("Starting service uninstall")
uninstall(p, s)
if cleanup {
logger.Debug().Msg("Performing cleanup operations")
var files []string
// Config file.
files = append(files, v.ConfigFileUsed())
// Log files. For safety, only remove the log_path chain if that path
// is absolute.
logFile := normalizeLogFilePath(cfg.Service.LogPath)
if !filepath.IsAbs(logFile) {
logFile = ""
}
internalLogs := []string{absHomeDir(logFileName), absHomeDir(journalLogFileName)}
for _, err := range removeLogFiles(logFile, debugLogBudget(&cfg.Service).backups, internalLogs) {
logger.Warn().Err(err).Msg("Failed to remove log file")
}
// Socket files.
if dir, _ := socketDir(); dir != "" {
files = append(files, filepath.Join(dir, ctrldControlUnixSock))
files = append(files, filepath.Join(dir, ctrldLogUnixSock))
}
// Static DNS settings files.
withEachPhysicalInterfaces("", "", func(i *net.Interface) error {
file := ctrld.SavedStaticDnsSettingsFilePath(i)
files = append(files, file)
return nil
})
bin, err := os.Executable()
if err != nil {
logger.Warn().Err(err).Msg("Failed to get executable path")
}
if bin != "" && supportedSelfDelete {
files = append(files, bin)
}
// Backup file after upgrading.
oldBin := bin + oldBinSuffix
if _, err := os.Stat(oldBin); err == nil {
files = append(files, oldBin)
}
for _, file := range files {
if file == "" {
continue
}
if err := os.Remove(file); err == nil {
logger.Notice().Str("file", file).Msg("File removed during cleanup")
} else {
logger.Debug().Err(err).Str("file", file).Msg("Failed to remove file during cleanup")
}
}
// Self-delete the ctrld binary if supported
if err := selfDeleteExe(); err != nil {
logger.Warn().Err(err).Msg("Failed to delete ctrld binary")
} else {
if !supportedSelfDelete {
logger.Debug().Msgf("File removed: %s", bin)
}
}
logger.Debug().Msg("Cleanup operations completed")
}
logger.Debug().Msg("Service uninstall command completed")
return nil
}
// removeLogFiles deletes the log files of this installation and returns what
// it could not remove. A missing file is not an error.
func removeLogFiles(logPath string, backups int, internalPaths []string) []error {
for _, path := range internalPaths {
pruneNumberedBackups(path, 0)
}
var errs []error
for _, path := range logFilesToRemove(logPath, backups, internalPaths) {
if err := os.Remove(path); err != nil && !os.IsNotExist(err) {
errs = append(errs, fmt.Errorf("remove %s: %w", path, err))
}
}
return errs
}
// logFilesToRemove names the log files of this installation. The log_path
// backups come from the configured count, because log_path can name a file in
// a directory that holds the files of other programs, and a scan of that
// directory would take their files too. An empty logPath leaves the internal
// files alone.
func logFilesToRemove(logPath string, backups int, internalPaths []string) []string {
var paths []string
if logPath != "" {
paths = append(paths, logPath)
for index := 1; index <= backups; index++ {
paths = append(paths, fmt.Sprintf("%s.%d", logPath, index))
}
}
return append(paths, internalPaths...)
}