IOS XE RESTCONF
Warning
Advanced stuff below.
The Cisco IOS XE implementation of YANG lists is ... weird.
Please don't use this reference as an introduction to RESTCONF - use it do deeper understand some of the special cases with IOS XE.
List element operations
In this blog post, we will cover RESTCONF on IOS XE, exploring supported HTTP methods and endpoint paths, along with example JSON payloads and the corresponding CLI configuration results. Understanding which combination of HTTP methods and endpoints paths are supported, as well as the appropriate JSON payloads, can be challenging. We can use the structure of the YANG model to get insights on how we can interact with each endpoint in the model.
The following error messages are commonly seen for unsupported combinations:
- Unknown element
- POST on list must be on list element
- Method Not Allowed
- Resource already exist
- Operation not allowed
A lot of the configuration that we provision through the RESTCONF API are dealing with lists (corresponding to YANG lists and leaf-lists) and list elements (corresponding to YANG leafs and containers). To find the correct API endpoint path we need to identify which of these variations we are dealing with.
Examples of what a list may represent:
- GigabitEthernet interfaces
- Access-list entries
- VRFs
Examples of what a list element may represent:
- One GigabitEthernet interface
- One access-list
- One VRF
Let's recap the basic HTTP methods that may be used to interact with device configuration via RESTCONF according to RFC 8040 section 4:
- GET: Retrieve existing configuration
- POST: Create new configuration
- PATCH: Merge configuration
- PUT: Replace existing configuration
- DELETE: Remove configuration
The examples below provides valid ways of configuring the Loopback9 interface on an IOS-XE router using the native YANG model.
The following pyang -f tree snippet shows the YANG model we will be using to construct the API endpoints and payload.
module: Cisco-IOS-XE-native
+--rw native
+--rw interface
+--rw GigabitEthernet* [name]
| +--rw name string
| +--rw description? string
+--rw Loopback* [name]
+--rw name string
+--rw description? string
One thing to keep in mind when dealing with IOS-XE YANG lists through RESTCONF is that the top-level element of the payload is always a JSON object with one single property. This statement may seem a bit confusing at first, but please revisit it when you have gone through the examples below.
Info
There are details and exceptions to the rules described in the examples below, important terms and variations are underlined for emphasis. Pay close attention to those.
The HTTP GET method
Retrieving a container with multiple lists
The following RESTCONF endpoint is representing a container that holds multiple lists, including the lists for GigabitEthernet and Loopback interfaces.
The JSON key of the top-level payload item corresponds to the last URL path segment - this means the string after the last slash in the path: Cisco-IOS-XE-native:native/interface in this case.
The key is prepended with the Cisco-IOS-XE-native prefix when the payload is returned.
Because the endpoint relates to a YANG container, the value of the item is a JSON object. (Curly-bracket syntax; similar to Python dict)
interface Loopback1
description Configured from CLI
no ip address
!
interface Loopback9
description Configured from CLI
no ip address
!
interface GigabitEthernet1
description Configured from CLI
no ip address
!
- GET
/restconf/data/Cisco-IOS-XE-native:native/interface
{
"Cisco-IOS-XE-native:interface": {
"Loopback": [
{
"name": 1,
"description": "Configured from CLI"
},
{
"name": 9,
"description": "Configured from CLI"
}
],
"GigabitEthernet": [
{
"name": 1,
"description": "Configured from CLI"
}
]
}
}
Retrieving a list
The following RESTCONF endpoint is representing single list of all Loopback interfaces.
The JSON key of the top-level payload item corresponds to the last URL path segment - this means the string after the last slash in the path: Cisco-IOS-XE-native:native/interface/Loopback in this case.
The key is prepended with the Cisco-IOS-XE-native prefix when the payload is returned.
Because the endpoint relates to a YANG list, the value of the item is a JSON array. (Square-bracket syntax; similar to Python list)
!
interface Loopback1
description Configured from CLI
no ip address
!
interface Loopback9
description Configured from CLI
no ip address
!
interface GigabitEthernet1
description Configured from CLI
no ip address
!
- GET
/restconf/data/Cisco-IOS-XE-native:native/interface/Loopback
{
"Cisco-IOS-XE-native:Loopback": [
{
"name": 1,
"description": "Configured from CLI"
},
{
"name": 9,
"description": "Configured from CLI"
}
]
}
Retrieving a single list item
The following RESTCONF endpoint is representing a single Loopback interface.
The JSON key of the top-level payload item corresponds to the last URL path segment - this means the string after the last slash in the path: Cisco-IOS-XE-native:native/interface/Loopback=9 in this case.
The key is prepended with the Cisco-IOS-XE-native prefix when the payload is returned.
The equal-sign is used to filter the list and return only one single item that matches the list key. The key of the Loopback interface list in the Cisco-IOS-XE-native YANG model, is the "name" leaf.
Because the endpoint relates to a YANG container, the value of the item is a JSON object. (Curly-bracket syntax; similar to Python dict)
interface Loopback9
description Configured from CLI
no ip address
!
interface Loopback10
description Configured from CLI
no ip address
!
interface GigabitEthernet1
description Configured from CLI
no ip address
!
- GET
/restconf/data/Cisco-IOS-XE-native:native/interface/Loopback=9
{
"Cisco-IOS-XE-native:Loopback": {
"name": 9,
"description": "Configured from CLI"
}
}
## The HTTP POST method
### Posting new configuration to a container
When posting new configuration to a container, the key of the top-level payload item must be the identifier of the YANG leaf we want to add the configuration to. In this case it is the ^^description^^ leaf.
For POST operations within a container, the API endpoint must be the ^^parent container^^ of the configuration payload: ^^Cisco-IOS-XE-native:native/interface/Loopback=9^^/description
Because we are adding data to one or more ^^YANG leaf(s)^^, the value of the payload item is a ^^JSON object^^. (Curly-bracket syntax; similar to Python dict)
```title="Existing CLI configuration before RESTCONF operation"
interface Loopback9
no ip address
- POST
/restconf/data/Cisco-IOS-XE-native:native/interface/Loopback=9
{
"description": "Configured from RESTCONF"
}
interface Loopback9
description Configured from RESTCONF
no ip address
Posting new items to lists
When posting new configuration to lists, the key of the top-level payload item must be the identifier of the YANG list we want to add one or more entries to. In this case it is the Loopback list.
For POST operations on a list, the API endpoint must be the parent container of the list we want to add new configuration items to: Cisco-IOS-XE-native:native/interface/Loopback
Because we are adding item(s) to a YANG list, the value of the payload item is a JSON array.
! (No loopback configured)
- POST
/restconf/data/Cisco-IOS-XE-native:native/interface
{
"Loopback": [
{
"name": 9,
"description": "Configured from RESTCONF"
}
]
}
interface Loopback9
description Configured from RESTCONF
no ip address
Explanation of "POST on list must be on list element" error message
The common RESTCONF error message "POST on list must be on list element" actually means: "POST on list must use the parent element API endpoint path and include the list identifier as the top-level payload element key."
It may seem a bit confusing, so here is a breakdown:
Let's say you got the "POST on list must be on list element" error when trying to POST to Cisco-IOS-XE-native:native/interface/Loopback.
You need to figure out what the parent element of the list is, what the list identifier is and what the top-level element key is. In this case:
- The parent element of the Loopback list is
Cisco-IOS-XE-native:native/interface - The list identifier of the Loopback list is
Loopback - The top-level element key is the first key in the JSON payload
- POST
/restconf/data/Cisco-IOS-XE-native:native/interface
{
"Loopback": [
{
...
The HTTP PUT method
Replacing configuration of a single list item
When replacing configuration of a single list item, the key of the top-level payload item must be the name of the YANG list we want to replace an entries inside. In this case it is the Loopback list.
For PUT operations on list items, the API endpoint is the container itself and we need to supply a filter to interact with one specific item.
The equal-sign is used to filter the list and return only one single item that matches the list key. The list key of interfaces in Cisco-IOS-XE-native YANG model is the "name" leaf.
Because we are replacing an item in a YANG list, the value of the payload item is a JSON array. (Curly-bracket syntax; similar to Python list)
In this case the Loopback9 exists with a description and an IPv4 address before the RESTCONF operation. Because the PUT payload only includes a description for the interface all other configuration for the interface wil be removed.
interface Loopback1
description Configured from CLI
ip address 1.1.1.1 255.255.255.255
!
interface Loopback9
description Configured from CLI
ip address 9.9.9.9 255.255.255.255
!
- PUT
/restconf/data/Cisco-IOS-XE-native:native/interface/Loopback=9
{
"Loopback": [
{
"name": 9,
"description": "Configured from RESTCONF"
}
]
}
interface Loopback1
description Configured from CLI
ip address 1.1.1.1 255.255.255.255
!
interface Loopback9
description Configured from RESTCONF
no ip address
!
Replacing or adding configuration with the PUT method
If the configuration items in the payload does not exist as a leaf or container before the PUT operation, it will be created dynamically.
The exception to this rule are list API endpoints such as Cisco-IOS-XE-native:native/interface/Loopback, because the PUT method is not allowed on such internal lists - it would result in HTTP error 405: Method Not Allowed. Please note that this error may not return any payload! So if you happen to use curl for testing, you wont see the error unless you add the -v parameter for verbose output.
To ensure a specific configuration on a sub element, it is possible to use the PUT method on the more specific API endpoint. The configuration will then be either replaced or created.
In this example, the interface does not have a description before the RESTCONF operation, so the description is created with the PUT method.
interface Loopback9
no ip address
!
- PUT
/restconf/data/Cisco-IOS-XE-native:native/interface/Loopback=9/description
{
"description": "Configured from RESTCONF"
}
interface Loopback9
no ip address
description Configured from RESTCONF
!
In the next example, the interface does have a description before the RESTCONF operation, so the description is replaced with the PUT method.
interface Loopback9
no ip address
description Configured from CLI
!
- PUT
/restconf/data/Cisco-IOS-XE-native:native/interface/Loopback=9/description
{
"description": "Configured from RESTCONF"
}
interface Loopback9
no ip address
description Configured from RESTCONF
!
The HTTP PATCH method
Merging new list items with existing configuration
When merging configuration using the PATCH method, the key of the top-level payload item matches both the identifier of YANG node and the last path segment in the API endpoint: Cisco-IOS-XE-native:native/interface
We do not need to specify any filtering at the API endpoint level because the key of YANG list items is present inside the payload. The list key of interfaces in Cisco-IOS-XE-native YANG model is the name leaf.
A shortcut to finding the correct JSON payload structure for the RESTCONF operation is to GET the API endpoint first, and evaluate the response.
The PATCH method never removes configuration. If the payload doesn't match existing configuration it will be appended to what is already there.
interface Loopback1
description Configured from CLI
ip address 1.1.1.1 255.255.255.255
!
- PATCH
/restconf/data/Cisco-IOS-XE-native:native/interface
{
"interface": {
"Loopback": [
{
"name": 9,
"description": "Configured from RESTCONF"
}
]
}
}
interface Loopback1
description Configured from CLI
ip address 1.1.1.1 255.255.255.255
!
interface Loopback9
description Configured from RESTCONF
no ip address
!
Merging configuration of an existing list item
In this case the Loopback9 exists with a description and an IPv4 address before the RESTCONF operation. Because the PATCH payload only includes a description for the interface, this is the only thing that will be changed.
interface Loopback9
description Configured from CLI
ip address 9.9.9.9 255.255.255.255
!
- PATCH
/restconf/data/Cisco-IOS-XE-native:native/interface
{
"interface": {
"Loopback": [
{
"name": 9,
"description": "Configured from RESTCONF"
}
]
}
}
interface Loopback9
description Configured from RESTCONF
ip address 9.9.9.9 255.255.255.255
!
Merging configuration for new and existing list items
It is possible to PATCH configuration on any level of the YANG tree and with any API endpoint, as long as the last path segment of the API endpoint matches the top-level item of the payload:
interface Loopback9
description Configured from CLI
ip address 9.9.9.9 255.255.255.255
!
- PATCH
/restconf/data/Cisco-IOS-XE-native:native/interface/Loopback
{
"Loopback": [
{
"name": 9,
"description": "Configured from RESTCONF"
},
{
"name": 10,
"description": "Configured from RESTCONF"
}
]
}
Merging list item configuration using endpoint key filter
It is possible to PATCH configuration of one specific list item without specifying the list item key inside the JSON payload, if it is added API endpoint as a filter instead:
interface Loopback9
description Configured from CLI
ip address 9.9.9.9 255.255.255.255
!
- PATCH
/restconf/data/Cisco-IOS-XE-native:native/interface/Loopback=9
{
"Loopback": [
{
"description": "Configured from RESTCONF"
}
]
}
interface Loopback9
description Configured from RESTCONF
ip address 9.9.9.9 255.255.255.255
!
Summary
To find the correct combination of RESTCONF API endpoint and JSON payload, you must know wether you are dealing with a list or list item in the YANG model.
For PUT and PATCH operations, the last URL path segment (the string after the very last slash) must match to the top-level item key.
For POST operations, the last URL path segment (the string after the very last slash) must correspond to the parent of the top-level item.
Finding the correct combination of method, endpoint and payload isn't easy, but looking at examples and being aware of the presence and limitations of lists does help.