mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-09-10 18:45:53 +00:00
eac9ffcabf
The vSphere adapter filled `Resource.Tags` with six fixed strings on every resource — `vmware`, `vsphere`, `<kind>`, `source:vcenter`, `connection:<name>`, `power:<state>` — and never read vCenter's own tag and category system. Every VM in an estate returned a byte-identical set, so the workload Tags column rendered the same dots on every row and filtering on any of them selected everything. Commit6b78feba8default-hid the column and said in as many words that the hide was a stopgap awaiting this fix. `internal/vmware/client_tags.go` reads the CIS tagging service. That is a different endpoint family from the `/api/vcenter/...` inventory reads, but the same vSphere Automation API, so it reuses the caller's `/api/session` token rather than opening and managing a second session. Associations come from one batched `list-attached-tags-on-objects` POST per bounded object batch, never a per-object request; tag and category names resolve through a client-scoped catalog with a 10-minute TTL, so a steady-state refresh of a tagged estate costs only the association reads while a rename still converges without a restart. A vCenter without the tagging service, or an account without the tag read privilege, degrades into a `tags` stage enrichment issue and leaves the inventory untagged; it never fails the refresh. The provenance strings stay. `Resource.Tags` is the only keyword set `resourceSearchMatch.ts`, the `?tags=` resources filter, and saved report-schedule tag filters read — `collectSearchCandidates` gathers no `technology`, `type`, or `platformScopes` candidate — so dropping "vmware" or "vsphere" would silently stop matching searches and saved filters that depend on them. Real vCenter labels are appended to that set, never substituted for it. Because that flat set is deliberately mixed, it is the wrong source for a per-row Tags cell. Real tags therefore also land on a canonical `VMware.Tags` facet that carries vCenter's category alongside each name, and `useWorkloads.ts` maps `WorkloadGuest.tags` from that facet for any resource carrying VMware metadata — including the empty case, so a vSphere VM nobody tagged renders an empty cell instead of falling back to the provenance dots. vCenter tag names are unique only inside their category, so the flat label is `category:name`: two categories may each hold a "Production". With the column carrying per-row meaning again, `tags` leaves VMWARE_WORKLOAD_DEFAULT_HIDDEN_COLUMN_IDS and the `defaultHiddenMigrationIds` retirement list, and the state-model test that pinned the stopgap now pins its absence. No un-hide migration ships alongside it:6b78feba8is on main but no tag contains it, so the stopgap never shipped and no install carries the auto-hidden preference. That holds only while the two stay together — the migration writes the hide into each user's saved preference on first load, so an rc cut from main carrying the stopgap without this commit would make an explicit un-hide path necessary. Mock fixtures carry uneven tag coverage — several categories on some objects, one on others, none on the rest — because a uniform fixture set would hide exactly the defect this data exists to catch. Verified against a mock estate built from this branch: `/api/resources` returns provenance plus real labels on the flat set and only real labels on `vmware.tags`; the Tags column renders 2-4 dots per tagged VM and none for untagged ones; a dot's tooltip reads `Backup:Nightly`, and clicking it searches `tags:Backup:Nightly` and narrows 18 VMs to the 3 that carry it. Contract deltas: performance-and-scalability.md Extension Point 17 replaces the stopgap paragraph with the two-surface tag contract and the bounded tag-read budget; unified-resources.md states the keyword-union vs facet split and that a present-but-empty facet means "no operator tags" rather than a fallback; storage-recovery.md extends its VMware descriptive-only boundary to `vmware.tags`, because vCenter tag vocabularies read like protection policy (`Backup:Nightly`) and a label the operator wrote must never satisfy a coverage or compliance verdict that recovery-owned evidence should decide.