diff --git a/puppetboard/app.py b/puppetboard/app.py index bf03ee4..08f4947 100644 --- a/puppetboard/app.py +++ b/puppetboard/app.py @@ -40,6 +40,12 @@ REPORTS_COLUMNS = [ 'name': 'Agent version'}, ] +CATALOGS_COLUMNS = [ + {'attr': 'certname', 'name': 'Certname', 'type': 'node'}, + {'attr': 'catalog_timestamp', 'name': 'Compile Time'}, + {'attr': 'form', 'name': 'Compare'}, +] + app = Flask(__name__) app.config.from_object('puppetboard.default_settings') @@ -828,9 +834,14 @@ def metric(env, metric): current_env=env) -@app.route('/catalogs', defaults={'env': app.config['DEFAULT_ENVIRONMENT']}) -@app.route('//catalogs') -def catalogs(env): +@app.route('/catalogs', + defaults={'env': app.config['DEFAULT_ENVIRONMENT'], + 'compare': None}) +@app.route('//catalogs', defaults={'compare': None}) +@app.route('/catalogs/compare/', + defaults={'env': app.config['DEFAULT_ENVIRONMENT']}) +@app.route('//catalogs/compare/') +def catalogs(env, compare): """Lists all nodes with a compiled catalog. :param env: Find the nodes with this catalog_environment value @@ -839,52 +850,78 @@ def catalogs(env): envs = environments() check_env(env, envs) - if app.config['ENABLE_CATALOG']: - nodenames = [] - catalog_list = [] - query = AndOperator() - - if env != '*': - query.add(EqualsOperator("catalog_environment", env)) - - query.add(NullOperator("catalog_timestamp", False)) - - order_by_str = '[{"field": "certname", "order": "asc"}]' - nodes = get_or_abort(puppetdb.nodes, - query=query, - with_status=False, - order_by=order_by_str) - nodes, temp = tee(nodes) - - for node in temp: - nodenames.append(node.name) - - for node in nodes: - table_row = { - 'name': node.name, - 'catalog_timestamp': node.catalog_timestamp - } - - if len(nodenames) > 1: - form = CatalogForm() - - form.compare.data = node.name - form.against.choices = [(x, x) for x in nodenames - if x != node.name] - table_row['form'] = form - else: - table_row['form'] = None - - catalog_list.append(table_row) - - return render_template( - 'catalogs.html', - nodes=catalog_list, - envs=envs, - current_env=env) - else: + if not app.config['ENABLE_CATALOG']: log.warn('Access to catalog interface disabled by administrator') abort(403) + return + + return render_template( + 'catalogs.html', + compare=compare, + columns=CATALOGS_COLUMNS) + + +@app.route('/catalogs/json', + defaults={'env': app.config['DEFAULT_ENVIRONMENT'], + 'compare': None}) +@app.route('//catalogs/json', defaults={'compare': None}) +@app.route('/catalogs/compare//json', + defaults={'env': app.config['DEFAULT_ENVIRONMENT']}) +@app.route('//catalogs/compare//json') +def catalogs_ajax(env, compare): + """Server data to catalogs as JSON to Jquery datatables + """ + draw = int(request.args.get('draw', 0)) + start = int(request.args.get('start', 0)) + length = int(request.args.get('length', app.config['NORMAL_TABLE_COUNT'])) + paging_args = {'limit': length, 'offset': start} + search_arg = request.args.get('search[value]') + order_column = int(request.args.get('order[0][column]', 0)) + order_filter = CATALOGS_COLUMNS[order_column].get( + 'filter', CATALOGS_COLUMNS[order_column]['attr']) + order_dir = request.args.get('order[0][dir]', 'asc') + order_args = '[{"field": "%s", "order": "%s"}]' % (order_filter, order_dir) + + envs = environments() + check_env(env, envs) + + query = AndOperator() + if env != '*': + query.add(EqualsOperator("catalog_environment", env)) + if search_arg: + query.add(RegexOperator("certname", r"%s" % search_arg)) + query.add(NullOperator("catalog_timestamp", False)) + + nodes = get_or_abort(puppetdb.nodes, + query=query, + include_total=True, + order_by=order_args, + **paging_args) + + catalog_list = [] + total = None + for node in nodes: + if total is None: + total = puppetdb.total + + catalog_list.append({ + 'certname': node.name, + 'catalog_timestamp': node.catalog_timestamp, + 'form': compare, + }) + + if total is None: + total = 0 + + return render_template( + 'catalogs.json.tpl', + total=total, + total_filtered=total, + draw=draw, + columns=CATALOGS_COLUMNS, + catalogs=catalog_list, + envs=envs, + current_env=env) @app.route('/catalog/', @@ -911,40 +948,6 @@ def catalog_node(env, node_name): abort(403) -@app.route('/catalog/submit', methods=['POST'], - defaults={'env': app.config['DEFAULT_ENVIRONMENT']}) -@app.route('//catalog/submit', methods=['POST']) -def catalog_submit(env): - """Receives the submitted form data from the catalogs page and directs - the users to the comparison page. Directs users back to the catalogs - page if no form submission data is found. - - :param env: This parameter only directs the response page to the right - environment. If this environment does not exist return the use to the - catalogs page with the right environment. - :type env: :obj:`string` - """ - envs = environments() - check_env(env, envs) - - if app.config['ENABLE_CATALOG']: - form = CatalogForm(request.form) - - form.against.choices = [(form.against.data, form.against.data)] - if form.validate_on_submit(): - compare = form.compare.data - against = form.against.data - return redirect( - url_for('catalog_compare', - env=env, - compare=compare, - against=against)) - return redirect(url_for('catalogs', env=env)) - else: - log.warn('Access to catalog interface disabled by administrator') - abort(403) - - @app.route('/catalogs/compare/...', defaults={'env': app.config['DEFAULT_ENVIRONMENT']}) @app.route('//catalogs/compare/...') diff --git a/puppetboard/templates/catalogs.html b/puppetboard/templates/catalogs.html index 62ef720..eee933b 100644 --- a/puppetboard/templates/catalogs.html +++ b/puppetboard/templates/catalogs.html @@ -1,40 +1,21 @@ {% extends 'layout.html' %} {% import '_macros.html' as macros %} {% block content %} -
- -
- +
- - - - + {% for column in columns %} + + {% endfor %} - - {% for node in nodes %} - - - - - - - {% endfor %} +
CertnameCompile TimeCompare With{{ column.name }}
{{node.name}}{{node.catalog_timestamp}} - {% if node.form %} -
-
- {{node.form.csrf_token}} -
- {{node.form.compare}} - {{node.form.against}} - -
-
-
- {% endif %} -
{% endblock content %} +{% block onload_script %} +{% macro extra_options(caller) %} + "order": [[ 0, "asc" ]], +{% endmacro %} +{{ macros.datatable_init(table_html_id="catalogs_table", ajax_url=url_for('catalogs_ajax', env=current_env, compare=compare), default_length=config.NORMAL_TABLE_COUNT, length_selector=config.TABLE_COUNT_SELECTOR, extra_options=extra_options) }} +{% endblock onload_script %} diff --git a/puppetboard/templates/catalogs.json.tpl b/puppetboard/templates/catalogs.json.tpl new file mode 100644 index 0000000..3554fb1 --- /dev/null +++ b/puppetboard/templates/catalogs.json.tpl @@ -0,0 +1,42 @@ +{ + "draw": {{draw}}, + "recordsTotal": {{total}}, + "recordsFiltered": {{total_filtered}}, + "data": [ + {% for catalog in catalogs -%} + {%- if catalog_flag %},{%- endif %} + {%- set catalog_flag = True -%} + [ + {%- for column in columns -%} + {%- if column_flag %},{%- endif -%} + {%- set column_flag = True -%} + {%- if column.attr == 'catalog_timestamp' -%} + "{{ catalog.catalog_timestamp }}" + {%- elif column.type == 'node' -%} + {% filter jsonprint %}{{ catalog.certname }}{% endfilter %} + {%- elif column.attr == 'form' -%} + {% filter jsonprint -%} +
+ {%- if catalog.form -%} +
+ {%- else -%} + + {%- endif -%} +
+ {%- if catalog.form -%} + + {%- else -%} + + {%- endif -%} +
+
+
+ {%- endfilter -%} + {%- else -%} + "" + {%- endif -%} + {%- endfor -%} + ] + {% endfor %} + ] +}