Repository navigation
fix: handle nodes, kinds and defaults defined without a body - #3518
Conversation
A topology entry with nothing under it, such as a node written as `n1:` or a kind whose settings are all commented out, unmarshals into a nil *NodeDefinition. #2835 and #2856 made most getters cope with nil node definitions, but some places still do not: - getFieldPtr, GetNodeGroup and GetNodeConfigDispatcher return early on a nil node definition, so privileged, enforce-startup-config, suppress-startup-config and auto-remove set on a group or kind, the group set on the node's kind, and inherited config vars never reach the node; - GetKind returns the nil definition of a kind without a body and GetNodeGroup dereferences it, which panics as reported in #2859; - GetNodeKind and GetNodeConfigDispatcher read t.Defaults directly, so a defaults block without a body panics. Only guard the read of the node's own field, return an empty definition for a kind without a body, and read the defaults through GetDefaults(), as the other getters already do. Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
/tofarev review |
ToFaRev review — completedReviewed eb2316dae741 · Session log · Workflow run
Detailed findings:P4 - Schema rejects bodyless
|
|
Thanks for running the review. Both findings are P4 and outside the change itself: the schema strictness for bodyless kinds predates this PR, and the kind != nil guards still behave the same. Happy to allow null for kinds in the schema or add a doc comment on GetKind saying it never returns nil, if you want either here. The red fdio_vpp job passed its tests; only the coverage artifact upload failed with ECONNRESET, so a rerun should clear it. |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #3518 +/- ##
===========================================
- Coverage 61.81% 19.91% -41.90%
===========================================
Files 299 296 -3
Lines 36726 35875 -851
===========================================
- Hits 22701 7144 -15557
- Misses 11727 27676 +15949
+ Partials 2298 1055 -1243
🚀 New features to boost your workflow:
|
A topology entry with nothing under it unmarshals into a nil
*NodeDefinition: a node written asn1:, a kind whose settings are all commented out, or an emptydefaults:block. #2835 and #2856 made most of the getters intypes/topology.gohandle nil node definitions, but a few places still don't.Three getters return early on a nil node definition, so a node without a body misses part of what it should inherit:
getFieldPtr, behindprivileged,enforce-startup-config,suppress-startup-configandauto-remove, returns the defaults value without looking at the group or the kind. For example,privileged: falseon a kind leaves its nodes without a body privileged.GetNodeGroupignores the group set on the node's kind, so that group's settings never reach the node.GetNodeConfigDispatcherreturns nil, which drops inheritedconfig.vars. A startup-config template that reads.Config.Varsthen fails withnil pointer evaluating *types.ConfigDispatcher.Vars.n1andn2below should come out the same, but the code onmainresolvesn1to privileged with auto-remove off, andn2to the kind's values:Kinds and defaults without a body panic.
GetKindreturns the nil definition of a kind with no body, andGetNodeGroupreads.Groupfrom it. That is the panic in #2859. The issue was closed as fixed by #2856, but #2856 only handled nil nodes, and going by the code onmainthe topology from the issue still panics inGetNodeGroup, called fromGetNodeRuntimeinparseTopology. The inventory builders read the result ofGetKindthe same way.GetNodeKindandGetNodeConfigDispatcheralso readt.Defaultsdirectly instead of throughGetDefaults(), so an emptydefaults:block panics too.Like #2833 and #2852, this goes back to the getter refactor in #2818. Before it, these lookups went through nil-safe
NodeDefinitionaccessors.The fix:
getFieldPtr,GetNodeGroupandGetNodeConfigDispatcherguard only the read of the node's own field, asgetFieldandGetNodeTypealready do.GetKindreturns an empty definition for a kind without a body, as it already does for an unknown kind. An exact match still wins over a case-insensitive one. TheGetNodeGroupchange depends on this, because it now looks up the kind of nodes without a body.GetNodeKindandGetNodeConfigDispatcherread the defaults throughGetDefaults().Entries that have a body resolve as before.
TestGetNodeFieldsOfNilNodeDefinitionchecks what a node with a nil definition inherits from its kind and group: the group, the four pointer-typed fields and the config vars.TestGetNodeFieldsOfNilKindAndDefaultsuses a kind with a nil definition and no defaults, and checksGetKind,GetNodeGroup,GetNodeKindandGetNodeConfigDispatcher. Going by the code onmain, every case of the first test fails and the second test panics.I have not compiled or run this: there is no Go toolchain on the machine I worked on. The expected values come from reading the code, and both files parse cleanly with tree-sitter-go. gofmt and golangci-lint were not run.
🤖 Generated with Claude Code