Subject: [Netconf] RESTCONF examples

From: Ladislav Lhotka <[email-masked]>
Date: Mon, 21 Mar 2016 11:35:54 +0100

Hi,

I am confused by this example in draft-ietf-netconf-restconf-10,
appendix D.3.4:

      POST /restconf/data/example-jukebox:jukebox/
          playlist=Foo-One?insert=first HTTP/1.1
      Host: example.com
      Content-Type: application/yang.data+json

      {
        "example-jukebox:song" : {
           "index" : 1,
           "id" : "/example-jukebox:jukebox/library/
               artist=Foo%20Fighters/album=Wasting%20Light/song=Rope"
         }
      }

The text says "..., a new first entry in the "Foo-One" playlist is being
created."

It seems to me that in fact a new first entry of the "song" list inside
the "Foo-One" playlist is supposed to be created. And then the request
should IMO be

      POST /restconf/data/example-jukebox:jukebox/
          playlist=Foo-One/song?insert=first HTTP/1.1
      Host: example.com
      Content-Type: application/yang.data+json

      {
        "index" : 1,
        "id" : "/example-jukebox:jukebox/library/
          artist=Foo%20Fighters/album=Wasting%20Light/song=Rope"
      }

That is, the client is posting to the "song" resource, namely creating
its new first entry whose content is specified in the body.

Am I missing something?

Thanks, Lada

-- 
Ladislav Lhotka, CZ.NIC Labs
PGP Key ID: E74E8C0C

---

From: Martin Bjorklund <[email-masked]>
Date: Tue, 22 Mar 2016 08:48:41 +0100 (CET)

Ladislav Lhotka <[email-masked]> wrote:
> the "Foo-One" playlist is supposed to be created.

You are right:

OLD:

  In this example, a new first entry in the "Foo-One" playlist
  is being created.

NEW:

  In this example, a new first song entry in the "Foo-One" playlist
  is being created.

> And then the request
> That is, the client is posting to the "song" resource

No, there is no "song" resource, since all data resources are YANG
data nodes.

/martin

>, namely creating
> _______________________________________________
> Netconf mailing list
> [email-masked]
> https://www.ietf.org/mailman/listinfo/netconf
>

---

From: Ladislav Lhotka <[email-masked]>
Date: Tue, 22 Mar 2016 09:36:59 +0100

> On 22 Mar 2016, at 08:48, Martin Bjorklund <[email-masked]> wrote:
> 

Are you saying that the user-ordered "song" list is *not* a YANG data node?

