Skip to content
Snippets Groups Projects
Commit 00358434 authored by Pavel Kácha's avatar Pavel Kácha
Browse files

Refactored configuration for outside world usage (also simplified and got rid of ugly globals())

parent 91a7f3ee
No related branches found
No related tags found
No related merge requests found
......@@ -1193,7 +1193,95 @@ def fallback_wsgi(environ, start_response, exc_info=None):
return [output]
def build_server(conf):
# Order in which the base objects must get initialized
section_order = ("log", "db", "auth", "validator", "handler", "server")
# List of sections and objects, configured by them
# First object in each object list is the default one, otherwise
# "type" keyword in section may be used to choose other
section_def = {
"log": [FileLogger, SysLogger],
"db": [MySQL],
"auth": [X509Authenticator, PlainAuthenticator, X509NameAuthenticator, X509MixMatchAuthenticator],
"validator": [JSONSchemaValidator, NoValidator],
"handler": [WardenHandler],
"server": [Server]
}
# Object parameter conversions and defaults
param_def = {
FileLogger: {
"req": {"type": "obj", "default": "req"},
"filename": {"type": "filepath", "default": path.join(path.dirname(__file__), path.splitext(path.split(__file__)[1])[0] + ".log")},
"level": {"type": "loglevel", "default": "info"},
},
SysLogger: {
"req": {"type": "obj", "default": "req"},
"socket": {"type": "filepath", "default": "/dev/log"},
"facility": {"type": "facility", "default": "daemon"},
"level": {"type": "loglevel", "default": "info"}
},
PlainAuthenticator: {
"req": {"type": "obj", "default": "req"},
"log": {"type": "obj", "default": "log"},
"db": {"type": "obj", "default": "db"}
},
X509Authenticator: {
"req": {"type": "obj", "default": "req"},
"log": {"type": "obj", "default": "log"},
"db": {"type": "obj", "default": "db"}
},
X509NameAuthenticator: {
"req": {"type": "obj", "default": "req"},
"log": {"type": "obj", "default": "log"},
"db": {"type": "obj", "default": "db"}
},
NoValidator: {
"req": {"type": "obj", "default": "req"},
"log": {"type": "obj", "default": "log"},
},
JSONSchemaValidator: {
"req": {"type": "obj", "default": "req"},
"log": {"type": "obj", "default": "log"},
"filename": {"type": "filepath", "default": path.join(path.dirname(__file__), "idea.schema")}
},
MySQL: {
"req": {"type": "obj", "default": "req"},
"log": {"type": "obj", "default": "log"},
"host": {"type": "str", "default": "localhost"},
"user": {"type": "str", "default": "warden"},
"password": {"type": "str", "default": ""},
"dbname": {"type": "str", "default": "warden3"},
"port": {"type": "natural", "default": 3306},
"retry_pause": {"type": "natural", "default": 5},
"retry_count": {"type": "natural", "default": 3},
"event_size_limit": {"type": "natural", "default": 5*1024*1024},
"catmap_filename": {"type": "filepath", "default": path.join(path.dirname(__file__), "catmap_mysql.json")},
"tagmap_filename": {"type": "filepath", "default": path.join(path.dirname(__file__), "tagmap_mysql.json")}
},
WardenHandler: {
"req": {"type": "obj", "default": "req"},
"log": {"type": "obj", "default": "log"},
"validator": {"type": "obj", "default": "validator"},
"db": {"type": "obj", "default": "DB"},
"auth": {"type": "obj", "default": "auth"},
"send_events_limit": {"type": "natural", "default": 500},
"get_events_limit": {"type": "natural", "default": 1000},
"description": {"type": "str", "default": ""}
},
Server: {
"req": {"type": "obj", "default": "req"},
"log": {"type": "obj", "default": "log"},
"auth": {"type": "obj", "default": "auth"},
"handler": {"type": "obj", "default": "handler"}
}
}
def build_server(conf, section_order=section_order, section_def=section_def, param_def=param_def):
objects = {} # Already initialized objects
# Functions for validation and conversion of config values
def facility(name):
......@@ -1212,93 +1300,20 @@ def build_server(conf):
# Make paths relative to dir of this script
return path.join(path.dirname(__file__), name)
def objdef(name):
def obj(name):
return objects[name.lower()]
obj = objdef # Draw into local namespace for init_obj
objects = {} # Already initialized objects
# List of sections and objects, configured by them
# First object in each object list is the default one, otherwise
# "type" keyword in section may be used to choose other
section_def = {
"log": ["FileLogger", "SysLogger"],
"db": ["MySQL"],
"auth": ["X509Authenticator", "PlainAuthenticator", "X509NameAuthenticator", "X509MixMatchAuthenticator"],
"validator": ["JSONSchemaValidator", "NoValidator"],
"handler": ["WardenHandler"],
"server": ["Server"]
# Typedef dictionary
conv_dict = {
"facility": facility,
"loglevel": loglevel,
"natural": natural,
"filepath": filepath,
"obj": obj,
"str": str
}
# Object parameter conversions and defaults
param_def = {
"FileLogger": {
"req": {"type": obj, "default": "req"},
"filename": {"type": filepath, "default": path.join(path.dirname(__file__), path.splitext(path.split(__file__)[1])[0] + ".log")},
"level": {"type": loglevel, "default": "info"},
},
"SysLogger": {
"req": {"type": obj, "default": "req"},
"socket": {"type": filepath, "default": "/dev/log"},
"facility": {"type": facility, "default": "daemon"},
"level": {"type": loglevel, "default": "info"}
},
"PlainAuthenticator": {
"req": {"type": obj, "default": "req"},
"log": {"type": obj, "default": "log"},
"db": {"type": obj, "default": "db"}
},
"X509Authenticator": {
"req": {"type": obj, "default": "req"},
"log": {"type": obj, "default": "log"},
"db": {"type": obj, "default": "db"}
},
"X509NameAuthenticator": {
"req": {"type": obj, "default": "req"},
"log": {"type": obj, "default": "log"},
"db": {"type": obj, "default": "db"}
},
"NoValidator": {
"req": {"type": obj, "default": "req"},
"log": {"type": obj, "default": "log"},
},
"JSONSchemaValidator": {
"req": {"type": obj, "default": "req"},
"log": {"type": obj, "default": "log"},
"filename": {"type": filepath, "default": path.join(path.dirname(__file__), "idea.schema")}
},
"MySQL": {
"req": {"type": obj, "default": "req"},
"log": {"type": obj, "default": "log"},
"host": {"type": str, "default": "localhost"},
"user": {"type": str, "default": "warden"},
"password": {"type": str, "default": ""},
"dbname": {"type": str, "default": "warden3"},
"port": {"type": natural, "default": 3306},
"retry_pause": {"type": natural, "default": 5},
"retry_count": {"type": natural, "default": 3},
"event_size_limit": {"type": natural, "default": 5*1024*1024},
"catmap_filename": {"type": filepath, "default": path.join(path.dirname(__file__), "catmap_mysql.json")},
"tagmap_filename": {"type": filepath, "default": path.join(path.dirname(__file__), "tagmap_mysql.json")}
},
"WardenHandler": {
"req": {"type": obj, "default": "req"},
"log": {"type": obj, "default": "log"},
"validator": {"type": obj, "default": "validator"},
"db": {"type": obj, "default": "DB"},
"auth": {"type": obj, "default": "auth"},
"send_events_limit": {"type": natural, "default": 500},
"get_events_limit": {"type": natural, "default": 1000},
"description": {"type": str, "default": ""}
},
"Server": {
"req": {"type": obj, "default": "req"},
"log": {"type": obj, "default": "log"},
"auth": {"type": obj, "default": "auth"},
"handler": {"type": obj, "default": "handler"}
}
}
def init_obj(sect_name):
config = conf.get(sect_name, {})
......@@ -1309,17 +1324,21 @@ def build_server(conf):
objtype = config["type"]
del config["type"]
except KeyError: # No, fetch default object type for this section
objtype = sect_def[0]
else:
if not objtype in sect_def:
cls = sect_def[0]
else: # Yes, get corresponding class/callable
names = [o.__name__ for o in sect_def]
try:
idx = names.index(objtype)
except ValueError:
raise KeyError("Unknown type %s in section %s" % (objtype, sect_name))
cls = sect_def[idx]
params = param_def[objtype]
params = param_def[cls]
# No surplus parameters? Disallow also 'obj' attributes, these are only
# to provide default referenced section
for name in config:
if name not in params or (name in params and params[name]["type"] is objdef):
if name not in params or (name in params and params[name]["type"] == "obj"):
raise KeyError("Unknown key %s in section %s" % (name, sect_name))
# Process parameters
......@@ -1327,24 +1346,24 @@ def build_server(conf):
for name, definition in params.iteritems():
raw_val = config.get(name, definition["default"])
try:
val = definition["type"](raw_val)
type_callable = conv_dict[definition["type"]]
val = type_callable(raw_val)
except Exception:
raise KeyError("Bad value \"%s\" for %s in section %s" % (raw_val, name, sect_name))
kwargs[name] = val
cls = globals()[objtype] # get class/function type
try:
obj = cls(**kwargs) # run it
obj_inst = cls(**kwargs) # run it
except Exception as e:
raise KeyError("Cannot initialize %s from section %s: %s" % (
objtype, sect_name, str(e)))
if isinstance(obj, Object):
if isinstance(obj_inst, Object):
# Log only objects here, functions must take care of themselves
logging.getLogger(__name__).info("Initialized %s" % str(obj))
logging.getLogger(__name__).info("Initialized %s" % str(obj_inst))
objects[sect_name] = obj
return obj
objects[sect_name] = obj_inst
return obj_inst
# Init logging with at least simple stderr StreamLogger
# Dunno if it's ok within wsgi, but we have no other choice, let's
......@@ -1356,7 +1375,7 @@ def build_server(conf):
try:
# Now try to init required objects
for o in ("log", "db", "auth", "validator", "handler", "server"):
for o in section_order:
init_obj(o)
except Exception as e:
logging.getLogger(__name__).critical(str(e))
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment