Jetconf/Restconf basics

In this demo we are going to see how jetconf works from an end user perspective and some of its capabilities.

Starting things up

Run:

make start-dev-containers

Now, let’s export some environment variables we need:

[1]:
export USER_CERT=../../tests/certs/test_user_curl.pem
export BASE_URL=https://ntc-rosetta-conf:8443

Basics

Jetconf adheres to RFC8040, with the exception of having support for candidate/running configuration database (which we will explore later).

Methods supported

Path Child type Method Use
container list POST Creates a list element (doesn’t fail if exists, but will fail on commit)
container leaf POST Creates a leaf (fails if exists)
container container POST Creates container (fails if exists)
container N/A PUT Replaces the container object targetted in the path
container N/A DELETE Deletes container targetted in the path
leaf N/A PUT Replaces existing leaf
leaf N/A DELETE Deletes existing leaf
list N/A PUT Replaces existing element
list N/A DELETE Deletes existing element

It’s important to understand the difference between path and child in this context, which only makes sense when the path points to a container and the method is a POST. The path is basically the URL you are querying, which might end in a container, list element or leaf. For instance:

  • container - /interfaces or /interfaces/interface=eth0
  • list - /interfaces/interfaces
  • leaf - /interfaces/interfaces=eth0/name

The child type is basically the object type you are POSTing. When working with containers the object can either be a child object, which can be of either type, or iselt. We will see this more clearly as we progress with examples for each method.

Adding operations and hooks

Finally, users can define their own operations. We will see examples of that in a later notebook when we explore napalm’s integration. Hooks can also be defined; hooks are action that can be attached to actions like “creating an interface”, “removing a vlan”, “updating a particular object or field”, etc…

Examples

Now, let’s explore the methods supported to deal with objects by example.

Here we are targing a container (openconfig-interfaces:interfaces) but the object inside will contain a list element (openconfig-interfaces:interface: {...}). You can use this to create new list elements:

[2]:
curl --http2 -k --cert-type PEM -E $USER_CERT \
    -X GET \
    $BASE_URL/restconf/data/openconfig-interfaces:interfaces
{
    "openconfig-interfaces:interfaces": {
        "interface": []
    }
}
[3]:
cat 1_jetconf_basics/add_interface_eth0.json
{
        "openconfig-interfaces:interface": {
                "name": "eth0",
                "config": {
                        "name": "eth0",
                        "description": "a test interface",
                        "type": "iana-if-type:ethernetCsmacd"
                }
        }
}
[4]:
curl --http2 -k --cert-type PEM -E $USER_CERT \
    -X POST \
    -d @1_jetconf_basics/add_interface_eth0.json \
    $BASE_URL/restconf/data/openconfig-interfaces:interfaces
[5]:
curl --http2 -k --cert-type PEM -E $USER_CERT \
    -X GET \
    $BASE_URL/restconf/data/openconfig-interfaces:interfaces
{
    "openconfig-interfaces:interfaces": {
        "interface": [
            {
                "name": "eth0",
                "config": {
                    "name": "eth0",
                    "description": "a test interface",
                    "type": "iana-if-type:ethernetCsmacd"
                }
            }
        ]
    }
}

Now we are targetting a different container but the object inside is a leaf. You can use this to create new leaves in a container. For instance, let’s add the mtu field to the configuration, which is missing:

[6]:
curl --http2 -k --cert-type PEM -E $USER_CERT \
    -X GET \
    $BASE_URL/restconf/data/openconfig-interfaces:interfaces/interface=eth0/config
{
    "openconfig-interfaces:config": {
        "name": "eth0",
        "description": "a test interface",
        "type": "iana-if-type:ethernetCsmacd"
    }
}
[7]:
cat 1_jetconf_basics/add_mtu.json
{
        "openconfig-interfaces:mtu": 9000
}
[8]:
curl --http2 -k --cert-type PEM -E $USER_CERT \
    -X POST \
    -d @1_jetconf_basics/add_mtu.json \
    $BASE_URL/restconf/data/openconfig-interfaces:interfaces/interface=eth0/config
[9]:
curl --http2 -k --cert-type PEM -E $USER_CERT \
    -X GET \
    $BASE_URL/restconf/data/openconfig-interfaces:interfaces/interface=eth0/config
{
    "openconfig-interfaces:config": {
        "name": "eth0",
        "description": "a test interface",
        "type": "iana-if-type:ethernetCsmacd",
        "mtu": 9000
    }
}

