Commit c0e8ffa7 authored by Morten Brekkevold's avatar Morten Brekkevold

augment slack log output with hyperlinks to equipment

parent edf01474
......@@ -6,11 +6,12 @@ NAVs liste over hva som skal overvåkes.
"""
from __future__ import division
import copy
import os
import socket
from collections import defaultdict
import logging
from operator import attrgetter
from operator import attrgetter, itemgetter
import requests
import argparse
......@@ -20,7 +21,9 @@ from slack_log_handler import SlackLogHandler
from kindnavsync.navapi import NAVAPI, ObjectNotFound
KIND_SERVICE_URL = "https://kind.cs.uninett.no/autoregister/utstyr_eksport.json"
KIND_SERVICE_URL = "https://kind.uninett.no/autoregister/utstyr_eksport.json"
KIND_UTSTYR_URL = "https://kind.uninett.no/utstyr/edit_utstyr.html?id={id}"
NAV_BOX_URL = "https://uninav.uninett.no/ipdevinfo/{sysname}/"
NAV_API_URL = "http://localhost/api/1"
DEFAULT_SNMP_COMMUNITY = 'public'
......@@ -110,11 +113,34 @@ def initlogging(debug=False, no_timestamps=False):
webhook_url = os.getenv('SLACK_URL')
if webhook_url:
slack_handler = SlackLogHandler(webhook_url)
slack_format = logging.Formatter('*%(levelname)s*: %(message)s')
slack_handler.setFormatter(slack_format)
slack_handler.setFormatter(SlackFormatter())
LOG.addHandler(slack_handler)
class SlackFormatter(logging.Formatter):
"""Add hyperlinks to some information when logging to Slack"""
def __init__(self):
super(SlackFormatter, self).__init__('*%(levelname)s*: %(message)s')
def format(self, record):
newargs = tuple(self._format_arg(arg) for arg in record.args)
newrecord = copy.copy(record) # don't screw up the record for other formatters
newrecord.args = newargs
return super(SlackFormatter, self).format(newrecord)
@classmethod
def _format_arg(cls, arg):
if isinstance(arg, (KindDevice, NAVBox)):
return "<{url}|{text}>".format(url=arg.get_absolute_url(),
text=str(arg))
elif (isinstance(arg, list) and
any(isinstance(i, (KindDevice, NAVBox)) for i in arg)):
newarg = [cls._format_arg(i) for i in arg]
return '\n'.join(" • {}".format(s) for s in newarg)
else:
return arg
def get_kind_data():
LOG.debug("Henter data fra %s", KIND_SERVICE_URL)
return requests.get(KIND_SERVICE_URL).json()
......@@ -141,20 +167,21 @@ def find_duplicates(names):
def clean_data(kind_data):
kind_devices = [KindDevice.from_json_record(record) for record in kind_data]
invalid_names = {device.name for device in kind_devices
invalid_names = {device for device in kind_devices
if not device_name_is_okay(device.name)}
if invalid_names:
LOG.error("Ignorerer følgende utstyr som ikke har gyldige navn i Kind: "
"%r", sorted(invalid_names))
LOG.error("Ignorerer følgende utstyr som ikke har gyldige navn i Kind:"
"\n%s", sorted(invalid_names, key=attrgetter('name')))
no_nettinstallasjon = {device.name for device in kind_devices
no_nettinstallasjon = {device for device in kind_devices
if not device.room}
if no_nettinstallasjon:
LOG.error("Ignorerer følgende utstyr som ikke har nettinstallasjon "
"satt i Kind: %r", sorted(no_nettinstallasjon))
"satt i Kind:\n%s",
sorted(no_nettinstallasjon, key=attrgetter('name')))
return {device.name: device for device in kind_devices
if device.name not in (invalid_names | no_nettinstallasjon)}
if device not in (invalid_names | no_nettinstallasjon)}
def device_name_is_okay(name):
......@@ -252,6 +279,19 @@ class NAVBox(dict):
def __hash__(self):
return hash(self.id)
def get_absolute_url(self):
if 'sysname' in self:
return NAV_BOX_URL.format(sysname=self['sysname'])
def __str__(self):
if 'sysname' in self:
return self['sysname']
else:
return super(NAVBox, self).__str__()
def __repr__(self):
return str(self)
def update_nav(kind_devices, api_url, api_token, dry_run=False):
kind_by_ip = {ip: dev
......@@ -276,14 +316,14 @@ def update_nav(kind_devices, api_url, api_token, dry_run=False):
if can_be_deleted(n)]
if matched_netboxes:
LOG.debug("Utstyr som allerede ligger i NAV:\n %s",
"\n ".join(sorted(n['sysname'] for n in matched_netboxes)))
LOG.debug("Utstyr som allerede ligger i NAV:\n%s",
sorted(matched_netboxes, key=itemgetter('sysname')))
if unmatched_kind_devices:
LOG.info("Utstyr som skal inn i NAV:\n %s",
"\n ".join(sorted(str(d) for d in unmatched_kind_devices)))
LOG.info("Utstyr som skal inn i NAV:\n%s",
sorted(unmatched_kind_devices, key=str))
if unmatched_netboxes:
LOG.info("Utstyr som skal ut av NAV:\n %s",
"\n ".join(sorted(n['sysname'] for n in unmatched_netboxes)))
LOG.info("Utstyr som skal ut av NAV:\n%s",
sorted(unmatched_netboxes, key=itemgetter('sysname')))
if not dry_run:
remove_from_nav(nav_api, unmatched_netboxes)
......@@ -424,6 +464,10 @@ class KindDevice(object):
splitname[0] += '-l0'
return ['.'.join(splitname), '%s.uninett.no' % splitname[0], self.name]
def get_absolute_url(self):
if self.id:
return KIND_UTSTYR_URL.format(id=self.id)
if __name__ == '__main__':
main()
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment