1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
|
#!/usr/bin/python3
import argparse
import traceback
import sys
import netaddr
import requests
from flask import Flask, request
from jinja2 import Environment, FileSystemLoader, TemplateNotFound, TemplateError
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"]
objects = {}
def getEndpoint(endpoint: str) -> dict:
"""
Fetches an endpoint and returns the data as a dict.
"""
uri = f"{args.server}/api/{endpoint}"
r = requests.get(uri, timeout=args.timeout)
r.raise_for_status()
return r.json()
def updateData():
for a in endpoints:
objects[a] = getEndpoint(a)
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)[2]
env.filters["getLastDhcpIp"] = lambda ip: netaddr.IPNetwork(ip)[-2]
env.filters["getIp"] = lambda ip,num: netaddr.IPNetwork(ip)[num]
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):
try:
updateData()
template = env.get_template(path)
body = template.render(objects=objects, options=request.args)
except (requests.exceptions.ConnectTimeout, requests.exceptions.ConnectionError) as error:
return f'Timeout or connection error from gondul: {err}', 500
except TemplateNotFound:
return f'Template "{path}" not found\n', 404
except TemplateError 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_exc()}\n', 400
except requests.exceptions.HTTPError as err:
return f'HTTP error from gondul: {err}', 500
except Exception as err:
return f'Uncaught error: {err}', 500
return body, 200
@app.route("/<path>", methods=["POST"])
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 '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_exc()}\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")
parser.add_argument("-s", "--server", type=str, default="http://localhost:80", help="gondul server address")
parser.add_argument("-x", "--timeout", type=int, default=2, help="gondul server timeout")
args = parser.parse_args()
env.loader.searchpath = args.templates
if not sys.argv[1:]:
parser.print_help()
sys.exit(1)
app.run(host=args.host, port=args.port, debug=args.debug)
|