Skip to content

Commit

Permalink
Add new action type force_full_control_data_fetch (#1779)
Browse files Browse the repository at this point in the history
  • Loading branch information
RebeccaMahany authored Jul 16, 2024
1 parent 2de0df2 commit 6df838c
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 1 deletion.
3 changes: 3 additions & 0 deletions cmd/launcher/launcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
"github.com/kolide/launcher/ee/agent/storage"
agentbbolt "github.com/kolide/launcher/ee/agent/storage/bbolt"
"github.com/kolide/launcher/ee/agent/timemachine"
"github.com/kolide/launcher/ee/control"
"github.com/kolide/launcher/ee/control/actionqueue"
"github.com/kolide/launcher/ee/control/consumers/acceleratecontrolconsumer"
"github.com/kolide/launcher/ee/control/consumers/flareconsumer"
Expand Down Expand Up @@ -449,6 +450,8 @@ func runLauncher(ctx context.Context, cancel func(), multiSlogger, systemMultiSl
actionsQueue.RegisterActor(uninstallconsumer.UninstallSubsystem, uninstallconsumer.New(k))
// register flare consumer
actionsQueue.RegisterActor(flareconsumer.FlareSubsystem, flareconsumer.New(k))
// register force full control data fetch consumer
actionsQueue.RegisterActor(control.ForceFullControlDataFetchAction, controlService)

// create notification consumer
notificationConsumer, err := notificationconsumer.NewNotifyConsumer(
Expand Down
31 changes: 30 additions & 1 deletion ee/control/control.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import (
"golang.org/x/exp/slices"
)

const ForceFullControlDataFetchAction = "force_full_control_data_fetch"

// ControlService is the main object that manages the control service. It is responsible for fetching
// and caching control data, and updating consumers and subscribers.
type ControlService struct {
Expand All @@ -27,6 +29,8 @@ type ControlService struct {
requestTicker *time.Ticker
fetcher dataProvider
fetchMutex sync.Mutex
fetchFull bool
fetchFullMutex sync.Mutex
store types.GetterSetter
lastFetched map[string]string
consumers map[string]consumer
Expand Down Expand Up @@ -276,6 +280,14 @@ func (cs *ControlService) Fetch() error {
return fmt.Errorf("decoding subsystems map: %w", err)
}

fetchFull := false
cs.fetchFullMutex.Lock()
if cs.fetchFull {
fetchFull = true // fetch all subsystems during this Fetch
cs.fetchFull = false // reset for next Fetch
}
cs.fetchFullMutex.Unlock()

for subsystem, hash := range subsystems {
lastHash, ok := cs.lastFetched[subsystem]
if !ok && cs.store != nil {
Expand All @@ -286,7 +298,7 @@ func (cs *ControlService) Fetch() error {
}
}

if hash == lastHash && !cs.knapsack.ForceControlSubsystems() {
if hash == lastHash && !cs.knapsack.ForceControlSubsystems() && !fetchFull {
// The last fetched update is still fresh
// Nothing to do, skip to the next subsystem
continue
Expand Down Expand Up @@ -382,3 +394,20 @@ func (cs *ControlService) update(subsystem string, reader io.Reader) error {

return nil
}

// Do handles the force_full_control_data_fetch action.
func (cs *ControlService) Do(data io.Reader) error {
cs.slogger.Log(context.TODO(), slog.LevelDebug,
"received request to perform full fetch of all subsystems",
)

// We receive this request in the middle of a `Fetch`, so we can't call
// `Fetch` again immediately. Instead, set `fetchFull` so that the next
// call to `Fetch` will fetch all subsystems.
cs.fetchFullMutex.Lock()
defer cs.fetchFullMutex.Unlock()
cs.fetchFull = true

// Treat this action as best-effort: try to do it once, no need to retry.
return nil
}

0 comments on commit 6df838c

Please sign in to comment.