You can POST a container object in a container object to create it. For instance, let’s create the hold-time container under the interface itself, which is missing:

[10]:
curl --http2 -k --cert-type PEM -E $USER_CERT \
    -X GET \
    $BASE_URL/restconf/data/openconfig-interfaces:interfaces/interface=eth0/hold-time
{
    "ietf-restconf:errors": {
        "error": [
            {
                "error-type": "protocol",
                "error-tag": "invalid-value",
                "error-path": "/openconfig-interfaces:interfaces/interface/0",
                "error-message": "NonexistentInstance: member 'hold-time'"
            }
        ]
    }
}
[11]:
cat 1_jetconf_basics/add_hold_time.json
{
        "openconfig-interfaces:hold-time": {}
}
[12]:
curl --http2 -k --cert-type PEM -E $USER_CERT \
    -X POST \
    -d @1_jetconf_basics/add_hold_time.json \
    $BASE_URL/restconf/data/openconfig-interfaces:interfaces/interface=eth0
[13]:
curl --http2 -k --cert-type PEM -E $USER_CERT \
    -X GET \
    $BASE_URL/restconf/data/openconfig-interfaces:interfaces/interface=eth0/hold-time
{
    "openconfig-interfaces:hold-time": {}
}

Note: In this example we added an empty container, but you can add an already populated one

When doing a PUT in a container, the object in the paylod is itself. You can use this to do replace the container:

[14]:
curl --http2 -k --cert-type PEM -E $USER_CERT \
    -X GET \
    $BASE_URL/restconf/data/openconfig-interfaces:interfaces/interface=eth0/config
{
    "openconfig-interfaces:config": {
        "name": "eth0",
        "description": "a test interface",
        "type": "iana-if-type:ethernetCsmacd",
        "mtu": 9000
    }
}
[15]:
cat 1_jetconf_basics/change_config.json
{
        "openconfig-interfaces:config": {
                "name": "eth0",
                "description": "a new interface description",
                "type": "iana-if-type:ethernetCsmacd"
        }
}
[16]:
curl --http2 -k --cert-type PEM -E $USER_CERT \
    -X PUT \
    -d @1_jetconf_basics/change_config.json \
    $BASE_URL/restconf/data/openconfig-interfaces:interfaces/interface=eth0/config
[17]:
curl --http2 -k --cert-type PEM -E $USER_CERT \
    -X GET \
    $BASE_URL/restconf/data/openconfig-interfaces:interfaces/interface=eth0/config
{
    "openconfig-interfaces:config": {
        "name": "eth0",
        "description": "a new interface description",
        "type": "iana-if-type:ethernetCsmacd"
    }
}

Use it to delete a container:

[18]:
curl --http2 -k --cert-type PEM -E $USER_CERT \
    -X GET \
    $BASE_URL/restconf/data/openconfig-interfaces:interfaces/interface=eth0
{
    "openconfig-interfaces:interface": [
        {
            "name": "eth0",
            "hold-time": {},
            "config": {
                "name": "eth0",
                "description": "a new interface description",
                "type": "iana-if-type:ethernetCsmacd"
            }
        }
    ]
}
[19]:
curl --http2 -k --cert-type PEM -E $USER_CERT \
    -X DELETE \
    $BASE_URL/restconf/data/openconfig-interfaces:interfaces/interface=eth0/hold-time
[20]:
curl --http2 -k --cert-type PEM -E $USER_CERT \
    -X GET \
    $BASE_URL/restconf/data/openconfig-interfaces:interfaces/interface=eth0
{
    "openconfig-interfaces:interface": [
        {
            "name": "eth0",
            "config": {
                "name": "eth0",
                "description": "a new interface description",
                "type": "iana-if-type:ethernetCsmacd"
            }
        }
    ]
}

You can use it to change a configuration element:

[21]:
curl --http2 -k --cert-type PEM -E $USER_CERT \
    -X GET \
    $BASE_URL/restconf/data/openconfig-interfaces:interfaces/interface=eth0/config/description
{
    "openconfig-interfaces:description": "a new interface description"
}
[22]:
cat 1_jetconf_basics/change_description.json
{
    "openconfig-interfaces:description": "yet another changed description"
}
[23]:
curl --http2 -k --cert-type PEM -E $USER_CERT \
    -X PUT \
    -d @1_jetconf_basics/change_description.json \
    $BASE_URL/restconf/data/openconfig-interfaces:interfaces/interface=eth0/config/description
