Skip to content

Commit

Permalink
Merge pull request #17 from ythadhani/nokia-master
Browse files Browse the repository at this point in the history
supporting PartialKeyMatch for SetNode
  • Loading branch information
ythadhani authored Jun 2, 2022
2 parents e24514a + 63271ee commit 738c041
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 17 deletions.
58 changes: 48 additions & 10 deletions ytypes/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ type retrieveNodeArgs struct {
// GoStruct to determine the path elements instead of the
// "path" tag, whenever the former is present.
preferShadowPath bool
// tolerateMissingElements means to not return an error if a node is not
// found at the given path.
tolerateMissingElements bool
}

// retrieveNode is an internal function that retrieves the node specified by
Expand Down Expand Up @@ -90,7 +93,7 @@ func retrieveNode(schema *yang.Entry, root interface{}, path, traversedPath *gpb
Data: root,
}}, nil
case util.IsValueNil(root):
if args.delete {
if args.delete || args.tolerateMissingElements {
// No-op in case of a delete on a field whose value is not populated.
return nil, nil
}
Expand Down Expand Up @@ -446,7 +449,7 @@ func GetNode(schema *yang.Entry, root interface{}, path *gpb.Path, opts ...GetNo
return retrieveNode(schema, root, path, nil, retrieveNodeArgs{
// We never want to modify the input root, so we specify modifyRoot.
modifyRoot: false,
partialKeyMatch: hasPartialKeyMatch(opts),
partialKeyMatch: hasGetNodePartialKeyMatch(opts),
handleWildcards: hasHandleWildcards(opts),
preferShadowPath: hasGetNodePreferShadowPath(opts),
})
Expand All @@ -458,19 +461,34 @@ type GetNodeOpt interface {
IsGetNodeOpt()
}

// GetPartialKeyMatch specifies that a match within GetNode should be allowed to partially match
// keys for list entries.
type GetPartialKeyMatch struct{}
// PartialKeyMatch specifies that a match within GetNode or SetNode should be allowed to partially
// match keys for list entries.
type PartialKeyMatch struct{}

// IsGetNodeOpt implements the GetNodeOpt interface.
func (*GetPartialKeyMatch) IsGetNodeOpt() {}
func (*PartialKeyMatch) IsGetNodeOpt() {}

// hasPartialKeyMatch determines whether there is an instance of GetPartialKeyMatch within the supplied
// IsSetNodeOpt implements the SetNodeOpt interface.
func (*PartialKeyMatch) IsSetNodeOpt() {}

// hasGetNodePartialKeyMatch determines whether there is an instance of PartialKeyMatch within the supplied
// GetNodeOpt slice. It is used to determine whether partial key matches should be allowed in an operation
// involving a GetNode.
func hasPartialKeyMatch(opts []GetNodeOpt) bool {
func hasGetNodePartialKeyMatch(opts []GetNodeOpt) bool {
for _, o := range opts {
if _, ok := o.(*PartialKeyMatch); ok {
return true
}
}
return false
}

// hasSetNodePartialKeyMatch determines whether there is an instance of PartialKeyMatch within the supplied
// SetNodeOpt slice. It is used to determine whether partial key matches should be allowed in an operation
// involving a SetNode.
func hasSetNodePartialKeyMatch(opts []SetNodeOpt) bool {
for _, o := range opts {
if _, ok := o.(*GetPartialKeyMatch); ok {
if _, ok := o.(*PartialKeyMatch); ok {
return true
}
}
Expand Down Expand Up @@ -516,12 +534,14 @@ func SetNode(schema *yang.Entry, root interface{}, path *gpb.Path, val interface
val: val,
tolerateJSONInconsistenciesForVal: hasTolerateJSONInconsistencies(opts),
preferShadowPath: hasSetNodePreferShadowPath(opts),
partialKeyMatch: hasSetNodePartialKeyMatch(opts),
tolerateMissingElements: hasTolerateMissingElements(opts),
})
if err != nil {
return err
}

if len(nodes) == 0 {
if len(nodes) == 0 && !hasTolerateMissingElements(opts) {
return status.Errorf(codes.NotFound, "unable to find any nodes for the given path %v", path)
}

Expand Down Expand Up @@ -571,6 +591,24 @@ func hasTolerateJSONInconsistencies(opts []SetNodeOpt) bool {
return false
}

// TolerateMissingElements signals SetNode to not return an error if a node
// is not found at the given path.
type TolerateMissingElements struct{}

// IsSetNodeOpt implements the SetNodeOpt interface.
func (*TolerateMissingElements) IsSetNodeOpt() {}

// hasTolerateMissingElements determines whether there is an instance of
// TolerateMissingElements within the supplied SetNodeOpt slice.
func hasTolerateMissingElements(opts []SetNodeOpt) bool {
for _, o := range opts {
if _, ok := o.(*TolerateMissingElements); ok {
return true
}
}
return false
}

// DelNodeOpt defines an interface that can be used to supply arguments to functions using DeleteNode.
type DelNodeOpt interface {
// IsDelNodeOpt is a marker method that is used to identify an instance of DelNodeOpt.
Expand Down
12 changes: 7 additions & 5 deletions ytypes/node_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1458,7 +1458,7 @@ func TestGetNode(t *testing.T) {
},
},
inPath: mustPath("/list"),
inArgs: []GetNodeOpt{&GetPartialKeyMatch{}},
inArgs: []GetNodeOpt{&PartialKeyMatch{}},
wantTreeNodes: []*TreeNode{{
Data: &listEntry{Key: ygot.String("one")},
Schema: simpleListSchema,
Expand All @@ -1474,7 +1474,7 @@ func TestGetNode(t *testing.T) {
},
},
inPath: mustPath("/list"),
inArgs: []GetNodeOpt{&GetPartialKeyMatch{}},
inArgs: []GetNodeOpt{&PartialKeyMatch{}},
wantTreeNodes: []*TreeNode{{
Data: &listEntry{Key: ygot.String("one")},
Schema: simpleListSchema,
Expand Down Expand Up @@ -1629,7 +1629,7 @@ func TestGetNode(t *testing.T) {
},
},
inPath: mustPath("/multilist[keyone=1]"),
inArgs: []GetNodeOpt{&GetPartialKeyMatch{}},
inArgs: []GetNodeOpt{&PartialKeyMatch{}},
wantTreeNodes: []*TreeNode{{
Data: &multiListEntry{Keyone: ygot.Uint32(1), Keytwo: ygot.Uint32(2)},
Schema: multiKeyListSchema,
Expand Down Expand Up @@ -1981,7 +1981,8 @@ func TestSetNode(t *testing.T) {
LeaflistVal: &gpb.ScalarArray{
Element: []*gpb.TypedValue{
{Value: &gpb.TypedValue_IntVal{IntVal: 42}},
}},
},
},
}},
inOpts: []SetNodeOpt{&InitMissingElements{}},
wantLeaf: []int32{42},
Expand All @@ -2008,7 +2009,8 @@ func TestSetNode(t *testing.T) {
LeaflistVal: &gpb.ScalarArray{
Element: []*gpb.TypedValue{
{Value: &gpb.TypedValue_IntVal{IntVal: 43}},
}},
},
},
}},
inOpts: []SetNodeOpt{&InitMissingElements{}},
wantLeaf: []int32{43},
Expand Down
4 changes: 2 additions & 2 deletions ytypes/schema_tests/get_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ func TestGetNodeFull(t *testing.T) {
}(),
inSchema: rootSchema,
inPath: mustPath("/interfaces/interface/config/description"),
inOpts: []ytypes.GetNodeOpt{&ytypes.GetPartialKeyMatch{}},
inOpts: []ytypes.GetNodeOpt{&ytypes.PartialKeyMatch{}},
wantNodes: []*ytypes.TreeNode{{
Path: mustPath("/interfaces/interface[name=eth0]/config/description"),
Data: ygot.String("eth0"),
Expand All @@ -161,7 +161,7 @@ func TestGetNodeFull(t *testing.T) {
}(),
inSchema: rootSchema,
inPath: mustPath("/interfaces/interface"),
inOpts: []ytypes.GetNodeOpt{&ytypes.GetPartialKeyMatch{}},
inOpts: []ytypes.GetNodeOpt{&ytypes.PartialKeyMatch{}},
wantNodes: []*ytypes.TreeNode{{
Path: mustPath("/interfaces/interface[name=eth0]"),
Data: &oc.Interface{
Expand Down

0 comments on commit 738c041

Please sign in to comment.