Skip to content

Commit b49bc64

Browse files
authored
Add a SetWildcardKeys function to Pathtranslator (#1026)
1 parent 2dd1852 commit b49bc64

File tree

2 files changed

+186
-1
lines changed

2 files changed

+186
-1
lines changed

ygot/pathtranslate/pathtranslate.go

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ func (r *PathTranslator) PathElem(p []string) ([]*gnmipb.PathElem, error) {
8080
// When keys are consumed, they are set as true in "used" slice.
8181
used := make([]bool, len(p))
8282

83-
// Keeps the path elements seeen so far by appending with a separator.
83+
// Keeps the path elements seen so far by appending with a separator.
8484
var pathSoFar string
8585

8686
var res []*gnmipb.PathElem
@@ -114,3 +114,27 @@ func (r *PathTranslator) PathElem(p []string) ([]*gnmipb.PathElem, error) {
114114

115115
return res, nil
116116
}
117+
118+
// SetWildcardKeys sets the keys of the given path elements based on stored rewrite rules,
119+
// with the value set to "*". Elems are modified in place.
120+
// It returns true if the path has been updated, and an error if any of the elems already has keys.
121+
func (r *PathTranslator) SetWildcardKeys(elems []*gnmipb.PathElem) (bool, error) {
122+
var pathSoFar string
123+
var updated bool
124+
for _, elem := range elems {
125+
pathSoFar = pathSoFar + separator + elem.GetName()
126+
keyNames, ok := r.rules[pathSoFar]
127+
if !ok {
128+
continue
129+
}
130+
if elem.GetKey() != nil {
131+
return false, fmt.Errorf("path %v already has keys", elems)
132+
}
133+
elem.Key = map[string]string{}
134+
for _, key := range keyNames {
135+
elem.Key[key] = "*"
136+
}
137+
updated = true
138+
}
139+
return updated, nil
140+
}

ygot/pathtranslate/pathtranslate_test.go

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,3 +245,164 @@ func TestPathElem(t *testing.T) {
245245
})
246246
}
247247
}
248+
249+
func TestSetWildcardKeys(t *testing.T) {
250+
schemas := []*yang.Entry{
251+
{Name: "root"},
252+
{
253+
Name: "simpleKeyedList",
254+
Key: "k1",
255+
Parent: &yang.Entry{
256+
Name: "simpleKeyedLists",
257+
Parent: &yang.Entry{
258+
Name: "b",
259+
Parent: &yang.Entry{
260+
Name: "a",
261+
Parent: &yang.Entry{Name: "root"},
262+
},
263+
},
264+
},
265+
},
266+
{
267+
Name: "structKeyedList",
268+
Key: "k1 k2 k3",
269+
Parent: &yang.Entry{Name: "structKeyedLists",
270+
Parent: &yang.Entry{
271+
Name: "simpleKeyedList",
272+
Key: "k1",
273+
Parent: &yang.Entry{
274+
Name: "simpleKeyedLists",
275+
Parent: &yang.Entry{
276+
Name: "b",
277+
Parent: &yang.Entry{
278+
Name: "a",
279+
Parent: &yang.Entry{Name: "root"},
280+
},
281+
},
282+
},
283+
},
284+
},
285+
},
286+
}
287+
288+
tests := []struct {
289+
inDesc string
290+
path []*gnmipb.PathElem
291+
wantPath []*gnmipb.PathElem
292+
wantUpdated bool
293+
wantErrSubstring string
294+
}{
295+
{
296+
inDesc: "success empty path",
297+
path: []*gnmipb.PathElem{},
298+
wantPath: []*gnmipb.PathElem{},
299+
wantUpdated: false,
300+
},
301+
{
302+
inDesc: "success path with no keyed list(note, it doesn't exist in schema)",
303+
path: []*gnmipb.PathElem{
304+
{Name: "a"},
305+
{Name: "b"},
306+
},
307+
wantPath: []*gnmipb.PathElem{
308+
{Name: "a"},
309+
{Name: "b"},
310+
},
311+
wantUpdated: false,
312+
},
313+
{
314+
inDesc: "success path with keyed list at the end",
315+
path: []*gnmipb.PathElem{
316+
{Name: "a"},
317+
{Name: "b"},
318+
{Name: "simpleKeyedLists"},
319+
{Name: "simpleKeyedList"},
320+
},
321+
wantPath: []*gnmipb.PathElem{
322+
{Name: "a"},
323+
{Name: "b"},
324+
{Name: "simpleKeyedLists"},
325+
{Name: "simpleKeyedList", Key: map[string]string{"k1": "*"}},
326+
},
327+
wantUpdated: true,
328+
},
329+
{
330+
inDesc: "success path with keyed list followed by arbitrary elements",
331+
path: []*gnmipb.PathElem{
332+
{Name: "a"},
333+
{Name: "b"},
334+
{Name: "simpleKeyedLists"},
335+
{Name: "simpleKeyedList"},
336+
{Name: "arbitrary1"},
337+
{Name: "arbitrary2"},
338+
},
339+
wantPath: []*gnmipb.PathElem{
340+
{Name: "a"},
341+
{Name: "b"},
342+
{Name: "simpleKeyedLists"},
343+
{Name: "simpleKeyedList", Key: map[string]string{"k1": "*"}},
344+
{Name: "arbitrary1"},
345+
{Name: "arbitrary2"},
346+
},
347+
wantUpdated: true,
348+
},
349+
{
350+
inDesc: "success path with struct keyed list",
351+
path: []*gnmipb.PathElem{
352+
{Name: "a"},
353+
{Name: "b"},
354+
{Name: "simpleKeyedLists"},
355+
{Name: "simpleKeyedList"},
356+
{Name: "structKeyedLists"},
357+
{Name: "structKeyedList"},
358+
},
359+
wantPath: []*gnmipb.PathElem{
360+
{Name: "a"},
361+
{Name: "b"},
362+
{Name: "simpleKeyedLists"},
363+
{Name: "simpleKeyedList", Key: map[string]string{"k1": "*"}},
364+
{Name: "structKeyedLists"},
365+
{Name: "structKeyedList", Key: map[string]string{"k1": "*", "k2": "*", "k3": "*"}},
366+
},
367+
wantUpdated: true,
368+
},
369+
{
370+
inDesc: "fail when input path already has keys",
371+
path: []*gnmipb.PathElem{
372+
{Name: "a"},
373+
{Name: "b"},
374+
{Name: "simpleKeyedLists"},
375+
{Name: "simpleKeyedList", Key: map[string]string{"k1": "key1"}},
376+
{Name: "arbitrary"},
377+
},
378+
wantPath: []*gnmipb.PathElem{
379+
{Name: "a"},
380+
{Name: "b"},
381+
{Name: "simpleKeyedLists"},
382+
{Name: "simpleKeyedList", Key: map[string]string{"k1": "key1"}},
383+
{Name: "arbitrary"},
384+
},
385+
wantUpdated: false,
386+
wantErrSubstring: "already has keys",
387+
},
388+
}
389+
r, err := NewPathTranslator(schemas)
390+
if err != nil {
391+
t.Errorf("failed to create path translator; %v", r)
392+
}
393+
for _, tc := range tests {
394+
t.Run(tc.inDesc, func(t *testing.T) {
395+
updated, err := r.SetWildcardKeys(tc.path)
396+
if diff := errdiff.Substring(err, tc.wantErrSubstring); diff != "" {
397+
t.Errorf("diff: %v", diff)
398+
return
399+
}
400+
if updated != tc.wantUpdated {
401+
t.Errorf("got matched %v, want %v", updated, tc.wantUpdated)
402+
}
403+
if !cmp.Equal(tc.path, tc.wantPath, cmp.Comparer(proto.Equal)) {
404+
t.Errorf("got %v, want %v", tc.path, tc.wantPath)
405+
}
406+
})
407+
}
408+
}

0 commit comments

Comments
 (0)