Merge pull request #55 from nedap/semantic
Transition to Semantic-UI framework
This commit is contained in:
@@ -4,8 +4,12 @@ from __future__ import absolute_import
|
|||||||
import os
|
import os
|
||||||
import logging
|
import logging
|
||||||
import collections
|
import collections
|
||||||
import urllib
|
try:
|
||||||
|
from urllib import unquote
|
||||||
|
except ImportError:
|
||||||
|
from urllib.parse import unquote
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
|
from multiprocessing.dummy import Pool as ThreadPool
|
||||||
|
|
||||||
from flask import (
|
from flask import (
|
||||||
Flask, render_template, abort, url_for,
|
Flask, render_template, abort, url_for,
|
||||||
@@ -88,19 +92,17 @@ def index():
|
|||||||
# TODO: Would be great if we could parallelize this somehow, doing these
|
# TODO: Would be great if we could parallelize this somehow, doing these
|
||||||
# requests in sequence is rather pointless.
|
# requests in sequence is rather pointless.
|
||||||
prefix = 'com.puppetlabs.puppetdb.query.population'
|
prefix = 'com.puppetlabs.puppetdb.query.population'
|
||||||
num_nodes = get_or_abort(
|
pool = ThreadPool()
|
||||||
puppetdb.metric,
|
endpoints = [
|
||||||
"{0}{1}".format(prefix, ':type=default,name=num-nodes'))
|
"{0}{1}".format(prefix, ':type=default,name=num-nodes'),
|
||||||
num_resources = get_or_abort(
|
"{0}{1}".format(prefix, ':type=default,name=num-resources'),
|
||||||
puppetdb.metric,
|
"{0}{1}".format(prefix, ':type=default,name=avg-resources-per-node'),
|
||||||
"{0}{1}".format(prefix, ':type=default,name=num-resources'))
|
]
|
||||||
avg_resources_node = get_or_abort(
|
fetched_metrics = pool.map(puppetdb.metric, endpoints)
|
||||||
puppetdb.metric,
|
|
||||||
"{0}{1}".format(prefix, ':type=default,name=avg-resources-per-node'))
|
|
||||||
metrics = {
|
metrics = {
|
||||||
'num_nodes': num_nodes['Value'],
|
'num_nodes': fetched_metrics[0]['Value'],
|
||||||
'num_resources': num_resources['Value'],
|
'num_resources': fetched_metrics[1]['Value'],
|
||||||
'avg_resources_node': "{0:10.0f}".format(avg_resources_node['Value']),
|
'avg_resources_node': "{0:10.0f}".format(fetched_metrics[2]['Value']),
|
||||||
}
|
}
|
||||||
|
|
||||||
nodes = puppetdb.nodes(
|
nodes = puppetdb.nodes(
|
||||||
@@ -284,10 +286,14 @@ def query():
|
|||||||
if app.config['ENABLE_QUERY']:
|
if app.config['ENABLE_QUERY']:
|
||||||
form = QueryForm()
|
form = QueryForm()
|
||||||
if form.validate_on_submit():
|
if form.validate_on_submit():
|
||||||
|
if form.query.data[0] == '[':
|
||||||
|
query = form.query.data
|
||||||
|
else:
|
||||||
|
query = '[{0}]'.format(form.query.data)
|
||||||
result = get_or_abort(
|
result = get_or_abort(
|
||||||
puppetdb._query,
|
puppetdb._query,
|
||||||
form.endpoints.data,
|
form.endpoints.data,
|
||||||
query='[{0}]'.format(form.query.data))
|
query=query)
|
||||||
return render_template('query.html', form=form, result=result)
|
return render_template('query.html', form=form, result=result)
|
||||||
return render_template('query.html', form=form)
|
return render_template('query.html', form=form)
|
||||||
else:
|
else:
|
||||||
@@ -298,14 +304,14 @@ def query():
|
|||||||
@app.route('/metrics')
|
@app.route('/metrics')
|
||||||
def metrics():
|
def metrics():
|
||||||
metrics = get_or_abort(puppetdb._query, 'metrics', path='mbeans')
|
metrics = get_or_abort(puppetdb._query, 'metrics', path='mbeans')
|
||||||
for key, value in metrics.iteritems():
|
for key, value in metrics.items():
|
||||||
metrics[key] = value.split('/')[3]
|
metrics[key] = value.split('/')[3]
|
||||||
return render_template('metrics.html', metrics=sorted(metrics.items()))
|
return render_template('metrics.html', metrics=sorted(metrics.items()))
|
||||||
|
|
||||||
|
|
||||||
@app.route('/metric/<metric>')
|
@app.route('/metric/<metric>')
|
||||||
def metric(metric):
|
def metric(metric):
|
||||||
name = urllib.unquote(metric)
|
name = unquote(metric)
|
||||||
metric = puppetdb.metric(metric)
|
metric = puppetdb.metric(metric)
|
||||||
return render_template(
|
return render_template(
|
||||||
'metric.html',
|
'metric.html',
|
||||||
|
|||||||
@@ -1,104 +1,65 @@
|
|||||||
body {
|
body {
|
||||||
padding-top: 60px;
|
margin: 0;
|
||||||
|
font-family: "Open Sans", sans-serif;
|
||||||
}
|
}
|
||||||
th.headerSortUp {
|
|
||||||
position: relative
|
a {
|
||||||
|
color: #2C3E50;
|
||||||
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
th.headerSortDown {
|
|
||||||
position: relative
|
h1.ui.header.no-margin-bottom {
|
||||||
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
th.header {
|
|
||||||
position: relative
|
.tablesorter-header-inner {
|
||||||
|
float: left;
|
||||||
}
|
}
|
||||||
th.header:after {
|
|
||||||
content: "\f0dc";
|
th.tablesorter-headerAsc::after {
|
||||||
font-family: FontAwesome;
|
content: '\25b4' !important;
|
||||||
font-style: normal;
|
float: right;
|
||||||
font-weight: normal;
|
|
||||||
text-decoration: inherit;
|
|
||||||
color: #000;
|
|
||||||
font-size: 18px;
|
|
||||||
padding-right: 0.5em;
|
|
||||||
float:right;
|
|
||||||
}
|
}
|
||||||
th.headerSortUp:after {
|
|
||||||
content: "\f0de";
|
th.tablesorter-headerDesc::after {
|
||||||
font-family: FontAwesome;
|
content: '\25be' !important;
|
||||||
font-style: normal;
|
float: right;
|
||||||
font-weight: normal;
|
|
||||||
text-decoration: inherit;
|
|
||||||
color: #000;
|
|
||||||
font-size: 18px;
|
|
||||||
padding-right: 0.5em;
|
|
||||||
float:right;
|
|
||||||
}
|
}
|
||||||
th.headerSortDown:after {
|
|
||||||
content: "\f0dd";
|
.ui.grid.padding-bottom {
|
||||||
font-family: FontAwesome;
|
padding-bottom: 40px !important;
|
||||||
font-style: normal;
|
|
||||||
font-weight: normal;
|
|
||||||
text-decoration: inherit;
|
|
||||||
color: #000;
|
|
||||||
font-size: 18px;
|
|
||||||
padding-right: 0.5em;
|
|
||||||
float:right;
|
|
||||||
}
|
}
|
||||||
.stat {
|
|
||||||
margin-bottom: 40px;
|
.status {
|
||||||
|
width: 47%;
|
||||||
|
text-align: center;
|
||||||
|
display: block;
|
||||||
}
|
}
|
||||||
.navbar .brand:hover {
|
.count {
|
||||||
color: #fff;
|
width: 21%;
|
||||||
|
text-align: center;
|
||||||
|
display: block;
|
||||||
}
|
}
|
||||||
.table tbody tr.error>td {
|
|
||||||
background-color: #f2dede;
|
.no-margin-top {
|
||||||
|
margin-top: -35px !important;
|
||||||
}
|
}
|
||||||
h1.error {
|
|
||||||
color: rgb(223, 46, 27);
|
.absolute {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
|
width: 100%;
|
||||||
|
background: #E8E8E8;
|
||||||
}
|
}
|
||||||
h1.success {
|
|
||||||
color: #18BC9C;
|
.absolute div {
|
||||||
|
padding: 1em;
|
||||||
}
|
}
|
||||||
h1.noop {
|
|
||||||
color:#aaa;
|
.ui.menu.darkblue {
|
||||||
|
background-color:#2C3E50;
|
||||||
}
|
}
|
||||||
tr.event {
|
|
||||||
cursor: pointer;
|
.ui.darkblue.header, i.darkblue {
|
||||||
}
|
color:#2C3E50;
|
||||||
td.message {
|
|
||||||
padding: 0;
|
|
||||||
border: 0;
|
|
||||||
background-color: #FFFFE9;
|
|
||||||
}
|
|
||||||
div[id^='message-event'] {
|
|
||||||
display: none;
|
|
||||||
padding: 4px 15px 4px 15px;
|
|
||||||
}
|
|
||||||
.label-count {
|
|
||||||
width:25px;
|
|
||||||
text-align:center;
|
|
||||||
}
|
|
||||||
.label-time {
|
|
||||||
width:73px;
|
|
||||||
text-align:center;
|
|
||||||
}
|
|
||||||
.label-status {
|
|
||||||
width:100px;
|
|
||||||
text-align:center;
|
|
||||||
}
|
|
||||||
.label-nothing {
|
|
||||||
background-color:#ddd;
|
|
||||||
color:#ddd;
|
|
||||||
}
|
|
||||||
.label.label-failed {
|
|
||||||
background-color: rgb(231, 76, 60);
|
|
||||||
}
|
|
||||||
.label.label-changed {
|
|
||||||
background-color: rgb(24, 188, 156);
|
|
||||||
}
|
|
||||||
.label.label-unreported {
|
|
||||||
background-color: rgb(231, 76, 60);
|
|
||||||
background-color: rgb(129, 145, 146);
|
|
||||||
}
|
|
||||||
.btn-lastreport {
|
|
||||||
width:100px;
|
|
||||||
}
|
}
|
||||||
|
|||||||
9
puppetboard/static/js/tablesort.min.js
vendored
Normal file
9
puppetboard/static/js/tablesort.min.js
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
/*
|
||||||
|
A simple, lightweight jQuery plugin for creating sortable tables.
|
||||||
|
https://github.com/kylefox/jquery-tablesort
|
||||||
|
Version 0.0.2
|
||||||
|
*/
|
||||||
|
$(function(){var a=window.jQuery;a.tablesort=function(d,c){var e=this;this.$table=d;this.$thead=this.$table.find("thead");this.settings=a.extend({},a.tablesort.defaults,c);this.$table.find("th").bind("click.tablesort",function(){e.sort(a(this))});this.direction=this.$th=this.index=null};a.tablesort.prototype={sort:function(d,c){var e=new Date,b=this,g=this.$table,n=0<this.$thead.length?g.find("tbody tr"):g.find("tr").has("td"),m=g.find("tr td:nth-of-type("+(d.index()+1)+")"),h=d.data().sortBy,k=[],
|
||||||
|
l=m.map(function(c,e){return h?"function"===typeof h?h(a(d),a(e),b):h:null!=a(this).data().sortValue?a(this).data().sortValue:a(this).text()});if(0!==l.length){b.$table.find("th").removeClass(b.settings.asc+" "+b.settings.desc);this.direction="asc"!==c&&"desc"!==c?"asc"===this.direction?"desc":"asc":c;c="asc"==this.direction?1:-1;b.$table.trigger("tablesort:start",[b]);b.log("Sorting by "+this.index+" "+this.direction);for(var f=0,p=l.length;f<p;f++)k.push({index:f,cell:m[f],row:n[f],value:l[f]});
|
||||||
|
k.sort(function(a,b){return a.value>b.value?1*c:a.value<b.value?-1*c:0});a.each(k,function(a,b){g.append(b.row)});d.addClass(b.settings[b.direction]);b.log("Sort finished in "+((new Date).getTime()-e.getTime())+"ms");b.$table.trigger("tablesort:complete",[b])}},log:function(d){(a.tablesort.DEBUG||this.settings.debug)&&console&&console.log&&console.log("[tablesort] "+d)},destroy:function(){this.$table.find("th").unbind("click.tablesort");this.$table.data("tablesort",null);return null}};a.tablesort.DEBUG=
|
||||||
|
!1;a.tablesort.defaults={debug:a.tablesort.DEBUG,asc:"sorted ascending",desc:"sorted descending"};a.fn.tablesort=function(d){var c,e;return this.each(function(){c=a(this);(e=c.data("tablesort"))&&e.destroy();c.data("tablesort",new a.tablesort(c,d))})}});
|
||||||
@@ -16,7 +16,7 @@ jQuery(function ($) {
|
|||||||
if (result == '') {
|
if (result == '') {
|
||||||
tstamp.text('Unknown');
|
tstamp.text('Unknown');
|
||||||
} else {
|
} else {
|
||||||
tstamp.text(localise_timestamp(tstring).format('LLLL'));
|
tstamp.text(localise_timestamp(tstring).format('MMM DD YYYY - HH:mm:ss'));
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,5 @@
|
|||||||
{% extends 'layout.html' %}
|
{% extends 'layout.html' %}
|
||||||
{% block row_fluid %}
|
{% block content %}
|
||||||
<div class="container" style="margin-bottom:55px;">
|
<h1>Bad Request</h1>
|
||||||
<div class="row">
|
<p>The request sent to PuppetDB was invalid. This is usually caused by using an unsupported operator.</p>
|
||||||
<div class="span12">
|
|
||||||
<h2>Bad Request</h2>
|
|
||||||
<p>The request sent to PuppetDB was invalid. This is usually caused by using an unsupported operator.</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -1,11 +1,5 @@
|
|||||||
{% extends 'layout.html' %}
|
{% extends 'layout.html' %}
|
||||||
{% block row_fluid %}
|
{% block content %}
|
||||||
<div class="container" style="margin-bottom:55px;">
|
<h1>Permission Denied</h1>
|
||||||
<div class="row">
|
<p>What you were looking for has been disabled by the administrator.</p>
|
||||||
<div class="span12">
|
|
||||||
<h2>Permission Denied</h2>
|
|
||||||
<p>What you were looking for has been disabled by the administrator.</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -1,11 +1,5 @@
|
|||||||
{% extends 'layout.html' %}
|
{% extends 'layout.html' %}
|
||||||
{% block row_fluid %}
|
{% block content%}
|
||||||
<div class="container" style="margin-bottom:55px;">
|
<h1>Not Found</h1>
|
||||||
<div class="row">
|
<p>What you were looking for could not be found in PuppetDB.</p>
|
||||||
<div class="span12">
|
|
||||||
<h2>Not Found</h2>
|
|
||||||
<p>What you were looking for could not be found in PuppetDB.</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -1,16 +1,10 @@
|
|||||||
{% extends 'layout.html' %}
|
{% extends 'layout.html' %}
|
||||||
{% block row_fluid %}
|
{% block content %}
|
||||||
<div class="container" style="margin-bottom:55px;">
|
<h2>Internal Server Error</h2>
|
||||||
<div class="row">
|
<p>This error usually occurs because:
|
||||||
<div class="span12">
|
<ul>
|
||||||
<h2>Internal Server Error</h2>
|
<li>We were unable to reach PuppetDB;</li>
|
||||||
<p>This error usually occurs because:
|
<Li>The query to be executed was malformed resulting in an incorrectly encoded request.</li>
|
||||||
<ul>
|
</ul></p>
|
||||||
<li>We were unable to reach PuppetDB;</li>
|
<p>Please have a look at the log output for further information.</p>
|
||||||
<Li>The query to be executed was malformed resulting in an incorrectly encoded request.</li>
|
|
||||||
</ul></p>
|
|
||||||
<p>Please have a look at the log output for further information.</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
{% macro facts_table(facts, autofocus=False, condensed=False, show_node=False, show_value=True, link_facts=False, margin_top=20, margin_bottom=20) -%}
|
{% macro facts_table(facts, autofocus=False, condensed=False, show_node=False, show_value=True, link_facts=False, margin_top=20, margin_bottom=20) -%}
|
||||||
<div class="filter" style="margin-bottom:{{margin_bottom}}px;margin-top:{{margin_top}}px;">
|
<div class="ui fluid icon input hide" style="margin-bottom:20px">
|
||||||
<input {% if autofocus %} autofocus="autofocus" {% endif %} style="width:100%" type="text" class="filter-table input-medium search-query" placeholder="Type here to filter">
|
<input {% if autofocus %} autofocus="autofocus" {% endif %} class="filter-table" placeholder="Type here to filter...">
|
||||||
</div>
|
</div>
|
||||||
<table class="filter-table facts table table-striped {% if condensed %}table-condensed{% endif%}" style="table-layout:fixed">
|
<table class="filter-table facts ui basic table facts {% if condensed %}compact{% endif%}" style="table-layout: fixed;">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
{% if show_node %}
|
{% if show_node %}
|
||||||
@@ -96,10 +96,10 @@
|
|||||||
{%- endmacro %}
|
{%- endmacro %}
|
||||||
|
|
||||||
{% macro reports_table(reports, nodename, condensed=False, hash_truncate=False, show_conf_col=True, show_agent_col=True, show_host_col=True) -%}
|
{% macro reports_table(reports, nodename, condensed=False, hash_truncate=False, show_conf_col=True, show_agent_col=True, show_host_col=True) -%}
|
||||||
<div class="alert alert-info">
|
<div class="ui info message">
|
||||||
Only showing the last ten reports.
|
Only showing the last ten reports.
|
||||||
</div>
|
</div>
|
||||||
<table class='table table-striped {% if condensed %}table-condensed{% endif %}'>
|
<table class='ui table basic {% if condensed %}compact{% endif %}'>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Start time</th>
|
<th>Start time</th>
|
||||||
@@ -119,7 +119,7 @@
|
|||||||
<tbody>
|
<tbody>
|
||||||
{% for report in reports %}
|
{% for report in reports %}
|
||||||
{% if hash_truncate %}
|
{% if hash_truncate %}
|
||||||
{% set rep_hash = "%s…"|format(report.hash_[0:6])|safe %}
|
{% set rep_hash = "%s…"|format(report.hash_[0:10])|safe %}
|
||||||
{% else %}
|
{% else %}
|
||||||
{% set rep_hash = report.hash_ %}
|
{% set rep_hash = report.hash_ %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@@ -139,7 +139,7 @@
|
|||||||
<td>{{report.agent_version}}</td>
|
<td>{{report.agent_version}}</td>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if show_host_col %}
|
{% if show_host_col %}
|
||||||
<td>{{nodename}}</td>
|
<td><a href="{{url_for('node', node_name=report.node)}}">{{ report.node }}</a></td>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
{% import '_macros.html' as macros %}
|
{% import '_macros.html' as macros %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h1>{{name}}{% if value %}/{{value}}{% endif %} ({{facts|length}})</h1>
|
<h1>{{name}}{% if value %}/{{value}}{% endif %} ({{facts|length}})</h1>
|
||||||
{{macros.facts_graph(facts, autofocus=True, show_node=True, margin_bottom=10)}}
|
{#{{macros.facts_graph(facts, autofocus=True, show_node=True, margin_bottom=10)}}#
|
||||||
{{macros.facts_graph_value(facts, autofocus=True, show_node=True, margin_bottom=10)}}
|
{{macros.facts_graph_value(facts, autofocus=True, show_node=True, margin_bottom=10)}}#}
|
||||||
{% if value %}
|
{% if value %}
|
||||||
{{macros.facts_table(facts, autofocus=True, show_node=True, show_value=False, margin_bottom=10)}}
|
{{macros.facts_table(facts, autofocus=True, show_node=True, show_value=False, margin_bottom=10)}}
|
||||||
{% else %}
|
{% else %}
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
{% extends 'layout.html' %}
|
{% extends 'layout.html' %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="hide" style="margin-bottom:20px">
|
<div class="ui fluid icon input hide" style="margin-bottom:20px">
|
||||||
<input autofocus="autofocus" style="width:100%" type="text" class="filter-list input-medium search-query" placeholder="Type here to filter">
|
<input autofocus="autofocus" class="filter-list" placeholder="Type here to filter...">
|
||||||
</div>
|
</div>
|
||||||
<div style="-moz-column-count:4; -webkit-column-count:4; column-count:4;">
|
<div style="-moz-column-count:4; -webkit-column-count:4; column-count:4;">
|
||||||
{%- for key,facts_list in facts_dict %}
|
{%- for key,facts_list in facts_dict %}
|
||||||
<span class='label label-success'>{{key}}</span>
|
<span class='ui label purple'>{{key}}</span>
|
||||||
<ul class="searchable">
|
<ul class="searchable">
|
||||||
{%- for fact in facts_list %}
|
{%- for fact in facts_list %}
|
||||||
<li><a href="{{url_for('fact', fact=fact)}}">{{fact}}</a></li>
|
<li><a href="{{url_for('fact', fact=fact)}}">{{fact}}</a></li>
|
||||||
|
|||||||
@@ -1,102 +1,106 @@
|
|||||||
{% extends 'layout.html' %}
|
{% extends 'layout.html' %}
|
||||||
{% block row_fluid %}
|
{% block content %}
|
||||||
<div class="container" style="margin-bottom:55px;">
|
<div class="ui vertical grid">
|
||||||
|
<div class="three column row">
|
||||||
<div class="row">
|
<div class="column">
|
||||||
<div class="span12">
|
<a href="nodes?status=failed">
|
||||||
<div class="span4 stat">
|
<h1 class="ui red header no-margin-bottom">
|
||||||
<a href="nodes?status=failed">
|
{{stats['failed']}}
|
||||||
<h1 class="error">{{stats['failed']}}
|
<small>{% if stats['failed']== 1 %} node {% else %} nodes {% endif %}</small>
|
||||||
<small>{% if stats['failed']== 1 %} node {% else %} nodes {% endif %}</small>
|
</h1>
|
||||||
</h1>
|
</a>
|
||||||
</a>
|
<span>with status failed</span>
|
||||||
<span>with status failed</span>
|
</div>
|
||||||
</div>
|
<div class="column">
|
||||||
<div class="span4 stat">
|
<a href="nodes?status=changed">
|
||||||
<a href="nodes?status=changed">
|
<h1 class="ui header green no-margin-bottom">
|
||||||
<h1 class="success">{{stats['changed']}}
|
{{stats['changed']}}
|
||||||
<small>{% if stats['changed']== 1 %} node {% else %} nodes {% endif %}</small>
|
<small>{% if stats['changed']== 1 %} node {% else %} nodes {% endif %}</small>
|
||||||
</h1>
|
</h1>
|
||||||
</a>
|
</a>
|
||||||
<span>with status changed</span>
|
<span>with status changed</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="span4 stat">
|
<div class="column">
|
||||||
<a href="nodes?status=unreported">
|
<a href="nodes?status=unreported">
|
||||||
<h1 class="noop">{{ stats['unreported'] }}
|
<h1 class="ui header black no-margin-bottom">
|
||||||
<small>{% if stats['unreported']== 1 %} node {% else %} nodes {% endif %}</small>
|
{{ stats['unreported'] }}
|
||||||
</h1>
|
<small>{% if stats['unreported']== 1 %} node {% else %} nodes {% endif %}</small>
|
||||||
</a>
|
</h1>
|
||||||
<span>
|
</a>
|
||||||
unreported in the last {{ config.UNRESPONSIVE_HOURS }} hours
|
<span>unreported in the last {{ config.UNRESPONSIVE_HOURS }} hours</span>
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="three column row">
|
||||||
<div class="row">
|
<div class="column">
|
||||||
<div class="span12">
|
<h1 class="ui header darkblue no-margin-bottom">{{metrics['num_nodes']}}</h1>
|
||||||
<div class="span4 stat">
|
<span>Population</span>
|
||||||
<h1>{{metrics['num_nodes']}}</h1>
|
</div>
|
||||||
<span>Population</span>
|
<div class="column">
|
||||||
</div>
|
<h1 class="ui header darkblue no-margin-bottom">{{metrics['num_resources']}}</h1>
|
||||||
<div class="span4 stat">
|
<span>Resources managed</span>
|
||||||
<h1>{{metrics['num_resources']}}</h1>
|
</div>
|
||||||
<span>Resources managed</span>
|
<div class="column">
|
||||||
</div>
|
<h1 class="ui header darkblue no-margin-bottom">{{metrics['avg_resources_node']}}</h1>
|
||||||
<div class="span4 stat">
|
<span>Avg. resources/node</span>
|
||||||
<h1>{{metrics['avg_resources_node']}}</h1>
|
|
||||||
<span>Avg. resources/node</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="ui divider">
|
||||||
<div class="row">
|
</div>
|
||||||
<div class="span12">
|
<div class="one column row no-margin-top">
|
||||||
|
<div class="column">
|
||||||
{% if nodes %}
|
{% if nodes %}
|
||||||
<h2>Nodes status detail ({{nodes|length}})</h2>
|
<h2>Nodes status detail ({{nodes|length}})</h2>
|
||||||
<table class='dashboard table table-striped table-condensed'>
|
<table class='ui compact basic table dashboard'>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th style="min-width:220px;">Status</th>
|
<th class="five wide">Status</th>
|
||||||
<th style="width:600px;">Hostname</th>
|
<th class="ten wide">Hostname</th>
|
||||||
<th style="width:120px;"></th>
|
<th class="one wide"></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody class="searchable">
|
<tbody class="searchable">
|
||||||
{% for node in nodes %}
|
{% for node in nodes %}
|
||||||
{% if node.status != 'unchanged' %}
|
{% if node.status != 'unchanged' %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<a href="{{url_for('report_latest', node_name=node.name)}}">
|
<a class="ui small status label
|
||||||
<span class="label label-status label-{{node.status}}">{{node.status}}</span>
|
{% if node.status == 'failed' %}
|
||||||
</a>
|
red
|
||||||
{% if node.status=='unreported'%}
|
{% elif node.status == 'changed' %}
|
||||||
<span class="label label-time label-unreported"> {{ node.unreported_time }} </label>
|
green
|
||||||
{% else %}
|
{% elif node.status == 'unreported' %}
|
||||||
{% if node.events['failures'] %}<span class="label label-important label-count">{{node.events['failures']}}</span>{% else %}<span class="label label-count">0</span>{% endif%}
|
black
|
||||||
{% if node.events['successes'] %}<span class="label label-success label-count">{{node.events['successes']}}</span>{% else %}<span class="label label-count">0</span>{% endif%}
|
|
||||||
{% endif %}
|
|
||||||
</td>
|
|
||||||
<td><a href="{{url_for('node', node_name=node.name)}}">{{ node.name }}</a></td>
|
|
||||||
<td>
|
|
||||||
{% if node.unreported_time != None or node.status != 'unreported' %}
|
|
||||||
<a class="btn btn-small btn-primary btn-lastreport" href="{{url_for('report_latest', node_name=node.name)}}">Latest Report</a>
|
|
||||||
{% else %}
|
|
||||||
<a class="btn btn-small btn-lastreport"> No Report </a>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
" href="{{url_for('report_latest', node_name=node.name)}}">
|
||||||
</tr>
|
{{node.status}}
|
||||||
{% endif %}
|
</a>
|
||||||
{% endfor %}
|
{% if node.status=='unreported'%}
|
||||||
</tbody>
|
<span class="ui small label status"> {{ node.unreported_time }} </label>
|
||||||
</table>
|
{% else %}
|
||||||
|
{% if node.events['failures'] %}<span class="ui small count label red">{{node.events['failures']}}</span>{% else %}<span class="ui small count label">0</span>{% endif%}
|
||||||
|
{% if node.events['successes'] %}<span class="ui small count label green">{{node.events['successes']}}</span>{% else %}<span class="ui small count label">0</span>{% endif%}
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<a href="{{url_for('node', node_name=node.name)}}">{{ node.name }}</a>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<a title="Latest Report" href="{{url_for('report_latest', node_name=node.name)}}">
|
||||||
|
<i class="large tasks darkblue icon"></i>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
{% else %}
|
{% else %}
|
||||||
<h2>Nodes status detail</h2>
|
<h2>Nodes status detail</h2>
|
||||||
<div class="alert alert-info">
|
<div class="ui info message">
|
||||||
Nothing seems to be changing.
|
Nothing seems to be changing.
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock row_fluid %}
|
{% endblock content %}
|
||||||
|
|||||||
@@ -2,66 +2,52 @@
|
|||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>Puppetᴃoard</title>
|
<title>Puppetboard</title>
|
||||||
<link href="//netdna.bootstrapcdn.com/bootswatch/2.3.2/flatly/bootstrap.min.css" rel="stylesheet">
|
<link href="//cdnjs.cloudflare.com/ajax/libs/semantic-ui/0.12.0/css/semantic.min.css" rel="stylesheet">
|
||||||
<link href="//netdna.bootstrapcdn.com/font-awesome/3.2.1/css/font-awesome.min.css" rel="stylesheet">
|
<link href='//fonts.googleapis.com/css?family=Open+Sans' rel='stylesheet' type='text/css'>
|
||||||
<link href="{{url_for('static', filename='css/puppetboard.css')}}" rel="stylesheet">
|
<link href="//cdnjs.cloudflare.com/ajax/libs/jquery.tablesorter/2.13.3/css/filter.formatter.css" rel="stylesheet">
|
||||||
|
<link href="{{ url_for('static', filename='css/puppetboard.css')}}" rel="stylesheet">
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div style="font-variant:small-caps" class="navbar navbar-fixed-top">
|
<nav class="ui fixed darkblue inverted menu">
|
||||||
<div class="navbar-inner">
|
<div class="title item">
|
||||||
<div class="container">
|
Puppetboard
|
||||||
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
|
|
||||||
<span class="icon-bar"></span>
|
|
||||||
<span class="icon-bar"></span>
|
|
||||||
<span class="icon-bar"></span>
|
|
||||||
</a>
|
|
||||||
<span style="margin-top:-2px;" class="brand">Puppetboard</span>
|
|
||||||
<div class="nav-collapse collapse">
|
|
||||||
<ul class="nav">
|
|
||||||
{%- for endpoint, caption in [
|
|
||||||
('index', 'Overview'),
|
|
||||||
('nodes', 'Nodes'),
|
|
||||||
('facts', 'Facts'),
|
|
||||||
('reports', 'Reports'),
|
|
||||||
('metrics', 'Metrics'),
|
|
||||||
('query', 'Query'),
|
|
||||||
] %}
|
|
||||||
<li{% if endpoint == request.endpoint %} class=active{% endif
|
|
||||||
%}><a href="{{ url_for(endpoint) }}">{{ caption }}</a></li>
|
|
||||||
{%- endfor %}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
{%- for endpoint, caption in [
|
||||||
{% block container %}
|
('index', 'Overview'),
|
||||||
<div class="container-fluid" style="margin-bottom:55px;">
|
('nodes', 'Nodes'),
|
||||||
<div class="row-fluid">
|
('facts', 'Facts'),
|
||||||
{% block row_fluid %}
|
('reports', 'Reports'),
|
||||||
<div class="span12">
|
('metrics', 'Metrics'),
|
||||||
{% block content %} {% endblock content %}
|
('query', 'Query'),
|
||||||
</div>
|
] %}
|
||||||
{% endblock row_fluid %}
|
<a {% if endpoint == request.endpoint %} class="active item" {% else %} class="item" {% endif %}
|
||||||
</div>
|
href="{{ url_for(endpoint) }}">{{ caption }}</a>
|
||||||
</div>
|
{%- endfor %}
|
||||||
{% endblock container %}
|
</nav>
|
||||||
<div class="navbar navbar-fixed-bottom" style="background-color:rgb(249, 249, 249);">
|
<div class="ui grid padding-bottom">
|
||||||
<div class="navbar" style="height:55px;margin-bottom:0;">
|
<div class="one wide column"></div>
|
||||||
<div class="container-fluid" style="line-height:55px;">
|
<div class="fourteen wide column">
|
||||||
Copyright © 2013 <a href="https://github.com/daenney">Daniele Sluijters</a>. <span style="float:right">Live from PuppetDB.</span>
|
{% block content %} {% endblock content %}
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div class="one wide column"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="//code.jquery.com/jquery-1.10.0.min.js"></script>
|
<footer class="ui absolute fixed bottom">
|
||||||
<script src="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/js/bootstrap.min.js"></script>
|
<div>
|
||||||
<script src="//cdn.jsdelivr.net/tablesorter/2.0.3/jquery.tablesorter.min.js"></script>
|
Copyright © 2013-2014 <a href="https://github.com/daenney">Daniele Sluijters</a>. <span style="float:right">Live from PuppetDB.</span>
|
||||||
<script src="{{ url_for('static', filename='js/moment.js')}}"></script>
|
</div>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
|
||||||
|
<script src="//cdnjs.cloudflare.com/ajax/libs/semantic-ui/0.12.0/javascript/semantic.min.js"></script>
|
||||||
|
<script src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.5.1/moment.min.js"></script>
|
||||||
|
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery.tablesorter/2.13.3/jquery.tablesorter.min.js"></script>
|
||||||
<script src="{{ url_for('static', filename='js/timestamps.js')}}"></script>
|
<script src="{{ url_for('static', filename='js/timestamps.js')}}"></script>
|
||||||
<script src="{{url_for('static', filename='js/tables.js')}}"></script>
|
|
||||||
<script src="{{url_for('static', filename='js/lists.js')}}"></script>
|
<script src="{{url_for('static', filename='js/lists.js')}}"></script>
|
||||||
|
<script src="{{url_for('static', filename='js/tables.js')}}"></script>
|
||||||
|
|
||||||
{% block script %} {% endblock script %}
|
{% block script %} {% endblock script %}
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -2,11 +2,21 @@
|
|||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="page-header">
|
<div class="page-header">
|
||||||
<h1>Metric
|
<h1>Metric
|
||||||
{% set name = "%s…"|format(name[:75])|safe if name|length > 75%}
|
{% if name|length > 75 %}
|
||||||
|
{% set name = "%s…"|format(name[:75])|safe %}
|
||||||
|
{% else %}
|
||||||
|
{% set name = name %}
|
||||||
|
{% endif %}
|
||||||
<small>{{name}}</small>
|
<small>{{name}}</small>
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
<table class="table table-striped">
|
<table class="ui segment table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Option</th>
|
||||||
|
<th>Value</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for key,value in metric %}
|
{% for key,value in metric %}
|
||||||
<tr>
|
<tr>
|
||||||
|
|||||||
@@ -1,37 +1,39 @@
|
|||||||
{% extends 'layout.html' %}
|
{% extends 'layout.html' %}
|
||||||
{% import '_macros.html' as macros %}
|
{% import '_macros.html' as macros %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="row-fluid">
|
<div class='ui two column grid'>
|
||||||
<div class="span12">
|
<div class='column'>
|
||||||
<h1>Details</h1>
|
<div class='row'>
|
||||||
<table class="table table-striped table-condensed" style="table-layout:fixed">
|
<h1>Details</h1>
|
||||||
<thead>
|
<table class="ui table compact basic">
|
||||||
<tr>
|
<tbody>
|
||||||
<th>Hostname</th>
|
<tr>
|
||||||
<th>Facts uploaded at</th>
|
<th>Hostname</th>
|
||||||
<th>Catalog compiled at</th>
|
<td style="word-wrap:break-word"><b>{{node.name}}</b></td>
|
||||||
<th>Report uploaded at</th>
|
</tr>
|
||||||
</tr>
|
<tr>
|
||||||
</thead>
|
<th>Facts <i title='uploaded at' class=' upload icon'></i></th>
|
||||||
<tbody>
|
<td rel="utctimestamp">{{node.facts_timestamp}}</td>
|
||||||
<tr>
|
</tr>
|
||||||
<td style="word-wrap:break-word"><b>{{node.name}}</b></td>
|
<tr>
|
||||||
<td rel="utctimestamp">{{node.facts_timestamp}}</td>
|
<th>Catalog <i title='uploaded at' class=' upload icon'></i></th>
|
||||||
<td rel="utctimestamp">{{node.catalog_timestamp}}</td>
|
<td rel="utctimestamp">{{node.catalog_timestamp}}</td>
|
||||||
<td rel="utctimestamp">{{node.report_timestamp}}</td>
|
</tr>
|
||||||
</tr>
|
<tr>
|
||||||
</tbody>
|
<th>Report <i title='uploaded at' class=' upload icon'></i></th>
|
||||||
</table>
|
<td rel="utctimestamp">{{node.report_timestamp}}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class='row'>
|
||||||
|
<h1>Reports</h1>
|
||||||
|
{{ macros.reports_table(reports, node.name, condensed=True, hash_truncate=True, show_conf_col=False, show_agent_col=False, show_host_col=False)}}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class='column'>
|
||||||
<div class="row-fluid">
|
|
||||||
<div class="span6">
|
|
||||||
<h1>Facts</h1>
|
<h1>Facts</h1>
|
||||||
{{macros.facts_table(facts, link_facts=True, condensed=True, margin_top=10)}}
|
{{macros.facts_table(facts, link_facts=True, condensed=True)}}
|
||||||
</div>
|
|
||||||
<div class="span6">
|
|
||||||
<h1>Reports</h1>
|
|
||||||
{{ macros.reports_table(reports, node.name, condensed=True, hash_truncate=True, show_conf_col=False, show_agent_col=False, show_host_col=False)}}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock content %}
|
{% endblock content %}
|
||||||
|
|||||||
@@ -1,56 +1,53 @@
|
|||||||
{% extends 'layout.html' %}
|
{% extends 'layout.html' %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="alert alert-info">
|
<div class="ui fluid icon input hide" style="margin-bottom:20px">
|
||||||
PuppetDB currently only returns active nodes.
|
<input autofocus="autofocus" class="filter-table" placeholder="Type here to filter...">
|
||||||
</div>
|
</div>
|
||||||
{% with messages = get_flashed_messages(with_categories=true) %}
|
<table class='ui compact basic table nodes'>
|
||||||
{% if messages %}
|
|
||||||
{% for category, message in messages %}
|
|
||||||
<div class="alert alert-{{category}}">
|
|
||||||
{{message}}
|
|
||||||
</div>
|
|
||||||
{% endfor %}
|
|
||||||
{% endif %}
|
|
||||||
{% endwith %}
|
|
||||||
<div class="hide" style="margin-bottom:20px">
|
|
||||||
<input autofocus="autofocus" style="width:100%" type="text" class="filter-table input-medium search-query" placeholder="Type here to filter">
|
|
||||||
</div>
|
|
||||||
<table class='nodes table table-striped table-condensed'>
|
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Status</th>
|
<th>Status</th>
|
||||||
<th>Hostname</th>
|
<th>Hostname</th>
|
||||||
<th>Catalog compiled at</th>
|
<th>Catalog</th>
|
||||||
<th>Last report</th>
|
<th>Report</th>
|
||||||
<th> </th>
|
<th> </th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody class="searchable">
|
<tbody class="searchable">
|
||||||
{% for node in nodes %}
|
{% for node in nodes %}
|
||||||
<tr>
|
<tr>
|
||||||
<td><a href="{{url_for('report_latest', node_name=node.name)}}">
|
<td>
|
||||||
<span class="label label-status label-{{ node.status }}">{{ node.status }}</span>
|
<a class="ui small status label
|
||||||
</a>
|
{% if node.status == 'failed' %}
|
||||||
{% if node.status=='unreported'%}
|
red
|
||||||
<span class="label label-time label-unreported"> {{ node.unreported_time }} </label>
|
{% elif node.status == 'changed' %}
|
||||||
{% else %}
|
green
|
||||||
{% if node.events['failures'] %}<span class="label label-count label-important">{{node.events['failures']}}</span>{% else %}<span class="label label-count">0</span>{% endif%}
|
{% elif node.status == 'unreported' %}
|
||||||
{% if node.events['successes'] %}<span class="label label-count label-success">{{node.events['successes']}}</span>{% else %}<span class="label label-count">0</span>{% endif%}
|
black
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
" href="{{url_for('report_latest', node_name=node.name)}}">
|
||||||
|
{{node.status}}
|
||||||
|
</a>
|
||||||
|
{% if node.status=='unreported'%}
|
||||||
|
<span class="ui small label status"> {{ node.unreported_time }} </label>
|
||||||
|
{% else %}
|
||||||
|
<span>{% if node.events['failures'] %}<span class="ui small count label red">{{node.events['failures']}}</span>{% else %}<span class="ui small count label">0</span>{% endif%}
|
||||||
|
{% if node.events['successes'] %}<span class="ui small count label green">{{node.events['successes']}}</span>{% else %}<span class="ui small count label">0</span>{% endif%}</span>
|
||||||
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
<td><a href="{{url_for('node', node_name=node.name)}}">{{node.name}}</a></td>
|
<td><a href="{{url_for('node', node_name=node.name)}}">{{node.name}}</a></td>
|
||||||
<td rel="utctimestamp">{{node.catalog_timestamp}}</td>
|
<td rel="utctimestamp">{{node.catalog_timestamp}}</td>
|
||||||
<td>
|
<td>
|
||||||
{% if node.report_timestamp %}
|
{% if node.report_timestamp %}
|
||||||
<span rel="utctimestamp">{{ node.report_timestamp }}</span>
|
<a href="{{url_for('report_latest', node_name=node.name)}}" rel='utctimestamp'>{{ node.report_timestamp }}</a>
|
||||||
{% else %}
|
{% else %}
|
||||||
<i class="icon icon-ban-circle"></i>
|
<i class="large ban circle icon"></i>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{% if node.report_timestamp %}
|
{% if node.report_timestamp %}
|
||||||
<a class="btn btn-small btn-primary" href="{{url_for('report_latest', node_name=node.name)}}">Latest Report</a>
|
<a title='Reports' href="{{url_for('reports_node', node=node.name)}}"><i class='large darkblue book icon'></i></a>
|
||||||
<a class="btn btn-small btn-primary" href="{{url_for('reports_node', node=node.name)}}">Reports</a>
|
<i class='large darkblue trash icon'></i>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@@ -1,61 +1,43 @@
|
|||||||
{% extends 'layout.html' %}
|
{% extends 'layout.html' %}
|
||||||
{% block row_fluid %}
|
{% block content %}
|
||||||
<div class="span12">
|
<h2>Compose</h2>
|
||||||
<div class="alert">
|
{% with messages = get_flashed_messages(with_categories=true) %}
|
||||||
This is highly experimental and will likely set your server on fire.
|
{% if messages %}
|
||||||
</div>
|
{% for category, message in messages %}
|
||||||
|
<div class="ui {{category}} message">
|
||||||
|
{{message}}
|
||||||
</div>
|
</div>
|
||||||
<div class="container" style="margin-bottom:55px;">
|
{% endfor %}
|
||||||
<div class="row">
|
{% endif %}
|
||||||
<div class="span12">
|
{% endwith %}
|
||||||
<h2>Compose</h2>
|
<div class="ui form">
|
||||||
{% with messages = get_flashed_messages(with_categories=true) %}
|
<form method="POST" action="{{ url_for('query')}}"
|
||||||
{% if messages %}
|
{{ form.csrf_token }}
|
||||||
{% for category, message in messages %}
|
<div class="field {% if form.query.errors %} error {% endif %}">
|
||||||
<div class="alert alert-{{category}}">
|
{{form.query(autofocus="autofocus", rows=5, placeholder="Enter your query: [\"=\", \"name\", \"hostname\"]. You may omit the opening and closing bracket.")}}
|
||||||
{{message}}
|
</div>
|
||||||
|
<div class="inline fields">
|
||||||
|
{% for subfield in form.endpoints %}
|
||||||
|
<div class="field">
|
||||||
|
<div class="ui radio checkbox">
|
||||||
|
{{subfield }}
|
||||||
|
{{subfield.label}}
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endif %}
|
|
||||||
{% endwith %}
|
|
||||||
<form class="form-horizontal" method="POST" action="{{ url_for('query')}}">
|
|
||||||
{{ form.csrf_token }}
|
|
||||||
<div class="control-group {% if form.query.errors %} error {% endif %}">
|
|
||||||
{{form.query.label(class_="control-label")}}
|
|
||||||
<div class="controls">
|
|
||||||
{{form.query(class_="input-block-level", autofocus="autofocus", rows=5, placeholder="\"=\", \"name\", \"hostname\"")}}
|
|
||||||
{% if form.query.errors %}
|
|
||||||
<span class="help-inline">{% for error in form.query.errors %}{{error}}{% endfor %}</span>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="control-group {% if form.endpoints.errors %} error {% endif %}">
|
|
||||||
{{form.endpoints.label(class_="control-label")}}
|
|
||||||
<div class="controls">
|
|
||||||
{% for subfield in form.endpoints %}
|
|
||||||
{{subfield.label(class_="radio inline")}}
|
|
||||||
{{subfield }}
|
|
||||||
{% endfor %}
|
|
||||||
{% if form.endpoints.errors %}
|
|
||||||
<span class="help-inline">{% for error in form.endpoints.errors %}{{error}}{% endfor %}</span>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="form-actions">
|
|
||||||
<button type="submit" class="btn btn-primary">Yes I'm sure</button>
|
|
||||||
<button type="button" class="btn">No thanks</button>
|
|
||||||
</div>
|
|
||||||
{{ form.hidden_tag() }}
|
|
||||||
</form>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
{{ form.hidden_tag() }}
|
||||||
{% if result %}
|
<input type=submit class="ui submit button" value='Submit'>
|
||||||
<div class="row">
|
<input type=reset class="ui red submit button" value='Cancel'>
|
||||||
<div class="span12">
|
</form>
|
||||||
<h2>Result</h2>
|
|
||||||
<pre><code>{{result|jsonprint}}</code></pre>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
</div>
|
||||||
{% endblock row_fluid %}
|
|
||||||
|
{% if result %}
|
||||||
|
<div class="row">
|
||||||
|
<div class="span12">
|
||||||
|
<h2>Result</h2>
|
||||||
|
<pre><code>{{result|jsonprint}}</code></pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% endblock content %}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{% extends 'layout.html' %}
|
{% extends 'layout.html' %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h1>Summary</h1>
|
<h1>Summary</h1>
|
||||||
<table class='table table-striped'>
|
<table class='ui basic table'>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Hostname</th>
|
<th>Hostname</th>
|
||||||
@@ -27,7 +27,7 @@
|
|||||||
</table>
|
</table>
|
||||||
|
|
||||||
<h1>Events</h1>
|
<h1>Events</h1>
|
||||||
<table class='table table-striped table-condensed'>
|
<table class='ui basic table compact'>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Resource</th>
|
<th>Resource</th>
|
||||||
@@ -39,22 +39,22 @@
|
|||||||
<tbody>
|
<tbody>
|
||||||
{% for event in events %}
|
{% for event in events %}
|
||||||
{% if not event.failed and event.item['old'] != event.item['new'] %}
|
{% if not event.failed and event.item['old'] != event.item['new'] %}
|
||||||
<tr id='event-{{loop.index}}' class='success event'>
|
<tr id='event-{{loop.index}}' class='positive'>
|
||||||
{% elif event.failed %}
|
{% elif event.failed %}
|
||||||
<tr id='event-{{loop.index}}' class='error event'>
|
<tr id='event-{{loop.index}}' class='error'>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<td>{{event.item['type']}}[{{event.item['title']}}]</td>
|
<td>{{event.item['type']}}[{{event.item['title']}}]</td>
|
||||||
<td>{{event.status}}</td>
|
<td>{{event.status}}</td>
|
||||||
<td>{{event.item['old']}}</td>
|
<td>{{event.item['old']}}</td>
|
||||||
<td>{{event.item['new']}}</td>
|
<td>{{event.item['new']}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
{# <tr>
|
||||||
<td class='message' colspan='4'>
|
<td class='message' colspan='4'>
|
||||||
<div id='message-event-{{loop.index}}'>
|
<div id='message-event-{{loop.index}}'>
|
||||||
{{event.item['message']}}
|
{{event.item['message']}}
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>#}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{% extends 'layout.html' %}
|
{% extends 'layout.html' %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="alert">
|
<div class="ui warning message">
|
||||||
Pending <a href="http://projects.puppetlabs.com/issues/21600">#21600</a>. You can access reports for a node or individual reports through the <a href="{{url_for('nodes')}}">Nodes</a> tab.
|
Pending <a href="http://projects.puppetlabs.com/issues/21600">#21600</a>. You can access reports for a node or individual reports through the <a href="{{url_for('nodes')}}">Nodes</a> tab.
|
||||||
</div>
|
</div>
|
||||||
{% endblock content %}
|
{% endblock content %}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ def get_or_abort(func, *args, **kwargs):
|
|||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
return func(*args, **kwargs)
|
return func(*args, **kwargs)
|
||||||
except HTTPError, e:
|
except HTTPError as e:
|
||||||
abort(e.response.status_code)
|
abort(e.response.status_code)
|
||||||
except ConnectionError:
|
except ConnectionError:
|
||||||
abort(500)
|
abort(500)
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
Flask==0.10.1
|
Flask==0.10.1
|
||||||
Flask-WTF==0.8.4
|
Flask-WTF==0.9.4
|
||||||
Jinja2==2.7
|
Jinja2==2.7.2
|
||||||
MarkupSafe==0.18
|
MarkupSafe==0.19
|
||||||
WTForms==1.0.4
|
WTForms==1.0.5
|
||||||
Werkzeug==0.9.3
|
Werkzeug==0.9.4
|
||||||
itsdangerous==0.22
|
itsdangerous==0.23
|
||||||
pypuppetdb==0.1.0
|
pypuppetdb==0.1.1
|
||||||
requests==1.2.3
|
requests==2.2.1
|
||||||
|
|||||||
3
setup.py
3
setup.py
@@ -45,5 +45,8 @@ setup(
|
|||||||
'Programming Language :: Python :: 2',
|
'Programming Language :: Python :: 2',
|
||||||
'Programming Language :: Python :: 2.6',
|
'Programming Language :: Python :: 2.6',
|
||||||
'Programming Language :: Python :: 2.7',
|
'Programming Language :: Python :: 2.7',
|
||||||
|
'Programming Language :: Python :: 3',
|
||||||
|
'Programming Language :: Python :: 3.2',
|
||||||
|
'Programming Language :: Python :: 3.3',
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user