Working parser

master
Micke Nordin 3 years ago
parent 878b8b6584
commit 8fb9601846
Signed by: micke
GPG Key ID: 0DA0A7A5708FE257

@ -1,7 +1,7 @@
from enum import Enum from enum import Enum
class ObjectType(Enum): class NagObjectType(Enum):
Command = "command" Command = "command"
ContactGroup = "contactgroup" ContactGroup = "contactgroup"
Contact = "contact" Contact = "contact"
@ -17,16 +17,16 @@ class ObjectType(Enum):
Nil = "nil" Nil = "nil"
class Object: class NagObject:
def __init__(self, def __init__(self,
config_file: str = str(), config_file: str = str(),
directives: list[tuple[str, str]] = list(), directives: list[list[str]] = list(),
line_no: int = 0, line_no: int = 0,
type: ObjectType = ObjectType.Nil): type: NagObjectType = NagObjectType.Nil):
self.m_config_file: str = config_file self.m_config_file: str = config_file
self.m_directives: list[tuple[str, str]] = directives self.m_directives: list[list[str]] = directives
self.m_line_no: int = line_no self.m_line_no: int = line_no
self.m_type: ObjectType = type self.m_type: NagObjectType = type
def __str__(self): def __str__(self):
string = "{}:\n\t{}: {}\n".format(self.m_config_file, self.m_line_no, string = "{}:\n\t{}: {}\n".format(self.m_config_file, self.m_line_no,
@ -35,8 +35,8 @@ class Object:
string += "\t\t{}: {}\n".format(dir[0], dir[1]) string += "\t\t{}: {}\n".format(dir[0], dir[1])
return string return string
def get_type(self) -> ObjectType: def get_type(self) -> NagObjectType:
return self.m_type return self.m_type
def get_directives(self) -> list[tuple[str, str]]: def get_directives(self) -> list[list[str]]:
return self.m_directives return self.m_directives

@ -1,7 +1,8 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import re import re
from enum import Enum, auto from enum import Enum, auto
from object import Object, ObjectType from nag_object import NagObject, NagObjectType
class ParserState(Enum): class ParserState(Enum):
DEFINE = auto() DEFINE = auto()
DIRECTIVE = auto() DIRECTIVE = auto()
@ -11,44 +12,44 @@ class ParserState(Enum):
class NagParse: class NagParse:
def __init__(self, config_files: list[str]): def __init__(self, config_files: list[str]):
self.m_config_files: list[str] = config_files self.m_config_files: list[str] = config_files
self.m_commands: list[Object] = list() self.m_commands: list[NagObject] = list()
self.m_contacts: list[Object] = list() self.m_contacts: list[NagObject] = list()
self.m_contactgroups: list[Object] = list() self.m_contactgroups: list[NagObject] = list()
self.m_hosts: list[Object] = list() self.m_hosts: list[NagObject] = list()
self.m_hostdependencies: list[Object] = list() self.m_hostdependencies: list[NagObject] = list()
self.m_hostescalations: list[Object] = list() self.m_hostescalations: list[NagObject] = list()
self.m_hostgroups: list[Object] = list() self.m_hostgroups: list[NagObject] = list()
self.m_services: list[Object] = list() self.m_services: list[NagObject] = list()
self.m_servicedependencies: list[Object] = list() self.m_servicedependencies: list[NagObject] = list()
self.m_serviceescalations: list[Object] = list() self.m_serviceescalations: list[NagObject] = list()
self.m_servicegroups: list[Object] = list() self.m_servicegroups: list[NagObject] = list()
self.m_timeperiods: list[Object] = list() self.m_timeperiods: list[NagObject] = list()
for config_file in self.m_config_files: for config_file in self.m_config_files:
for object in self.parse_config(config_file): for object in self.parse_config(config_file):
match object.m_type: match object.m_type:
case ObjectType.Command: case NagObjectType.Command:
self.m_commands.append(object) self.m_commands.append(object)
case ObjectType.Contact: case NagObjectType.Contact:
self.m_contacts.append(object) self.m_contacts.append(object)
case ObjectType.ContactGroup: case NagObjectType.ContactGroup:
self.m_contactgroups.append(object) self.m_contactgroups.append(object)
case ObjectType.Host: case NagObjectType.Host:
self.m_hosts.append(object) self.m_hosts.append(object)
case ObjectType.HostDependency: case NagObjectType.HostDependency:
self.m_hostdependencies.append(object) self.m_hostdependencies.append(object)
case ObjectType.HostEscalation: case NagObjectType.HostEscalation:
self.m_hostescalations.append(object) self.m_hostescalations.append(object)
case ObjectType.HostGroup: case NagObjectType.HostGroup:
self.m_hostgroups.append(object) self.m_hostgroups.append(object)
case ObjectType.Service: case NagObjectType.Service:
self.m_services.append(object) self.m_services.append(object)
case ObjectType.ServiceDependency: case NagObjectType.ServiceDependency:
self.m_servicedependencies.append(object) self.m_servicedependencies.append(object)
case ObjectType.ServiceEscalation: case NagObjectType.ServiceEscalation:
self.m_serviceescalations.append(object) self.m_serviceescalations.append(object)
case ObjectType.ServiceGroup: case NagObjectType.ServiceGroup:
self.m_servicegroups.append(object) self.m_servicegroups.append(object)
case ObjectType.TimePeriod: case NagObjectType.TimePeriod:
self.m_timeperiods.append(object) self.m_timeperiods.append(object)
def __str__(self): def __str__(self):
string = str() string = str()
@ -78,42 +79,54 @@ class NagParse:
string += str(fragment) + "\n" string += str(fragment) + "\n"
return string return string
def parse_config(self,config_file: str) -> list[Object]: def parse_config(self,config_file: str) -> list[NagObject]:
state = ParserState.DEFINE state = ParserState.DEFINE
objects: list[Object] = list() objects: list[NagObject] = list()
with open(config_file, 'r') as file_handle: with open(config_file, 'r') as file_handle:
line_no = 0 line_no = 0
cur_object = Object(config_file=config_file) cur_object = NagObject(config_file=config_file)
for rawline in file_handle.readlines(): for rawline in file_handle.readlines():
# Clean up the config
line = re.sub(r'([a-z]){', r'\1 {',rawline.strip()) line = re.sub(r'([a-z]){', r'\1 {',rawline.strip())
#line = re.sub(r'([a-zA-Z0-9])}', r'\1\n}',line.strip())
#line = re.sub(r'([a-zA-Z0-9]) }', r'\1\n}',line.strip())
line_no += 1 line_no += 1
if len(line) == 0 or re.match('^#', line): # This means it is a comment, we might want to save those later on
if len(line) == 0 or re.match('^[\t ]*[#]+', line):
continue continue
# This means we are done parsing and should reset for new object
if re.match(r'}', line): if re.match(r'}', line):
objects.append(cur_object) objects.append(cur_object)
cur_object = Object() del cur_object
state = ParserState.DEFINE state = ParserState.DEFINE
continue continue
#if we get here it is not a comment and not the end of an object
fragments: list[str] = re.sub(' +', ' ', line.strip()).split() fragments: list[str] = re.sub(' +', ' ', line.strip()).split()
# This is a new object and we should see what type it is, and what line number it is on
if state == ParserState.DEFINE: if state == ParserState.DEFINE:
if fragments[0] == 'define': if fragments[0] == 'define':
cur_object = NagObject(config_file=config_file, directives=list())
cur_object.m_line_no = line_no cur_object.m_line_no = line_no
cur_object.m_type = ObjectType(fragments[1]) cur_object.m_type = NagObjectType(fragments[1])
state = ParserState.DIRECTIVE # For the next line we should be in DIRECTIVE state
elif state == ParserState.MULTILINE:
cur_object.m_directive[-1:][1] = cur_object.m_directives[-1:][1] + ' ' + " ".join(fragments)
if fragments[-1:][-1:] != '\\':
state = ParserState.DIRECTIVE state = ParserState.DIRECTIVE
else: else:
fragments[-1:][-1:] = '' print("It's fucked up man")
# This is ParserState.DIRECTIVE break
else: # This is the DIRECTIVE state, where we want to collect key, values and find out if we should go to multiline mode
if fragments[-1:][-1:] == '\\': elif state == ParserState.DIRECTIVE:
fragments[-1:][-1:] = '' if fragments[-1][-1] == '\\':
state = ParserState.MULTILINE state = ParserState.MULTILINE
if re.match('^[a-z]+', fragments[0]): if re.match('^[a-z]+', fragments[0]):
cur_object.m_directives.append( cur_object.m_directives.append(
(fragments[0], " ".join(fragments[1:]))) [fragments[0], " ".join(fragments[1:])])
# This is the MULTILINE state, directives can be on many lines if the '\n' is escaped with '\'
elif state == ParserState.MULTILINE:
cur_object.m_directives[-1][1] = cur_object.m_directives[-1][1].strip('\\') + ' ' + " ".join(fragments)
if fragments[-1][-1] != '\\':
state = ParserState.DIRECTIVE
else:
print("It's fucked up man")
break
return objects return objects

@ -1 +0,0 @@
from .object import Object, ObjectType
Loading…
Cancel
Save