fix(spurd): stop warning when no spur.conf exists at the default path - #631
Open
nikhilsk wants to merge 1 commit into
Open
fix(spurd): stop warning when no spur.conf exists at the default path#631nikhilsk wants to merge 1 commit into
nikhilsk wants to merge 1 commit into
Conversation
spurd loads spur.conf best-effort for local agent settings, so an agent configured entirely by flags legitimately has no such file. Reporting that absence at WARN on every startup tells operators something is wrong when nothing is, which is how people learn to ignore warnings. Report an absent default path at INFO instead, and keep WARN for every case where settings the operator intended are being ignored: a --config path they named themselves that cannot be loaded, or a file that is present but malformed, invalid, or unreadable. A missing file is an expected deployment shape; a broken one is a misconfiguration worth surfacing. The decision is a pure predicate rather than logic inside main(), so it is covered by unit tests. Whether --config was named explicitly comes from the argument's ValueSource, which leaves the Args declaration and the documented default in --help untouched.
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #631 +/- ##
==========================================
+ Coverage 77.68% 77.72% +0.04%
==========================================
Files 172 172
Lines 72396 72612 +216
==========================================
+ Hits 56238 56437 +199
- Misses 16158 16175 +17 🚀 New features to boost your workflow:
|
nikhilsk
marked this pull request as ready for review
August 14, 2026 09:19
nikhilsk
requested review from
sgopinath1,
shiv-tyagi and
yansun1996
as code owners
August 14, 2026 09:19
Contributor
There was a problem hiding this comment.
Pull request overview
Adjusts spurd’s best-effort config loading so that an absent /etc/spur/spur.conf at the default path is treated as an expected deployment shape (logged at info), while preserving warn visibility for malformed/unreadable configs or explicitly provided --config paths. This improves operational signal-to-noise by eliminating a routine startup warning when nothing is wrong.
Changes:
- Determine whether
--configwas explicitly set using ClapValueSource(non-default sources are treated as operator intent). - Classify config-load failures so “default path + not found” logs at
info, while all other failures remainwarn. - Add unit tests covering the config-path/source + failure-kind matrix.
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| /// | ||
| /// Anything else — an explicitly requested path, or a file that is present but malformed, | ||
| /// invalid, or unreadable — means settings the operator intended are being ignored, and | ||
| /// has to stay visible. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
spurdreadsspur.confbest-effort — it supplies local agent settings ([hooks],[devices],rlimits.memlock,[cluster],[mpi]) and the agent runs on defaultswithout it. An agent configured entirely by flags therefore has no such file, yet every
startup logged:
A warning that fires when nothing is wrong is how operators learn to skip warnings, which
costs them the ones that matter.
Fixes #586.
Approach
Failures are now classified rather than reported uniformly:
--configinfo— expected shape, the fixwarnwarnspurctldalready draws this line (info!("no config file found, using defaults")), sothe two daemons now agree on what an absent config means.
Design notes
A malformed file at the default path still warns. The issue asks for a narrower rule —
"only an explicitly-passed
--configpath that fails to load warrants a warning" — butread literally that also silences a broken file at the default path, which is worse than
the noise being removed: the file exists, its settings are being ignored, and nothing says
so. A missing file is a deployment shape; a malformed, invalid, or unreadable one is a
misconfiguration. Flagging this as a deliberate deviation from the issue text.
Classify the error, don't stat the path.
Path::exists()would be the shorter test butcannot separate "absent" from "present and unreadable", so a permission-denied config would
take the quiet path. Matching
io::ErrorKind::NotFoundon the errorload_from_filealready returns distinguishes the two exactly and costs no extra syscall.
Explicitness is read as "not the default value", not "came from the command line". The
field has no
env, soValueSource::CommandLinewould work today, but it would silentlymisclassify an env-supplied path as a default if one were ever added — the surrounding code
already treats
EnvVariableas user intent (spur-cli/src/sbatch.rs). Testing againstDefaultValuestays correct through that change.ValueSourceoverconfig: Option<PathBuf>. Droppingdefault_valueto detect anexplicit path is less code, but
--helpwould lose its[default: /etc/spur/spur.conf]line. Reading the value's source leaves the
Argsdeclaration and the help outputuntouched; a test in the smoke table below pins that.
The predicate is a free function so the rule is unit-tested directly rather than through
main().Compatibility
No change to persisted state, the Raft log, proto, the config schema, or any CLI flag,
default, or help text. The load remains best-effort:
spurdstill starts on defaults inevery failure case.
The one visible change is the log line itself — anything grepping
spurdoutput forfailed to load spur.confon a host with no config file will stop matching, which is thepoint of the fix.
Testing
cargo test --locked→ 2853 passed, 0 failed, 25 ignored (ignored tests needPostgreSQL). Five new unit tests cover the matrix above, including a validation failure and
a permission-denied read, and build their
ConfigErrorvalues throughSlurmConfig::load_from_strrather than hand-rolling stand-ins.Gates green:
cargo fmt --all --check;cargo clippy --workspace --exclude spur-ffi --all-targets --lockedwithRUSTFLAGS="-D warnings";cargo test --locked;cargo deny check(advisories ok, bans ok, licenses ok, sources ok).Verified against a built binary on a host with no
/etc/spur/spur.conf:spurd -D(no config present)INFO no spur.conf found, using default config— no warningspurd -D --config <absent>WARN failed to load spur.conf … No such file or directoryspurd -D -f <absent>(short form)WARN …— short and long forms agreespurd -D --config <invalid TOML>WARN … failed to parse TOMLspurd -D --config <valid>INFO loaded spur.confspurd --help-f, --config <CONFIG> … [default: /etc/spur/spur.conf]intactNote for reviewers
main()is not unit-testable, so the wiring — that each branch reaches the intended macro— rests on the smoke runs above rather than on a test. Keeping the rule in a pure predicate
confines that gap to a single
match.