Subject: Re: [netconf] Trouble with RFC 8040 (Restconf) fields Query Parameter

From: Mahesh Jethanandani <[email-masked]>
Date: Thu, 7 May 2020 13:33:34 -0700

Hi Henning,

> On Apr 20, 2020, at 3:44 AM, Henning Rogge <[email-masked]> wrote:
> 
> are there any set of test-cases the IETF used for interoperability tests?

While not IETF blessed, ODL ran into multiple issues with the fields query parameter, and documented in this <https://jira.opendaylight.org/browse/NETCONF-660> Jira report. Documented in there are some of the test cases that might interest you to run. There were other test cases run in this <https://jira.opendaylight.org/browse/NETCONF-658> and this <https://jira.opendaylight.org/browse/NETCONF-657> report also that should be of interest.

Cheers.

Mahesh Jethanandani (as contributor)
[email-masked]

---

From: Henning Rogge <[email-masked]>
Date: Fri, 8 May 2020 07:18:52 +0200

On Thu, May 7, 2020 at 10:33 PM Mahesh Jethanandani
<[email-masked]> wrote:
>
> Hi Henning,
> While not IETF blessed, ODL ran into multiple issues with the fields query parameter, and documented in this Jira report. Documented in there are some of the test cases that might interest you to run. There were other test cases run in this and this report also that should be of interest.

Thank you very much for these links...

hmm, when reading through them I noticed something... is
fields=uuid;actual-equipment(manufactured-thing(equipment-type);structure)
even valid?

According to the RFC8040 4.8.3. the bracket part of the expression can
only nest in the last of the fields...

'path ; fields-expr', but not 'fields-expr ; path"

What do you think ? I guess this was don to prevent a whole tree of
field subexpressions... the ABNF does only seem to support a "line" of
them.

Henning Rogge

---

From: Henning Rogge <[email-masked]>
Date: Fri, 8 May 2020 12:24:13 +0200

Hi,

I finally got the okay to push my testcases to a public repository...
both the description and the filenames are still a little bit rough
and could use some work, but this is what I am working with at the
moment.

https://github.com/fkie/ietf-restconf-testcases

Henning Rogge

---

From: Douglas Hubler <[email-masked]>
Date: Fri, 8 May 2020 09:11:35 -0400

I've been very interested in restconf test cases and glad to see some
activity here.

So is the idea restconf server implementations stand up a server that loads
each config/state one-by-one then a utility will also read in same test
cases, exercise queries and assert the expected results?

I'd definitely like to hear more about how you're using this currently and
if you have a working model.

Thanks for sharing.

On Fri, May 8, 2020 at 6:25 AM Henning Rogge <[email-masked]> wrote:

> > While not IETF blessed, ODL ran into multiple issues with the fields
> query parameter, and documented in this Jira report. Documented in there
> are some of the test cases that might interest you to run. There were other
> test cases run in this and this report also that should be of interest.
> >
> > Cheers.
> >
> _______________________________________________
> netconf mailing list
> [email-masked]
> https://www.ietf.org/mailman/listinfo/netconf
>

---

From: Henning Rogge <[email-masked]>
Date: Fri, 8 May 2020 15:59:13 +0200

On Fri, May 8, 2020 at 3:11 PM Douglas Hubler <[email-masked]> wrote:
>
> I've been very interested in restconf test cases and glad to see some activity here.
>
> So is the idea restconf server implementations stand up a server that loads each config/state one-by-one then a utility will also read in same test cases, exercise queries and assert the expected results?

Yes.

> I'd definitely like to hear more about how you're using this currently and if you have a working model.

I use python with two threads... one thread starts the server and
loads the "before" state into the datamodel.
The other one waits 100ms, sends the HTTP request, parses the answer,
check the answers body and headers and then checks the (possibly)
changed internal state of the server.
Both before and after uses the standard Restconf JSON encoding.
After this the server thread is stopped and the client closes the connection.

This is iterated for each test.

At the moment the "/restconf" part of the URL is hardcoded... I will
definitely change this when I switch to the "unified data store".
I think I also have some tests where "before.json" and "after.json"
are the same, so I could replace them with a single "state.json" file
(easier to read).

The trickiest part was to write a compare function for the servers
response body and for the final server state (and setup and teardown
of the second thread ^^).

My tests use "pytest", so no special things involved. I am currently
trying to get permission to share the code of the server under LGPLv3,
same licence as the yangson library I use.
I have also written a couple of extensions for the yangson library
(e.g. XML input/output support), but I am trying to get them pulled
into the upstream implementation.

In theory the "write initial state" and "read final state" could be
done with Restconf HTTP commands, but I would like to keep each test
using only a single HTTP request.

Henning Rogge

---

From: Mahesh Jethanandani <[email-masked]>
Date: Fri, 8 May 2020 11:07:35 -0700

Hi Henning,

> On May 7, 2020, at 10:18 PM, Henning Rogge <[email-masked]> wrote:
> 
> 'path ; fields-expr', but not 'fields-expr ; path”

I will let one of the authors comment on what the intent was.

> field subexpressions... the ABNF does only seem to support a "line" of

