Nornir Inspect is a tool, developed by Packet Coders to help learn, and troubleshoot the config management framework - Nornir, by allowing you to visualise the various result objects, attributes and hierarchies. Like so:
nornir_inspect(result)
<class 'nornir.core.task.AggregatedResult'>
├── failed = False
├── failed_hosts = {}
├── name = task_1
├── <class 'nornir.core.task.MultiResult'> ['node1']
│ ├── failed = False
│ ├── failed_hosts = {}
│ ├── name = task_1
│ └── <class 'nornir.core.task.Result'> [0]
│ ├── changed = False
│ ├── diff =
│ ├── exception = None
│ ├── failed = False
│ ├── host = node1
│ ├── name = task_1
│ ├── result = 2
│ ├── severity_level = 20
│ ├── stderr = None
│ └── stdout = None
├── <class 'nornir.core.task.MultiResult'> ['node2']
│ ├── failed = False
│ ├── failed_hosts = {}
│ ├── name = task_1
│ └── <class 'nornir.core.task.Result'> [0]
│ ├── changed = False
│ ├── diff =
│ ├── exception = None
│ ├── failed = False
│ ├── host = node2
│ ├── name = task_1
│ ├── result = 2
│ ├── severity_level = 20
│ ├── stderr = None
│ └── stdout = None
└── <class 'nornir.core.task.MultiResult'> ['node3']
├── failed = False
├── failed_hosts = {}
├── name = task_1
└── <class 'nornir.core.task.Result'> [0]
├── changed = False
├── diff =
├── exception = None
├── failed = False
├── host = node3
├── name = task_1
├── result = 2
├── severity_level = 20
├── stderr = None
└── stdout = None
Why is this useful?
Well, Nornir provides various result objects, each object containing attributes/result data, like so.
<class 'nornir.core.task.AggregatedResult'> # All results.
├── <class 'nornir.core.task.MultiResult'> # Results of all tasks for a single device.
│ └── <class 'nornir.core.task.Result'> # Result of a single task for a single device.
├── <class 'nornir.core.task.MultiResult'>
│ └── <class 'nornir.core.task.Result'>
└── <class 'nornir.core.task.MultiResult'>
└── <class 'nornir.core.task.Result'>
Typically, the Nornir function print_result
is used to print out the main data from the Nornir results, however, you may need to visualise the "result tree" for learning purposes, or to help understand how to lookup data from the various nested result objects. This is where Nornir Inspect comes into play.
Installation
Nornir Inspect can be installed like so:
$ pip install nornir-inspect
or
$ poetry add nornir-inspect
Example
Once installed after running your Nornir tasks, you can inspect your results by supplying then to Nornir Inspect, from which it will display the "result tree".
Inital Nornir setup and task execution.
from nornir import InitNornir
from nornir.core.task import Result, Task
nr = InitNornir(
runner={
"plugin": "threaded",
"options": {
"num_workers": 10,
},
},
inventory={
"plugin": "SimpleInventory",
"options": {"host_file": "tests/hosts.yaml"},
},
logging={"enabled": False},
)
def task_1(task: Task, number: int) -> Result:
n = number + 1
return Result(host=task.host, result=f"{n}")
result = nr.run(task=task_1, number=1)
from nornir_inspect import nornir_inspect
nornir_inspect(result)
<-output->
<class 'nornir.core.task.AggregatedResult'>
├── failed = False
├── failed_hosts = {}
├── name = task_1
├── <class 'nornir.core.task.MultiResult'> ['node1']
│ ├── failed = False
│ ├── failed_hosts = {}
│ ├── name = task_1
│ └── <class 'nornir.core.task.Result'> [0]
│ ├── changed = False
│ ├── diff =
│ ├── exception = None
│ ├── failed = False
│ ├── host = node1
│ ├── name = task_1
│ ├── result = 2
│ ├── severity_level = 20
│ ├── stderr = None
│ └── stdout = None
├── <class 'nornir.core.task.MultiResult'> ['node2']
│ ├── failed = False
│ ├── failed_hosts = {}
│ ├── name = task_1
│ └── <class 'nornir.core.task.Result'> [0]
│ ├── changed = False
│ ├── diff =
│ ├── exception = None
│ ├── failed = False
│ ├── host = node2
│ ├── name = task_1
│ ├── result = 2
│ ├── severity_level = 20
│ ├── stderr = None
│ └── stdout = None
└── <class 'nornir.core.task.MultiResult'> ['node3']
├── failed = False
├── failed_hosts = {}
├── name = task_1
└── <class 'nornir.core.task.Result'> [0]
├── changed = False
├── diff =
├── exception = None
├── failed = False
├── host = node3
├── name = task_1
├── result = 2
├── severity_level = 20
├── stderr = None
└── stdout = None
We can now see the result tree structure. We can also use the heading helpers to help us navigate through the result structure like so:
Additional Options
Nornir Inspect provides 2 additional options:
Values
Allows you to hide the various object attributes. This is performed by passing in the argument vals=False
. The default is True
.
nornir_inspect(vals=False, nr_result=result)
<class 'nornir.core.task.AggregatedResult'>
├── <class 'nornir.core.task.MultiResult'> ['node1']
│ └── <class 'nornir.core.task.Result'> [0]
├── <class 'nornir.core.task.MultiResult'> ['node2']
│ └── <class 'nornir.core.task.Result'> [0]
└── <class 'nornir.core.task.MultiResult'> ['node3']
└── <class 'nornir.core.task.Result'> [0]
Headings
Allows you to hide the additional heading information that is shown, such as the object key or list index. The default is True
.
nornir_inspect(vals=False, headings=False, nr_result=result)
<class 'nornir.core.task.AggregatedResult'>
├── <class 'nornir.core.task.MultiResult'>
│ └── <class 'nornir.core.task.Result'>
├── <class 'nornir.core.task.MultiResult'>
│ └── <class 'nornir.core.task.Result'>
└── <class 'nornir.core.task.MultiResult'>
└── <class 'nornir.core.task.Result'>