Compare commits

..

7 commits

4 changed files with 110 additions and 22 deletions

41
error.html Normal file
View file

@ -0,0 +1,41 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>${title}</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="bootstrap.min.css">
<link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>🔥</text></svg>">
</head>
<body>
<div class="container">
<div class="page-header my-5" id="banner">
<div class="row">
<div class="col-lg-8">
<h1>Status: 🔥</h1>
</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="card text-white border-primary mb-3">
<div class="card-header d-flex justify-content-between align-items-center">
<h4>Something went wrong</h4>
</div>
<div class="card-body">
<p>
There was an error rendering the status page.
Admins have been notified.
</p>
</div>
</div>
</div>
</div>
</div>
<script type="text/javascript">
window.setTimeout(function() {
window.location.reload();
}, 10000);
</script>
</body>
</html>

View file

@ -1,2 +1,3 @@
Mako
tomlkit
requests

View file

@ -1,29 +1,39 @@
#!/usr/bin/env python3
import requests
import urllib3
import logging
import shutil
import sys
from datetime import datetime
from os import environ
import requests
import tomlkit
import urllib3
from mako.template import Template
urllib3.disable_warnings()
CONFIGFILE = environ.get('STATUSPAGE_CONFIG', 'config.toml')
class StatusPage:
def get_api_result(self):
if self.services:
log.debug('services already exist, returning early')
return self.services
headers = {
'Accept': 'application/json',
'X-HTTP-Method-Override': 'GET'
}
headers = {'Accept': 'application/json', 'X-HTTP-Method-Override': 'GET'}
requestbody = {
"attrs": [ "name", "state", "last_check_result", "host_name", "display_name" ],
"joins": [ "host.name", "host.state", "host.last_check_result", "host.vars" ],
"attrs": [
"name",
"state",
"last_check_result",
"host_name",
"display_name",
],
"joins": ["host", "host.state", "host.last_check_result", "host.vars"],
"filter": self.config['filters']['services'],
}
@ -31,17 +41,24 @@ class StatusPage:
'{}/v1/objects/services'.format(self.config['icinga2_api']['baseurl']),
headers=headers,
json=requestbody,
auth=(self.config['icinga2_api']['username'], self.config['icinga2_api']['password']),
verify=False
auth=(
self.config['icinga2_api']['username'],
self.config['icinga2_api']['password'],
),
verify=False,
)
if (r.status_code == 200):
self.logger.info(f'got http status code {r.status_code}')
self.logger.debug(r.text)
if r.status_code == 200:
self.services = r.json()['results']
else:
r.raise_for_status()
return self.services
self.logger.info(f'got {len(self.services)} services from api')
return self.services
def prettify(self, text):
for search, replace in self.config.get('prettify', {}).items():
@ -49,7 +66,6 @@ class StatusPage:
return text
def get_services_per_host(self):
state_to_design_mapping = [
('success', 'OK'),
@ -60,6 +76,11 @@ class StatusPage:
result = {}
for service in self.get_api_result():
self.logger.info(
f'now processing {service["attrs"]["host_name"]} "{service["attrs"]["display_name"]}"'
)
self.logger.debug(service)
host = service['joins']['host']['vars']['pretty_name']
if host not in result:
@ -80,14 +101,16 @@ class StatusPage:
if state in (1, 2):
self.ragecounter += state
result[host]['services'][self.prettify(service['attrs']['display_name'])] = {
result[host]['services'][
self.prettify(service['attrs']['display_name'])
] = {
'badge': state_to_design_mapping[state][0],
'state': state_to_design_mapping[state][1],
}
self.logger.info(f'ragecounter is now {self.ragecounter}')
return result
def render_html(self, service_details):
if self.ragecounter == 0:
mood = '🆗'
@ -96,27 +119,45 @@ class StatusPage:
else:
mood = '🔥'
template = Template(filename=self.config['output'].get('template', 'template.html'))
self.logger.info('rendering output html')
start = datetime.now()
template = Template(
filename=self.config['output'].get('template', 'template.html')
)
output = template.render(
title=self.config['output'].get('page_title', 'Status Page'),
mood=mood,
hosts=service_details,
)
end = datetime.now()
self.logger.info(f'rendered in {(end-start).total_seconds():.09f}s')
with open(self.config['output']['filename'], 'w') as f:
f.write(output)
def __init__(self):
self.config = tomlkit.loads(open(CONFIGFILE).read())
self.services = {}
self.ragecounter = 0
self.logger = logging.getLogger('StatusPage')
handler = logging.StreamHandler(sys.stdout)
formatter = logging.Formatter(
'%(levelname)s {%(filename)s:%(lineno)d} %(message)s'
)
handler.setFormatter(formatter)
self.logger.addHandler(handler)
self.logger.setLevel(self.config.get('loglevel', 'INFO'))
if __name__ == "__main__":
page = StatusPage()
service_details = page.get_services_per_host()
from pprint import pprint
pprint(service_details)
page.render_html(service_details)
try:
service_details = page.get_services_per_host()
page.render_html(service_details)
except Exception as e:
shutil.copyfile('error.html', page.config['output']['filename'])
raise e

View file

@ -39,5 +39,10 @@
</div>
% endfor
</div>
<script type="text/javascript">
window.setTimeout(function() {
window.location.reload();
}, 30000);
</script>
</body>
</html>