From 98ad4f6078bfb45eec824a65757ea6d447cace3c Mon Sep 17 00:00:00 2001 From: Christophe Fergeau Date: Mon, 15 Mar 2021 16:21:09 +0100 Subject: [PATCH] macos: Reinstall launchd services when their definition changes At the moment, the tray/daemon launchd code only checks that the plist for the launchd service exists, but it does not check if its content is what crc expects. This commit addresses this limitation. The behaviour with respect to daemon/tray restarts should not change with this commit. When we have an easier way to query the running daemon for its version, we can improve on this. This fixes https://github.com/code-ready/crc/issues/2099 --- .../preflight/preflight_checks_tray_darwin.go | 78 +++++++++++++------ pkg/os/launchd/launchd_darwin.go | 32 ++++++-- 2 files changed, 77 insertions(+), 33 deletions(-) diff --git a/pkg/crc/preflight/preflight_checks_tray_darwin.go b/pkg/crc/preflight/preflight_checks_tray_darwin.go index bc565bf36d..2c3e3a187c 100644 --- a/pkg/crc/preflight/preflight_checks_tray_darwin.go +++ b/pkg/crc/preflight/preflight_checks_tray_darwin.go @@ -21,33 +21,35 @@ const ( trayAgentLabel = "crc.tray" ) -var ( - stdOutFilePathDaemon = filepath.Join(constants.CrcBaseDir, ".crcd-agent.log") - stdOutFilePathTray = filepath.Join(constants.CrcBaseDir, ".crct-agent.log") -) - type TrayVersion struct { ShortVersion string `plist:"CFBundleShortVersionString"` } func checkIfDaemonPlistFileExists() error { - // crc setup can be ran from any location in the - // users computer, and we need to update the plist - // file with the path of the crc executable which was - // used to run setup, to force it this check needs - // to always fail so the fix routine is triggered + // we have no way of detecting if a running crc daemon instance uses + // the same binary as the one running 'crc setup' + // Safer for now to keep the previous behaviour of always + // recreating the plist/restarting the daemon + // When we have a way of checking the version of the running + // daemon instance, we can recreate the plist less often. + + return fmt.Errorf("Ignoring this check and triggering re-creation of daemon plist") - return fmt.Errorf("Ignoring this check and triggering creation of daemon plist") + /* + daemonConfig, err := getDaemonConfig() + if err != nil { + return err + } + return launchd.CheckPlist(*daemonConfig) + */ } -func fixDaemonPlistFileExists() error { - // Try to remove the daemon agent from launchd - // and recreate its plist - _ = launchd.Remove(daemonAgentLabel) +func getDaemonConfig() (*launchd.AgentConfig, error) { + stdOutFilePathDaemon := filepath.Join(constants.CrcBaseDir, ".crcd-agent.log") currentExecutablePath, err := goos.Executable() if err != nil { - return err + return nil, err } daemonConfig := launchd.AgentConfig{ Label: daemonAgentLabel, @@ -55,7 +57,33 @@ func fixDaemonPlistFileExists() error { StdOutFilePath: stdOutFilePathDaemon, Args: []string{"daemon"}, } - return fixPlistFileExists(daemonConfig) + + return &daemonConfig, nil +} + +func getTrayConfig() (*launchd.AgentConfig, error) { + stdOutFilePathTray := filepath.Join(constants.CrcBaseDir, ".crct-agent.log") + + trayConfig := launchd.AgentConfig{ + Label: trayAgentLabel, + ExecutablePath: constants.TrayExecutablePath, + StdOutFilePath: stdOutFilePathTray, + } + + return &trayConfig, nil +} + +func fixDaemonPlistFileExists() error { + // Try to remove the daemon agent from launchd + // and recreate its plist + _ = launchd.Remove(daemonAgentLabel) + + daemonConfig, err := getDaemonConfig() + if err != nil { + return nil + } + + return fixPlistFileExists(*daemonConfig) } func removeDaemonPlistFile() error { @@ -63,19 +91,19 @@ func removeDaemonPlistFile() error { } func checkIfTrayPlistFileExists() error { - if !launchd.PlistExists(trayAgentLabel) { - return fmt.Errorf("Tray plist file does not exist") + trayConfig, err := getTrayConfig() + if err != nil { + return err } - return nil + return launchd.CheckPlist(*trayConfig) } func fixTrayPlistFileExists() error { - trayConfig := launchd.AgentConfig{ - Label: trayAgentLabel, - ExecutablePath: constants.TrayExecutablePath, - StdOutFilePath: stdOutFilePathTray, + trayConfig, err := getTrayConfig() + if err != nil { + return err } - return fixPlistFileExists(trayConfig) + return fixPlistFileExists(*trayConfig) } func removeTrayPlistFile() error { diff --git a/pkg/os/launchd/launchd_darwin.go b/pkg/os/launchd/launchd_darwin.go index a0d9a99faa..fcf511719c 100644 --- a/pkg/os/launchd/launchd_darwin.go +++ b/pkg/os/launchd/launchd_darwin.go @@ -65,23 +65,31 @@ func getPlistPath(label string) string { return filepath.Join(launchAgentsDir, plistName) } +func generatePlistContent(config AgentConfig) ([]byte, error) { + var plistContent bytes.Buffer + t, err := template.New("plist").Parse(plistTemplate) + if err != nil { + return nil, err + } + err = t.Execute(&plistContent, config) + if err != nil { + return nil, err + } + + return plistContent.Bytes(), nil +} + // CreatePlist creates a launchd agent plist config file func CreatePlist(config AgentConfig) error { if err := ensureLaunchAgentsDirExists(); err != nil { return err } - var plistContent bytes.Buffer - t, err := template.New("plist").Parse(plistTemplate) - if err != nil { - return err - } - err = t.Execute(&plistContent, config) + plist, err := generatePlistContent(config) if err != nil { return err } - // #nosec G306 - err = ioutil.WriteFile(getPlistPath(config.Label), plistContent.Bytes(), 0644) + err = ioutil.WriteFile(getPlistPath(config.Label), plist, 0600) return err } @@ -89,6 +97,14 @@ func PlistExists(label string) bool { return os.FileExists(getPlistPath(label)) } +func CheckPlist(config AgentConfig) error { + plist, err := generatePlistContent(config) + if err != nil { + return err + } + return os.FileContentMatches(getPlistPath(config.Label), plist) +} + // LoadPlist loads a launchd agents' plist file func LoadPlist(label string) error { return runLaunchCtl("load", getPlistPath(label))