Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions pkg/tree/api/leaf_variants.go
Original file line number Diff line number Diff line change
Expand Up @@ -233,9 +233,12 @@ func (lv *LeafVariants) RemainsToExist() bool {
defaultOrRunningExists = true
continue
}
// if an entry exists that does not have the delete flag set,
// then a remaining LeafVariant exists.
if !l.GetDeleteFlag() {
// If an entry exists that does not have the delete flag set, OR is
// only being removed from the intended store (orphan delete: the
// device value stays unchanged), then a remaining LeafVariant exists.
// This keeps RemainsToExist() consistent with CanDelete()/ShouldDelete()
// which already treat DeleteOnlyIntended as "stays on device".
if !l.GetDeleteFlag() || l.GetDeleteOnlyIntendedFlag() {
return true
}
deleteExists = true
Expand Down
45 changes: 45 additions & 0 deletions pkg/tree/api/leaf_variants_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,51 @@ func TestLeafVariants_remainsToExist(t *testing.T) {
},
expected: false,
},
{
// Orphan delete: the only owner is being removed from the intended
// store but the device value stays. Running stays. The entry must
// be reported as remaining so that mandatory/leafref validation
// does not falsely fire on paths that the device will still keep.
name: "Orphan delete with running",
setup: func() *LeafVariants {
lv := &LeafVariants{
les: make(LeafVariantSlice, 0),
}
lerun := NewLeafEntry(
types.NewUpdate(&mockUpdateParent{}, &sdcpb.TypedValue{}, RunningValuesPrio, RunningIntentName, 0),
types.NewUpdateInsertFlags(),
nil,
)
ledel := NewLeafEntry(
types.NewUpdate(&mockUpdateParent{}, &sdcpb.TypedValue{}, 10, "owner1", 0),
types.NewUpdateInsertFlags().SetDeleteFlag().SetDeleteOnlyUpdatedFlag(),
nil,
)
lv.Add(lerun)
lv.Add(ledel)
return lv
},
expected: true,
},
{
// Same as above but no running. The intent is being orphan-deleted
// (only-intended), and there's no other variant to fall back to.
// The device still has the value, so the entry remains.
name: "Orphan delete without running",
setup: func() *LeafVariants {
lv := &LeafVariants{
les: make(LeafVariantSlice, 0),
}
ledel := NewLeafEntry(
types.NewUpdate(&mockUpdateParent{}, &sdcpb.TypedValue{}, 10, "owner1", 0),
types.NewUpdateInsertFlags().SetDeleteFlag().SetDeleteOnlyUpdatedFlag(),
nil,
)
lv.Add(ledel)
return lv
},
expected: true,
},
}

for _, tt := range tests {
Expand Down
Loading