refactor: unified ingest pipeline + modular Redfish profile framework
Implement the full architectural plan: unified ingest.Service entry point for archive and Redfish payloads, modular redfishprofile package with composable profiles (generic, ami-family, msi, supermicro, dell, hgx-topology), score-based profile matching with fallback expansion mode, and profile-driven acquisition/analysis plans. Vendor-specific logic moved out of common executors and into profile hooks. GPU chassis lookup strategies and known storage recovery collections (IntelVROC/HA-RAID/MRVL) now live in ResolvedAnalysisPlan, populated by profiles at analysis time. Replay helpers read from the plan; no hardcoded path lists remain in generic code. Also splits redfish_replay.go into domain modules (gpu, storage, inventory, fru, profiles) and adds full fixture/matcher/directive test coverage including Dell, AMI, unknown-vendor fallback, and deterministic ordering. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
72
internal/server/manual_input_inspect_test.go
Normal file
72
internal/server/manual_input_inspect_test.go
Normal file
@@ -0,0 +1,72 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"git.mchus.pro/mchus/logpile/internal/models"
|
||||
)
|
||||
|
||||
// TestManualInspectInput is a persistent local debugging harness for checking
|
||||
// how the current server code analyzes a real input file. It is skipped unless
|
||||
// LOGPILE_MANUAL_INPUT points to a file on disk.
|
||||
//
|
||||
// Usage:
|
||||
//
|
||||
// LOGPILE_MANUAL_INPUT=/abs/path/to/file.zip go test ./internal/server -run TestManualInspectInput -v
|
||||
func TestManualInspectInput(t *testing.T) {
|
||||
path := strings.TrimSpace(os.Getenv("LOGPILE_MANUAL_INPUT"))
|
||||
if path == "" {
|
||||
t.Skip("set LOGPILE_MANUAL_INPUT to inspect a real input file")
|
||||
}
|
||||
|
||||
payload, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
t.Fatalf("read input: %v", err)
|
||||
}
|
||||
|
||||
s := &Server{}
|
||||
filename := path
|
||||
|
||||
if rawPkg, ok, err := parseRawExportBundle(payload); err != nil {
|
||||
t.Fatalf("parseRawExportBundle: %v", err)
|
||||
} else if ok {
|
||||
result, vendor, err := s.reanalyzeRawExportPackage(rawPkg)
|
||||
if err != nil {
|
||||
t.Fatalf("reanalyzeRawExportPackage: %v", err)
|
||||
}
|
||||
logManualAnalysisResult(t, "raw_export_bundle", vendor, result)
|
||||
return
|
||||
}
|
||||
|
||||
result, vendor, err := s.parseUploadedPayload(filename, payload)
|
||||
if err != nil {
|
||||
t.Fatalf("parseUploadedPayload: %v", err)
|
||||
}
|
||||
logManualAnalysisResult(t, "uploaded_payload", vendor, result)
|
||||
}
|
||||
|
||||
func logManualAnalysisResult(t *testing.T, mode, vendor string, result *models.AnalysisResult) {
|
||||
t.Helper()
|
||||
if result == nil || result.Hardware == nil {
|
||||
t.Fatalf("missing hardware result")
|
||||
}
|
||||
|
||||
t.Logf("mode=%s vendor=%s source_type=%s protocol=%s target=%s", mode, vendor, result.SourceType, result.Protocol, result.TargetHost)
|
||||
t.Logf("counts: gpus=%d pcie=%d cpus=%d memory=%d storage=%d nics=%d psus=%d",
|
||||
len(result.Hardware.GPUs),
|
||||
len(result.Hardware.PCIeDevices),
|
||||
len(result.Hardware.CPUs),
|
||||
len(result.Hardware.Memory),
|
||||
len(result.Hardware.Storage),
|
||||
len(result.Hardware.NetworkAdapters),
|
||||
len(result.Hardware.PowerSupply),
|
||||
)
|
||||
for i, g := range result.Hardware.GPUs {
|
||||
t.Logf("gpu[%d]: slot=%s model=%s bdf=%s serial=%s status=%s", i, g.Slot, g.Model, g.BDF, g.SerialNumber, g.Status)
|
||||
}
|
||||
for i, p := range result.Hardware.PCIeDevices {
|
||||
t.Logf("pcie[%d]: slot=%s class=%s model=%s bdf=%s serial=%s vendor=%s", i, p.Slot, p.DeviceClass, p.PartNumber, p.BDF, p.SerialNumber, p.Manufacturer)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user