-
Notifications
You must be signed in to change notification settings - Fork 107
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add PathElemsMatchQuery helper for checking path membership to a telemetry path #467
base: master
Are you sure you want to change the base?
Conversation
…metry path This helper checks whether a particular concrete path matches a query path per [gNMI path specifications](https://github.com/openconfig/reference/blob/master/rpc/gnmi/gnmi-path-conventions.md) NOTE: the new pathstrings.go is **COPIED** from the ygot package, as otherwise we have a circular dependency. In the future, the copied helpers should move to the util package.
gnmipb "github.com/openconfig/gnmi/proto/gnmi" | ||
) | ||
|
||
// XXX: This is copied code from ygot package. ygot's code should probably |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason to take on this debt in the codebase rather than fix it now? It seems like there'd be relatively minimal refactoring here -- i.e., we move the actual implementation to util, and keep the public APIs in ygot just calling these util functions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We maybe also should consider whether util
itself is going to grow into a similar situation, and create a smaller package just for path handling functions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From a quick scan of the internal dependencies it looks like it's possible to split out all gnmi-path related functions into a new package. This is all of gnmi.go
and the GetNode
and relatives in reflect.go
.
If we move all path-related functions into a new package, we'll essentially be moving util
to a new package.
So, I'm not sure if we can quite create a package called pathutil
, but gnmiutil
is still possible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I looked at the internal dependencies further.
The util
package has roughly the following high-level components in topological/dependency order:
- Debug utilities
- Basic error type
- ygot-specific goyang schema helpers
- string path helpers operating on the goyang schema, which uses 3
- gNMI path helpers, which uses 4
note: 4 can be separated into helpers that don't use the goyang schema (4a) vs. do (4b), and 5 only depends on those that don't (4b); however, 4a&4b are so intertwined that 4b also depends on 4a's internal methods, so it doesn't make sense functionally to split 4 into two. - GoStruct helpers
- GoStruct helpers that operating on goyang's schema, which uses 4
- GoStruct traversal functions based on goyang's schema, which uses 4, 6-7
- GoStruct traversal functions based on gNMI paths and goyang's schema, that uses 3-7.
While 5&9 can be separated into another package called gnmiutil
, which would contain pathstrings.go as well, it would be splitting based on that they both use gpb.Path
-- the meaning of gnmiutil
would still be unclear to the reader, which I think is the true problem: that when a reader reads util
, they don't know what it does.
I think it makes sense, rather, to split util
into the following packages in topological order:
util
: 1-3pathutil
: 4-5 + ygot/pathstrings.gogostructutil
6-9
What do you think @robshakir
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this set sounds a good set to have. Apologies for the delay in responding here. I'm happy with this split, which AIUI should mean that we don't need to duplicate code here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since generic package names are not recommended, perhaps a better set of names would be
internal
: 1 https://golang.org/doc/go1.4#internalpackages
ygoterrors
: 2
yangschema
: 3 (we have the option of simplifying some of the function names, e.g. util.SchemaPath
-> yangschema.Path
)
yangpath
: 4-5 + ygot/pathstrings.go
gostruct
: 6-9
We might also consider renaming genutil
to ygotgen
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Part of util refactoring effort: #556
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, sorry -- I thought that this was what you had decided upon. I think that this sounds a reasonable split -- I'm all OK with dividing out to very specific packages, I think in general it means that we end up with a cleaner import set from other modules.
// PathElem is a possible gNMI telemetry name match for the reference PathElem. | ||
// In particular, it matches wildcards for names and list keys, but *not* "...". | ||
// See https://github.com/openconfig/reference/blob/master/rpc/gnmi/gnmi-path-conventions.md | ||
func pathElemMatchesQuery(elem, refElem *gpb.PathElem) bool { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd suggest to call the first argument here queryElem
and the second pathElem
so that it's clear which of the two we're trying to match against each other.
@@ -134,6 +134,41 @@ func FindPathElemPrefix(paths []*gpb.Path) *gpb.Path { | |||
} | |||
} | |||
|
|||
// pathElemMatchesQuery returns true if the given concrete (no wildcard) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you clarify concrete
here? I think that you're trying to say if the given query element matches the reference element -- but the no wildcard
disclaimer is throwing me off, because it seems like wildcards are handled?
} | ||
|
||
for k, ref := range refElem.Key { | ||
if v, ok := elem.Key[k]; !ok || (ref != "*" && v != ref) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If ref == "*"
then you don't need to check that v != ref
right? Because even if v == ref
then if ref == *
we'll return true.
return false | ||
} | ||
|
||
for k, ref := range refElem.Key { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's one confusing thing here -- you say that the reference path must not include wildcards, but then we check whether ref == "*"
, which can presumably never happen.
We should probably note that if the key is not specified in the reference path, then we never check the value in the queried path, so therefore we assume that the element matches. This seems fine, but we should say that this function isn't schema aware -- it just takes in good faith that both paths are valid schema paths.
// reference PathElem path slice. | ||
// In particular, it matches wildcards for names and list keys, but *not* "...". | ||
// See https://github.com/openconfig/reference/blob/master/rpc/gnmi/gnmi-path-conventions.md | ||
func PathElemsMatchQuery(elems, refElems []*gpb.PathElem) bool { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similar comment here as above about making the concrete wording clearer, and the argument names.
|
||
// stringToStructuredPath takes a string representing a path, and converts it to | ||
// a gnmi.Path, using the PathElem element message that is defined in gNMI 0.4.0. | ||
// XXX: This is copied code from ygot package. ygot's code should probably |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same comment here about making the change to avoid code duplication.
// the name of the element, a map keyed by key name with values of the predicates | ||
// specified. It removes escape characters from keys and values where they are | ||
// specified. | ||
// XXX: This is copied code from ygot package. ygot's code should probably |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above - please don't duplicate code.
Wen, this was on the review stack but looks to have outstanding comments. Is there anything you need from me here? |
It's actually not this PR, but rather this comment: #467 (comment) |
This helper checks whether a particular concrete path matches a query
path per gNMI path specifications
NOTE: the new pathstrings.go is COPIED from the ygot package, as
otherwise we have a circular dependency. In the future, the copied
helpers should move to the util package.