Skip to content

Commit c067ad9

Browse files
committed
Support for simple custom columns via --cust-cols.
1 parent d1e5ea0 commit c067ad9

8 files changed

+137
-7
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ Features
4747
* Gathered host facts and manual custom facts.
4848
* Adding and extending facts of existing hosts and manually adding entirely
4949
new hosts.
50+
* Custom columns
5051

5152

5253
Getting started

docs/usage.md

+71-6
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ You can now open `overview.html` in your browser to view the results.
3636
-q, --quiet Don't report warnings
3737
-c COLUMNS, --columns=COLUMNS
3838
Show only given columns
39+
-C CUST_COLS, --cust-cols=CUST_COLS
40+
Path to a custom columns definition file
3941
-l LIMIT, --limit=LIMIT
4042
Limit hosts to pattern
4143
--exclude-cols=EXCLUDE_COLUMNS
@@ -92,7 +94,7 @@ For example, let's say we have the following `hosts` file:
9294
[cust.megacorp]
9395
db1.dev.megacorp.com dtap=dev comment="Old database server"
9496
db2.dev.megacorp.com dtap=dev comment="New database server"
95-
test.megacorp.com dtap=test
97+
test.megacorp.com dtap=test
9698
acc.megacorp.com dtap=acc comment="24/7 support"
9799
megacorp.com dtap=prod comment="Hosting by Foo" ext_id="SRV_10029"
98100

@@ -273,7 +275,8 @@ same as `--columns`. For example:
273275
-i hosts \
274276
facts/
275277

