netviz GitHub

netviz validate

Check the inventory for schema and semantic problems. It exits 1 when anything is reported as an error and 0 otherwise — so it drops straight into CI, into a pre-commit hook, or into a make check without any wrapping. Nothing is probed and no device is contacted: every finding comes from the files.

This page is the reference for the command. docs/validation.md is the treatment of the three passes, severities and suppression, and docs/validation-rules.md is the catalogue of every rule.


Contents


Synopsis

netviz [GLOBAL OPTIONS] validate [OPTIONS]

A clean inventory

Nothing to say is said in one line, and the exit code is 0:

$ netviz -i examples/quickstart validate
no problems found

There is no --summary and no verbosity level that turns this into a report of what was checked. If you want to know what the tool would have complained about, netviz rules prints the whole vocabulary.

An inventory with a problem

Findings are grouped by severity, most severe first, and each line reads file.yaml#doc:line RULE message. The repository keeps one deliberately broken fixture per rule, each producing exactly one finding, which makes them the smallest honest examples available:

$ netviz -i tests/fixtures/invalid/e001-unknown-endpoint.yaml validate
errors (1):
  e001-unknown-endpoint.yaml#1:19  E001  cable 'cbl-dangling' endpoint pc-ghost:eth0: no element named 'pc-ghost' is declared in this inventory

1 error

#1:19 is the second document of the file (documents are counted from 0, across --- separators) beginning at line 19. E001 is the id you would name to suppress the rule, and the message lists every element the finding involves — here the cable and the endpoint that resolves to nothing. How to read a finding takes the line apart column by column.

-i accepts a single YAML file as well as a directory, which is what makes the invocation above possible. In an inventory tree the location is relative to the root -i names.

Warnings, --strict and --disable

A warning is legal-but-probably-wrong, and it does not fail the run:

$ netviz -i tests/fixtures/invalid/w103-orphan-device.yaml validate
warnings (1):
  w103-orphan-device.yaml#0:6  W103  device 'pc-a' terminates no cable and hosts no adapter; it is drawn as an isolated node

1 warning

--strict promotes every surviving warning to an error, so any finding fails the run. This is the setting for a pipeline, where a warning nobody has to look at is a warning nobody looks at:

$ netviz -i tests/fixtures/invalid/w103-orphan-device.yaml validate --strict
errors (1):
  w103-orphan-device.yaml#0:6  W103  device 'pc-a' terminates no cable and hosts no adapter; it is drawn as an isolated node

1 error

--strict can only turn strictness on: strict = true in netviz.toml makes it the default for a tree and no command-line flag undoes that.

--disable RULE silences a rule by id. It is repeatable, accepts the short id or either NV-* alias, and accepts * for all of them. It adds to whatever netviz.toml already ignores and cannot re-enable a rule the file disabled. The two flags combine in the obvious way — be strict about everything except the exceptions you have decided are exceptions:

$ netviz -i tests/fixtures/invalid/w103-orphan-device.yaml validate --strict --disable W103
no problems found

Only the pass-3 semantic rules can be disabled. Naming a schema rule is a usage error rather than a flag that quietly applies to nothing, and the message lists what you could have meant instead:

$ netviz -i examples/quickstart validate --disable NV-D005
error: --disable: 'NV-D005' is not a known rule id; expected one of E001, E002, E003, E004, E005, E006, E007, E008, E009, E010, E011, E012, E013, E014, E015, E016, E017, E018, E019, E020, E021, E022, E023, E024, E025, E026, E027, E028, E029, E030, E031, E032, E033, E034, E035, E036, E037, E038, E039, E040, E041, E042, E043, E044, E045, E046, E047, E048, E049, E050, W101, W102, W103, W104, W105, W106, W107, W108, W109, W110, W111, W112, W113, W114, W115, W116, W117, W118, W119, W120, W121, W122, W123, W124, W125, W126, W127, W128, W129, W130, W131, W132, W133, W134, W135, W136, W137, W138, W139, W140, W141, W142, W143, W144, W145, W146, W147, W148, W149, W150, W151, W152, W153, W154, I001, I002, I003, I004, I005, an NV-* alias from docs/schema.md §10, or '*'

A suppression that belongs to the inventory rather than to one command line belongs in netviz.toml or in an element's netviz/ignore annotation — Saying "not here" sets the four mechanisms side by side, and Suppressing a rule gives each one in full.

Repairing what can be repaired

--fix applies the repairs the inventory itself determines and reports everything else. --dry-run prints the unified diff instead of writing:

$ netviz -i tests/fixtures/fixable validate --fix --dry-run
would fix 3 problems:
  W138  drop 'sw-gone' from the l1 view of layout 'default'
  W108  remove the MAC address from loopback sw-a:Loopback0
  W113  declare VLANs 20, 30 in the 'vlans' database of 'sw-a'
W114 at switches.yaml#0:11 not fixed: 2 repairs are possible; choose one with --choose W114=list|drop
    --choose W114=list  list VLAN 30 in the trunk_vlans of sw-a:GigabitEthernet0/1
    --choose W114=drop  remove the native_vlan of sw-a:GigabitEthernet0/1, so it tags every VLAN it carries

