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
106
107
108
109
110
111
112
113
|
#!/usr/bin/python
import sys
try:
import cjson
except ImportError:
print "Warning: skipping audit log verification because the cjson module" \
" is unavailable"
sys.exit(0)
from collections import defaultdict
from optparse import OptionParser
class Parser(object):
DEFAULTS = {int:0,
str:'',
list:[]}
def __init__(self, defconf=None):
self.defaults = None
if defconf is not None:
self.defaults = self.flatten(defconf)
def run(self, logs, verbose=None):
result = self.parse(logs)
if len(result) != len(self.defaults):
diff = set(self.defaults.keys()).difference(result.keys())
print 'Test failed.'
print 'The following attributes were not set:'
for it in diff:
print it
sys.exit(1)
def flatten(self, defaults):
"""
Flattens pathes to attributes.
Parameters
----------
defaults : a dictionaries populated with default values
Returns :
dict : with flattened attributes
"""
result = dict()
for path,value in self._walk(defaults):
if path in result:
print 'Warning: attribute path %s already exists' % path
result[path] = value
return result
def parse(self, logs):
result = defaultdict(list)
for msg in logs:
# each message is treated as a dictionary of dictionaries
for a,v in self._walk(msg):
# see if path is registered in defaults
if a in self.defaults:
dv = self.defaults.get(a)
if dv is None:
# determine default value by type
if v is not None:
dv = self.DEFAULTS[type(v)]
else:
print 'Warning: attribute %s is set to None' % a
continue
# by now we have default value
if v != dv:
# test passed
result[a].append(v)
return result
def _walk(self, adict):
"""
Generator that works through dictionary.
"""
for a,v in adict.iteritems():
if isinstance(v,dict):
for (attrpath,u) in self._walk(v):
yield (a+'.'+attrpath,u)
else:
yield (a,v)
if __name__ == '__main__':
parser = OptionParser()
parser.add_option("-i", "--logfile", dest="filename",
help="input log file in json fmt", metavar="FILE")
parser.add_option("-d", "--defaults", dest="defaults",
help="dictionary with defaults", metavar="FILE")
(options, args) = parser.parse_args()
if options.filename is not None:
with open(options.filename, 'r') as f:
content = list()
for l in f:
content.append(cjson.decode(l.rstrip()))
f.close()
else:
print 'Input file in jason format is required'
exit()
defaults = None
if options.defaults is not None:
with open(options.defaults, 'r') as f:
defaults = cjson.decode(f.read())
f.close()
# run test
p = Parser(defaults)
p.run(content)
exit()
|