""" App object setup for application. Contains the create_app() procedure for instansiating new Flask app ins. Settings are instanciated from instance/settings.py, and extra functionallity is pulled in from other modules. """ import logging import random import os.path import subprocess from domonic.html import ( a, div, img, span, ) import flask from flask import ( Flask, request, flash, redirect, url_for ) from sqlalchemy.orm import joinedload import werkzeug.datastructures import http.client import urllib.parse from .app import model from .app import cmdline from .app import api logging.basicConfig(level=logging.DEBUG) def create_app(): """ Create new flask app. Should bind everything needed to it. This method is also used by `flask run` https://flask.palletsprojects.com/en/2.1.x/cli/ """ app = Flask(__name__, instance_relative_config=True) app.config.from_pyfile('settings.py') for module in [ model, cmdline, api, ]: module.init_app(app) @app.route('/') def root_page(): # flash('Test') return flask.render_template('index.html') @app.route('/host') def hosts(): result = model.Host.query.all() return flask.render_template( 'list.html', title='Hosts', items=[div(img(_class='distroicon', _height=16, **{'_data-host':x.fqdn}), a(x.fqdn, _href=f'/host/{x.fqdn}'), span(x.summary,_class='summary') if x.summary else [], _class='hostline', ) for x in result]) @app.route('/host/') def host(host): host = model.Host.query.where(model.Host.fqdn == host).one() return flask.render_template('host.html', host=host) @app.route('/environment') def environments(): # TODO sqlalchemy order by for children? envs = model.Environment.query.all() return flask.render_template( 'list.html', title='Environments', items=[a(env.name, _href=f'/environment/{env.name}') for env in envs]) @app.route('/environment/') def environment(name): env = model.Environment \ .query \ .where(model.Environment.name == name) \ .one() return flask.render_template( 'environment.html', title=name, env=env) @app.route('/class') def classes(): clss = model.PuppetClass \ .query \ .all() return flask.render_template( 'list.html', title='Classes', items=[div(a(cls.name, _href=f'/class/{cls.name}'), span(_class="count", **{'_data-cls': cls.name})) for cls in clss]) @app.route('/class/') def class_(name): cls = model.PuppetClass \ .query \ .where(model.PuppetClass.name == name) \ .options(joinedload('files').joinedload('environment')) \ .one() return flask.render_template('class.html', title=name, cls=cls) @app.route('/file') def file(): environment = request.args.get('environment') path = request.args.get('path') path_base = '/var/lib/machines/busting/etc/puppetlabs/code/environments/' with open(os.path.join(path_base, environment, path)) as f: content = f.read() return flask.render_template('file.html', title=f'{environment}/{path}', content=content) @app.route('/pdb') def pdb_proxy(): h1 = http.client.HTTPConnection('busting.adrift.space:8080') params = urllib.parse.urlencode({ 'query': request.args.get('query') }) type = request.args.get('type') # h1.request('GET', f'/pdb/query/v4?{params}') h1.request('GET', f'/pdb/query/v4/{type}?{params}') r1 = h1.getresponse() data = r1.read() d = werkzeug.datastructures.Headers() for key, value in r1.headers.items(): d.add(key, value) return flask.Response(response=[data], status=r1.status, headers=d) # API? @app.route('/remove', methods=['POST']) def remove_classes(): print(request.form['fqdn']) print(request.form.getlist('cls')) flash('Classes removed') return redirect(url_for('root_page')) # a /enc route for the classifier might be a good idea return app