--- a/layout.yaml
+++ b/layout.yaml
@@ -9,4 +9,3 @@
       nodes:
         sw-a: {position: [54, 18]}
         sw-b: {position: [54, 126]}
-        sw-gone: {position: [54, 234]}
--- a/switches.yaml
+++ b/switches.yaml
@@ -16,6 +16,8 @@
   vlans:
     - id: 10
       name: office
+    - id: 20
+    - id: 30
   interfaces:
     - name: GigabitEthernet0/1
       type: ethernet
@@ -26,7 +28,6 @@
         native_vlan: 30
     - name: Loopback0
       type: loopback
-      mac: 00:11:22:33:44:55
       ipv4:
         - 10.255.0.1/32
 ---
warnings (1):
  switches.yaml#0:11  W114  trunk 'sw-a:GigabitEthernet0/1' has native VLAN 30, which is not in its trunk_vlans (10,20); it is carried untagged all the same, so list it

1 warning

Three of these four warnings had exactly one sensible repair, so they were made. The fourth has two, and the command names them rather than choosing: --choose W114=list writes the native VLAN into trunk_vlans, --choose W114=drop removes the native_vlan instead. With one of those the tree comes out clean:

$ netviz -i tests/fixtures/fixable validate --fix --dry-run --choose W114=list
would fix 4 problems:
  W138  drop 'sw-gone' from the l1 view of layout 'default'
  W108  remove the MAC address from loopback sw-a:Loopback0
  W113  declare VLANs 20, 30 in the 'vlans' database of 'sw-a'
  W114  list VLAN 30 in the trunk_vlans of sw-a:GigabitEthernet0/1
--- a/layout.yaml
+++ b/layout.yaml
@@ -9,4 +9,3 @@
       nodes:
         sw-a: {position: [54, 18]}
         sw-b: {position: [54, 126]}
-        sw-gone: {position: [54, 234]}
--- a/switches.yaml
+++ b/switches.yaml
@@ -16,17 +16,18 @@
   vlans:
     - id: 10
       name: office
+    - id: 20
+    - id: 30
   interfaces:
     - name: GigabitEthernet0/1
       type: ethernet
       mtu: 1500
       vlan:
         mode: trunk
-        trunk_vlans: "10,20"
+        trunk_vlans: "10,20,30"
         native_vlan: 30
     - name: Loopback0
       type: loopback
-      mac: 00:11:22:33:44:55
       ipv4:
         - 10.255.0.1/32
 ---
no problems found

Every repair is applied on its own and the tree is validated again; a repair is kept only if the finding it was aimed at is gone and no rule reports more than it did before. One that fails that test is rolled back to the byte and reported with the findings it would have introduced, so --fix cannot make an inventory worse and never needs a --force.

Writes go through the same path as netviz edit: comments, key order and quoting survive, and only the lines the repair is about change. --fix needs a folder, because an edit session resolves addresses across a whole tree; pointing -i at a single file is a usage error.

Fixing a finding lists which rules are fixable and what each repair does, and netviz rules --fixable prints the same table.

Machine-readable output

-F, --output-format is text to read; json, sarif or github for automation. The three structured formats put their document on stdout and move the human summary to stderr, so the output stays pipeable; --quiet drops that summary and never the document.

netviz -i inventory validate -F sarif --strict > netviz.sarif
netviz -i inventory validate -F github

Text output locates a finding at its document; the structured formats carry the line and column of the offending value, which costs a little memory and is why only they pay for it.

docs/ci.md documents all three envelopes key by key, plus the composite GitHub Action and the pre-commit hook this repository ships.

Arguments

Takes no positional arguments.

Options

Flag Value Default Meaning
--strict off Promote every warning to an error, so any finding fails the run.
--disable RULE Silence a rule by id (E001, NV-C002, ...). Repeatable.
-F, --output-format [text|json|sarif|github] text text is for reading; json, sarif and github are for CI.
--fix off Repair every problem that has one unambiguous mechanical fix, then report what is left. A fix that would introduce a new finding is undone and reported instead.
-n, --dry-run off With --fix: print the unified diff the repairs would apply, and write nothing.
--choose RULE=FIX Pick which repair to use for a rule that offers several, e.g. --choose W114=list. Repeatable. 'netviz rules --fixable' lists the keys.

The global options apply as everywhere else: -i/--inventory names the tree, -q/--quiet silences the commentary under the structured formats, and -v says where the inventory was loaded from, how many elements it holds and how many findings the validator produced.

Exit codes

Code Meaning
0 No errors. Warnings and infos may still have been reported.
1 At least one error, or a document that could not be loaded at all.
2 Usage error — an unknown option, an unknown rule id in --disable — or an unusable netviz.toml.
3 The inventory could not be discovered or read at all.
130 Interrupted.
141 The downstream end of a pipe closed first.

A structured document is written for 0 and 1. It is not written for the rest: those are failures to run the check rather than results of it.

See also