mpenning / ciscoconfparse

Parse, Audit, Query, Build, and Modify Arista / Cisco / Juniper / Palo Alto / F5 configurations.
http://www.pennington.net/py/ciscoconfparse/
GNU General Public License v3.0
793 stars 220 forks source link

F5 "else" statement (junos) #70

Closed petzah closed 4 years ago

petzah commented 7 years ago

if { something } { do X
} else { do Y }

Traceback (most recent call last): File "./test.py", line 4, in parse = CiscoConfParse('file.conf', syntax='junos', debug=True, comment='#') File "/usr/lib/pymodules/python2.7/ciscoconfparse/ciscoconfparse.py", line 225, in init config = self.convert_braces_to_ios(rgx.split(text)) File "/usr/lib/pymodules/python2.7/ciscoconfparse/ciscoconfparse.py", line 351, in convert_braces_to_ios line, line_offset = line_level(tmp.strip()) File "/usr/lib/pymodules/python2.7/ciscoconfparse/ciscoconfparse.py", line 345, in line_level raise ValueError("Could not parse: '{0}'".format(input)) ValueError: Could not parse: '} else {'

kthned commented 7 years ago

Hi Did you get the solution for this ? I am having the similar issue while parsing F5.

timothyfranson commented 7 years ago

After fussing with it for the better part of today I came up with the below solution which finally allowed all my F5 parsing to run without issue. It's not the cleanest solution and I'm sure it can be improved but it works well enough to allow me to accomplish what I set out for. Python 3.5.2.

# Prep F5 config before instantiating the CiscoConfParse instance
import re

clean_conf = []
for line in bigip_conf:
    # the comment kwarg of CiscoConfParse does not work right
    if re.match(r'^(\s*#)', line):
        continue
    # kill empty '{ }' that break the parser
    new_line = line.replace(' { }', '')
    # remove one-line configs.  cause problems with parser
    # example of line removed:  'monitor min 1 of { /some/monitor /some/othermonitor }'
    if re.match(r'^(.+?{)(.+?}\s*)$', new_line):
        continue
    # separate '} else(if) {' lines so parser interprets them properly
    if re.match(r'\s*\}\s+else(if)?', new_line):
        new_line = re.sub(r'\}\s+elseif', '}\nelseif', new_line, count=1)
        new_line = re.sub(r'\}\s+else\s*{', '}\nelse {', new_line, count=1)
        new_line = new_line.split('\n', maxsplit=1)
        clean_conf.extend(new_line)
        continue
    clean_conf.append(new_line)
mpenning commented 6 years ago

Please try version 1.2.52 and see if this helps...

timothyfranson commented 6 years ago

Just gave it a shot, still runs into an issue. Lines like the below would be common in iRules.

File "/var/www/asdf/fetch.py", line 344, in fetch_f5_config parse = CiscoConfParse(bigip_conf, syntax='junos', comment='#') File "/var/www/asdf/venv/lib/python3.5/site-packages/ciscoconfparse/ciscoconfparse.py", line 188, in init config = self.convert_braces_to_ios(config) File "/var/www/asdf/venv/lib/python3.5/site-packages/ciscoconfparse/ciscoconfparse.py", line 402, in convert_braces_to_ios line, line_offset = line_level(tmp.strip()) File "/var/www/asdf/venv/lib/python3.5/site-packages/ciscoconfparse/ciscoconfparse.py", line 396, in line_level raise ValueError("Could not parse: '{0}'".format(input)) ValueError: Could not parse: '} elseif { $path starts_with "/abc" || $path starts_with "/abc/123" } {'

mpenning commented 6 years ago

I don't have access to an F5 anymore... can someone respond with a sanitized F5 config with some else and elseif conditions in it?

timothyfranson commented 6 years ago

Attached below. Very generically sanitized. Ctrl+f for 'if_elseif_rule' for a good example complete with nested if statements.

sanitized_bigip.conf.txt

mpenning commented 4 years ago

@timothyfranson , I finally rewrote the junos parser to support these kind of F5 configs... please test version 1.5.1 and tell me whether this works for you.