fix(exporter): populate Present on exported Memory/PSU so reanimator re-import keeps them
ReanimatorMemory.Present and ReanimatorPSU.Present were already declared as *bool fields (matching ReanimatorStorage.Present), but convertMemoryFromDevices and convertPSUsFromDevices never set them, unlike convertStorageFromDevices. Exported JSON therefore had "present" for storage but not for memory/PSU items. Re-importing a previously exported reanimator.json via parseUploadedSnapshot (a direct json.Unmarshal into models.AnalysisResult) left Present=false on those two categories, and the existing IsInstalledInventory()/present-required filters then dropped them on the next /chart/current render — reproduced live: fresh TSR upload showed Memory and Power Supplies correctly, re-uploading the exported reanimator.json for the same result did not. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
f599215760
commit
eb6cc207ce
@@ -1270,3 +1270,43 @@ of raw Redfish walk is picked up automatically without a dedicated parser.
|
||||
`redfishtree.FindCandidateArchives` + `redfishtree.Build`, not re-implement tar/zip walking.
|
||||
- `redfishwalk` is a genuine fallback: it only wins `Detect()` when no dedicated vendor parser
|
||||
scores higher on the same archive, per the registry's highest-confidence-wins rule.
|
||||
|
||||
---
|
||||
|
||||
## ADL-049 — Reanimator export/re-import round trip silently dropped Memory and PSUs
|
||||
|
||||
**Date:** 2026-08-11
|
||||
**Context:** After ADL-048 fixed Dell iDRAC10 inventory parsing, the same PowerEdge R7715 archive
|
||||
still showed no Memory or Power Supplies sections in the `/chart/current` web view, even though
|
||||
`internal/exporter.ConvertToReanimator` produced both correctly from a fresh TSR upload (verified via
|
||||
direct API calls against the running server). The web view *did* break identically after re-uploading
|
||||
a previously downloaded `reanimator.json` export back into LOGPile (the "Reanimator" round trip: export,
|
||||
then re-import the same file to inspect/verify it) — reproduced via `POST /api/upload` with that file.
|
||||
Root cause: `ReanimatorMemory.Present` and `ReanimatorPSU.Present` (`internal/exporter/reanimator_models.go`)
|
||||
were already declared as `*bool` `json:"present,omitempty"`, matching `ReanimatorStorage.Present`, but
|
||||
unlike `convertStorageFromDevices` (which sets `Present: &presentValue` on every emitted item),
|
||||
`convertMemoryFromDevices` and `convertPSUsFromDevices` never populated that field on the structs they
|
||||
built — a plain omission, not a deliberate contract choice. So exported JSON always had `"present": true`
|
||||
for storage but no `present` key at all for memory/PSU items. `parseUploadedSnapshot` (handlers.go)
|
||||
re-imports a reanimator export via a direct `json.Unmarshal` straight into `models.AnalysisResult`
|
||||
(the internal shape, not a dedicated import mapper); with no `present` key to unmarshal, Go's zero
|
||||
value left `MemoryDIMM.Present` / `PSU.Present` as `false`. On the next `ConvertToReanimator` call (every
|
||||
`/chart/current` render re-converts from the current in-memory result), `MemoryDIMM.IsInstalledInventory()`
|
||||
requires `Present == true`, and `convertPSUsFromDevices` has an explicit `if !present { continue }` — so
|
||||
every memory/PSU entry, despite carrying full data, got filtered out as "not installed".
|
||||
**Decision:** Populate `Present` on `ReanimatorMemory`/`ReanimatorPSU` in `convertMemoryFromDevices`/
|
||||
`convertPSUsFromDevices`, mirroring what `convertStorageFromDevices` already does. No changes needed to
|
||||
the import path or the `Present`-based filtering — the filtering itself is correct, it was just never
|
||||
given the field it needs from a re-imported export.
|
||||
**Consequences:**
|
||||
- Re-uploading a LOGPile-exported `reanimator.json` now preserves Memory and Power Supplies through the
|
||||
round trip, verified against the live server: upload TSR → export reanimator.json → re-upload it →
|
||||
`/chart/current` still shows both sections.
|
||||
- Regression test: `TestConvertToReanimator_MemoryAndPSURoundTripSurvivesReimport` in
|
||||
`internal/exporter/reanimator_converter_test.go` — converts a minimal result, marshals it, unmarshals
|
||||
back into `models.AnalysisResult` (simulating `parseUploadedSnapshot`), and asserts the reconverted
|
||||
output still contains both entries.
|
||||
- General lesson for this converter: any `Reanimator*` struct field meant to round-trip through
|
||||
`parseUploadedSnapshot` must actually be populated by its `convert*FromDevices` function — the struct
|
||||
declaring the field is not enough. `Storage` was the only category doing this correctly before this fix;
|
||||
worth auditing PCIe/NIC/GPU conversion the same way if a similar round-trip gap is reported for them.
|
||||
|
||||
Reference in New Issue
Block a user