Source code for nettoolkit.pyJuniper.hierarchy

# -----------------------------------------------------------------------------
# IMPORTS
# -----------------------------------------------------------------------------
from collections import OrderedDict

from .hierarchy_rules import *
from nettoolkit.nettoolkit_common.gpl import STR, IO

# # -- Enablebelow - only if Max Recursion depth reach.
# import sys
# sys.setrecursionlimit(10**5)


[docs] def mysplit(line, by=" "): """ split line by (default space), also retain the strings like descriptions as it is. Args: line (str): string line by (character, optional): Split by option. Defaults to " ". Returns: list: split line and return list """ spl = line.split(by) for item in description_strings: if item in spl: s1 = spl[:spl.index(item)+1] s2 = " ".join(spl[spl.index(item)+1:]) s1.append(s2) return s1 return spl
[docs] def li_li_words(in_str): """ converts multiline string in to list of list of words. Args: in_str (str): Multiline string Returns: list: list of list of words. """ return [[w for w in mysplit(line[4:])] for line in in_str.split('\n')]
[docs] def section_dict(in_list, word, full_review=False): """ create section dectionary from given input list for the selected word. Args: in_list (list, str): Input list or string word (str): selected word for which list to be search up on and generate dictionary full_review (bool, optional): go thru full list if set to true, else only check first match only. Defaults to False. Raises: NotImplementedError: Unmatched input type for input. Returns: dict: dictionary with key equal input word and value as list of words from matched suffixes. """ section_config_dict = OrderedDict() section_config_dict[word] = [] if isinstance(in_list, str): in_list = li_li_words(in_list) elif isinstance(in_list, (list, tuple)): pass else: raise NotImplementedError for line in in_list: section_config_list = [] add_to = False for i, w in enumerate(line): wordCheck = i == 0 if wordCheck and w == word: add_to = True continue elif wordCheck and w != word: if not full_review: break if add_to: section_config_list.append(w) if add_to: section_config_dict[word].append(section_config_list) else: if not full_review: break return section_config_dict
[docs] def zero_items(in_list): """ Return all Zero (0) indexed Items from list of lists Args: in_list (list): input list of lists Returns: list: all 0-index items from list of lists """ _zi = [] for item_zero in in_list: if item_zero[0] not in _zi: _zi.append(item_zero[0]) return _zi
[docs] def recursive_item_lookup(lili_words): """ create and yields dictionary/list from provided list of list of words. Args: lili_words (list): input list of list of words Yields: dict: yields dictionary item/value pairs """ for ezi in zero_items(lili_words): nv = related_list(lili_words, ezi) ns_dic = section_dict(nv, ezi) yield ns_dic
[docs] def excluded(dic, members, member_key): """Checks for matching key from provided dictionary (dic) in to members dictionary's member_key, returns True if found any. Args: dic ([type]): input dictionary for which keys to be searched in to members dictinary members members ([type]): members dicationary to be looked in to. member_key (str): member key to be looked in to members dictionary Returns: bool: True if any excluded member found, None Else """ if member_key in members: for k in dic.keys(): if k in members[member_key]: return True
[docs] def included(dic, members, member_key): """Checks for matching key from provided dictionary (dic) in to members dictionary's member_key, returns True if found or member_key not found in members dict. Args: dic ([type]): input dictionary for which keys to be searched in to members dictinary members members ([type]): members dicationary to be looked in to. member_key (str): member key to be looked in to members dictionary Returns: bool: True if any excluded member found or member_key not in members, False Else """ if member_key in members: for k in dic.keys(): if k in members[member_key]: return True return False else: return True
[docs] class Section(): """Configuration Section Creator""" def __init__(self, in_list, ordered=False): """Section Object Initializer Args: in_list (list): list of list ordered (bool, optional): Section Dictionary to be ordered or unordered. Defaults to False. """ self.lst = in_list self.dic = OrderedDict() if not ordered: self.dic = {} self.add(ordered)
[docs] def add(self, ordered): """add the key value to self.dic go thru recursive lookup for dictionary tree Args: ordered (bool): dictionary to be ordered or not """ try: for dic in recursive_item_lookup(self.lst): if isinstance(dic, OrderedDict): for k, v in dic.items(): s = Section(v, ordered=ordered) self.dic[k] = s.dic except: pass
[docs] class Convert(): """Converts Dicationary to Hierarchical config string Args: dic (dict): dictionary tabs (int): front tabs is_tailed (bool, optional): tailed config. Defaults to True. is_grouped (bool, optional): grouped config. Defaults to False. is_distributed (bool, optional): distributed config. Defaults to False. is_straight (bool, optional): straight config. Defaults to False. is_straight_anyway (bool, optional): straight anyway config. Defaults to False. parent_prefix (str, optional): parent prefix. Defaults to ''. """ def __init__(self, dic, tabs, is_tailed=True, is_grouped=False, is_distributed=False, is_straight=False, is_straight_anyway=False, parent_prefix = '', test=False ): """Initializer """ self.dic = dic self.tabs = tabs self.is_tailed = is_tailed self.is_grouped = is_grouped self.is_distributed = is_distributed self.is_straight = is_straight self.is_straight_anyway = is_straight_anyway self.parent_prefix = parent_prefix self.test = test self.s = '' self.tab = ' ' self.front_tabs = self.tabs self.convert def __str__(self): return self.s @property def front_tabs(self): return self._front_tabs @front_tabs.setter def front_tabs(self, tabs): self._front_tabs = f'{self.tab*tabs}'
[docs] def add_to_str(self, s): self.s += s
[docs] def update_front_tabs(self, n): """update front tab value with add of n Args: n (int): adds n to tabs """ self.tabs += n self.front_tabs = self.tabs
[docs] def update_prefix(self, k): """update prefix value to k Args: k (str): key to be added """ if self.parent_prefix: self.prefix = self.front_tabs + self.parent_prefix + " " + k else: self.prefix = self.front_tabs + k if self.is_tailed or self.is_straight: self.prefix = self.parent_prefix + " " + k if self.is_distributed: pfx_list = self.prefix.split()[-1] if pfx_list[-1] != k: self.prefix = self.front_tabs + self.parent_prefix + " " + k
@property def convert(self): """ start Converting dictionary to config string. Returns: None: None """ if len(self.dic) == 0: return None for dic_key, dic_value in self.dic.items(): self.exception(dic_key) self.update_prefix(dic_key) if isinstance(dic_value, (dict, OrderedDict)): self.update_front_tabs(1) self.update_prefix(dic_key) if self.logic_terminators(dic_key, dic_value): pass elif self.logic_groups(dic_key, dic_value): pass self.update_front_tabs(-1) self.closure # - LOGICS -----------------------------------------------------
[docs] def exception(self, dic_key): """Exceptional identifiex configurations - Add more as found any Args: dic_key (str): key to be found in set line """ if self.tabs == -1: if dic_key == 'policy-options': # candidates_not_expand_in_anycase.clear() candidates_not_expand_if_single.clear() candidates_not_expand_if_single.add('from') candidates_not_expand_if_single.add('then') candidates_not_expand_if_single.add('community') elif dic_key =='firewall': # candidates_not_expand_in_anycase.clear() candidates_not_expand_if_single.clear() candidates_not_expand_if_single.add('then') elif dic_key =='class-of-service': # candidates_not_expand_in_anycase.clear() candidates_not_expand_if_single.clear() candidates_not_expand_if_single.add('class') else: candidates_not_expand_if_single.clear()
# candidates_not_expand_in_anycase.clear()
[docs] def logic_terminators(self, dic_key, dic_value): """line terminators selector logic Args: dic_key (str): string key to be pass on to selector logic dic_value (dic): dictionary for the key to be pass on to selector logic Returns: bool: Returns True if any terminator logic matches found else None """ # if self.test : print(dic_key) # if self.is_straight: print(dic_key) # ex: destination-port [ <"telnet tacacs ldap 636"> ]; if self.is_grouped: self.clubbed_candidate_terminator_lines(dic_key, dic_value) return True # ex: <"community add blue;\n community add yellow;\n ...."> elif self.is_distributed: self.distributed_candidate_terminator_lines(dic_key, dic_value) return True # Terminators elif not dic_value : # ex: <"ip-protocol tcp;"> # ex: <"0.0.0.0/0;"> self.terminator_line return True
[docs] def logic_groups(self, dic_key, dic_value): """section group selector logic Args: dic_key (str): string key to be pass on to selector logic dic_value (dic): dictionary for the key to be pass on to selector logic """ # if self.test : print(dic_key) # if self.is_straight: print(dic_key) if dic_key == "community": self.test = True if False: pass elif (len(dic_value) == 1 and (self.is_straight or dic_key in candidates_not_expand_if_single) ): self.grp_candidate_straight(dic_key, dic_value) # elif (self.is_straight_anyway # or dic_key in candidates_not_expand_in_anycase # ): # self.grp_candidate_straight_anyway(dic_key, dic_value) # ex: <"destination-port"> [ telnet tacacs ldap 636 ]; elif dic_key in candidates_can_club_members: self.grp_candidates_clubbed(dic_key, dic_value) # ex: <"community add blue;\n community add yellow;\n ...."> elif (dic_key in candidates_distributed_to_multi_lines and not excluded(dic_value, candidates_distributed_to_multi_lines_exclude, dic_key) and included(dic_value, candidates_distributed_to_multi_lines_include, dic_key) ): self.grp_candidates_distributed(dic_key, dic_value) # ex: <"term"> al_att_forward_class2_protocol_seq_100 { elif (dic_key in candidates_require_suffix and not excluded(dic_value, candidates_require_suffix_exclude_members, dic_key) and included(dic_value, candidates_require_suffix_include_members, dic_key) ): self.grp_has_suffix_candidate(dic_key, dic_value) # ex: term <"al_att_forward_class2_protocol_seq_100"> { elif self.is_tailed: self.grp_suffixes(dic_key, dic_value) # ex: <"ip-source-address"> { else: self.grp_nested(dic_key, dic_value)
# - CLOSURES ----------------------------------------------------- @property def closure(self): """Append Section closure to string """ if not self.is_tailed and not self.is_grouped: s = self.front_tabs + "}\n" self.add_to_str(s) # - TERMINATORS ----------------------------------------------------- @property def terminator_line(self): s = self.prefix + ";\n" self.add_to_str(s)
[docs] def clubbed_candidate_terminator_lines(self, dic_key, dic_value): """Clubbed candidates terminator words getting added to string Args: dic_key (str): key/string to be added to config dic_value (dict): sub-section config (if any) """ # if self.test : print(dic_key) sObj = Convert(dic_value, self.tabs, is_tailed=True, is_grouped=True) s = dic_key + " " + str(sObj) self.add_to_str(s)
[docs] def distributed_candidate_terminator_lines(self, dic_key, dic_value): """Distributed terminator candidate words getting added to string Args: dic_key (str): key/string to be added to config dic_value (dict): sub-section config (if any) """ # if self.test : print(dic_key) for k, v in dic_value.items(): s = self.prefix + " " + k + ";\n" self.add_to_str(s)
# - GROUPS ----------------------------------------------------- """ Args: dic_key (str): key/string to be added to config dic_value (dict): sub-section config (if any) Returns: None: None """
[docs] def grp_candidate_straight(self, dic_key, dic_value): """group config, which has straight candidate Args: dic_key (str): key/string to be added to config dic_value (dict): sub-section config (if any) """ # if self.test : print(self.is_straight, dic_key) sObj = Convert(dic_value, self.tabs, is_tailed=True, is_straight=self.is_straight) # if self.test: print(">", self.prefix, sObj.s) s = self.prefix + str(sObj) self.add_to_str(s)
# def grp_candidate_straight_anyway(self, dic_key, dic_value): # s = dic_key # for k, v in dic_value.items(): # # print(k) # sObj = Convert(v, self.tabs, is_tailed=True, is_straight_anyway=self.is_straight_anyway, test=self.test) # s += "X" + k + "\n" # self.add_to_str(self.prefix + s)
[docs] def grp_has_suffix_candidate(self, dic_key, dic_value): """group config, which has suffix candidate. Args: dic_key (str): key/string to be added to config dic_value (dict): sub-section config (if any) """ # if self.test : print(self.is_straight, dic_key) if len(dic_value) > 1: sObj = Convert(dic_value, self.tabs, is_tailed=True, parent_prefix=self.prefix) s = str(sObj) else: sObj = Convert(dic_value, self.tabs, is_tailed=True) s = self.prefix + str(sObj) self.add_to_str(s)
[docs] def grp_suffixes(self, dic_key, dic_value): """group config Args: dic_key (str): key/string to be added to config dic_value (dict): sub-section config (if any) """ # if self.test : print(dic_key) self.update_front_tabs(-1) sObj = Convert(dic_value, self.tabs, is_tailed=False) s = self.prefix + " {\n"+ str(sObj) self.add_to_str(s) self.update_front_tabs(1)
[docs] def grp_candidates_clubbed(self, dic_key, dic_value): """clubbed group config Args: dic_key (str): key/string to be added to config dic_value (dict): sub-section config (if any) """ # if self.test : print(dic_key) sObj = Convert(dic_value, self.tabs, is_tailed=True, is_grouped=True) if dic_value.get("") and len(dic_value[""]) > 1: s = self.prefix + " ["+ str(sObj) + "];\n" else: s = self.prefix + " "+ str(sObj)[:-1] + ";\n" self.add_to_str(s)
[docs] def grp_candidates_distributed(self, dic_key, dic_value): """Distributed group config Args: dic_key (str): key/string to be added to config dic_value (dict): sub-section config (if any) """ # if self.test : print(dic_key) pp = self.parent_prefix + dic_key sObj = Convert(dic_value, self.tabs-1, is_tailed=True, is_distributed=True, parent_prefix=pp) s = str(sObj) self.add_to_str(s)
# DEFAUT AT END
[docs] def grp_nested(self, dic_key, dic_value): """nested group config Args: dic_key (str): key/string to be added to config dic_value (dict): sub-section config (if any) """ # ELSE AFTER ALL grp matches # if self.test : print(dic_key) sObj = Convert(dic_value, self.tabs, is_tailed=False) s = self.prefix + " {\n"+ str(sObj) self.add_to_str(s)
[docs] class Hierarchy(): """Hierarchical config conversion Args: input_file (str): input set config file output_file (str): output file """ def __init__(self, input_file, output_file): """Object initializer """ self.input_file = input_file self.output_file = output_file
[docs] def convert(self): """convert input file """ section = self._gen_section_dict( IO.file_to_str(self.input_file) ) self._conv_dict_to_hierarchy(section)
def _gen_section_dict(self, input_file_lst): return Section(li_li_words(input_file_lst), ordered=False) def _conv_dict_to_hierarchy(self, section): self.output = str(Convert(section.dic, -1, is_tailed=False))
# ------------------------------------------------------------------------------ if __name__ == '__main__': pass # ------------------------------------------------------------------------------