aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--build/test/gondul-templating-test.Dockerfile6
-rw-r--r--templating/requirements.txt4
-rwxr-xr-xtemplating/templating.py180
3 files changed, 85 insertions, 105 deletions
diff --git a/build/test/gondul-templating-test.Dockerfile b/build/test/gondul-templating-test.Dockerfile
index 80c09c0..6dabc9c 100644
--- a/build/test/gondul-templating-test.Dockerfile
+++ b/build/test/gondul-templating-test.Dockerfile
@@ -1,7 +1,9 @@
FROM debian:jessie
RUN apt-get update
-RUN apt-get -y install \
- python3-jinja2 \
+RUN apt-get -y install \
+ python3-jinja2 \
+ python3-netaddr \
+ python3-flask \
python3-requests
RUN mkdir -p /opt/gondul
diff --git a/templating/requirements.txt b/templating/requirements.txt
new file mode 100644
index 0000000..20e96a0
--- /dev/null
+++ b/templating/requirements.txt
@@ -0,0 +1,4 @@
+jinja2
+requests
+flask
+netaddr
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)