From 8fb960184628dd6c7b2da3289aab5bb6520400cc Mon Sep 17 00:00:00 2001 From: Micke Nordin Date: Mon, 28 Mar 2022 10:01:36 +0200 Subject: [PATCH] Working parser --- src/__pycache__/nagparse.cpython-39.pyc | Bin 1840 -> 0 bytes src/{object/object.py => nag_object.py} | 16 ++-- src/nagparse.py | 99 ++++++++++++++---------- src/object/__init__.py | 1 - 4 files changed, 64 insertions(+), 52 deletions(-) delete mode 100644 src/__pycache__/nagparse.cpython-39.pyc rename src/{object/object.py => nag_object.py} (73%) delete mode 100644 src/object/__init__.py diff --git a/src/__pycache__/nagparse.cpython-39.pyc b/src/__pycache__/nagparse.cpython-39.pyc deleted file mode 100644 index 729003a582d37e955f51042456b73d692c372046..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1840 zcmZuyL5~|X6t+E{$t0WIrY)_yRgr=~NMS`6!~ui=t!Nk6ON1x_F{q4YV`q1^nMu|& zL25d4O1Z!RegKE$$e-ZIg@529oXUxF50vjY8(3N<@$-AO=h^S`_ueF%n=OXtyIKqp!gluYd(TE*6#@`_w#9HWilFqc^ohGBzjPc;o2DkS=IOy-&=Iw(|_HTW9 z@Y()P%n%+;}X-CdHL_$RclrVkDIhi~{SwKN=724G4zyLpr&*g;rdLP`qL>EBTzE z7bU5?i<^74aa+DUOZD+AcjUJTg*ShF&D+@gu z{tJTvEf`^%=4lzn+q824!4PA}XIt)&H`mkuIW2+QKy#;k3yR_kobLo@J`qb%Q}5ko zcW>090tA>7%G)L>x7kv>$!dOjwIag!{aNEd{dV_3-I|5XGtGtf$i*maFdUmKDa|If zF&9W&gy?zZ5;_|o>@+{J9wL1@v_>3bHjbai!XkuVyu(}kI-hN>V{`NUo^O228j9Xf zT!t>(5IfKLbo?RAOdEnG&nOW}H}VW62&Fw*)`eJ8LVH?je;bJXC=^h6D3Lmnkg#Dt zIdY6g`ZR|r$W5HKfzjpEi3VdEr;p)w$Fh5tpNoR5K%#**kL>?6T27Z@( zD3

v)Ly0`K|J>I-v2@xmS_F?^FAHj%p?Go1;$UmtJQ-@FIMTargTIvho0Gt8ck+ zbTZEYu9@iWJmy^>u7}8**^39=Bn` z#kzOdCBGpunGS@NBv&Jho|S^AIhdOGkV*^{ zf?P+ z+LJ)EF@|d42@(GFvNyZ3X7J7Pe*3+~)A_Z9O&ov@IUqQANsN=>)w|J>Q|oz++4J$lQPgphYS9e=C+H{7d<&;S4c diff --git a/src/object/object.py b/src/nag_object.py similarity index 73% rename from src/object/object.py rename to src/nag_object.py index 2d0fab1..1e70396 100644 --- a/src/object/object.py +++ b/src/nag_object.py @@ -1,7 +1,7 @@ from enum import Enum -class ObjectType(Enum): +class NagObjectType(Enum): Command = "command" ContactGroup = "contactgroup" Contact = "contact" @@ -17,16 +17,16 @@ class ObjectType(Enum): Nil = "nil" -class Object: +class NagObject: def __init__(self, config_file: str = str(), - directives: list[tuple[str, str]] = list(), + directives: list[list[str]] = list(), line_no: int = 0, - type: ObjectType = ObjectType.Nil): + type: NagObjectType = NagObjectType.Nil): 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_type: ObjectType = type + self.m_type: NagObjectType = type def __str__(self): 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]) return string - def get_type(self) -> ObjectType: + def get_type(self) -> NagObjectType: return self.m_type - def get_directives(self) -> list[tuple[str, str]]: + def get_directives(self) -> list[list[str]]: return self.m_directives diff --git a/src/nagparse.py b/src/nagparse.py index 3763fa3..849ddd4 100644 --- a/src/nagparse.py +++ b/src/nagparse.py @@ -1,7 +1,8 @@ #!/usr/bin/env python3 import re from enum import Enum, auto -from object import Object, ObjectType +from nag_object import NagObject, NagObjectType + class ParserState(Enum): DEFINE = auto() DIRECTIVE = auto() @@ -11,44 +12,44 @@ class ParserState(Enum): class NagParse: def __init__(self, config_files: list[str]): self.m_config_files: list[str] = config_files - self.m_commands: list[Object] = list() - self.m_contacts: list[Object] = list() - self.m_contactgroups: list[Object] = list() - self.m_hosts: list[Object] = list() - self.m_hostdependencies: list[Object] = list() - self.m_hostescalations: list[Object] = list() - self.m_hostgroups: list[Object] = list() - self.m_services: list[Object] = list() - self.m_servicedependencies: list[Object] = list() - self.m_serviceescalations: list[Object] = list() - self.m_servicegroups: list[Object] = list() - self.m_timeperiods: list[Object] = list() + self.m_commands: list[NagObject] = list() + self.m_contacts: list[NagObject] = list() + self.m_contactgroups: list[NagObject] = list() + self.m_hosts: list[NagObject] = list() + self.m_hostdependencies: list[NagObject] = list() + self.m_hostescalations: list[NagObject] = list() + self.m_hostgroups: list[NagObject] = list() + self.m_services: list[NagObject] = list() + self.m_servicedependencies: list[NagObject] = list() + self.m_serviceescalations: list[NagObject] = list() + self.m_servicegroups: list[NagObject] = list() + self.m_timeperiods: list[NagObject] = list() for config_file in self.m_config_files: for object in self.parse_config(config_file): match object.m_type: - case ObjectType.Command: + case NagObjectType.Command: self.m_commands.append(object) - case ObjectType.Contact: + case NagObjectType.Contact: self.m_contacts.append(object) - case ObjectType.ContactGroup: + case NagObjectType.ContactGroup: self.m_contactgroups.append(object) - case ObjectType.Host: + case NagObjectType.Host: self.m_hosts.append(object) - case ObjectType.HostDependency: + case NagObjectType.HostDependency: self.m_hostdependencies.append(object) - case ObjectType.HostEscalation: + case NagObjectType.HostEscalation: self.m_hostescalations.append(object) - case ObjectType.HostGroup: + case NagObjectType.HostGroup: self.m_hostgroups.append(object) - case ObjectType.Service: + case NagObjectType.Service: self.m_services.append(object) - case ObjectType.ServiceDependency: + case NagObjectType.ServiceDependency: self.m_servicedependencies.append(object) - case ObjectType.ServiceEscalation: + case NagObjectType.ServiceEscalation: self.m_serviceescalations.append(object) - case ObjectType.ServiceGroup: + case NagObjectType.ServiceGroup: self.m_servicegroups.append(object) - case ObjectType.TimePeriod: + case NagObjectType.TimePeriod: self.m_timeperiods.append(object) def __str__(self): string = str() @@ -78,42 +79,54 @@ class NagParse: string += str(fragment) + "\n" return string - def parse_config(self,config_file: str) -> list[Object]: + def parse_config(self,config_file: str) -> list[NagObject]: state = ParserState.DEFINE - objects: list[Object] = list() + objects: list[NagObject] = list() with open(config_file, 'r') as file_handle: line_no = 0 - cur_object = Object(config_file=config_file) + cur_object = NagObject(config_file=config_file) 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-zA-Z0-9])}', r'\1\n}',line.strip()) + #line = re.sub(r'([a-zA-Z0-9]) }', r'\1\n}',line.strip()) 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 + # This means we are done parsing and should reset for new object if re.match(r'}', line): objects.append(cur_object) - cur_object = Object() + del cur_object state = ParserState.DEFINE 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() + + # 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 fragments[0] == 'define': + cur_object = NagObject(config_file=config_file, directives=list()) cur_object.m_line_no = line_no - cur_object.m_type = ObjectType(fragments[1]) - state = ParserState.DIRECTIVE - elif state == ParserState.MULTILINE: - cur_object.m_directive[-1:][1] = cur_object.m_directives[-1:][1] + ' ' + " ".join(fragments) - if fragments[-1:][-1:] != '\\': + cur_object.m_type = NagObjectType(fragments[1]) + # For the next line we should be in DIRECTIVE state state = ParserState.DIRECTIVE else: - fragments[-1:][-1:] = '' - # This is ParserState.DIRECTIVE - else: - if fragments[-1:][-1:] == '\\': - fragments[-1:][-1:] = '' + print("It's fucked up man") + break + # This is the DIRECTIVE state, where we want to collect key, values and find out if we should go to multiline mode + elif state == ParserState.DIRECTIVE: + if fragments[-1][-1] == '\\': state = ParserState.MULTILINE if re.match('^[a-z]+', fragments[0]): 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 diff --git a/src/object/__init__.py b/src/object/__init__.py deleted file mode 100644 index fda6ad4..0000000 --- a/src/object/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from .object import Object, ObjectType