Formatters¶
TTP supports raw, yaml, json, csv, jinja2, pprint, tabulate, table, excel formatters. Formatters have a number of attributes that can be used to supply additional information or modify behavior.
In general case formatters take python structured data - dictionary, list, list of dictionaries etc. - as an input, format that data in certain way and return string representation of results, except for raw output formatter, which just returns input data without modifying it.
raw¶
If format is raw, no formatting will be applied and native python structure will be returned, results will not be converted to string.
yaml¶
Prerequisites: Python PyYAML library needs to be installed
This formatter will run results through PyYAML module to produce YAML structured results.
JSON¶
This formatter will run results through Python built-in JSON module dumps
method to produce JSON (JavaScript Object Notation) <http://json.org> structured results.
Note
json.dumps() will have these additional attributes set sort_keys=True, indent=4, separators=(',', ': ')
pprint¶
As the name implies, python built-in pprint module will be used to structure python data in a more readable.
table¶
This formatter will transform results into a list of lists, where first list item will represent table headers, all the rest of items will represent table rows.
For table formatter to work correctly, results data should have certain structure, namely:
- list of flat dictionaries
- single flat dictionary
- dictionary of flat dictionaries if key attribute provided
Flat dictionary - such a dictionary where all values are strings. It is not a limitation and in fact dictionary values can be of any structure, but they will be placed in table as is.
Example
Template:
<input load="text">
interface Loopback0
ip address 192.168.0.113/24
!
interface Vlan778
ip address 2002::fd37/124
!
</input>
<input load="text">
interface Loopback10
ip address 192.168.0.10/24
!
interface Vlan710
ip address 2002::fd10/124
!
</input>
<group>
interface {{ interface }}
ip address {{ ip }}/{{ mask }}
</group>
<output format="pprint" returner="terminal"/>
<output format="table" returner="terminal"/>
Results:
First output will print to terminal, after passing results through pprint function:
[ [ {'interface': 'Loopback0', 'ip': '192.168.0.113', 'mask': '24'},
{'interface': 'Vlan778', 'ip': '2002::fd37', 'mask': '124'}],
[ {'interface': 'Loopback10', 'ip': '192.168.0.10', 'mask': '24'},
{'interface': 'Vlan710', 'ip': '2002::fd10', 'mask': '124'}]]
Above data will serve as an input to second outputter, that outputter
will format data in table list of lists:
[['interface', 'ip', 'mask'],
['Loopback0', '192.168.0.113', '24'],
['Vlan778', '2002::fd37', '124'],
['Loopback10', '192.168.0.10', '24'],
['Vlan710', '2002::fd10', '124']]
Note
csv and tabulate outputters use table outputter to construct a list of lists, after that they use it to represent data in certain format. Meaning all the attributes supported by table outputter, inherently supported by csv and tabulate outputters.
csv¶
This outputter takes parsing result as an input, transforms it in list of lists using table outputter and emits csv structured table.
Example
Template:
<input load="text">
interface Loopback0
ip address 192.168.0.113/24
!
interface Vlan778
ip address 2002::fd37/124
!
</input>
<group>
interface {{ interface }}
ip address {{ ip }}/{{ mask }}
</group>
<output format="csv" returner="terminal"/>
Results:
interface,ip,mask
Loopback0,192.168.0.113,24
Vlan778,2002::fd37,124
tabulate¶
Prerequisites: tabulate module needs to be installed on the system.
Tabulate outputter uses python tabulate module to transform and emit results in a plain-text table.
Example
Template:
<input load="text">
interface Loopback0
ip address 192.168.0.113/24
!
interface Vlan778
ip address 2002::fd37/124
!
</input>
<group>
interface {{ interface }}
ip address {{ ip }}/{{ mask }}
</group>
<output format="tabulate" returner="terminal"/>
Results:
interface ip mask
----------- ------------- ------
Loopback0 192.168.0.113 24
Vlan778 2002::fd37 124
jinja2¶
Prerequisites: Jinja2 module needs to be installed on the system
This outputters allow to render parsing results with jinja2 template. Jinja2 template can be enclosed in output tag text data. Jinja2 templates can help to produce any text output out of parsing results. There are lots of use cases for it, to name a few:
- vendor configuration translator - parse vendor A configuration, emit configuration for vendor B
- markdown - use Jinja2 template to produce markdown report etc.
Within jinja2, the whole parsing results data passed into the renderer within _data_ variable, that variable can be referenced in template accordingly.
Example
Template:
<input load="text">
interface Loopback0
ip address 192.168.0.113/24
!
interface Vlan778
ip address 2002::fd37/124
!
</input>
<input load="text">
interface Loopback10
ip address 192.168.0.10/24
!
interface Vlan710
ip address 2002::fd10/124
!
</input>
<group>
interface {{ interface }}
ip address {{ ip }}/{{ mask }}
</group>
<output format="jinja2" returner="terminal">
{% for input_result in _data_ %}
{% for item in input_result %}
if_cfg id {{ item['interface'] }}
ip address {{ item['ip'] }}
subnet mask {{ item['mask'] }}
#
{% endfor %}
{% endfor %}
</output>
Results:
if_cfg id Loopback0
ip address 192.168.0.113
subnet mask 24
#
if_cfg id Vlan778
ip address 2002::fd37
subnet mask 124
#
if_cfg id Loopback10
ip address 192.168.0.10
subnet mask 24
#
if_cfg id Vlan710
ip address 2002::fd10
subnet mask 124
#
excel¶
Prerequisites: openpyxl module needs to be installed on the system
This formatter takes table structure defined in output tag text and transforms parsing results into table on a per tab basis using table formatter, as a results all attributes supported by table formatter can be used in excel formatter as well.
Example
Template:
<input load="text">
interface Loopback0
description Router-id-loopback
ip address 192.168.0.113/24
!
interface Vlan778
ip address 2002::fd37/124
ip vrf CPE1
!
</input>
<group name="interfaces_1">
interface {{ interface }}
ip address {{ ip }}/{{ mask }}
description {{ description }}
ip vrf {{ vrf }}
</group>
<group name="interfaces_2">
interface {{ interface }}
ip address {{ ip }}/{{ mask }}
description {{ description }}
ip vrf {{ vrf }}
</group>
<output
format="excel"
returner="file"
filename="excel_out_%Y-%m-%d_%H-%M-%S"
url="C:/result/"
load="yaml"
>
table:
- headers: interface, ip, mask, vrf, description
path: interfaces_1
tab_name: tab-1
- path: interfaces_2
tab_name: tab-2
</output>
TTP will produce excel table with two tabs using results from different groups. Table will be saved under C:/result/ path in excel_out_%Y-%m-%d_%H-%M-%S.xslx file.
Formatter attributes¶
Formatter | Attribute | Description |
---|---|---|
table, csv, tabulate, excel | path | dot separated string that denotes path to data within results tree |
tabulate | format_attributes | string of *args, **kwargs to pass to formatter |
table, csv, tabulate, excel | headers | comma separated string of table headers |
csv | sep | character to separate items, by default it is comma |
table, csv, tabulate, excel | missing | string to replace missing items based on provided headers |
table, csv, tabulate, excel | key | string to use while flattening dictionary of data results |
path¶
path="path_to_data"
- path_to_data - dot separated string of path items within results tree, used to specify location of data to work with.
In the case when results data is a nested structure and we want to output only part of it in a certain format, path attribute can be used to identify the portion of results to work with.
Supported by: table, csv, tabulate output formatters
Example
In this example we want to emit BGP peers in a table format, however, list of peer dictionaries is nested within results tree behind bgp_config and peers sections. We can set path to bgp_config.peers value to reference required data and pass it through output formatter, in this case csv.
Template:
<input load="text">
router bgp 65100
neighbor 10.145.1.9
description vic-mel-core1
!
neighbor 192.168.101.1
description qld-bri-core1
</input>
<group name="bgp_config">
router bgp {{ bgp_as }}
<group name="peers">
neighbor {{ peer }}
description {{ description }}
</group>
</group>
<output name="out1" format="pprint" returner="terminal"/>
<output name="out2" path="bgp_config.peers" format="csv" returner="terminal"/>
Results:
[ { 'bgp_config': { 'bgp_as': '65100',
'peers': [ { 'description': 'vic-mel-core1',
'peer': '10.145.1.9'},
{ 'description': 'qld-bri-core1',
'peer': '192.168.101.1'}]}}]
description,peer
vic-mel-core1,10.145.1.9
qld-bri-core1,192.168.101.1
Outputter out1 will emit data in native python format but structured by pprint for ease of read, while outputter out2 will format peers data in a table using tabulate formatter. Returner terminal will print results to command line screen.
format_attributes¶
format_attributes="**args, **kwargs"
- args - list of attribute values e.g. value1, value2, value3, to pass to formatter
- kwargs - list of attribute name-value pairs e.g. key1=value1, key2-value2, to pass to formatter
Supported by: tabulate output formatter
Some outputters can be invoked with a number of additional arguments to modify their behavior, this arguments can be passed to them using format_attributes attribute.
Example
Tabulate outputter supports a number of table formates that can be specified using tablefmt argument, in below template data will be formatted using tabulate formatter with tabulate table format set to fancy_grid and results will be printer to terminal screen.
Template:
<input load="text">
router bgp 65100
neighbor 10.145.1.9
description vic-mel-core1
!
neighbor 192.168.101.1
description qld-bri-core1
</input>
<group name="bgp_config">
router bgp {{ bgp_as }}
<group name="peers">
neighbor {{ peer }}
description {{ description }}
</group>
</group>
<output name="out2" path="bgp_config.peers" format="csv"
returner="terminal" format_attributes="tablefmt='fancy_grid'"/>
Results:
╒═══════════════╤═══════════════╕
│ description │ peer │
╞═══════════════╪═══════════════╡
│ vic-mel-core1 │ 10.145.1.9 │
├───────────────┼───────────────┤
│ qld-bri-core1 │ 192.168.101.1 │
╘═══════════════╧═══════════════╛
headers¶
headers="header1, header2, ... headerN"
- headers - comma separated string of table headers
Table formatter will identify the list of headers automatically, however, their order will be undefined and can change. To solve that problem, predefined list of headers can be supplied to formatter. Headers have to match key names of the results dictionaries and they are case sensitive.
Supported by: table, csv, tabulate output formatters
Example
Template:
<input load="text">
interface Loopback0
description Router-id-loopback
ip address 192.168.0.113/24
!
interface Vlan778
description CPE_Acces_Vlan
ip address 2002::fd37/124
ip vrf CPE1
!
</input>
<group>
interface {{ interface }}
ip address {{ ip }}/{{ mask }}
description {{ description }}
ip vrf {{ vrf }}
</group>
<output
format="tabulate"
returner="terminal"
headers="interface, description, vrf, ip, mask"
/>
Results:
interface description vrf ip mask
----------- ------------------ ----- ------------- ------
Loopback0 Router-id-loopback 192.168.0.113 24
Vlan778 CPE_Acces_Vlan CPE1 2002::fd37 124
sep¶
sep="char"
- char - separator character to use for csv formatter, default value is comma “,”
Supported by: csv output formatter
missing¶
missing="value"
- value - string to use to substitute empty cells in table, default is empty - “”
Supported by: table, csv, tabulate output formatters
Example
Template:
<input load="text">
interface Loopback0
description Router-id-loopback
ip address 192.168.0.113/24
!
interface Vlan778
ip address 2002::fd37/124
ip vrf CPE1
!
</input>
<group>
interface {{ interface }}
ip address {{ ip }}/{{ mask }}
description {{ description }}
ip vrf {{ vrf }}
</group>
<output
format="tabulate"
returner="terminal"
missing="UNDEFINED"
/>
Results:
description interface ip mask vrf
------------------ ----------- ------------- ------ ---------
Router-id-loopback Loopback0 192.168.0.113 24 UNDEFINED
UNDEFINED Vlan778 2002::fd37 124 CPE1
key¶
key="name"
- name - name of the key to use in a dictionary to associate data value
This attribute helps to solve specific problem when results data is a dictionary of dictionaries similar to this:
{
"Loopback0": {
"description": "Router-id-loopback",
"ip": "192.168.0.113",
"mask": "24"
},
"Vlan778": {
"ip": "2002::fd37",
"mask": "124",
"vrf": "CPE1"
}
}
If key
will be set to “intf_name”, above data will be transformed into list of dictionaries such as:
[
{
"intf_name": "Loopback0",
"description": "Router-id-loopback",
"ip": "192.168.0.113",
"mask": "24"
},
{
"intf_name": "Vlan778",
"ip": "2002::fd37",
"mask": "124",
"vrf": "CPE1"
}
]
With that list of lists table formatter will be able to create below list of lists and emit it in desirable format (csv, tabulate):
[
['description', 'intf_name', 'ip', 'mask', 'vrf'],
['Router-id-loopback', 'Loopback0', '192.168.0.113', '24', ''],
['', 'Vlan778', '2002::fd37', '124', 'CPE1']
]
Example
Template:
<input load="text">
interface Loopback0
description Router-id-loopback
ip address 192.168.0.113/24
!
interface Vlan778
ip address 2002::fd37/124
ip vrf CPE1
!
</input>
<group name="{{ interface }}">
interface {{ interface }}
ip address {{ ip }}/{{ mask }}
description {{ description }}
ip vrf {{ vrf }}
</group>
<output
format="tabulate"
returner="terminal"
key="intf_name"
/>
Results:
description intf_name ip mask vrf
------------------ ----------- ------------- ------ -----
Router-id-loopback Loopback0 192.168.0.113 24
Vlan778 2002::fd37 124 CPE1