Revamp fact pages and tables to datatables
This commit is contained in:
@@ -412,11 +412,10 @@ def node(env, node_name):
|
||||
query.add(EqualsOperator("certname", node_name))
|
||||
|
||||
node = get_or_abort(puppetdb.node, node_name)
|
||||
facts = node.facts()
|
||||
|
||||
return render_template(
|
||||
'node.html',
|
||||
node=node,
|
||||
facts=yield_or_stop(facts),
|
||||
envs=envs,
|
||||
current_env=env,
|
||||
columns=REPORTS_COLUMNS[:2])
|
||||
@@ -661,73 +660,102 @@ def facts(env):
|
||||
current_env=env)
|
||||
|
||||
|
||||
@app.route('/fact/<fact>', defaults={'env': app.config['DEFAULT_ENVIRONMENT']})
|
||||
@app.route('/<env>/fact/<fact>')
|
||||
def fact(env, fact):
|
||||
"""Fetches the specific fact from PuppetDB and displays its value per
|
||||
@app.route('/fact/<fact>',
|
||||
defaults={'env': app.config['DEFAULT_ENVIRONMENT'], 'value': None})
|
||||
@app.route('/<env>/fact/<fact>', defaults={'value': None})
|
||||
@app.route('/fact/<fact>/<value>',
|
||||
defaults={'env': app.config['DEFAULT_ENVIRONMENT']})
|
||||
@app.route('/<env>/fact/<fact>/<value>')
|
||||
def fact(env, fact, value):
|
||||
"""Fetches the specific fact(/value) from PuppetDB and displays per
|
||||
node for which this fact is known.
|
||||
|
||||
:param env: Searches for facts in this environment
|
||||
:type env: :obj:`string`
|
||||
:param fact: Find all facts with this name
|
||||
:type fact: :obj:`string`
|
||||
:param fact: Find all facts with this value
|
||||
:type fact: :obj:`string`
|
||||
"""
|
||||
envs = environments()
|
||||
check_env(env, envs)
|
||||
|
||||
# we can only consume the generator once, lists can be doubly consumed
|
||||
# om nom nom
|
||||
render_graph = False
|
||||
if fact in graph_facts:
|
||||
if fact in graph_facts and not value:
|
||||
render_graph = True
|
||||
|
||||
if env == '*':
|
||||
query = None
|
||||
else:
|
||||
query = EqualsOperator("environment", env)
|
||||
|
||||
localfacts = [f for f in yield_or_stop(puppetdb.facts(
|
||||
name=fact, query=query))]
|
||||
return Response(stream_with_context(stream_template(
|
||||
return render_template(
|
||||
'fact.html',
|
||||
name=fact,
|
||||
fact=fact,
|
||||
value=value,
|
||||
render_graph=render_graph,
|
||||
facts=localfacts,
|
||||
envs=envs,
|
||||
current_env=env)))
|
||||
current_env=env)
|
||||
|
||||
|
||||
@app.route('/fact/<fact>/<value>',
|
||||
defaults={'env': app.config['DEFAULT_ENVIRONMENT']})
|
||||
@app.route('/<env>/fact/<fact>/<value>')
|
||||
def fact_value(env, fact, value):
|
||||
"""On asking for fact/value get all nodes with that fact.
|
||||
@app.route('/fact/<fact>/json',
|
||||
defaults={'env': app.config['DEFAULT_ENVIRONMENT'],
|
||||
'node': None, 'value': None})
|
||||
@app.route('/<env>/fact/<fact>/json', defaults={'node': None, 'value': None})
|
||||
@app.route('/fact/<fact>/<value>/json',
|
||||
defaults={'env': app.config['DEFAULT_ENVIRONMENT'], 'node': None})
|
||||
@app.route('/<env>/fact/<fact>/<value>/json', defaults={'node': None})
|
||||
@app.route('/node/<node>/facts/json',
|
||||
defaults={'env': app.config['DEFAULT_ENVIRONMENT'],
|
||||
'fact': None, 'value': None})
|
||||
@app.route('/<env>/node/<node>/facts/json',
|
||||
defaults={'fact': None, 'value': None})
|
||||
def fact_ajax(env, node, fact, value):
|
||||
"""Fetches the specific facts matching (node/fact/value) from PuppetDB and
|
||||
return a JSON table
|
||||
|
||||
:param env: Searches for facts in this environment
|
||||
:type env: :obj:`string`
|
||||
:param fact: Find all facts for this node
|
||||
:type fact: :obj:`string`
|
||||
:param fact: Find all facts with this name
|
||||
:type fact: :obj:`string`
|
||||
:param value: Filter facts whose value is equal to this
|
||||
:type value: :obj:`string`
|
||||
:param fact: Find all facts with this value
|
||||
:type fact: :obj:`string`
|
||||
"""
|
||||
draw = int(request.args.get('draw', 0))
|
||||
|
||||
envs = environments()
|
||||
check_env(env, envs)
|
||||
|
||||
if env == '*':
|
||||
query = None
|
||||
else:
|
||||
query = EqualsOperator("environment", env)
|
||||
render_graph = False
|
||||
if fact in graph_facts and not value and not node:
|
||||
render_graph = True
|
||||
|
||||
facts = get_or_abort(puppetdb.facts,
|
||||
query = AndOperator()
|
||||
if node:
|
||||
query.add(EqualsOperator("certname", node))
|
||||
|
||||
if env != '*':
|
||||
query.add(EqualsOperator("environment", env))
|
||||
|
||||
if len(query.operations) == 0:
|
||||
query = None
|
||||
|
||||
# Generator needs to be converted (graph / total)
|
||||
facts = [f for f in get_or_abort(
|
||||
puppetdb.facts,
|
||||
name=fact,
|
||||
value=value,
|
||||
query=query)
|
||||
localfacts = [f for f in yield_or_stop(facts)]
|
||||
query=query)]
|
||||
|
||||
total = len(facts)
|
||||
|
||||
return render_template(
|
||||
'fact.html',
|
||||
name=fact,
|
||||
'fact.json.tpl',
|
||||
fact=fact,
|
||||
node=node,
|
||||
value=value,
|
||||
facts=localfacts,
|
||||
draw=draw,
|
||||
total=total,
|
||||
total_filtered=total,
|
||||
render_graph=render_graph,
|
||||
facts=facts,
|
||||
envs=envs,
|
||||
current_env=env)
|
||||
|
||||
|
||||
@@ -76,6 +76,8 @@
|
||||
// Paging options
|
||||
"lengthMenu": {{ length_selector }},
|
||||
"pageLength": {{ default_length }},
|
||||
// Search as regex (does not apply if serverSide)
|
||||
"search": {"regex": true},
|
||||
// Default sort
|
||||
"order": [[ 0, "desc" ]],
|
||||
// Custom options
|
||||
|
||||
@@ -1,50 +1,45 @@
|
||||
{% extends 'layout.html' %}
|
||||
{% import '_macros.html' as macros %}
|
||||
|
||||
{% block javascript %}
|
||||
{% block onload_script %}
|
||||
{% macro extra_options(caller) %}
|
||||
// No per page AJAX
|
||||
'serverSide': false,
|
||||
{% endmacro %}
|
||||
{{ macros.datatable_init(table_html_id="facts_table", ajax_url=url_for('fact_ajax', env=current_env, fact=fact, value=value), default_length=config.NORMAL_TABLE_COUNT, length_selector=config.TABLE_COUNT_SELECTOR, extra_options=extra_options) }}
|
||||
|
||||
{% if render_graph %}
|
||||
var chart = null;
|
||||
var data = [
|
||||
{% for fact in facts|groupby('value') %}
|
||||
{
|
||||
label: '{{ fact.grouper.replace("\n", " ") }}',
|
||||
value: {{ fact.list|length }}
|
||||
},
|
||||
{% endfor %}
|
||||
{
|
||||
value: 0,
|
||||
}
|
||||
]
|
||||
var fact_values = data.map(function(item) { return [item.label, item.value]; }).filter(function(item){return item[0];}).sort(function(a,b){return b[1] - a[1];});
|
||||
table.on('xhr', function(e, settings, json){
|
||||
var fact_values = json['chart'].map(function(item) { return [item.label, item.value]; }).filter(function(item){return item[0];}).sort(function(a,b){return b[1] - a[1];});
|
||||
var realdata = fact_values.slice(0, 15);
|
||||
var otherdata = fact_values.slice(15);
|
||||
if (otherdata.length > 0) {
|
||||
realdata.push(["other", otherdata.reduce(function(a,b){return a + b[1];},0)]);
|
||||
}
|
||||
{% endif %}
|
||||
{% endblock javascript %}
|
||||
|
||||
{% block onload_script %}
|
||||
$('table').tablesort();
|
||||
{% if render_graph %}
|
||||
chart = c3.generate({
|
||||
c3.generate({
|
||||
bindto: '#factChart',
|
||||
data: {
|
||||
columns: realdata,
|
||||
type : '{{config.GRAPH_TYPE|default('pie')}}',
|
||||
}
|
||||
});
|
||||
})
|
||||
{% endif %}
|
||||
{% endblock onload_script %}
|
||||
|
||||
{% block content %}
|
||||
{% if render_graph %}
|
||||
<div id="factChart" width="300" height="300"></div>
|
||||
<h1>{{name}}{% if value %}/{{value}}{% endif %} ({{facts|length}})</h1>
|
||||
|
||||
|
||||
{% if value %}
|
||||
{{macros.facts_table(facts, current_env=current_env, autofocus=True, show_node=True, show_value=False, margin_bottom=10)}}
|
||||
{% else %}
|
||||
{{macros.facts_table(facts, current_env=current_env, autofocus=True, show_node=True, link_facts=True, margin_bottom=10)}}
|
||||
{% endif %}
|
||||
<h1>{{ fact }}{% if value %}/{{ value }}{% endif %}</h1>
|
||||
<table id="facts_table" class='ui fixed very basic compact table stackable'>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Node</th>
|
||||
{% if not value %}<th>Value</th>{% endif %}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
</tbody>
|
||||
</table>
|
||||
{% endblock content %}
|
||||
|
||||
38
puppetboard/templates/fact.json.tpl
Normal file
38
puppetboard/templates/fact.json.tpl
Normal file
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"draw": {{draw}},
|
||||
"recordsTotal": {{total}},
|
||||
"recordsFiltered": {{total_filtered}},
|
||||
"data": [
|
||||
{% for fact_h in facts -%}
|
||||
{%- if not loop.first %},{%- endif -%}
|
||||
[
|
||||
{%- if not fact -%}
|
||||
{{ fact_h.name | jsonprint }}
|
||||
{%- if node or value %},{% endif -%}
|
||||
{%- endif -%}
|
||||
{%- if not node -%}
|
||||
{% filter jsonprint %}<a href="{{ url_for('node', env=current_env, node_name=fact_h.node) }}">{{ fact_h.node }}</a>{% endfilter %}
|
||||
{%- if not value %},{% endif -%}
|
||||
{%- endif -%}
|
||||
{%- if not value -%}
|
||||
{%- if fact_h.value is mapping -%}
|
||||
{% filter jsonprint %}<a href="{{ url_for('fact', env=current_env, fact=fact_h.name, value=fact_h.value) }}"><pre>{{ fact_h.value | jsonprint }}</pre></a>{% endfilter %}
|
||||
{%- else -%}
|
||||
{% filter jsonprint %}<a href="{{ url_for('fact', env=current_env, fact=fact_h.name, value=fact_h.value) }}"><pre>{{ fact_h.value }}</pre></a>{% endfilter %}
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
]
|
||||
{% endfor -%}
|
||||
]
|
||||
{%- if render_graph %},
|
||||
"chart": [
|
||||
{% for fact_h in facts | groupby('value') -%}
|
||||
{%- if not loop.first %},{%- endif -%}
|
||||
{
|
||||
"label": {{ fact_h.grouper.replace("\n", " ") | jsonprint }},
|
||||
"value": {{ fact_h.list|length }}
|
||||
}
|
||||
{% endfor %}
|
||||
]
|
||||
{% endif %}
|
||||
}
|
||||
@@ -17,7 +17,13 @@
|
||||
'pagingType': 'simple',
|
||||
"bFilter": false,
|
||||
{% endmacro %}
|
||||
{% macro facts_extra_options(caller) %}
|
||||
'paging': false,
|
||||
// No per page AJAX
|
||||
'serverSide': false,
|
||||
{% endmacro %}
|
||||
{{ macros.datatable_init(table_html_id="reports_table", ajax_url=url_for('reports_ajax', env=current_env, node_name=node.name), default_length=config.LITTLE_TABLE_COUNT, length_selector=config.TABLE_COUNT_SELECTOR, extra_options=extra_options) }}
|
||||
{{ macros.datatable_init(table_html_id="facts_table", ajax_url=url_for('fact_ajax', env=current_env, node=node.name), default_length=config.LITTLE_TABLE_COUNT, length_selector=config.TABLE_COUNT_SELECTOR, extra_options=facts_extra_options) }}
|
||||
{% endblock onload_script %}
|
||||
|
||||
{% block content %}
|
||||
@@ -69,7 +75,16 @@
|
||||
</div>
|
||||
<div class='column'>
|
||||
<h1>Facts</h1>
|
||||
{{macros.facts_table(facts, link_facts=True, condensed=True, current_env=current_env)}}
|
||||
<table id="facts_table" class='ui fixed very basic very compact table stackable'>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Value</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock content %}
|
||||
|
||||
Reference in New Issue
Block a user