feat(inventory): deep hardware capture + per-probe substeps + verbose logs
Extend Inventory stage from a one-liner summary to a per-probe substep emitter with ~20-30 narrative log lines per run. - spec: per-DIMM memory (slot/size/speed/manufacturer/part_number), richer CPU (vendor/stepping/physical_cores/flags), disk model/transport/rotational, NIC driver/pci_addr, GPU vram/pci/driver, new System/Baseboard/PSU/OS top-level sections. All fields omitempty so existing expected-spec YAML and artifacts stay compatible. - spec.Diff: new diffDIMMs/diffSystem/diffBaseboard/diffPSU/diffOS helpers; extended diffDisks/diffNICs/diffGPUs for new fields. GPU diff gains PCIAddr-pinned matching alongside count-by-model. - agent/probes/inventory: CPU (/proc/cpuinfo extended), Memory (dmidecode -t 17 multi-block), Disks (+model/transport/rotational), NICs (+driver/pci from sysfs), GPUs (VRAM from lspci -vv), new System/Baseboard (dmidecode -t system/baseboard), PSU (dmidecode -t 39), OS (/proc/sys/kernel/osrelease + /etc/os-release). All probes accept a Logger and emit per-finding info/warn lines. - agent/probes/firmware: parseDmidecodeAllSections for multi-block fixtures (memory / PSU). - agent/runner: Inventory case becomes 9 substep rows (CPU / Memory / Disks / NICs / GPUs / System / Baseboard / PSU / OS) with per-probe start/complete timestamps. - report: new Inventory HTML section between Stages and Firmware; resolveReporting loads the inventory.json artifact. - agent/tests/fakes/dmidecode: dispatches on -t flag to serve bios / memory / system / baseboard / 39 fixtures for unit tests. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -18,6 +18,7 @@ import (
|
||||
"time"
|
||||
|
||||
"vetting/internal/model"
|
||||
"vetting/internal/spec"
|
||||
)
|
||||
|
||||
// Data is the payload fed to the HTML template. Callers assemble it
|
||||
@@ -30,6 +31,7 @@ type Data struct {
|
||||
SpecDiffs []model.SpecDiff
|
||||
Aggregates []Aggregate // flattened measurement summary; see Aggregate
|
||||
Firmware []FirmwareSnapshot // captured firmware versions, empty if none
|
||||
Inventory *spec.Inventory // captured inventory, nil if artifact missing
|
||||
}
|
||||
|
||||
// FirmwareSnapshot is the report-facing view of one firmware row.
|
||||
@@ -206,6 +208,146 @@ const htmlTemplate = `<!doctype html>
|
||||
</table>
|
||||
</section>
|
||||
|
||||
{{if .Inventory}}
|
||||
<section>
|
||||
<h2>Inventory</h2>
|
||||
|
||||
{{with .Inventory.System}}{{if or .Manufacturer .ProductName .SerialNumber .UUID}}
|
||||
<h3>System</h3>
|
||||
<table>
|
||||
{{if .Manufacturer}}<tr><th>Manufacturer</th><td>{{.Manufacturer}}</td></tr>{{end}}
|
||||
{{if .ProductName}}<tr><th>Product</th><td>{{.ProductName}}</td></tr>{{end}}
|
||||
{{if .SerialNumber}}<tr><th>Serial</th><td><code>{{.SerialNumber}}</code></td></tr>{{end}}
|
||||
{{if .UUID}}<tr><th>UUID</th><td><code>{{.UUID}}</code></td></tr>{{end}}
|
||||
</table>
|
||||
{{end}}{{end}}
|
||||
|
||||
{{with .Inventory.Baseboard}}{{if or .Manufacturer .ProductName .SerialNumber}}
|
||||
<h3>Baseboard</h3>
|
||||
<table>
|
||||
{{if .Manufacturer}}<tr><th>Manufacturer</th><td>{{.Manufacturer}}</td></tr>{{end}}
|
||||
{{if .ProductName}}<tr><th>Product</th><td>{{.ProductName}}</td></tr>{{end}}
|
||||
{{if .SerialNumber}}<tr><th>Serial</th><td><code>{{.SerialNumber}}</code></td></tr>{{end}}
|
||||
</table>
|
||||
{{end}}{{end}}
|
||||
|
||||
{{with .Inventory.CPU}}{{if .Model}}
|
||||
<h3>CPU</h3>
|
||||
<table>
|
||||
<tr><th>Model</th><td>{{.Model}}</td></tr>
|
||||
{{if .Vendor}}<tr><th>Vendor</th><td>{{.Vendor}}</td></tr>{{end}}
|
||||
{{if .PhysicalCores}}<tr><th>Physical cores</th><td>{{.PhysicalCores}}</td></tr>{{end}}
|
||||
{{if .LogicalCores}}<tr><th>Logical cores</th><td>{{.LogicalCores}}</td></tr>{{end}}
|
||||
{{if .Stepping}}<tr><th>Stepping</th><td>{{.Stepping}}</td></tr>{{end}}
|
||||
{{if .Flags}}<tr><th>Flags</th><td>{{range $i, $f := .Flags}}{{if $i}}, {{end}}<code>{{$f}}</code>{{end}}</td></tr>{{end}}
|
||||
</table>
|
||||
{{end}}{{end}}
|
||||
|
||||
{{with .Inventory.Memory}}{{if or .TotalGiB .Modules}}
|
||||
<h3>Memory</h3>
|
||||
<table>
|
||||
<tr><th>Total</th><td>{{.TotalGiB}} GiB</td></tr>
|
||||
</table>
|
||||
{{if .Modules}}
|
||||
<table>
|
||||
<thead><tr><th>Slot</th><th>Size</th><th>Speed</th><th>Manufacturer</th><th>Part number</th><th>Populated</th></tr></thead>
|
||||
<tbody>
|
||||
{{range .Modules}}
|
||||
<tr>
|
||||
<td><code>{{.Slot}}</code></td>
|
||||
<td>{{if .SizeGB}}{{.SizeGB}} GiB{{else}}—{{end}}</td>
|
||||
<td>{{if .SpeedMTS}}{{.SpeedMTS}} MT/s{{else}}—{{end}}</td>
|
||||
<td>{{.Manufacturer}}</td>
|
||||
<td><code>{{.PartNumber}}</code></td>
|
||||
<td>{{if .Populated}}<span class="pass">yes</span>{{else}}<span class="skip">no</span>{{end}}</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</tbody>
|
||||
</table>
|
||||
{{end}}
|
||||
{{end}}{{end}}
|
||||
|
||||
{{if .Inventory.Disks}}
|
||||
<h3>Disks</h3>
|
||||
<table>
|
||||
<thead><tr><th>Serial</th><th>Model</th><th>Size</th><th>Transport</th><th>Rotational</th></tr></thead>
|
||||
<tbody>
|
||||
{{range .Inventory.Disks}}
|
||||
<tr>
|
||||
<td><code>{{.Serial}}</code></td>
|
||||
<td>{{.Model}}</td>
|
||||
<td>{{.SizeGB}} GB</td>
|
||||
<td>{{.Transport}}</td>
|
||||
<td>{{if .Rotational}}yes{{else}}no{{end}}</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</tbody>
|
||||
</table>
|
||||
{{end}}
|
||||
|
||||
{{if .Inventory.NICs}}
|
||||
<h3>NICs</h3>
|
||||
<table>
|
||||
<thead><tr><th>MAC</th><th>Speed</th><th>Driver</th><th>PCI</th></tr></thead>
|
||||
<tbody>
|
||||
{{range .Inventory.NICs}}
|
||||
<tr>
|
||||
<td><code>{{.MAC}}</code></td>
|
||||
<td>{{if .SpeedGbps}}{{.SpeedGbps}} Gbps{{else}}—{{end}}</td>
|
||||
<td>{{.Driver}}</td>
|
||||
<td><code>{{.PCIAddr}}</code></td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</tbody>
|
||||
</table>
|
||||
{{end}}
|
||||
|
||||
{{if .Inventory.GPUs}}
|
||||
<h3>GPUs</h3>
|
||||
<table>
|
||||
<thead><tr><th>Model</th><th>VRAM</th><th>PCI</th><th>Driver</th></tr></thead>
|
||||
<tbody>
|
||||
{{range .Inventory.GPUs}}
|
||||
<tr>
|
||||
<td>{{.Model}}</td>
|
||||
<td>{{if .VRAMGiB}}{{.VRAMGiB}} GiB{{else}}—{{end}}</td>
|
||||
<td><code>{{.PCIAddr}}</code></td>
|
||||
<td>{{.Driver}}</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</tbody>
|
||||
</table>
|
||||
{{end}}
|
||||
|
||||
{{if .Inventory.PSU}}
|
||||
<h3>Power supplies</h3>
|
||||
<table>
|
||||
<thead><tr><th>Slot</th><th>Manufacturer</th><th>Model</th><th>Max watts</th><th>Status</th></tr></thead>
|
||||
<tbody>
|
||||
{{range .Inventory.PSU}}
|
||||
<tr>
|
||||
<td>{{.Slot}}</td>
|
||||
<td>{{.Manufacturer}}</td>
|
||||
<td>{{.Model}}</td>
|
||||
<td>{{if .MaxWatts}}{{.MaxWatts}} W{{else}}—{{end}}</td>
|
||||
<td>{{.Status}}</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</tbody>
|
||||
</table>
|
||||
{{end}}
|
||||
|
||||
{{with .Inventory.OS}}{{if or .Kernel .Distribution .Version}}
|
||||
<h3>OS</h3>
|
||||
<table>
|
||||
{{if .Kernel}}<tr><th>Kernel</th><td><code>{{.Kernel}}</code></td></tr>{{end}}
|
||||
{{if .Distribution}}<tr><th>Distribution</th><td>{{.Distribution}}</td></tr>{{end}}
|
||||
{{if .Version}}<tr><th>Version</th><td>{{.Version}}</td></tr>{{end}}
|
||||
</table>
|
||||
{{end}}{{end}}
|
||||
</section>
|
||||
{{end}}
|
||||
|
||||
<section>
|
||||
<h2>Firmware ({{len .Firmware}})</h2>
|
||||
{{if .Firmware}}
|
||||
|
||||
Reference in New Issue
Block a user