Perform early restart before starting sub-systems and minor refactor of orbit sub-systems (#20610)
#20397 Am calling these things that orbit run "sub-systems". - [X] Changes file added for user-visible changes in `changes/`, `orbit/changes/` or `ee/fleetd-chrome/changes`. See [Changes files](https://fleetdm.com/docs/contributing/committing-changes#changes-files) for more information. - [X] Manual QA for all new/changed functionality - For Orbit and Fleet Desktop changes: - [X] Orbit runs on macOS, Linux and Windows. Check if the orbit feature/bugfix should only apply to one platform (`runtime.GOOS`). - [X] Manual QA must be performed in the three main OSs, macOS, Windows and Linux. - [X] Auto-update manual QA, from released version of component to new version (see [tools/tuf/test](../tools/tuf/test/README.md)).
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
package update
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
@@ -23,8 +22,8 @@ import (
|
||||
// It uses an OrbitConfigFetcher (which may be the OrbitClient with additional middleware), along
|
||||
// with FlagUpdateOptions to connect to Fleet
|
||||
type FlagRunner struct {
|
||||
queueOrbitRestart context.CancelFunc
|
||||
opt FlagUpdateOptions
|
||||
triggerOrbitRestart func(reason string)
|
||||
opt FlagUpdateOptions
|
||||
}
|
||||
|
||||
// FlagUpdateOptions is options provided for the flag update runner
|
||||
@@ -35,10 +34,10 @@ type FlagUpdateOptions struct {
|
||||
|
||||
// NewFlagRunner creates a new runner with provided options
|
||||
// The runner must be started with Execute
|
||||
func NewFlagReceiver(queueOrbitRestart context.CancelFunc, opt FlagUpdateOptions) *FlagRunner {
|
||||
func NewFlagReceiver(triggerOrbitRestart func(reason string), opt FlagUpdateOptions) *FlagRunner {
|
||||
return &FlagRunner{
|
||||
queueOrbitRestart: queueOrbitRestart,
|
||||
opt: opt,
|
||||
triggerOrbitRestart: triggerOrbitRestart,
|
||||
opt: opt,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,7 +78,7 @@ func (r *FlagRunner) Run(config *fleet.OrbitConfig) error {
|
||||
return fmt.Errorf("error writing flags to disk: %w", err)
|
||||
}
|
||||
|
||||
r.queueOrbitRestart()
|
||||
r.triggerOrbitRestart("osquery flags updated")
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -89,9 +88,9 @@ func (r *FlagRunner) Run(config *fleet.OrbitConfig) error {
|
||||
// It uses an an OrbitConfigFetcher (which may be the OrbitClient with additional middleware), along
|
||||
// with ExtensionUpdateOptions and updateRunner to connect to Fleet.
|
||||
type ExtensionRunner struct {
|
||||
opt ExtensionUpdateOptions
|
||||
updateRunner *Runner
|
||||
queueOrbitRestart context.CancelFunc
|
||||
opt ExtensionUpdateOptions
|
||||
updateRunner *Runner
|
||||
triggerOrbitRestart func(reason string)
|
||||
}
|
||||
|
||||
// ExtensionUpdateOptions is options provided for the extensions fetch/update runner
|
||||
@@ -102,19 +101,18 @@ type ExtensionUpdateOptions struct {
|
||||
|
||||
// NewExtensionConfigUpdateRunner creates a new runner with provided options
|
||||
// The runner must be started with Execute
|
||||
func NewExtensionConfigUpdateRunner(opt ExtensionUpdateOptions, updateRunner *Runner, queueOrbitRestart context.CancelFunc) *ExtensionRunner {
|
||||
func NewExtensionConfigUpdateRunner(opt ExtensionUpdateOptions, updateRunner *Runner, triggerOrbitRestart func(reason string)) *ExtensionRunner {
|
||||
return &ExtensionRunner{
|
||||
opt: opt,
|
||||
updateRunner: updateRunner,
|
||||
queueOrbitRestart: queueOrbitRestart,
|
||||
opt: opt,
|
||||
updateRunner: updateRunner,
|
||||
triggerOrbitRestart: triggerOrbitRestart,
|
||||
}
|
||||
}
|
||||
|
||||
// DoExtensionConfigUpdate calls the /config API endpoint to grab extensions from Fleet
|
||||
// It parses the extensions, computes the local hash, and writes the binary path to extension.load file
|
||||
//
|
||||
// It returns a (bool, error), where bool indicates whether orbit should restart
|
||||
// It only returns (true, nil) when extensions were previously configured and now are cleared
|
||||
// It will only trigger a orbit restart when extensions were previously configured and now are cleared.
|
||||
func (r *ExtensionRunner) Run(config *fleet.OrbitConfig) error {
|
||||
extensionAutoLoadFile := filepath.Join(r.opt.RootDir, "extensions.load")
|
||||
if len(config.Extensions) == 0 {
|
||||
@@ -126,7 +124,6 @@ func (r *ExtensionRunner) Run(config *fleet.OrbitConfig) error {
|
||||
// Handle case 1, where our autoload file does not exist, so there is nothing to update and no error
|
||||
case errors.Is(err, os.ErrNotExist):
|
||||
log.Debug().Msg(extensionAutoLoadFile + " not found, nothing to update")
|
||||
// we do not want orbit to restart
|
||||
return nil
|
||||
case err == nil:
|
||||
// handle case 2: create/truncate the extensions.load file and let the runner interrupt, so that
|
||||
@@ -135,19 +132,14 @@ func (r *ExtensionRunner) Run(config *fleet.OrbitConfig) error {
|
||||
if stat.Size() > 0 {
|
||||
err := os.WriteFile(extensionAutoLoadFile, []byte(""), constant.DefaultFileMode)
|
||||
if err != nil {
|
||||
// we do not want orbit to restart
|
||||
return fmt.Errorf("extensionsUpdate: error creating file %s, %w", extensionAutoLoadFile, err)
|
||||
}
|
||||
// we want to return true here, and restart with the empty extensions.load file
|
||||
// so that we "unload" the previously loaded
|
||||
// extensions
|
||||
r.queueOrbitRestart()
|
||||
// Restart with the empty extensions.load file so that we "unload" the previously loaded extensions.
|
||||
r.triggerOrbitRestart("unloading extensions")
|
||||
return nil
|
||||
}
|
||||
// we do not want orbit to restart
|
||||
return nil
|
||||
default:
|
||||
// we do not want orbit to restart, just log the error
|
||||
return fmt.Errorf("stat file: %s", extensionAutoLoadFile)
|
||||
}
|
||||
}
|
||||
@@ -157,7 +149,6 @@ func (r *ExtensionRunner) Run(config *fleet.OrbitConfig) error {
|
||||
var extensions fleet.Extensions
|
||||
err := json.Unmarshal(config.Extensions, &extensions)
|
||||
if err != nil {
|
||||
// we do not want orbit to restart
|
||||
return fmt.Errorf("error unmarshing json extensions config from fleet: %w", err)
|
||||
}
|
||||
|
||||
@@ -205,7 +196,6 @@ func (r *ExtensionRunner) Run(config *fleet.OrbitConfig) error {
|
||||
}
|
||||
|
||||
if err := r.updateRunner.StoreLocalHash(targetName); err != nil {
|
||||
// we do not want orbit to restart
|
||||
return fmt.Errorf("unable to lookup metadata for target: %s, %w", targetName, err)
|
||||
}
|
||||
|
||||
@@ -215,8 +205,6 @@ func (r *ExtensionRunner) Run(config *fleet.OrbitConfig) error {
|
||||
return fmt.Errorf("error writing extensions autoload file: %w", err)
|
||||
}
|
||||
|
||||
// we do not want orbit to restart
|
||||
// runner.UpdateAction() will fetch the new targets and restart for us if needed
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -90,7 +90,7 @@ func TestDoFlagsUpdateWithEmptyFlags(t *testing.T) {
|
||||
}
|
||||
|
||||
var restartQueued bool
|
||||
queueOrbitRestart := func() { restartQueued = true }
|
||||
queueOrbitRestart := func(string) { restartQueued = true }
|
||||
|
||||
fr := NewFlagReceiver(queueOrbitRestart, FlagUpdateOptions{
|
||||
RootDir: rootDir,
|
||||
|
||||
@@ -165,8 +165,6 @@ func randomizeDuration(max time.Duration) (time.Duration, error) {
|
||||
|
||||
// Execute begins a loop checking for updates.
|
||||
func (r *Runner) Execute() error {
|
||||
log.Debug().Msg("start updater")
|
||||
|
||||
// Randomize the initial interval so that all agents don't synchronize their updates
|
||||
initialInterval := r.opt.CheckInterval
|
||||
// Developers use a shorter update interval (10s), so they need a faster first update check
|
||||
@@ -322,7 +320,6 @@ func (r *Runner) updateTarget(target string) error {
|
||||
|
||||
func (r *Runner) Interrupt(err error) {
|
||||
r.cancel <- struct{}{}
|
||||
log.Error().Err(err).Msg("interrupt updater")
|
||||
}
|
||||
|
||||
// compareVersion compares the old and new versions of a binary and prints the appropriate message.
|
||||
|
||||
Reference in New Issue
Block a user