Skip to content

Commit

Permalink
macos: Reinstall launchd services when their definition changes
Browse files Browse the repository at this point in the history
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 #2099
  • Loading branch information
cfergeau authored and praveenkumar committed Mar 18, 2021
1 parent 04150bd commit 98ad4f6
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 33 deletions.
78 changes: 53 additions & 25 deletions pkg/crc/preflight/preflight_checks_tray_darwin.go
Expand Up @@ -21,61 +21,89 @@ 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,
ExecutablePath: currentExecutablePath,
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 {
return launchd.RemovePlist(daemonAgentLabel)
}

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 {
Expand Down
32 changes: 24 additions & 8 deletions pkg/os/launchd/launchd_darwin.go
Expand Up @@ -65,30 +65,46 @@ 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
}

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))
Expand Down

0 comments on commit 98ad4f6

Please sign in to comment.