276-
If you want to add custom columns, please refer to 'Custom templates' section.
278+
If you want to add custom columns, please refer to [Custom
279+
columns](#custom-columns) section.
277280

278281

279282
## Extending facts
@@ -285,7 +288,7 @@ hosts.
285288

286289
Extended facts are basically the same as normal Ansible fact files. When you
287290
specify multiple fact directories, Ansible-cmdb scans all of the in order and
288-
overlays the facts.
291+
overlays the facts.
289292

290293
Note that the host *must still* be present in your hosts file, or it will not
291294
generate anything.
@@ -424,11 +427,73 @@ Generate the overview:
424427

425428
The software items will be listed under the "*Custom facts*" heading.
426429

430+
431+
## Custom columns
432+
433+
You can add custom columns to the host overview with the `-C` (`--cust-cols`)
434+
option. This allows you to specify
435+
[jsonxs](https://github.com/fboender/jsonxs) expressions to extract and
436+
display custom host facts. Such columns are fairly limited in what they can
437+
display. If you need a more powerful method of adding custom data to your
438+
CMDB, please refer to the [Custom templates](#custom-templates) section.
439+
440+
Custom columns are currently only supported by the `html_fancy` and
441+
`html_fancy_split` templates!
442+
443+
The `-C` option takes a parameter which is the path to a JSON file containing
444+
your custom column definitions. An example can be found in the
445+
`examples/cust_cols.json` file in the repo:
446+
447+
[
448+
{
449+
"title": "AppArmor",
450+
"id": "apparmor",
451+
"sType": "string",
452+
"visible": true,
453+
"jsonxs": "ansible_facts.ansible_apparmor.status"
454+
},
455+
{
456+
"title": "Proc type",
457+
"id": "proctype",
458+
"sType": "string",
459+
"visible": true,
460+
"jsonxs": "ansible_facts.ansible_processor[2]"
461+
}
462+
]
463+
464+
This defines two new columns: 'AppArmor' and 'Proc type'. All keys are
465+
required.
466+
467+
* `title` is what is displayed as the columns user-friendly title.
468+
* The `id` key must have a unique value, to differentiate between
469+
columns.
470+
* The `sType` value determines how the values will be sorted in the host
471+
overview. Possible values include `string` and `num`. `visible` determines
472+
whether the column will be active (shown) by default.
473+
* The `jsonxs` expression points to an entry in the facts files for each host,
474+
and determines what will be shown for the column's value for each host.
475+
The easiest way to figure out a jsonxs expression is by opening one of the
476+
gathered facts files in a json editor. Please see
477+
[jsonxs](https://github.com/fboender/jsonxs) for info on how to write jsonxs
478+
expressions.
479+
480+
To use it:
481+
482+
../ansible-cmdb/src/ansible-cmdb -C example/cust_cols.json -i example/hosts example/out/ > cmdb.html
483+
484+
When opening the `cmdb.html` file in your browser, you may have to hit the
485+
'Clear settings' button in the top-right before the new columns show up or
486+
when you get strange behaviour.
487+
488+
427489
## Custom templates
428490

429-
If you want to add custom columns or other data to the output, you can create
430-
a custom template. Ansible-cmdb uses the [Mako templating
431-
engine](http://www.makotemplates.org/) to render output.
491+
Custom columns can be added with the `-C` param. See the [Custom
492+
columns](#custom-columns) section for more info. Custom columns are somewhat
493+
limited in the type of information they can display (basically only strings
494+
and numbers). If you want to add more elaborate custom columns or other data
495+
to the output, you can create a custom template. Ansible-cmdb uses the [Mako
496+
templating engine](http://www.makotemplates.org/) to render output.
432497

433498
For example, if you want to add a custom column to the `html_fancy` template:
434499

example/cust_cols.json

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
[
2+
{
3+
"title": "AppArmor",
4+
"id": "apparmor",
5+
"sType": "string",
6+
"visible": false,
7+
"jsonxs": "ansible_facts.ansible_apparmor.status"
8+
},
9+
{
10+
"title": "First processor",
11+
"id": "firstproc",
12+
"sType": "string",
13+
"visible": true,
14+
"jsonxs": "ansible_facts.ansible_processor[2]"
15+
}
16+
]

example/generate.sh

+2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ python2 ../src/ansible-cmdb.py -q -t markdown -i hosts out > gen_markdown_2.md
2020
python2 ../src/ansible-cmdb.py -q -t sql -i hosts out > gen_sql_2.md
2121
python2 ../src/ansible-cmdb.py -q -t html_fancy_split -i hosts out
2222
python2 ../src/ansible-cmdb.py -q -i hosts -f out_factcache > gen_fact_cache_2.html
23+
python2 ../src/ansible-cmdb.py -q -i hosts -C cust_cols.json out > gen_fact_cust_cols_2.html
2324

2425

2526
# Python v3
@@ -31,3 +32,4 @@ python3 ../src/ansible-cmdb.py -q -t markdown -i hosts out > gen_markdown_3.md
3132
python3 ../src/ansible-cmdb.py -q -t sql -i hosts out > gen_sql_3.md
3233
python3 ../src/ansible-cmdb.py -q -t html_fancy_split -i hosts out
3334
python3 ../src/ansible-cmdb.py -q -i hosts -f out_factcache > gen_fact_cache_3.html
35+
python3 ../src/ansible-cmdb.py -q -i hosts -C cust_cols.json out > gen_fact_cust_cols_2.html

src/ansible-cmdb.py

+31
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import sys
1616
import os
1717
import logging
18+
import json
1819
from mako import exceptions
1920
import ansiblecmdb
2021
import ansiblecmdb.util as util
@@ -92,6 +93,30 @@ def get_hosts_files(option):
9293
return [line.split('=', 1)[1].strip()]
9394

9495

96+
def get_cust_cols(path):
97+
"""
98+
Load custom column definitions.
99+
"""
100+
required_keys = ["title", "id", "sType", "visible", "jsonxs"]
101+
102+
with open(path, 'r') as f:
103+
try:
104+
cust_cols = json.load(f)
105+
except json.decoder.JSONDecodeError as err:
106+
sys.stderr.write("Invalid custom columns json file: {}\n".format(path))
107+
sys.stderr.write("{}\n".format(err.args[0]))
108+
sys.exit(1)
109+
110+
# Validate
111+
for col in cust_cols:
112+
for required_key in required_keys:
113+
if required_key not in col:
114+
sys.stderr.write("Missing required key '{}' in custom "
115+
"column {}\n".format(required_key, col))
116+
sys.exit(1)
117+
118+
return cust_cols
119+
95120
def parse_user_params(user_params):
96121
"""
97122
Parse the user params (-p/--params) and them as a dict.
@@ -126,6 +151,7 @@ def parse_user_params(user_params):
126151
parser.add_option("-d", "--debug", dest="debug", action="store_true", default=False, help="Show debug output")
127152
parser.add_option("-q", "--quiet", dest="quiet", action="store_true", default=False, help="Don't report warnings")
128153
parser.add_option("-c", "--columns", dest="columns", action="store", default=None, help="Show only given columns")
154+
parser.add_option("-C", "--cust-cols", dest="cust_cols", action="store", default=None, help="Path to a custom columns definition file")
129155
parser.add_option("-l", "--limit", dest="limit", action="store", default=None, help="Limit hosts to pattern")
130156
parser.add_option("--exclude-cols", dest="exclude_columns", action="store", default=None, help="Exclude cols from output")
131157
(options, args) = parser.parse_args()
@@ -142,6 +168,10 @@ def parse_user_params(user_params):
142168

143169
hosts_files = get_hosts_files(options.inventory)
144170

171+
cust_cols = []
172+
if options.cust_cols is not None:
173+
cust_cols = get_cust_cols(options.cust_cols)
174+
145175
# Handle template params
146176
params = {
147177
'lib_dir': data_dir, # Backwards compatibility for custom templates < ansible-cmdb v1.7
@@ -150,6 +180,7 @@ def parse_user_params(user_params):
150180
'log': log,
151181
'columns': None,
152182
'exclude_columns': None,
183+
'cust_cols': cust_cols
153184
}
154185
params.update(parse_user_params(options.params))
155186
if options.columns is not None:

src/ansiblecmdb/data/tpl/html_fancy.tpl

+3
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ skip_empty = to_bool(context.get('skip_empty', '0'))
1313
# Get column definitions from html_fancy_defs.html
1414
cols = var_cols(columns, exclude_columns)
1515

16+
# Extend default columns with custom columns
17+
cols.extend(cust_cols)
18+
1619
# Set the Javascript resource URL (local disk or CDN)
1720
if local_js is False:
1821
res_url = "https://cdn.datatables.net/1.10.2/"

src/ansiblecmdb/data/tpl/html_fancy_defs.html

+10-1
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,11 @@ <h2>Host overview</h2>
279279
% if skip_empty is False or 'ansible_facts' in host:
280280
<tr>\
281281
% for col in cols:
282-
<td>${col["func"](host, **kwargs)}</td>\
282+
% if "func" in col:
283+
<td>${col["func"](host, **kwargs)}</td>\
284+
% elif "jsonxs" in col:
285+
<td>${col__cust(host, col=col, **kwargs)}</td>\
286+
% endif
283287
% endfor
284288
</tr>
285289
% endif
@@ -469,6 +473,11 @@ <h3 class="toggle-collapse ${collapsed_class}" id="${host['name']}" data-host-na
469473
## in the function scope in Mako for some reason, so if we need to use them, we
470474
## need to do a `kwargs.get()`. I don't like Mako much.
471475

476+
<%def name="col__cust(host, col, **kwargs)">
477+
## Special column function for custom columns that does a jsonxs lookup
478+
${jsonxs(host, col["jsonxs"], default='')}
479+
</%def>
480+
472481
<%def name="col_name(host, **kwargs)">
473482
<%
474483
link_type = kwargs.get("link_type")

src/ansiblecmdb/data/tpl/html_fancy_split_overview.tpl

+3
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ skip_empty = to_bool(context.get('skip_empty', '0'))
1313
# Get column definitions from html_fancy_defs.html
1414
cols = var_cols(columns, exclude_columns)
1515

16+
# Extend default columns with custom columns
17+
cols.extend(cust_cols)
18+
1619
# Set the Javascript resource URL (local disk or CDN)
1720
if local_js is False:
1821
res_url = "https://cdn.datatables.net/1.10.2/"

0 commit comments

Comments
 (0)