Also, the body

      {

is counter-intuitive, to say the least, because it looks like "song" is a container, which it isn't.

Lada

---

From: Ladislav Lhotka <[email-masked]>
Date: Tue, 22 Mar 2016 14:10:33 +0100

Hi,

I checked the book RESTful Web Services by Richardson & Ruby, and they
illustrate a recommended design of resources with the following example:

| Operation      | HTTP action      |
|----------------+------------------|
| List the users | GET /users       |
| Create a user  | POST /users      |
| View a user    | GET /users/52    |
| Modify a user  | PUT /users/52    |
| Delete a user  | DELETE /users/52 |

I think RESTCONF should follow the same pattern because this is what
developers are used to. The logic of some examples in the RESTCONF spec
- namely what's a resource and what's its value - isn't very clear to
me.

Lada

---

From: Andy Bierman <[email-masked]>
Date: Tue, 22 Mar 2016 07:16:49 -0700

> - namely what's a resource and what's its value - isn't very clear to

This is what we have except lists are encoded in 1 segment instead
of list key values in their own segment.

Please provide OLD and NEW text fragments that you think need to be changed

> Lada

Andy

---

From: Ladislav Lhotka <[email-masked]>
Date: Tue, 22 Mar 2016 15:26:43 +0100

> Please provide OLD and NEW text fragments that you think need to be

I did it already, without the OLD and NEW labels, so here it is again:

---------------------------------------------------------------------
OLD

      {

NEW

      {
	"index" : 1,
	"id" : "/example-jukebox:jukebox/library/
	  artist=Foo%20Fighters/album=Wasting%20Light/song=Rope"
      }
---------------------------------------------------------------------

If we agree that this example adds an entry to the "song" list, then IMO
"song" needs to appear in the Request-URI.

Lada

---

From: Andy Bierman <[email-masked]>
Date: Tue, 22 Mar 2016 08:11:26 -0700

> I did it already, without the OLD and NEW labels, so here it is again:

This is not how RESTCONF has been defined from the start.
The parent of the new song is used in POST URI because
the song does not exist yet.   The parent album MUST exist already.

If PUT is used to create the song resource, then the URI points to the song
resource
instance.

Lada

Andy

> >> > is counter-intuitive, to say the least, because it looks like "song"
> is
> >> a container, which it isn't.
> >> >
> >> > Lada
> >> >
> >> >>
> >> >>
> >> >> /martin
> >> >>
> >> >>
> >> >>> , namely creating

---

From: Ladislav Lhotka <[email-masked]>
Date: Wed, 23 Mar 2016 10:31:06 +0100

> This is not how RESTCONF has been defined from the start.

Let's see. The Request-URI in the OLD version is

/restconf/data/example-jukebox:jukebox/playlist=Foo-One?insert=first

According to sec. 1.1.4, the target resource is the "Foo-One" entry of
the "playlist" list. Correct?

Then sec. 4.8.4 says:

   [The "insert" query parameter] is also only supported if the target
   resource is a data resource, and that data represents a YANG list or
   leaf-list that is ordered by the user.

To me, this means that the example is incorrect because the target
resource is *not* a list ordered-by user.

Lada

---

From: Martin Bjorklund <[email-masked]>
Date: Wed, 23 Mar 2016 21:55:44 +0100 (CET)

> resource is *not* a list ordered-by user.

I think the quoted text is wrong.  For PUT, "insert" is only valid
if the target resource is an obu list.  For POST, "insert" is only
valid if the child resource is an obu list.

/martin

---

From: Ladislav Lhotka <[email-masked]>
Date: Thu, 24 Mar 2016 12:44:03 +0100

> valid if the child resource is an obu list.

Yes, the POST part explains the example. An alternative would be to keep
the text and update the example(s), as I suggested.

I am also wondering about the use of "insert" with PUT - it seems to
violate the HTTP spec. RFC 7231: "The PUT method requests that the state
of the target resource be created or replaced with the state defined by
the representation enclosed in the request message payload." This IMO
means that PUT should be used only for creating/replacing a whole list
or leaf-list.

Also, RFC 7231 states that PUT is idempotent, but is it satisfied in our
case? What happens if the same PUT request with the "insert" query
parameter is used twice?

Lada

---

From: Martin Bjorklund <[email-masked]>
Date: Thu, 24 Mar 2016 14:27:17 +0100 (CET)

> the text and update the example(s), as I suggested.

You cannot just update the example.  We'd have to rework lots of text,
e.g. we'd no longer map yang data node instances to resources; we'd
have to come up with an encoding for the result of doing GET on such a
URI.

> means that PUT should be used only for creating/replacing a whole list

There is no resource for the "entire list".  Each list entry is its
own resource.

> case? What happens if the same PUT request with the "insert" query

I think it should be ok.

/martin

---

From: Ladislav Lhotka <[email-masked]>
Date: Thu, 24 Mar 2016 15:07:59 +0100

> On 24 Mar 2016, at 14:27, Martin Bjorklund <[email-masked]> wrote:
> 

OK. This is easy to do for JSON encoding but I agree XML encoding would need some extra containers or something.

> There is no resource for the "entire list".  Each list entry is its

Your new text says otherwise: 'For PUT, "insert" is only valid if the target resource is an obu list.' If it is so, then the semantics of PUT require that the content of the target resource be replaced with the payload. RESTCONF's PUT with "insert" modifies the target resource, and such tasks should IMO be done with POST. Let's see if APPS folks have any comments during the IETF LC.

>> case? What happens if the same PUT request with the "insert" query

Do you mean that the second PUT should be silently ignored? Is it what existing implementations do?

Lada

---

From: Pavel Špírek <[email-masked]>
Date: Thu, 24 Mar 2016 15:26:51 +0100

> There is no resource for the "entire list".  Each list entry is its

So if I understand correctly, it's not possible to retrieve an entire 
list with single GET request? As we are discussing the "jukebox" 
example, I can easily imagine that a user would like to retrieve all 
songs in particular playlist. It's really ineffective to retrieve them 
one by one, because playlist can contain thousands of songs. In this 
case, is the only way to request the parent "playlist" entry and 
manually separate the unneeded fluff like "name" and "description" leaves?

---

From: Martin Bjorklund <[email-masked]>
Date: Thu, 24 Mar 2016 15:44:47 +0100 (CET)

Ladislav Lhotka <[email-masked]> wrote:
> OK. This is easy to do for JSON encoding but I agree XML encoding
> would need some extra containers or something.
> 
> > 
> Your new text says otherwise: 'For PUT, "insert" is only valid if the
> target resource is an obu list.'

s/list/list entry/

> If it is so, then the semantics of
> PUT require that the content of the target resource be replaced with
> the payload. RESTCONF's PUT with "insert" modifies the target
> resource, and such tasks should IMO be done with POST. Let's see if
> APPS folks have any comments during the IETF LC.
> 
> > 

The second PUT replaces the existing one (with exactly the same data).

/martin

---

From: Martin Bjorklund <[email-masked]>
Date: Thu, 24 Mar 2016 15:48:20 +0100 (CET)

Pavel Špírek <[email-masked]> wrote:
> one by one, because playlist can contain thousands of songs.

Agreed.  This is why we had 'collections' earlier; they got punted to
a separate document.  That work needs to continue once the base is
done.

> In this

You can use the 'fields' parameter:

    GET .../playlist=Foo-One?fields=song

/martin

---

From: Ladislav Lhotka <[email-masked]>
Date: Thu, 24 Mar 2016 16:26:24 +0100

> On 24 Mar 2016, at 15:44, Martin Bjorklund <[email-masked]> wrote:
> 

So, if I understand you correctly, the two possible requests for inserting an entry as the new head of the "Foo-One" playlist's "song" list are

POST /restconf/data/example-jukebox:jukebox/playlist=Foo-One?insert=first HTTP/1.1

and

PUT /restconf/data/example-jukebox:jukebox/playlist=Foo-One/song=2?insert=first HTTP/1.1

Both are pretty weird, IMO, given that we are adding an entry to the "song" list.

> The second PUT replaces the existing one (with exactly the same data).

But after the first insert we have a new head of the list, so doing insert=first again may be interpreted as an attempt to put the same entry to the head of the list for the second time.

I am sorry we are arriving so late with these comments, but the ambiguities in the spec pop up only now that we are implementing it ourselves.

Lada