From 1bef81de3ec67933fdbf39a963a9f5fd0d1fa0a4 Mon Sep 17 00:00:00 2001 From: Rick Date: Wed, 14 Oct 2020 00:57:28 +0200 Subject: [PATCH] Add python script, cli and guit --- cli.py | 41 +++++++++++++++++++ controllers/controller.py | 36 +++++++++++++++++ gui.py | 36 +++++++++++++++++ juniper-config-to-set.php | 85 --------------------------------------- parser.py | 64 +++++++++++++++++++++++++++++ views/principal.ui | 78 +++++++++++++++++++++++++++++++++++ 6 files changed, 255 insertions(+), 85 deletions(-) create mode 100644 cli.py create mode 100644 controllers/controller.py create mode 100644 gui.py delete mode 100644 juniper-config-to-set.php create mode 100644 parser.py create mode 100644 views/principal.ui diff --git a/cli.py b/cli.py new file mode 100644 index 0000000..6efd4f5 --- /dev/null +++ b/cli.py @@ -0,0 +1,41 @@ +########## +# IMPORT # +########## +import argparse +from os.path import exists, isfile +from parser import ParserJuniper + +__author__ = "rick@gnous.eu" +__licence__ = "GPL3" + +parserJuniper = ParserJuniper() +parserArg = argparse.ArgumentParser( + description="Parse a Juniper conf file and print the series of set commands for." + ) +parserArg.add_argument("-f", "--file", nargs=1, required=True, type=str, help="The conf file.") +parserArg.add_argument("-o", "--output", nargs=1, type=str, help="The output file.") + +arg = parserArg.parse_args() + +inputFile = str(arg.file[0]) +outputFile = None +if arg.output: + outputFile = str(arg.output[0]) + if exists(outputFile) and isfile(outputFile): + writeOverFile = input("The file already exists, write over it ? o/O") + if writeOverFile.lower() != 'o': + print("STOP EVERYTHING!!!!!!!!!!!!!") + exit(0) + elif exists(outputFile): + print("The output musts be a file.") + exit(0) + +if exists(inputFile) and isfile(inputFile): + parseResul = parserJuniper.parseFile(inputFile) + if outputFile: + with open(outputFile, 'w') as file: + file.write(parseResul) + else: + print(parseResul) +else: + print("Pass an existing file.") diff --git a/controllers/controller.py b/controllers/controller.py new file mode 100644 index 0000000..df54de3 --- /dev/null +++ b/controllers/controller.py @@ -0,0 +1,36 @@ +########## +# IMPORT # +########## +from PyQt5.QtWidgets import QTextEdit, QTextBrowser +from parser import ParserJuniper + +__author__ = "rick@gnous.eu" +__licence__ = "GPL3" + +class Controller: + def __init__(self, inputText, outputText): + """ + Init the controller + + :param inputText QTextEdit: the area where Juniper conf in write + :param outputText QTextBrowser: area where a series of set + command is showed + """ + self.inputText = inputText + self.outputText = outputText + self.parser = ParserJuniper() + + def click(self): + """ + Called when the user press the Parse button. + Gets the text of inputText and parse it. Shows the result on + outputText. + """ + self.parser.resetTree() + textToParse = self.inputText.toPlainText() + parsedText = "" + for line in textToParse.splitlines(): + textConf = self.parser.parse(line) + if textConf: + parsedText += textConf + "\n" + self.outputText.setText(parsedText) diff --git a/gui.py b/gui.py new file mode 100644 index 0000000..03c7429 --- /dev/null +++ b/gui.py @@ -0,0 +1,36 @@ +########## +# IMPORT # +########## +from sys import argv +from PyQt5 import uic +from PyQt5.QtWidgets import QMainWindow, QApplication, QPushButton, QTextEdit,\ + QTextBrowser +from controllers.controller import Controller + +__author__ = "rick@gnous.eu" +__licence__ = "GPL3" + +class Interface(QMainWindow): + def __init__(self): + super(Interface, self).__init__() + + self.setWindowTitle("Parser Juniper") + self.ui = uic.loadUi("views/principal.ui") + self.setCentralWidget(self.ui) + + inputText = self.ui.findChildren(QTextEdit, "inputText")[0] + outputText = self.ui.findChildren(QTextBrowser, "outputText")[0] + parseButton = self.ui.findChildren(QPushButton, "parse")[0] + quitButton = self.ui.findChildren(QPushButton, "quit")[0] + + self.controller = Controller(inputText, outputText) + + parseButton.clicked.connect(self.controller.click) + quitButton.clicked.connect(quit) + + self.show() + +if __name__ == "__main__": + app = QApplication(argv) + window = Interface() + exit(app.exec_()) diff --git a/juniper-config-to-set.php b/juniper-config-to-set.php deleted file mode 100644 index 171e677..0000000 --- a/juniper-config-to-set.php +++ /dev/null @@ -1,85 +0,0 @@ -#!/usr/bin/php - $strlen) return false; - return substr_compare($string, $test, $strlen - $testlen, $testlen) === 0; -} - -function addtotree($tree,$word) { - array_push($tree,$word); - return $tree; -} - -function removewordfromtree($tree) { - array_pop($tree); - return $tree; -} - -function printtree($tree) { - return implode(" ",$tree); -} - -$tree=array(); - -while($line = fgets(STDIN)){ - - // Skip any commented lines - if(strpos($line,'#')===0) { - continue; - } - - // Trim white space from the line - $line=trim($line); - - // Trim inline comments from the line - if(preg_match('/; ##/',$line)==1) { - list($line,$comment)=preg_split('/; ##/',$line); - $line .= ";"; - } - - // What remains is a series of tests to see what the line ends with. - - // This test matches a ';' character which means its a leaf and we can output the whole line to STDOUT - if(endswith($line,';')) { - - // Trim the semi-colon from the end of the line, we don't need that. - $line = rtrim($line,';'); - - //Test to see if the tree is empty, if it is then we'll just print the leaf and not the tree - //to avoid excess white spaces - if(count($tree)==0) { - echo "set $line\n"; - } else { - echo "set " . printtree($tree) . " $line\n"; - } - } - - // This test matches a '{' character on the end of the line and means we need to add a branch to the tree - if(endswith($line,'{')) { - $line = rtrim($line,' {'); - $tree=addtotree($tree,$line); - } - - // This test matches a '}' character on the end of the line and means we need to remove the last branch that we added to the tree - if(endswith($line,'}')) { - $tree=removewordfromtree($tree); - } -} - -?> diff --git a/parser.py b/parser.py new file mode 100644 index 0000000..c4befe6 --- /dev/null +++ b/parser.py @@ -0,0 +1,64 @@ +# Tom Price writes the program in PHP here : https://github.com/pgnuta/juniper-config-to-set +# I adapt it in Python and add some enhancements +__author__ = "Tim Price | rick@gnous.eu" +__licence__ = "GPL3" + +class ParserJuniper: + def __init__(self): + self.tree = [] + + def resetTree(self): + self.tree = [] + + def printTree(self, tree): + return ''.join(map(str, tree)) + + def parse(self, line): + """ + Parse a line of conf + + :param line str: line will be parse + :ret str: a parse string, empty if its a comment + """ + ret = "" + line = line.strip() + if not line.startswith('#'): + if '#' in line: + line, comment = line.split('#', 1) + line = line.strip() + + if line.endswith(';'): + line = line[:-1] + + if not self.tree: + ret = "set " + line + else: + ret = "set " + self.printTree(self.tree) + line + + if line.endswith('{'): + line = line[:-1] + self.tree.append(line) + + if line.endswith('}'): + self.tree.pop() + + return ret + + def parseFile(self, path): + """ + parse a file and return the commands + + :param path str: the path to file + :ret str: the series of set commands + """ + ret = "" + with open(path, 'r') as file: + self.resetTree() + for line in file: + lineConf = self.parse(line) + if lineConf: + ret += lineConf + "\n" + return ret + +#parser = ParserJuniper() +#parser.parseFile("test") diff --git a/views/principal.ui b/views/principal.ui new file mode 100644 index 0000000..1c12d34 --- /dev/null +++ b/views/principal.ui @@ -0,0 +1,78 @@ + + + MainWindow + + + + 0 + 0 + 800 + 550 + + + + MainWindow + + + + + + 20 + 20 + 361 + 391 + + + + + + + 420 + 430 + 131 + 41 + + + + Parse ! + + + + + + 420 + 20 + 351 + 391 + + + + + + + 250 + 430 + 131 + 41 + + + + Quit + + + + + + + 0 + 0 + 800 + 20 + + + + + + + +