diff --git a/internal/unifiedresources/resolved_host_set_test.go b/internal/unifiedresources/resolved_host_set_test.go index d018608dca..a6b3292a06 100644 --- a/internal/unifiedresources/resolved_host_set_test.go +++ b/internal/unifiedresources/resolved_host_set_test.go @@ -691,3 +691,27 @@ func TestBroadcastGroupingMatchesPreviousAlgorithm(t *testing.T) { } } } + +func TestTopLevelOwnerIndexPreservesAmbiguityInMonitoredCountAndAdmission(t *testing.T) { + for _, targetCount := range []int{1, 2} { + t.Run(fmt.Sprintf("%d_targets", targetCount), func(t *testing.T) { + resources := []Resource{ + topLevelTestProxmoxNode("platform", "tower.lab", "pve-source", "https://tower.lab:8006"), + topLevelTestTrueNAS("nas", "tower.lab"), + } + registry := NewRegistry(nil) + registry.IngestResources(resources[:targetCount]) + if got := MonitoredSystemCount(registry); got != targetCount { + t.Fatalf("counted inventory changed: %d/%d", got, targetCount) + } + projection := ProjectMonitoredSystemCandidate(registry, MonitoredSystemCandidate{Source: SourceAgent, Type: ResourceTypeAgent, Hostname: "tower", AgentID: "new-agent"}) + additional := targetCount - 1 + if projection.CurrentCount != targetCount || projection.AdditionalCount != additional || projection.ProjectedCount != targetCount+additional { + t.Fatalf("unique attachment/ambiguous admission changed: %+v", projection) + } + if got := len(registry.List()); got != targetCount { + t.Fatalf("read-only projection changed stored inventory: %d/%d", got, targetCount) + } + }) + } +} diff --git a/internal/unifiedresources/top_level_owner_index_test.go b/internal/unifiedresources/top_level_owner_index_test.go index 98137bcf2e..81a9b60a67 100644 --- a/internal/unifiedresources/top_level_owner_index_test.go +++ b/internal/unifiedresources/top_level_owner_index_test.go @@ -310,7 +310,7 @@ func CheckTopLevelOwnerIndexResourcesForTest(t testing.TB, resources []Resource) t.Logf("connected grouping retains %d resources in %d groups with byte-equal records", members, got.Count()) } -func BenchmarkTopLevelOwnerIndexResourcesForTest(b *testing.B, resources []Resource) { +func RunTopLevelOwnerIndexBenchmarkForTest(b *testing.B, resources []Resource) { for _, method := range []struct { name string resolve func([]Resource) TopLevelSystemResolver diff --git a/internal/unifiedresources/top_level_owner_integration_test.go b/internal/unifiedresources/top_level_owner_integration_test.go index f8ecaac7da..69fea88963 100644 --- a/internal/unifiedresources/top_level_owner_integration_test.go +++ b/internal/unifiedresources/top_level_owner_integration_test.go @@ -58,5 +58,5 @@ func TestTopLevelOwnerIndexConnectedDemo(t *testing.T) { func BenchmarkTopLevelOwnerIndexConnectedDemo(b *testing.B) { resources := connectedOwnerIndexResources(b) - unified.BenchmarkTopLevelOwnerIndexResourcesForTest(b, resources) + unified.RunTopLevelOwnerIndexBenchmarkForTest(b, resources) } diff --git a/internal/unifiedresources/top_level_systems.go b/internal/unifiedresources/top_level_systems.go index ed9dc70805..bfb8d87b6f 100644 --- a/internal/unifiedresources/top_level_systems.go +++ b/internal/unifiedresources/top_level_systems.go @@ -433,9 +433,6 @@ func buildTopLevelSystemFallbackIndex(groups map[int]topLevelSystemResolvedGroup return roots[i] < roots[j] }) add := func(owners map[string][]int, key string, root int) { - if key == "" { - return - } bucket := owners[key] // All aliases of one root are added together, so a last-entry check // deduplicates its comparable/short forms without a per-key set. @@ -448,9 +445,11 @@ func buildTopLevelSystemFallbackIndex(groups map[int]topLevelSystemResolvedGroup for host := range group.exactHosts { add(index.hosts, host, root) comparable := normalizeComparableHostname(host) - add(index.hostForms, comparable, root) if comparable != "" { - add(index.hostForms, NormalizeHostname(comparable), root) + add(index.hostForms, comparable, root) + if short := NormalizeHostname(comparable); short != "" { + add(index.hostForms, short, root) + } } } for ip := range group.exactIPs {