Skip to content
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

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

wenovus
Copy link
Collaborator

@wenovus wenovus commented Oct 22, 2020

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.

…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.
@googlebot googlebot added the cla: yes This PR author has signed the CLA label Oct 22, 2020
@coveralls
Copy link

Coverage Status

Coverage increased (+0.02%) to 90.634% when pulling 78691db on wildcard-path-helper into 00a6fee on master.

gnmipb "github.com/openconfig/gnmi/proto/gnmi"
)

// XXX: This is copied code from ygot package. ygot's code should probably
Copy link
Contributor

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.

Copy link
Contributor

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.

Copy link
Collaborator Author

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.

Copy link
Collaborator Author

@wenovus wenovus Oct 23, 2020

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:

  1. Debug utilities
  2. Basic error type
  3. ygot-specific goyang schema helpers
  4. string path helpers operating on the goyang schema, which uses 3
  5. 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.
  6. GoStruct helpers
  7. GoStruct helpers that operating on goyang's schema, which uses 4
  8. GoStruct traversal functions based on goyang's schema, which uses 4, 6-7
  9. 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-3
  • pathutil: 4-5 + ygot/pathstrings.go
  • gostructutil 6-9
    What do you think @robshakir

Copy link
Contributor

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.

Copy link
Collaborator Author

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.

Copy link
Collaborator Author

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

Copy link
Contributor

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 {
Copy link
Contributor

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)
Copy link
Contributor

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) {
Copy link
Contributor

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 {
Copy link
Contributor

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 {
Copy link
Contributor

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
Copy link
Contributor

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
Copy link
Contributor

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.

@wenovus wenovus added the needs-discussion Needs Discussion on Next Steps label Nov 9, 2021
@robshakir
Copy link
Contributor

Wen, this was on the review stack but looks to have outstanding comments. Is there anything you need from me here?

@wenovus
Copy link
Collaborator Author

wenovus commented Dec 29, 2021

It's actually not this PR, but rather this comment: #467 (comment)
I'm wondering if you think it's worth splitting the util package up into these packages in order to make the functionalities more modular. If you think this is a good idea we might consider doing this prior to v1 release.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cla: yes This PR author has signed the CLA needs-discussion Needs Discussion on Next Steps
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants