Repository navigation
Conversation
The freshness sweeper needs to mark a scan configuration's check results STALE on a time schedule, but the only STALE-marking entry point so far (MarkScanChecksStale) is keyed by scan ref ID, which the sweeper does not have. Add MarkScanChecksStaleByConfig, keyed by scan configuration name. It mirrors MarkScanChecksStale exactly: same SAC check, same empty-key no-op, same predicate (non-nil LastStartedTime before the cutoff), and it delegates to the shared markStale helper. Only the query field differs (ComplianceOperatorScanConfigName instead of ComplianceOperatorScanRef), so it inherits the same idempotent, batched, key-fenced read-modify-upsert and the STALE-only guarantee. Add sql_integration coverage: a mixed-timestamp test across two clusters and a second configuration, and an agreement test showing a sweeper-style cutoff reverts neither ingest-CURRENT nor timeout-STALE rows. Implement the compliance data freshness sweeper (ROX-37814): a STALE-only, time-driven background loop for ROX-35712, built on the write-time hooks (#23765). Grace = ComplianceScanScheduleWatcherTimeout + ComplianceScanWatcherTimeout. Generated with AI assistance.
The write-time hooks mark a result CURRENT on ingest and STALE when a scan times out, but neither fires when a scheduled scan simply never runs or its results never arrive. Such results stay CURRENT forever and silently go out of date. Add a periodic, time-driven sweeper to close that gap. The sweeper lists every scan configuration, derives the most recent time its schedule expected a scan (via the existing Schedule->cron conversion and gronx), and marks STALE the configuration's results whose LastStartedTime predates (expected refresh - grace). Grace is the sum of the two scan-watcher timeouts, the combined budget for a scheduled scan to complete and be ingested. It is STALE-only by construction: it reuses MarkScanChecksStaleByConfig, which never sets CURRENT or UNKNOWN, so the sweeper can never revert the write-time hooks. The loop mirrors the CVE unsuppress loop (central/cve/suppress) for Start/Stop/ticker/stopper structure, runs under an elevated all-access context, and tolerates per-config errors. Wiring in main.go gates both Start and the stoppable registration on the same ComplianceSurfaceStaleData flag: gating only one would make shutdown block forever on a stopper that never reports stopped. The sweep interval is configurable and defaults to 5m, well under the grace window. Implement the compliance data freshness sweeper (ROX-37814): a STALE-only, time-driven background loop for ROX-35712, built on the write-time hooks (#23765). Grace = ComplianceScanScheduleWatcherTimeout + ComplianceScanWatcherTimeout. Generated with AI assistance.
|
Skipping CI for Draft Pull Request. |
Contributor
🚀 Build Images ReadyImages are ready for commit d310682. To use with deploy scripts: export MAIN_IMAGE_TAG=5.1.x-429-gd310682465 |
1 similar comment
Contributor
🚀 Build Images ReadyImages are ready for commit d310682. To use with deploy scripts: export MAIN_IMAGE_TAG=5.1.x-429-gd310682465 |
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## gualvare/rox-35712-freshness-hooks #23851 +/- ##
======================================================================
- Coverage 52.63% 52.52% -0.12%
======================================================================
Files 2833 2920 +87
Lines 177818 182385 +4567
======================================================================
+ Hits 93598 95795 +2197
- Misses 75997 78192 +2195
- Partials 8223 8398 +175
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
The time-driven freshness sweeper for ROX-37814 — the last of the three enforcement points that keep a compliance check result's
data_freshnesscorrect (feature ROX-35712). The two write-time hooks (ingest → CURRENT, scan timeout → STALE) land in #23765; this PR adds the periodic backstop that catches staleness no event reports: a scheduled scan that silently stops cycling, or a secured cluster whose sensor is disconnected so no timeout ever fires.Each
ROX_COMPLIANCE_FRESHNESS_SWEEP_INTERVAL(default 5m), gated on theComplianceSurfaceStaleDatafeature flag, the sweeper:cutoff = previousScheduledFire − grace, wheregrace = ComplianceScanScheduleWatcherTimeout + ComplianceScanWatcherTimeout(85m);LastStartedTimepredates the cutoff.Design choices:
markStalehelper (read-modify-upsert under the sameKeyFence).central/complianceoperator/v2/freshness, modeled on the CVE unsuppress loop (central/cve/suppress): ticker +concurrency.Stopper+ singleton, wired inmain.go(bothStart()and the stoppable gated on the same flag).New surface: datastore method
MarkScanChecksStaleByConfig(mirrorsMarkScanChecksStale, keyed by config name) and envROX_COMPLIANCE_FRESHNESS_SWEEP_INTERVAL.Scope: sweeper + datastore method + wiring only. API surfacing (so the UI can read/filter/sort by freshness), an on-demand ("scan now") refresh term, and orphan-row cleanup are deferred to later slices.
Alternatives considered:
User-facing documentation
Not needed: behind the
ComplianceSurfaceStaleDatafeature flag (default off); no user-visible API surface in this PR.Testing and quality
Gated by the
ComplianceSurfaceStaleDatafeature flag (default off).Automated testing
How I validated my change
Unit (
freshness/sweeper_test.go):expectedRefresh(nil / valid daily / unconvertible schedule);sweep(scheduled config →MarkScanChecksStaleByConfigcalled withcutoff = prevTick − grace, asserted; nil-schedule skipped; list error tolerated; a per-config error does not stop the next);Start()→Stop()terminates.sql_integration (
checkresults/datastore/datastore_freshness_test.go):TestMarkScanChecksStaleByConfig(old → STALE; recent and nil-timestamp rows untouched; other config untouched; write context required; idempotent re-run) andTestMarkScanChecksStaleByConfigAgreesWithWriteHooks(ingest-CURRENT + timeout-STALE rows, run the sweeper's method at the tightest cutoff → 0 reverts).Live OpenShift cluster (grace shortened to 2m, sweep 1m; managed config
rox35712-sweeper,ocp4-moderate, 125 check results).datafreshnesscolumn,count:LastStartedTimefrozen), socutofffell after the stored timestamp and all 125 rows went CURRENT→STALE within one tick, with the log linecompliance freshness sweeper: marked 125 check result(s) stale for scan configuration "rox35712-sweeper".time.Now()agree).🤖 This change was developed with AI assistance (
ai-assisted).