U 2g:D@sdZddlZddlZz ddlZWnek r4YnXddlZddlZddlZddlm Z ddl Z ddl m m ZddlmZddlZddlmZmZddlmZdd Zz*Gd d d ejZd d ZeeeWnek rYnXddZddZzejdeej dWnek r(YnXddZ!ddZ"dAddZ#ddZ$ddZ%dBddZ&dCd d!Z'dDd"d#Z(dEd$d%Z)d&d'Z*dFd(d)Z+d*d+Z,d,d-Z-dGd.d/Z.d0d1Z/dHd2d3Z0d4d5Z1dId7d8Z2d9d:Z3d;d<Z4dJd=d>Z5d?d@Z6dS)Ka% This file provides utilities for processing different configuration file formats. Supported formats include: a) YAML b) JSON c) SHELL d) INI e) XML Typical usage involves first loading the config file, then using the dictionary returnded by load_config to make queries. N)dedent)minidom) list_to_str str_to_list) run_commandc Cs$t|d}t|}W5QRX|S)zSafe load a yaml filer)openyamlZ safe_load) config_filefcfgrG/lfs/h1/ops/prod/packages/aqm.v7.0.11/ush/python_utils/config_parser.pyload_yaml_config/s rcs"eZdZdZdfdd ZZS) custom_dumperz.Custom yaml dumper to correct list indentationFcstt||dS)NF)superrincrease_indent)selfZflowZ indentless __class__rrr=szcustom_dumper.increase_indent)FF)__name__ __module__ __qualname____doc__r __classcell__rrrrr:srcCs,t|dkr |jd|ddS|d|S)Nrztag:yaml.org,2002:str|)style)len splitlinesZrepresent_scalar)Zdumperdatarrr str_presenter@sr!cCstj|tdddS)z,Get contents of config file as a yaml stringF)Dumper sort_keysZdefault_flow_style)r dumprr rrrcfg_to_yaml_strKs r&cCs||}ddd|DS)z"Custom tag hangler to join stringscSsg|] }t|qSr)str).0irrr Vszjoin_str..)Zconstruct_sequencejoin)loadernodeseqrrrjoin_strSs r0z !join_str)ZLoadercCs tjj|S)z$A filter for jinja2 that joins paths)ospathr,argrrr path_join_sr5cCstjtj|ddS)zLA filter for jinja2 that gives us a date string for x number of days ago)daysz%Y%m%d00)datetimedatetoday timedeltastrftimer3rrrdays_agoes  r<c s|dkr |}t|tsdS|D]h\}}t|trBt||q"t|tjrXt|jnt|tfdddD}|r"d|krg}n t d}g}|D]}t j t j t jd}t|jd<t|jd <||} z| jf||}Wnnt jjk r} zW5d} ~ XYnHtk r"Yn4tk r6Yn t|d |YnX||qt|tjr~d ||_q"d |||<q"dS) zi Updates yaml_dict inplace by rendering any existing Jinja2 templates that exist in a value. Nc3s|]}|kr|VqdS)Nr)r)ZeleZv_strrr szextend_yaml..){{{%r@z {{[^}]*}}|\S)r-Z undefinedr5r<z: r') isinstancedictitems extend_yamlETElementr(textanyrefindalljinja2Z EnvironmentZ BaseLoaderZStrictUndefinedr5filtersr<Z from_stringZrender exceptionsZUndefinedError TypeErrorZeroDivisionErrorprintappendr,) Z yaml_dictZ full_dictkvZ is_a_templateZ templatesr templateZj2envZj2tmplerr=rrDmsJ         rDc Cs\z$t|d}t|}W5QRXWn2tjk rV}ztd|W5d}~XYnX|S)zLoad json config filerzUnable to load json file N)r jsonloadZJSONDecodeError Exception)r r r rUrrrload_json_configs   rYcCstj|ddddS)z,Get contents of config file as a json stringF)r#indent )rVdumpsr%rrrcfg_to_json_strsr^c Cst|d&}|}|dd}|dd}W5QRXtjtdttd}t|d}| |W5QRXzt ||}W5t |X|S) z:Load shell config file with embedded structure in commentsr# [[z\  z_temp.z.iniw) r readreplacer1r2r,getcwdr(getpidwriteremoveload_ini_config) file_name return_stringfiler Z temp_filerrrload_shell_as_ini_configs  "  rmc Cszt||}|WSYnXt}td|d|d|d}t|\}}}|}i}|D]8}|d} |d| } t|| dd|} | || <q`|S)aLoads old style shell config files. We source the config script in a subshell and gets the variables it sets Args: config_file: path to config file script Returns: dictionary that should be equivalent to one obtained from parsing a yaml file. z! #!/bin/bash t1="./t1.z" t2="./t2.z," (set -o posix; set) > $t1 { . z|; set +x; } &>/dev/null (set -o posix; set) > $t2 diff $t1 $t2 | grep "> " | cut -c 3- rm -rf $t1 $t2 =Nr)rmr1rfrrrfindr) r rkr pidcode_Z config_strlineslidxrRrSrrrload_shell_configs0      rvcCsd}|D]\}}t|tr`|r2|d|}n|}|d|d7}|t||7}|d7}q t|}t|tr||d|d7}q |dd}|dd }||d |d 7}q |S) z2Get contents of config file as shell script stringr'.r_] r\rn'"ra='' )rCrArBcfg_to_shell_strrlistrd)r kname shell_strrRrSn_knamev1rrrr}s"    r}cstj|s ttd|dtt_ |fdd D}| D](\}}| D]\}}t ||||<qfqV|S)zALoad a config file with a format similar to Microsoft's INI fileszS The specified configuration file does not exist: 'rycsi|]}|t|qSr)rBrC)r)sconfigrr <sz#load_ini_config..) r1r2existsFileNotFoundErrorr configparserZRawConfigParserr(Z optionxformrcZsectionsrCr)r rkZ config_dictrrZvsrRrSrrrri-s   ricCs(||krtd|n |||SdS)z0Finds the value of a property in a given sectionzSection not found: N)KeyError)rZsectionkeyrrr get_ini_valueCs rcCsd}|D]\}}t|tr`|r2|d|}n|}|d|d7}|t||7}|d7}q t|d}t|tr||d|d7}q ||d|d 7}q |S) z)Get contents of config file as ini stringr'rwr`rxr\Trnr{r|)rCrArBcfg_to_ini_strrr~)r rZini_strrRrSrrrrrrNs   rcCsJi}|D]<}tt|dkr2t||}|||j<qt|j|||j<q|S)z!Convert an xml tree to dictionaryr)rr~ xml_to_dicttagrrG)rootrkr childrrrrrgs  rcCs`t|}|D]H\}}t|tr:t||}||qt|}t|d|_||q|S)z!Convert dictionary to an xml treeT) rErFrCrArB dict_to_xmlrQrrG)drelemrRrSrrrrrrts       rcCs t|}|}t||}|S)zLoad xml config file)rEparsegetrootr)r rktreerr rrrload_xml_configs  rcCs>t|d}tj|dd}t|}|jdd}|dd}|S)z+Get contents of config file as a xml stringrunicode)encodingz )r[z"rz)rrEtostringrZ parseStringZ toprettyxmlrd)r rrrrrcfg_to_xml_strs     rcCsLi}|D]:\}}|r ||kr t|tr>t|}||q |||<q |S)a"Flatten a recursive dictionary (e.g.yaml/json) to be one level deep Args: dictionary: the source dictionary keys: list of keys on top level whose contents to flatten, if None all of them Returns: A one-level deep dictionary for the selected set of keys )rCrArB flatten_dictupdate) dictionarykeysZ flat_dictrRrSrrrrrs     rcCsTi}|D]B\}}t|tr6t||}|rN|||<q ||kr ||||<q |S)aStructure a dictionary based on a template dictionary Args: dict_o: dictionary to structure (flat one level structure) dict_t: template dictionary used for structuring Returns: A dictionary with contents of dict_o following structure of dict_t )rCrArBstructure_dictr)dict_odict_tZ struct_dictrRrSrrrrrs     rFcCs|D]~\}}t|trFt||tr.)rIcompiler~filtermatchr)rZ keys_regexrrRrrrrr filter_dicts  rcCsrtj|ddd}|dkr*t||S|dkrsf      I   -