skip to content

An automation job used a RESTCONF PUT to change one interface's description, and the interface's other settings vanished; what happened, and what should it have sent?

level: seniorimportance: must knowfreq 15%

answer

  1. the URI decided the blast radius
  2. target plus all descendants
  3. replace, not merge
  4. aim lower, or merge instead

basics

~20 s

PUT replaces the whole target resource with the body, so every configured child the body omitted was deleted or reverted to its YANG default. The job should have sent a plain PATCH (a merge) or a PUT aimed at the description leaf.

solid answer

~40 s

In RESTCONF a method acts on the target node *and all its descendants*, and `PUT` is create-or-replace: the body becomes the new content of the node the URI names. The job aimed its `PUT` at the interface list entry and sent only `name`, `type` and `description`, so every other configured child of that entry was removed — leaves with a YANG default such as `enabled` fell back to it, and configuration that other modules augment into the entry went too. The server did exactly what RFC 8040 §4.5 says. The fix is to match the method to the intent: a plain `PATCH` to the entry (a `merge` that leaves unmentioned children alone), or a `PUT` whose URI is the `description` leaf, so the subtree being replaced is just that leaf.

code

http · 7 lines
http
PUT /restconf/data/ietf-interfaces:interfaces/interface=uplink-1 HTTP/1.1
Host: router1.example.net
Content-Type: application/yang-data+json

{"ietf-interfaces:interface": [{"name": "uplink-1",
  "type": "iana-if-type:ethernetCsmacd",
  "description": "to core-2"}]}

go deeper

for a junior

Recall that PUT replaces the node its URI names, including everything inside it, while plain PATCH merges.

for a middle

Explain how subtree scope, replace semantics and YANG defaults combine to turn a one-leaf change into lost configuration.

for a senior

Diagnose the incident from the request and the 204, pick the corrected request, and harden the job with narrow URIs, merge by default and entity-tags.

for a principal

Decide where declarative full-state PUT belongs in an automation estate and where partial-change tooling must be forced onto merge or YANG Patch.

## The incident, reconstructed A job owns interface descriptions on a fleet of devices. On one router it was asked to set the description of `uplink-1`, an interface an engineer had administratively disabled for maintenance and that carries IP addressing configured through a module that augments the interface entry. The job built a body from a template and sent: 1. `PUT /restconf/data/ietf-interfaces:interfaces/interface=uplink-1` with `name`, `type` and the new `description`. 2. The server answered `204 No Content` — an existing resource was replaced, which is a success. 3. Afterwards the description was right, but the addressing was gone, and `enabled`, which had been configured `false`, was no longer configured at all. In the `ietf-interfaces` module (RFC 8343) `enabled` has `default "true"`, so the interface's intended state was now *up*. Nothing malfunctioned. Every step is what the specification requires. ## Why PUT did it - **Methods act on subtrees.** RFC 8040 §3.5 says HTTP methods on a data resource affect the targeted node and all of its descendants. A list entry's descendants include every leaf and container inside it, including nodes added by other modules' `augment` statements. - **`PUT` is create-or-replace.** RFC 8040 §4.5 says `PUT` creates or replaces the target data resource, and §4 maps it to NETCONF `<edit-config>` create/replace. NETCONF's `replace` (RFC 6241 §7.2) replaces "any related configuration" with what was sent. Whatever the body omits is not "left alone"; it is absent from the new content. - **Defaults fill the gap.** A leaf that is no longer configured but has a YANG `default` is treated as having that value. That is how a missing `enabled` turns into `true`. - **The wider the URI, the wider the loss.** Aimed one level higher, at `ietf-interfaces:interfaces`, the same body would have replaced the whole container and removed every other interface entry. Aimed at `{+restconf}/data`, a `PUT` is a NETCONF `<copy-config>`: RFC 8040's example warns that any child not in the body but present on the server is deleted. A mandatory leaf offers a little protection: if the template had also left out `type`, which is `mandatory true` in `ietf-interfaces`, the replaced entry would have failed validation and the server would have refused the request. Optional leaves enjoy no such guard. ## Three requests that would have been right | Request | Target | What it changes | |---|---|---| | plain `PATCH` with `name` and `description` | the list entry | merges: `description` updated, every other child untouched | | `PUT` with `{"ietf-interfaces:description": "..."}` | `.../interface=uplink-1/description` | replaces only the leaf it names | | `GET`, modify, then `PUT` of the complete entry | the list entry | replaces the entry with a body that still contains everything | The third is legitimate only when the job really owns the entry's full content, and it should carry the entity-tag from the `GET` in `If-Match`, so that an edit made by someone else in between is not overwritten. ## Making the job safe - **Name the smallest target that holds the change.** The URI, not the body, decides the blast radius of a `PUT`. - **Default to merge for partial changes.** Plain `PATCH` creates or updates children and never removes one it was not told about. - **Reserve `PUT` for declared full state** — a source of truth that renders the entire subtree and wants drift removed. That is `PUT`'s real strength: repeating it converges. - **Use YANG Patch (RFC 8072) for multi-step edits** that must add, replace and delete in one ordered, all-or-nothing request. - **Restrict who may replace large subtrees.** NACM (RFC 8341) rules on the paths a job's account may write limit what a wrong URI can reach. ## Why PATCH is not the answer to everything Plain `PATCH` has limits of its own. It cannot delete a child — removing a leaf needs `DELETE` or a YANG Patch `delete`/`remove` edit. It never creates the target node itself; RFC 8040 says the server must not. And on a list entry, the key values in the body must match the URI, for `PATCH` as for `PUT`. The rule for an interview is short: **`PUT` says "this is the whole thing", plain `PATCH` says "add or change these parts".**

  • When is a RESTCONF PUT on a whole list entry the right choice despite this risk?
    When the client is the source of truth for the entire entry and renders all of it every time — a declarative pipeline that wants anything not in its model removed. Then replacement is the point: repeating the request converges and strips drift. The body must be complete, including children other tools used to set, and the request should carry `If-Match` with the entity-tag it read.
  • The job must now clear the description instead of changing it. Which RESTCONF request does that?
    A `DELETE` aimed at `.../interface=uplink-1/description`. Plain `PATCH` cannot delete anything, and a `PUT` of the entry without the leaf would also remove every other omitted child. Because `DELETE` maps to NETCONF `delete`, it fails if no description is configured, so the job should treat that error as already done.

PUT hands in a fresh copy of the whole form, so any box left blank is blank afterwards; a plain PATCH is a correction slip that changes only the boxes written on it.

saying these in an interview costs you the question

  • PUT only writes the leaves in the body and keeps the rest.
  • The server should have rejected a PUT that omitted configured leaves.
  • A 204 response proves that only the intended leaf changed.
  • Switching to plain PATCH also lets the job delete leaves it omits.
  • The safe fix is to PUT the whole interfaces container instead.