Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

⭐️ Randomize the start time of scanning in serve mode #628

Merged
merged 1 commit into from
Jun 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion apps/cnspec/cmd/backgroundjob/background.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ func New() (*BackgroundScanner, error) {
type BackgroundScanner struct{}

func (bs *BackgroundScanner) Run(runScanFn JobRunner) error {
Serve(time.Duration(viper.GetInt64("timer"))*time.Minute, runScanFn)
Serve(
time.Duration(viper.GetInt64("timer"))*time.Minute,
time.Duration(viper.GetInt64("splay"))*time.Minute,
runScanFn)
return nil
}
19 changes: 10 additions & 9 deletions apps/cnspec/cmd/backgroundjob/serve_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
package backgroundjob

import (
"math/rand"
"os"
"os/signal"
"sync"
Expand All @@ -13,19 +14,19 @@ import (
"github.com/rs/zerolog/log"
)

func Serve(timer time.Duration, handler JobRunner) {
func Serve(timer time.Duration, splay time.Duration, handler JobRunner) {
log.Info().Msg("start cnspec background service")
log.Info().Msgf("scan interval is %d minute(s)", int(timer.Minutes()))
log.Info().Msgf("scan interval is %d minute(s) with a splay of %d minutes(s)", int(timer.Minutes()), int(splay.Minutes()))

quitChannel := make(chan os.Signal)
signal.Notify(quitChannel, syscall.SIGINT, syscall.SIGTERM)

shutdownChannel := make(chan struct{})
waitGroup := &sync.WaitGroup{}

initTick := time.Tick(1 * time.Second)
defaultTick := time.Tick(timer)
tick := initTick
t := time.NewTimer(time.Duration(rand.Int63n(int64(time.Minute))))
defer t.Stop()

waitGroup.Add(1)

go func(shutdownChannel chan struct{}, wg *sync.WaitGroup) {
Expand All @@ -40,14 +41,14 @@ func Serve(timer time.Duration, handler JobRunner) {
}

select {
case <-tick:
if tick == initTick {
tick = defaultTick
}
case <-t.C:
err := handler()
if err != nil {
log.Error().Err(err).Send()
}
nextRun := timer + time.Duration(rand.Int63n(int64(splay)))
log.Info().Msgf("next scan in %v", nextRun)
t.Reset(nextRun)
case <-shutdownChannel:
log.Info().Msg("stop worker")
return
Expand Down
15 changes: 8 additions & 7 deletions apps/cnspec/cmd/backgroundjob/serve_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,10 @@ type windowsService struct {
func (m *windowsService) Execute(args []string, r <-chan svc.ChangeRequest, changes chan<- svc.Status) (ssec bool, errno uint32) {
const cmdsAccepted = svc.AcceptStop | svc.AcceptShutdown
changes <- svc.Status{State: svc.StartPending}
initTick := time.Tick(1 * time.Second)
defaulttick := time.Tick(m.Timer)
tick := initTick

t := time.NewTimer(time.Duration(rand.Int63n(int64(time.Minute))))
defer t.Stop()

log.Info().Msg("schedule background scan")
changes <- svc.Status{State: svc.Running, Accepts: cmdsAccepted}

Expand All @@ -68,15 +69,15 @@ func (m *windowsService) Execute(args []string, r <-chan svc.ChangeRequest, chan
loop:
for {
select {
case <-tick:
if tick == initTick {
tick = defaulttick
}
case <-t.C:
select {
case runChan <- struct{}{}:
default:
log.Error().Msg("scan not started. may be stuck")
}
nextRun := timer + time.Duration(rand.Int63n(int64(splay)))
log.Info().Msgf("next scan in %v", nextRun)
t.Reset(nextRun)
case c := <-r:
switch c.Cmd {
case svc.Interrogate:
Expand Down
3 changes: 3 additions & 0 deletions apps/cnspec/cmd/serve.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ func init() {
rootCmd.AddCommand(serveCmd)
// background scan flags
serveCmd.Flags().Int("timer", 60, "scan interval in minutes")
serveCmd.Flags().Int("splay", 60, "randomize the timer by up to this many minutes")
serveCmd.Flags().MarkHidden("timer")
serveCmd.Flags().MarkHidden("splay")
// set inventory
serveCmd.Flags().String("inventory-file", "", "Set the path to the inventory file")
}
Expand All @@ -47,6 +49,7 @@ var serveCmd = &cobra.Command{

PreRun: func(cmd *cobra.Command, args []string) {
viper.BindPFlag("timer", cmd.Flags().Lookup("timer"))
viper.BindPFlag("splay", cmd.Flags().Lookup("splay"))
viper.BindPFlag("inventory-file", cmd.Flags().Lookup("inventory-file"))
},
Run: func(cmd *cobra.Command, args []string) {
Expand Down