How to approach Multiple Keys in the RESTCONF URL
In a week when I see the same question pop up twice, I know it’s something worth diving into. Add into the mix that it relates to one of my favorite topics, RESTCONF, and it was an obvious choice for an Ask Hank blog post.
I got this question over on Twitter from a Guille who identifies as a “DevNet student” (aren’t we all).
“Quick question, how can the RESTCONF is built by me url when there are two identifiers?”
In this context, “identifiers” refer to the keys defined in YANG for a list.
Before we dive into the answer, let’s make sure we understand the relevant question.
Crafting RESTCONF URLs for a specific element of a list
Going to my tried and true YANG model for learning back, ietf-interfaces.yang, we can see see that every “ interface ” is uniquely identified by it’s “ name ”
pyang -f tree --tree-path /interfaces/interface ietf-interfaces.yang module: ietf-interfaces +--rw interfaces +--rw interface * [ name ] +--rw name string +--rw description? string +--rw type identityref +--rw enabled? boolean +--rw link-up-down-trap-enable? enumeration if-mib?
The square brackets around the leaf indicate that it is the key. This is configured in the YANG model itself like this. (Note: the YANG model below has been edited for brevity. You can see the full YANG model on GitHub )
container interfaces description "Interface parameters."; list interface key " name "; description "The list of interfaces on the device."; leaf name type string; description "The name of the interface."
So how do we use this given information with RESTCONF to craft a URL? I think an example is the real way to go.
curl 'https://sandbox-iosxe-latest-1.cisco.com/restconf/data/ietf-interfaces:interfaces/ interface = GigabitEthernet2 ' --header 'Accept: application/yang-data+json' --user developer:C1sco12345 "ietf-interfaces:interface": "name": "GigabitEthernet2", "description": "Configured by RESTCONF", "type": "iana-if-type:ethernetCsmacd", "enabled": true, "ietf-ip:ipv4": "address": [ "ip": "10.255.255.2", "netmask": "255.255.255.0" ] , "ietf-ip:ipv6":
What we have above shows that an equals sign followed by the value of the key you are interest in is used in the URL. Straightforward pretty.
But what about lists with more than one key?
So we find ourselves at the question now. What if you’ve got a list with more than one key? Many lists shall have a single key, but let’s consider this example from the IOS XE Native models related to route lists.
pyang -f tree --tree-path=/native/ip/route Cisco-IOS-XE-native.yang module: Cisco-IOS-XE-native +--rw native +--rw ip +--rw route +--rw ip-route-interface-forwarding-list * [ prefix mask ] | +--rw prefix inet:ipv4-address | +--rw mask inet:ipv4-address | +--rw dhcp? empty | +--rw metric? uint8 | +--rw fwd-list* [fwd] | | +--rw fwd union | | +--rw interface-next-hop* [ip-address] | | | +--rw ip-address inet:ipv4-address
If you logically think, an entry in a routing table requires both the mask and prefix to be uniquely identified. This is because you could configured the following on a router:
ip route 192.168.100.0 255.255.255.0 10.10.10.1 ip route 192.168.100.0 255.255.255.224 172.16.32.1
The prefix of “ here;192.168.100.0” is used with two different routes, but one route has a longer-mask. The YANG model reflects this need to capture both mask and prefix for a unique list element.
But how is this reflected in the RESTCONF URL? It is times like this, when I turn to the documentation. Which for RESTCONF means RFC8040.
Section 3.5.3. Encoding Data Resource Identifiers in the Request URI gives us the information we need.
o If there is only one key leaf value, the path segment is
constructed by having the list name, followed by an “=” character,
followed by the single key leaf value.
o If there are multiple key leaf values, the path segment is
constructed by having the list name, followed by the value of each
leaf identified in the “key” statement, encoded in the order
specified in the YANG “key” statement. Each key leaf value except
the last one is followed by a comma character.
While the RFCs are found by me great resources, they can directly be tough to read. But their examples are golden
Examples: container top list list1 key " key1 key2 key3 "; ... list list2 key "key4 key5"; ... leaf X type string; leaf-list Y type uint32; For the above YANG definition, the container "top" is defined in the "example-top" YANG module, and a target resource URI for leaf "X" would be encoded as follows: /restconf/data/example-top:top/ list1 = key1 , key2 , key3
The key (pun intended) part of how this works is the comma. You common separate the key values in the URL simply. Applying this to our routing model above:
curl 'https://sandbox-iosxe-latest-1.cisco.com/restconf/data/Cisco-IOS-XE-native:native/ip/route/ ip-route-interface-forwarding-list = 220.127.116.11 , 255.255.255.0 ' --header 'Accept: application/yang-data+json' --user developer:C1sco12345 "Cisco-IOS-XE-native:ip-route-interface-forwarding-list": "prefix": "18.104.22.168", "mask": "255.255.255.0", "fwd-list": [ "fwd": "10.10.20.253" ]
Well, that’s about it, and it is hoped by me helps better demystify RESTCONF use for everyone. If you’d like to continue digging into RESTCONF, I’d suggest checking out the other blogs in the Ask Hank series . Several have touched on model driven programmability topics, in fact the first one was about creating RESTCONF URLs . And of course, the examples in this post used one of the DevNet Always On Sandboxes . Feel free to explore RESTCONF with this great, free resource, available to everyone – yOU even! There are also Learning Labs and videos that dig into RESTCONF you can explore while you are at it.