aboutsummaryrefslogtreecommitdiffstats
path: root/templating/templating.py
diff options
context:
space:
mode:
authorMorten Linderud <morten@linderud.pw>2019-01-21 23:11:51 +0100
committerMorten Linderud <morten@linderud.pw>2019-01-21 23:40:32 +0100
commitd4cd5cfac3c3c4028575114708eb551d25e1933e (patch)
treef9bcf4d5a1a6b63e46cfd6f62f6780962a8874b3 /templating/templating.py
parent4f9cd6706692eb6b1a000efb37cfe76e202e6d07 (diff)
Added slight rewrite of template webserver
Moved to flask for more "free" things. Possibly easier to extend in the future. Added argparser so we are able to define settings from the command line.
Diffstat (limited to 'templating/templating.py')
-rwxr-xr-xtemplating/templating.py180
1 files changed, 77 insertions, 103 deletions
diff --git a/templating/templating.py b/templating/templating.py
index fff5d42..9584fe3 100755
--- a/templating/templating.py
+++ b/templating/templating.py
@@ -1,115 +1,89 @@
-#!/usr/bin/env python3
+#!/usr/bin/python3
+
+import argparse
+import traceback
+import sys
-import requests,traceback
-from jinja2 import Template,Environment,FileSystemLoader,TemplateNotFound
-import json
import netaddr
-import http.server
-from enum import Enum
+import requests
+
+from flask import Flask, request
+from jinja2 import Environment, FileSystemLoader, TemplateNotFound
endpoints = "read/networks read/oplog read/snmp read/switches-management public/distro-tree public/config public/dhcp public/dhcp-summary public/ping public/switches public/switch-state".split()
-objects = dict()
+
+objects = {}
+
def getEndpoint(endpoint):
- r = requests.get("http://localhost:80/api/%s" % endpoint)
- if (r.status_code != 200):
- raise Exception("Bad status code for endpoint %s: %s" % (endpoint, r.status_code))
+ r = requests.get(f"http://localhost:80/api/{endpoint}")
+ if r.status_code != 200:
+ raise Exception(f"Bad status code for endpoint {endpoint}: {r.status_code}")
return r.json()
+
def updateData():
for a in endpoints:
objects[a] = getEndpoint(a)
-def netmask(ip):
- return netaddr.IPNetwork(ip).netmask
-def cidr(ip):
- return netaddr.IPNetwork(ip).prefixlen
-def networkId(ip):
- return netaddr.IPNetwork(ip).ip
-def getFirstDhcpIp(ip):
- return netaddr.IPNetwork(ip)[3]
-def getLastDhcpIp(ip):
- return netaddr.IPNetwork(ip)[-1]
-def getDistro(src):
- return src.split(":")[0]
-def getPort(src):
- return src.split(":")[1]
-def getFirstFapIp(ip):
- return netaddr.IPNetwork(ip)[netaddr.IPNetwork(ip).size/2]
-
-env = Environment(loader=FileSystemLoader(['templates/','/opt/gondul/data/templates', '/opt/gondul/web/templates']), trim_blocks=True)
-
-env.filters["netmask"] = netmask
-env.filters["cidr"] = cidr
-env.filters["networkId"] = networkId
-env.filters["getFirstDhcpIp"] = getFirstDhcpIp
-env.filters["getLastDhcpIp"] = getLastDhcpIp
-env.filters["agentDistro"] = getDistro
-env.filters["agentPort"] = getPort
-env.filters["getFirstFapIP"] = getFirstFapIp
-
-class Mode(Enum):
- Get = 1
- Post = 2
-
-class MyHandler(http.server.BaseHTTPRequestHandler):
-
- options = dict()
-
- def parse_options(self):
- self.url = self.path[1:]
- self.options = dict()
- if self.url.find("?") != -1:
- (self.url, tmpoptions) = self.url.split("?")
- tmptuples = tmpoptions.split("&")
- for a in tmptuples:
- (x,y) = a.split("=")
- self.options[x] = y
-
- def generic(self, mode):
- updateData()
- self.parse_options()
- body = ""
- try:
- if mode == Mode.Get:
- template = env.get_template(self.url)
- elif mode == Mode.Post:
- length = self.headers.get('content-length')
- if not length:
- length = 0
- content = self.rfile.read(int(length)).decode('UTF-8')
- template = env.from_string(content)
- else:
- raise Exception("Invalid mode")
-
- body = template.render(objects=objects, options=self.options)
- self.send_response(200)
- except TemplateNotFound as err:
- body = "Template \"%s\" not found\n" % self.url
- self.send_response(404)
- except Exception as err:
- body = ("Templating of \"%s\" failed to render. Most likely due to an error in the template. Error transcript:\n\n%s\n----\n\n%s\n" % (self.url, err, traceback.format_exc()))
- if mode == Mode.Get:
- self.send_response(400)
- else:
- self.send_response(500)
- finally:
- self.send_header('Cache-Control','max-age=5, s-maxage=1')
- body = body.encode('UTF-8')
- self.send_header('Content-Length', int(len(body)))
- self.end_headers()
- self.wfile.write(body)
- self.wfile.flush()
-
- def do_GET(self):
- self.generic(Mode.Get)
-
- def do_POST(self):
- self.generic(Mode.Post)
-
-def run(server_class=http.server.HTTPServer, handler_class=http.server.BaseHTTPRequestHandler):
- server_address = ('localhost', 8081)
- httpd = server_class(server_address, handler_class)
- httpd.serve_forever()
-
-run(handler_class=MyHandler)
+
+env = Environment(loader=FileSystemLoader([]), trim_blocks=True)
+
+env.filters["netmask"] = lambda ip: netaddr.IPNetwork(ip).netmask
+env.filters["cidr"] = lambda ip: netaddr.IPNetwork(ip).prefixlen
+env.filters["networkId"] = lambda ip: netaddr.IPNetwork(ip).ip
+env.filters["getFirstDhcpIp"] = lambda ip: netaddr.IPNetwork(ip)[3]
+env.filters["getLastDhcpIp"] = lambda ip: netaddr.IPNetwork(ip)[-1]
+env.filters["agentDistro"] = lambda src: src.split(":")[0]
+env.filters["agentPort"] = lambda src: src.split(":")[1]
+env.filters["getFirstFapIP"] = lambda ip: netaddr.IPNetwork(ip)[netaddr.IPNetwork(ip).size / 2]
+
+app = Flask(__name__)
+
+
+@app.after_request
+def add_header(response):
+ if response.status_code == 200:
+ response.cache_control.max_age = 5
+ response.cache_control.s_maxage = 1
+ return response
+
+
+@app.route("/<path>", methods=["GET"])
+def root_get(path):
+ updateData()
+ try:
+ template = env.get_template(path)
+ body = template.render(objects=objects, options=request.args)
+ except TemplateNotFound:
+ return f'Template "{path}" not found\n', 404
+ except Exception as err:
+ return f'Templating of "{path}" failed to render. Most likely due to an error in the template. Error transcript:\n\n{err}\n----\n\n{traceback.format_exe()}\n', 400
+ return body, 200
+
+
+@app.route("/<path>", methods=["POST", "PUT"])
+def root_post(path):
+ updateData()
+ try:
+ content = request.stream.read(int(request.headers["Content-Length"]))
+ template = env.from_string(content.decode("utf-8"))
+ body = template.render(objects=objects, options=request.args)
+ except Exception as err:
+ return f'Templating of "{path}" failed to render. Most likely due to an error in the template. Error transcript:\n\n{err}\n----\n\n{traceback.format_exe()}\n', 400
+ return body, 200
+
+
+parser = argparse.ArgumentParser(description="Process templates for gondul.", add_help=False)
+parser.add_argument("-t", "--templates", type=str, nargs="+", help="location of templates")
+parser.add_argument("-h", "--host", type=str, default="127.0.0.1", help="host address")
+parser.add_argument("-p", "--port", type=int, default=8080, help="host port")
+parser.add_argument("-d", "--debug", action="store_true", help="enable debug mode")
+
+args = parser.parse_args()
+env.loader.searchpath = args.templates
+
+if not sys.argv[1:]:
+ parser.print_help()
+
+app.run(host=args.host, port=args.port, debug=args.debug)