feat(synchronizer): evict unmanaged inventory rows matching discovery filters during sync#544
Open
clanker-pel[bot] wants to merge 3 commits into
Open
feat(synchronizer): evict unmanaged inventory rows matching discovery filters during sync#544clanker-pel[bot] wants to merge 3 commits into
clanker-pel[bot] wants to merge 3 commits into
Conversation
…lters on sync read When the synchronizer reads a resource that already exists in inventory as an unmanaged row, check whether the freshly-read cloud state matches any attached discovery filter. If so, tombstone the row (DB-only delete, no cloud mutation) instead of updating it. This closes the gap where a resource discovered before a filter was added would remain in inventory forever. The eviction check runs after the nil-guard (so only existing rows are evaluated) but before the JsonEqualRaw early-return (so a wedged row with unchanged properties is still evicted when it begins to match a filter). Managed rows and non-matching rows fall through to the normal persist path. The filter evaluation merges Properties and ReadOnlyProperties to get the complete cloud state, mirroring the merge that Discovery uses. Filters with no conditions are skipped to avoid accidentally evicting every unmanaged row.
…naged rows Extend the synchronizer's per-namespace plugin cache to capture the MatchFilters reported by each plugin alongside the resource schemas. After the available resource-update list is assembled, attach the type-matched filters to each update using the resource's own namespace cache so no filter can bleed across namespaces. A small unexported helper findMatchFiltersForType mirrors the identical helper in the discovery package, selecting only the filters whose ResourceTypes list includes the resource type being synchronized. Adds an integration test that proves the end-to-end path: an unmanaged inventory row whose freshly-read cloud state matches a plugin discovery filter is evicted from the datastore after a ForceSync, while a managed row matching the same filter is left untouched.
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.
Summary
Discovery filters (
agent.resourcePlugins[].discoveryFilters) were forward-only. Discovery applies them when scanning the cloud, so a matching resource is never added to inventory — but the Synchronizer, which polls each existing inventory row via the pluginReadand removes a row only onNotFound, never consulted the filters. A resource discovered before a filter existed (or before the filter matched its tags) therefore stayed in inventory permanently, even though the filter should now exclude it. This surfaced as ~25 bootstrap-tier unmanaged rows wedged informae inventory.This makes the Synchronizer respect discovery filters: what Discovery skips on the way in, the Synchronizer now evicts on the next poll, keeping a single mental model for filter semantics.
MatchFilters(already carried onPluginInfoResponse) and attaches the type-matching filters to each sync resource update, scoped strictly namespace-then-type so a filter never bleeds across namespaces that reuse a type name.Read, the persister evicts an inventory row when the authoritative current DB row is unmanaged and its freshly-read cloud state matches any attached filter. The check runs before the "only persist if changed" comparison, so an unchanged-but-matching wedged row is still removed.DeleteResource) — the identical call the existingNotFoundpath uses. The cloud object is never touched; the row simply stops appearing in inventory, matching Discovery's "never added" semantics. A distinct log line makes filter-eviction distinguishable fromNotFoundeviction.A managed row that happens to match a filter is never evicted — the guard gates on the authoritative current DB row's managed flag, so a filter change can never silently drop a resource that is under management. The reused matcher fails closed, so a match-evaluation error never triggers a delete.