GeezerVisonThe World Wide Web, restored to 800 pixels of glory. | ||||||||
| Home|About|Gaming cabinet|Archives|How it works|Starter sites | ||||||||
GeezerVison is showing github.com — ROX-37456: add compliance data freshness e2e tests by guzalv · Pull Request #24043 · stackrox/stackrox Conversation
Contributor
DescriptionAdds end-to-end tests for the compliance "data freshness / stale data" feature (parent ROX-35712), matching the existing single-cluster compliance e2e suite in Three new tests in
Supporting changes:
Stacked on #23981 (v2-API wiring); also depends on #23851 (sweeper). The feature flag User-facing documentation
Testing and quality
Automated testing
How I validated my changeValidated live on a single-cluster OpenShift environment (
AI-assisted.
Sorry, something went wrong. Uh oh!
There was an error while loading. Please reload this page. All reactionsThe merged storage column `data_freshness` (ROX-35712 slice #23694) is written by the freshness hooks and sweeper, but the v2 API converters never copied it, so every endpoint returned UNKNOWN/0. The UI already consumes these fields (per-check indicator, per-check/per-cluster rollup, stale-data banner), so it showed nothing. This wires the read path: - Per-check `data_freshness`: new storage->v2 enum converter, populated in `clusterStatus` and `checkResult`. - Aggregate rollup (`ComplianceCheckResultStatusCount`, `ComplianceClusterOverallStats`): new current/stale COUNT(...) FILTER selects via a dedicated freshness-count helper (applied only to the queries that surface it), rolled up to CURRENT/STALE/INCONSISTENT/UNKNOWN. - Banner counts on `ComplianceProfileScanStats`: `stale_check_result_count` (stale rows) and `stale_cluster_count` (distinct clusters with any stale result, via COUNT(DISTINCT cluster_id) FILTER). Filter/sort by freshness needs no backend change: the `data_freshness` search field is already registered and flows through the existing raw-query/sort path. Rollup rule favors surfacing staleness: any stale alongside any current is INCONSISTENT, otherwise it reflects whichever is present, else UNKNOWN. The response-level `ListComplianceCheckResultResponse.data_freshness` rollup is intentionally left UNKNOWN for now (no consumer; correct population needs an unpaginated current/stale count) - noted with a shortcut comment. Depends only on master (the merged column), not on the hooks or sweeper PRs. When the feature flag is off all rows are UNKNOWN, so the converters naturally yield UNKNOWN/0 and the UI keeps the feature hidden. Prompt: "build the API wiring in parallel with the sweeper (they should not depend on each other)" for the compliance stale-data topic. Partially generated by AI (Claude Opus 4.8). Address CodeRabbit docstring-coverage warning: add concise doc comments to the new freshness converter and the freshness tests. No behavior change. Partially generated by AI (Claude Opus 4.8). …list The call-site enumeration can go stale; keep only what the function does. Partially generated by AI (Claude Opus 4.8).
All reactions
Sorry, something went wrong. Uh oh!
There was an error while loading. Please reload this page.
|
There was an error while loading. Please reload this page.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@ ## gualvare/rox-35712-freshness-api #24043 +/- ## ===================================================================== + Coverage 40.78% 52.70% +11.92% ===================================================================== Files 2751 2815 +64 Lines 175114 177519 +2405 ===================================================================== + Hits 71414 93562 +22148 + Misses 98070 75759 -22311 - Partials 5630 8198 +2568
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:
|
Sorry, something went wrong.
There was an error while loading. Please reload this page.
datastore_impl_test.go grew past the ~50KB no-large-files limit after adding the v2-API freshness converter/stats tests. Allow-list it, matching the existing central/cluster and central/processlisteningonport datastore_impl_test.go entries. Partially generated by AI (opencode).
Adds TestComplianceV2FreshnessCurrent, TestComplianceV2FreshnessStaleViaSweeper, and TestComplianceV2FreshnessStaleViaScanWatcherTimeout to tests/compliance_operator_v2_freshness_test.go, covering the CURRENT write-time path, the time-driven freshness sweeper, and the scan-watcher-timeout stale marking path, plus the v2 API freshness/banner fields and the 'Compliance Check Data Freshness' search filter. Not run against a live cluster in this change (compile/vet only). Partially generated with AI assistance.
Sets ROX_COMPLIANCE_SCAN_WATCHER_TIMEOUT=2m, ROX_COMPLIANCE_SCAN_SCHEDULE_WATCHER_TIMEOUT=1m, and ROX_COMPLIANCE_FRESHNESS_SWEEP_INTERVAL=20s for e2e Central deployments (helm and operator-managed paths), mirroring the existing ROX_REDHAT_SIGNING_KEY_WATCH_INTERVAL precedent. Production defaults (40m/45m/5m) give the sweeper/scan-watcher-timeout tests in compliance_operator_v2_freshness_test.go an ~85m grace window; shortened to ~3m so they finish within e2e test timeouts. Does not touch ROX_COMPLIANCE_SURFACE_STALE_DATA, already enabled in CI. Searched tests/ and qa-tests-backend/ for existing assertions on DataFreshness/StaleClusterCount/StaleCheckResultCount: none found, so this is safe to shorten globally. Partially generated with AI assistance.
TestComplianceV2FreshnessStaleViaSweeper failed on a real cluster: it scheduled the sweeper's tick at (client-side scanStart + 1 minute), truncated to whole minutes. Compliance Operator stamps LastStartedTime with second granularity and started the scan within ~1s of the request, landing both values in the same minute (observed: tick 12:58, LastStartedTime 2026-11-12T12:58:00Z exactly) so LastStartedTime < cutoff was never true and the sweeper never marked anything stale (confirmed: no sweeper log output, condition never satisfied after 6m). Fix: derive the tick from Central's own LastScanTime (scan completion, always >= every result's LastStartedTime) returned by GetComplianceProfileClusterResults, plus a 2-minute buffer, instead of a client-side guess of the scan's start time. waitForCheckResultsFreshness now returns the last successful response so the caller can read it. Verified against ga-ocp-cron: PASS, central logs show 'compliance freshness sweeper: marked 89 check result(s) stale for scan configuration ...' at the expected time (tick+grace). Partially generated with AI assistance.
Finding 2 (cross-test contamination): GetComplianceProfileClusterResults and GetComplianceProfileStats are keyed by profile+cluster, not by scan config, so 'all results CURRENT/STALE' could see rows left behind by any other scan config (deleted or not) that has used ocp4-cis on this cluster -- confirmed live: a stray leftover scan config using ocp4-cis was found on ga-ocp-cron from an earlier session. Fix: - Added scanConfigQuery() building a 'Compliance Scan Config Name:<name>' filter (search.ComplianceOperatorScanConfigName), confirmed live that it correctly isolates one config's rows (bogus name -> 0 rows; AND'd with a freshness clause via '+' also verified live). - waitForCheckResultsFreshness and every per-check read/filter assertion in all 3 tests now scope to the test's own scan config name. - The stale-data banner (GetComplianceProfileStats) can't be scoped by config (it's profile-global), so: TestComplianceV2FreshnessCurrent drops the global Stale*==0 assertion and instead proves CURRENT-ness via the scoped per-check wait + a scoped STALE-filter query (must return 0 rows); TestComplianceV2FreshnessStaleViaSweeper/...ScanWatcherTimeout relax the banner assertions to >= bounds derived from this test's own known result count instead of exact/== 1 values. Finding 4: replaced the Compliance-Operator-CRD RUNNING poll + blind 15s sleep in TestComplianceV2FreshnessStaleViaScanWatcherTimeout with waitForScanConfigRescanObserved, which polls Central's OWN view of the scan config (GetComplianceScanConfiguration) until its suite phase moves off DONE. That only happens once sensor has relayed a new ComplianceSuite update to Central, which is a stronger 'the rescan started and Central knows it' signal than the raw CRD. A short 10s buffer remains for the separate scan/check-result relay that creates the scan watcher. Nit: dropped the now-unused complianceoperatorv1/types imports. Partially generated with AI assistance.
The freshness tests (TestComplianceV2Freshness*) each add several minutes of time-based waits (sweeper grace window up to 8m, scan-watcher timeout up to 4m), which doesn't comfortably fit the suite's previous 30m -timeout alongside the other TestComplianceV2* tests. Partially generated with AI assistance.
Finding 3: add a short note at each ROX_COMPLIANCE_SCAN_WATCHER_TIMEOUT / ROX_COMPLIANCE_SCAN_SCHEDULE_WATCHER_TIMEOUT / ROX_COMPLIANCE_FRESHNESS_SWEEP_INTERVAL site explaining why shortening them is e2e-only and benign: a first scan has no prior results (so a short scan-watcher timeout is a no-op for it), no existing e2e test reads the freshness column or stale-data banner besides the new freshness tests, and a short timeout only sets that column and skips DeleteOldResults, both invisible to every other test. Partially generated with AI assistance.
6c279ef to
9ac4537
Compare
60d8c9c to
45cfeef
Compare
There was an error while loading. Please reload this page.
Successfully merging this pull request may close these issues.
There was an error while loading. Please reload this page.