netviz GitHub

draw.io round trips

netviz's pitch is draw.io for infrastructure, with the YAML as the source of truth. This page is where that meets the actual tool: how to hand a diagram to somebody who has never installed netviz, and how to bring back what they did to it.

The loop is two commands:

$ netviz export drawio -o site.drawio      # hand this out
$ netviz import drawio site.drawio         # bring it back

Between them, the file is an ordinary .drawio document. It opens in app.diagrams.net, in the draw.io desktop app, in the VS Code extension and in Confluence, needs nothing installed beside it, and can be mailed to somebody who will never read a line of YAML.


Contents


What the exported file is

netviz export drawio writes one mxGraph model of one view:

--view picks the view — l1 by default, but l2, l3, routing, rack and the rest all export. --icons none draws coloured boxes instead of icons, and --no-frames leaves the namespace containers out.

Every cell also carries what makes the round trip possible: a block of custom attributes in netviz's own XML namespace.

Attribute Holds
netviz:role node, link, group or metadata
netviz:node / netviz:link the key the arrangement is stored under
netviz:name the fully-qualified name of the element it stands for
netviz:kind switch, cable, namespace, …
netviz:document the file the element is written in
netviz:hash a digest of the element as it was when exported
netviz:x / netviz:y where the cell was when it left netviz

Identity lives there and nowhere else. Not in the label, not in the position, not in the cell id. That is deliberate, and it is what makes the four gestures below unambiguous: a cell is the same element however far it has been dragged and whatever it now says on the canvas — so a changed label is free to mean something, and what it means is a rename.


What a draw.io user may safely change

Four things, and each has exactly one meaning coming back:

On the canvas In the inventory
Move a cell a geometry write — the arrangement, and nothing else
Retype a label rename, with every reference to it rewritten across the tree
Delete a cell delete, cascading to the cables that cannot survive it
Draw an edge between two cells connect, on the first free port at each end

Dragging the bends of a link is a fifth, and lands as a waypoint write. Dragging a namespace frame moves everything inside it, because the frame is a real mxGraph container.

You can also do as much as you like that netviz will simply ignore: add a legend, a title block, a note, an arrow pointing at the thing you want somebody to look at. Cells netviz did not write are reported on import and left exactly where they are — in the diagram, out of the inventory.


What they may not

Not forbidden — draw.io will let anybody do anything — but these do not come back, and it is worth saying so in the mail you attach the file to:


Bringing it back

netviz import drawio FILE reconciles the file against the inventory as it is now — not as it was when the file was exported — and expresses everything it finds as netviz edit operations. Those go through netviz plan, so what you are shown is the ordinary changeset, and nothing is written until you confirm it:

$ netviz import drawio site.drawio -n
site.drawio (l1 view): 1 moved, 1 renamed, 1 deleted
netviz plan: inventory → site.drawio

  - cable.cables/wl-ap-phone  [cable]
  - device.hosts/phone  [computer]
  → device.hosts/srv-nas → device.hosts/srv-store  [server]
  ~ cable.cables/cbl-sw-nas  [cable]
      ~ spec.endpoints: [srv-nas:eth0, …] -> [srv-store:eth0, …]
  ~ layout.layout  [layout]
      ~ spec.views.l1.nodes.hosts/pc-desk.position.x: 847.0 -> 947.0

Plan: ~ 2 to change, - 2 to destroy, → 1 to rename.

Read that plan the way you read any other. The geometry write is in it because an arrangement is inventory too — a kind: layout document, addressable and diffable like everything else.

-n/--dry-run shows the changeset and the unified diff and writes nothing. --auto-approve skips the confirmation, for a pipeline. Each of the four gestures can be turned off on its own: --no-geometry, --no-renames, --no-deletions, --no-connections.

A diagram exported from an older state of the tree still imports. Each cell carries a digest of the element it stood for, so an element that has changed since is reported — the geometry and the label are still applied, and you are told you are applying them to a moved target. Refusing the whole import over somebody else's unrelated commit would lose the reviewer's work.

Re-importing an unedited file changes nothing. That is a property netviz's own test suite asserts over every published example: export, import, and the plan is empty. A move is measured against the position netviz stamped into the cell, so a position netviz invented — because nothing had been arranged — is not written back when it comes home untouched. Nobody's arrangement gets committed by accident.


Deletions, and the one rule that keeps them safe

A missing cell is only a deletion when the file said it held the whole view.

netviz export drawio stamps netviz:scope="complete" when nothing narrowed the export, and partial when --namespace, --kind, --vlan, --name or --neighbors-of did. Import a partial diagram and nothing is deleted at all, whatever --deletions says; the elements that are not in it are counted and reported instead.

The reasoning is that absence proves nothing about a diagram that was filtered before it was drawn — and the failure mode of getting it wrong is deleting a site. If deletions are meant to come back, export without a filter.


A diagram netviz did not write

A hand-drawn .drawio file carries no identity attributes, so there is nothing to reconcile it against: every cell in it is either a new element or noise, and netviz cannot tell which. It is read anyway, and reported cell by cell — the kind each one looks like, from its shape style and its label, and a note for each one that could not be placed. Nothing is written.

That is the honest answer rather than a limitation. Inferring a computer from a rectangle would put hardware in an inventory that nobody owns, and the person who would find out is whoever trusts the inventory six months later.

To make a diagram netviz can reconcile, start from netviz export drawio — on an empty inventory if you have to — and edit that.


The two encodings

draw.io writes a diagram either as plain XML or as base64(deflate(uri-encode(xml))) inside the <diagram> element. It reads both, and so does netviz: netviz import drawio decides from what is in the file.

netviz writes the plain form by default, because a diagram that is text is a diagram that reviews, diffs and merges, which is the whole argument for keeping the YAML as the source of truth. --compress writes the compact form instead — about a fifth of the size, and what you want if the file is destined for an attachment rather than for a repository.


Limits


See also