Repository navigation
Conversation
kaysond
left a comment
There was a problem hiding this comment.
Thanks for putting this together. Two requests:
- the method added to config.go should be an actual method, not a pkg func (e.g.
func (c *Config) Has...), and we should not use strings.EqualFold, we should do an O(1) lookup on the device overrides keys, because it should be a map. (this might need some extra work, which should live in its own commit) - I like adding tests, but it's way too many lines and too verbose with the struct, as LLMs like to do
|
Sure, doing the 1. |
|
Both done, in two commits.
|
The scsi/ata suppression keyed off the type's value, so it could not tell a
type that came from `smartctl --scan` from one the user pinned in
collector.yaml. TransformDetectedDevices writes the override into the same
models.Device.DeviceType field the scanner writes to, so provenance was already
lost by the time the guard ran.
A user setting `devices: [{device: /dev/sda, type: scsi}]` therefore got a bare
`smartctl --info --json /dev/sda`, smartctl auto-selected SAT, exited 2, and the
drive was dropped with no device information.
HasDeviceTypeOverride asks the config directly instead, so suppression now only
applies to a scanned type. The len(type) > 0 short-circuit keeps the lookup off
the path when no type is set, so existing strict-gomock tests see no extra call.
Both call sites need it: detect.go builds --info and metrics.go builds --xall.
Fixing only detect.go registers the device and then drops the type again at
collection time.
Fixes AnalogJ#1063
- Factor the repeated `strings.EqualFold` override walk into `getDeviceOverride` - Make `HasDeviceTypeOverride` a config method reading the same lookup - Regenerate the mock for the added interface method - Keep matching case-insensitive, first entry for a device still wins
The table-driven cases repeated the whole config struct per row. Keep the cases that distinguish an unset type from an explicitly configured one and drop the rest.
c405ebd to
6dbe074
Compare
|
@justadityaraj - I rebased this on some changes I merged. decided to keep things as case-insensitive, for now, since its not consistent elsewhere. can you please do a quick sanity check? |
|
Checked it, rebase looks right. Both of your edits hold up, and one of them was load-bearing in a way I had not accounted for. The fix still works end to end. Driving the real The first line is byte-for-byte the log in #1063. The configured The operand reorder was not cosmetic, it was needed. The other two cases pass under that mutation, which is correct: they exist to pin the behaviour that must not change.
#803 composes cleanly, and makes the
One thing worth a release note, not a code change: anyone who already has I also fixed the PR description: it still claimed there was no Same disclosure as before, per AI_POLICY.md: this check was done with Claude Code. The before/after commands above are real runs against the two trees, not reasoning about the code. I still do not have the reporter's USB Seagate drive, so smartctl's exit status on that specific hardware remains the one thing I cannot confirm. |
Fixes #1063.
What was wrong
The scsi/ata suppression keyed off the device type's value, so it could not tell a type that came from
smartctl --scanfrom one the user pinned incollector.yaml:The suppression itself is correct and stays — the comment explains it, ata drives get scanned as scsi under docker and metadata is lost. The problem is that
TransformDetectedDeviceswrites a config override into the samemodels.Device.DeviceTypefield the scanner writes to, so provenance is already gone by the time the guard runs.So
devices: [{device: /dev/sda, type: scsi}]produced a baresmartctl --info --json /dev/sda, smartctl auto-selected SAT, exited 2, and the drive was dropped with no device info.ValidateConfigalso rejects-dinsidemetrics_info_args, so there is no user-side workaround.Both call sites need it.
detect.gobuilds--info,metrics.gobuilds--xall. Fixing onlydetect.gogets the device registered and thenCollect()drops the type again — I confirmed that second drop with its own failing test.The fix
HasDeviceTypeOverrideasks the config whether the type was pinned, so suppression now applies only to a scanned type. It is a method onconfig.Interface, sharing onegetDeviceOverridelookup withGetCommandMetricsInfoArgsandGetCommandMetricsSmartArgs, and the checked-in gomock is updated to match.The guard reads
(type != "scsi" && type != "ata") || HasDeviceTypeOverride(...), so the config is only consulted for a type that is already scsi/ata. Every other device keeps exactly the old code path, and the existing strict-gomock tests make no unexpected call.Verification
End to end, with the real collector binary and a stub
smartctlonPATHthat logs its argv, againstdevices: [{device: /dev/sda, type: scsi}]:The "before" line is byte-for-byte the log in the issue, and the "after" line is exactly the expected behaviour it asks for.
Tests — table tests at both call sites. Against the unpatched tree they fail with:
They cover the cases that must not change too: a scanned
satstill passes through, a scannedscsiis still dropped, an override on a different device doesn't leak, and an override with notypeset doesn't count.go test ./collector/...is green,go vetandgofmt -lclean.Re-verified after the rebase
Against the rebased head, driving the real
configpackage and the realDetectwith a capturing shell and the issue's exact config (devices: [{device: /dev/sda, type: scsi}]) and scan result (/dev/sda, scanned typesat):The configured
scsibeats the scannedsat, which is the behaviour #803 now preserves throughSmartCtlInfo.Behavioural equivalence of the shared lookup was checked the same way:
GetCommandMetricsInfoArgsandGetCommandMetricsSmartArgsreturn byte-identical results to master across duplicatedevice:entries and mixed-case paths.go test ./collector/...fails the same five pre-existing path tests as master on a Windows host, no more and no fewer;go vetandgofmt -lare clean.AI usage disclosure
Per AI_POLICY.md: this was written with Claude Code, used substantially — for tracing the two call sites, drafting the patch and the tests, and writing this description.
On the "fully verified with human use" requirement, precisely what I did and did not do: the fix is verified by running the actual
collector-metricsbinary and reading the command it executed, before and after, plus the tests above — not by reasoning about the code. I do not have the reporter's USB Seagate BUP drive, so the finalsmartctlexit-status-2 behaviour on that specific hardware is not something I can reproduce; what I verified is the argv scrutiny constructs, which is the part this changes. Happy to adjust if you'd rather see it done differently.