[24]:
curl --http2 -k --cert-type PEM -E $USER_CERT \
    -X GET \
    $BASE_URL/restconf/data/openconfig-interfaces:interfaces/interface=eth0/config/description
{
    "openconfig-interfaces:description": "yet another changed description"
}

This is useful to remove configuration elements:

[25]:
curl --http2 -k --cert-type PEM -E $USER_CERT \
    -X GET \
    $BASE_URL/restconf/data/openconfig-interfaces:interfaces/interface=eth0/config
{
    "openconfig-interfaces:config": {
        "name": "eth0",
        "type": "iana-if-type:ethernetCsmacd",
        "description": "yet another changed description"
    }
}
[26]:
curl --http2 -k --cert-type PEM -E $USER_CERT \
    -X DELETE \
    $BASE_URL/restconf/data/openconfig-interfaces:interfaces/interface=eth0/config/description
[27]:
curl --http2 -k --cert-type PEM -E $USER_CERT \
    -X GET \
    $BASE_URL/restconf/data/openconfig-interfaces:interfaces/interface=eth0/config
{
    "openconfig-interfaces:config": {
        "name": "eth0",
        "type": "iana-if-type:ethernetCsmacd"
    }
}

You can use this to replace the entire list:

[28]:
curl --http2 -k --cert-type PEM -E $USER_CERT \
    -X GET \
    $BASE_URL/restconf/data/openconfig-interfaces:interfaces/interface
{
    "openconfig-interfaces:interface": [
        {
            "name": "eth0",
            "config": {
                "name": "eth0",
                "type": "iana-if-type:ethernetCsmacd"
            }
        }
    ]
}
[29]:
cat 1_jetconf_basics/replace_interfaces.json
{
        "openconfig-interfaces:interface": [
                {
                        "name": "eth1",
                        "config": {
                                "name": "eth1",
                                "type": "iana-if-type:ethernetCsmacd"
                        }
                },
                {
                        "name": "eth2",
                        "config": {
                                "name": "eth2",
                                "type": "iana-if-type:ethernetCsmacd"
                        }
                }
        ]
}
[30]:
curl --http2 -k --cert-type PEM -E $USER_CERT \
    -X PUT \
    -d @1_jetconf_basics/replace_interfaces.json \
    $BASE_URL/restconf/data/openconfig-interfaces:interfaces/interface
[31]:
curl --http2 -k --cert-type PEM -E $USER_CERT \
    -X GET \
    $BASE_URL/restconf/data/openconfig-interfaces:interfaces/interface
{
    "openconfig-interfaces:interface": [
        {
            "name": "eth1",
            "config": {
                "name": "eth1",
                "type": "iana-if-type:ethernetCsmacd"
            }
        },
        {
            "name": "eth2",
            "config": {
                "name": "eth2",
                "type": "iana-if-type:ethernetCsmacd"
            }
        }
    ]
}

You can use this to delete the entire list (although you will need to reinitialize it with a POST, much better to replace the list with an empty one instead):

[32]:
curl --http2 -k --cert-type PEM -E $USER_CERT \
    -X GET \
    $BASE_URL/restconf/data/openconfig-interfaces:interfaces
{
    "openconfig-interfaces:interfaces": {
        "interface": [
            {
                "name": "eth1",
                "config": {
                    "name": "eth1",
                    "type": "iana-if-type:ethernetCsmacd"
                }
            },
            {
                "name": "eth2",
                "config": {
                    "name": "eth2",
                    "type": "iana-if-type:ethernetCsmacd"
                }
            }
        ]
    }
}
[33]:
curl --http2 -k --cert-type PEM -E $USER_CERT \
    -X DELETE \
    $BASE_URL/restconf/data/openconfig-interfaces:interfaces/interface
[34]:
curl --http2 -k --cert-type PEM -E $USER_CERT \
    -X GET \
    $BASE_URL/restconf/data/openconfig-interfaces:interfaces
{
    "openconfig-interfaces:interfaces": {}
}
[35]:
# ignore me, this discards the changes so the notebook can be rerun
curl --http2 -k --cert-type PEM -E $USER_CERT \
    -X POST \
    $BASE_URL/restconf/operations/jetconf:conf-reset
{
    "status": "OK"
}