The implementation in ODL does not care what order the query is placed in. Even if the bracket part of the query is placed in the last field, when it builds up the hash index for the search, the bracketed parts can appear anywhere based on how it gets hashed.

Cheers.

> Henning Rogge

Mahesh Jethanandani
[email-masked]

---

From: Henning Rogge <[email-masked]>
Date: Fri, 8 May 2020 20:37:48 +0200

> The implementation in ODL does not care what order the query is placed in. Even if the bracket part of the query is placed in the last field, when it builds up the hash index for the search, the br…

Not sure about my implementation, I have to look at the code... but I
think all test cases should be within the specification, because an
implementation might have found a reason to care about it.

Henning

---

From: Kent Watsen <[email-masked]>
Date: Fri, 8 May 2020 18:49:08 +0000

Hi Henning,

> I will let one of the authors comment on what the intent was.

This is likely an errata in just the ABNF.

Supporting this view, note that fields=genre;year == fields=year;genre (i.e., order doesn't matter)

> The implementation in ODL does not care what order the query is placed in. Even if the bracket part of the query is placed in the last field, when it builds up the hash index for the search, the br…

A reasonable application of Postel's principle.

Kent // as a co-author and quasi-instigator of the sub-select syntax

---

From: Henning Rogge <[email-masked]>
Date: Sat, 9 May 2020 09:36:38 +0200

> Supporting this view, note that fields=genre;year == fields=year;genre (i.e., order doesn't matter)

Good to know... does it make sense to transform this (and maybe the
example error) into a formal errata?

Henning Rogge

---

From: Henning Rogge <[email-masked]>
Date: Tue, 12 May 2020 12:57:59 +0200

Hi,

hopefully last question about the field operator.

I finally managed to switch me datamodel to a "unified model" that
includes everything beginning from the "/restconf" path.

I noticed the following parts:
* "fields" and "depth" query can be combined
* "depth" default is unlimited
* "fields" can be done on the "/restconf/data" level
* a query to "/restconf/data" does NOT result in unlimited depth...

does this mean "depth" is always 2 for /restconf/data queries (but not
on sub-paths)?
what is about a GET to "/restconf" ?
is the "depth" default still 2 for "/restconf/data" if there is a
"field" query operator?

Henning

---

From: "Per Andersson (perander)" <[email-masked]>
Date: Tue, 12 May 2020 11:46:56 +0000

> * a query to "/restconf/data" does NOT result in unlimited depth...

The depth default would still be unbounded if not set explicitly.

>From RFC 8040

    The requested data node has a depth level of "1".

So, a request towards /restconf/data would yield depth level 1
on /restconf/data, /restconf/data/node would be depth level 2,
and so on.

If the request would be towards /restconf/data/node instead,
/restconf/data/node would be depth level 1.

> is the "depth" default still 2 for "/restconf/data" if there is a

If depth and fields are combined, nodes that would be selected
in fields (and all ancestor nodes) would have a depth value of 1.
I.e. the path to the selected node is included even if depth is
lower than the nodes included in fields. Otherwise the depth
query parameter is obeyed.

--
Per

---

From: Henning Rogge <[email-masked]>
Date: Tue, 12 May 2020 14:15:32 +0200

> The depth default would still be unbounded if not set explicitly.

the second/third in Example B.1.2 suggest otherwise... Client request
something from "/restconf" and only gets a tree "1 deep" (node itself
plus direct children), which would be an equivalent of "?depth=2"...

> on /restconf/data, /restconf/data/node would be depth level 2,

Yes... "?depth=2" gives you the node itself and the direct children.

> query parameter is obeyed.

Does the counting just begin when the explicit selected fields end or
does it directly jump to the depth measured from the root node?

Henning Rogge

---

From: Kent Watsen <[email-masked]>
Date: Tue, 12 May 2020 19:53:15 +0000

Hi Henning,

> does it directly jump to the depth measured from the root node?

It's measured from the target resource.

Think of "fields" as like a SQL "WHERE" clause and "depth" as a post-op on the result.   Note that certain combinations of depth and fields can lead to all the selected fields being trimmed out of the response.  That is a valid user-error scenario.

> Henning Rogge

Kent // contributor

---

From: Andy Bierman <[email-masked]>
Date: Tue, 12 May 2020 14:16:29 -0700

On Tue, May 12, 2020 at 12:53 PM Kent Watsen <[email-masked]> wrote:

> Think of "fields" as like a SQL "WHERE" clause and "depth" as a post-op on
> the result.   Note that certain combinations of depth and fields can lead
> to all the selected fields being trimmed out of the response.  That is a
> valid user-error scenario.
>
>
The fields nodes are supposed to be included in depth=1

https://tools.ietf.org/html/rfc8040#section-4.8.2

   The requested data node has a depth level of "1".  If the "fields"
   parameter (Section 4.8.3
<https://tools.ietf.org/html/rfc8040#section-4.8.3>) is used to select
descendant data nodes,
   then these nodes and all of their ancestor nodes have a "depth" value
   of "1".  (This has the effect of including the nodes specified by the
   fields, even if the "depth" value is less than the actual depth level
   of the specified fields.)  Any other child node has a "depth" value

      that is 1 greater than its parent.

> Kent // contributor

Andy