Skip to content

Commit b40c526

Browse files
committed
config: T2636: get_config_dict() returns a list on multi node by default
Unless no_multi_convert is True, a single valued multi node will be returned as a list by get_config_dict(). Modification of Thomas Mangin's version.
1 parent bab1534 commit b40c526

File tree

4 files changed

+60
-26
lines changed

4 files changed

+60
-26
lines changed

python/vyos/config.py

Lines changed: 37 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@
6767
import json
6868
from copy import deepcopy
6969

70+
import vyos.xml
7071
import vyos.util
7172
import vyos.configtree
7273
from vyos.configsource import ConfigSource, ConfigSourceSession
@@ -193,50 +194,62 @@ def show_config(self, path=[], default=None, effective=False):
193194
"""
194195
return self._config_source.show_config(path, default, effective)
195196

196-
def get_cached_dict(self, effective=False):
197+
def get_cached_root_dict(self, effective=False):
197198
cached = self._dict_cache.get(effective, {})
198199
if cached:
199-
config_dict = cached
200+
return cached
201+
202+
if effective:
203+
config = self._running_config
200204
else:
201-
config_dict = {}
205+
config = self._session_config
202206

203-
if effective:
204-
if self._running_config:
205-
config_dict = json.loads((self._running_config).to_json())
206-
else:
207-
if self._session_config:
208-
config_dict = json.loads((self._session_config).to_json())
207+
if config:
208+
config_dict = json.loads(config.to_json())
209+
else:
210+
config_dict = {}
209211

210-
self._dict_cache[effective] = config_dict
212+
self._dict_cache[effective] = config_dict
211213

212214
return config_dict
213215

214-
def get_config_dict(self, path=[], effective=False, key_mangling=None, get_first_key=False):
216+
def get_config_dict(self, path=[], effective=False, key_mangling=None,
217+
get_first_key=False, no_multi_convert=False):
215218
"""
216219
Args:
217220
path (str list): Configuration tree path, can be empty
218221
effective=False: effective or session config
219222
key_mangling=None: mangle dict keys according to regex and replacement
220223
get_first_key=False: if k = path[:-1], return sub-dict d[k] instead of {k: d[k]}
224+
no_multi_convert=False: if convert, return single value of multi node as list
221225
222226
Returns: a dict representation of the config under path
223227
"""
224-
config_dict = self.get_cached_dict(effective)
228+
lpath = self._make_path(path)
229+
root_dict = self.get_cached_root_dict(effective)
230+
conf_dict = vyos.util.get_sub_dict(root_dict, lpath, get_first_key)
225231

226-
config_dict = vyos.util.get_sub_dict(config_dict, self._make_path(path), get_first_key)
232+
if not key_mangling and no_multi_convert:
233+
return deepcopy(conf_dict)
227234

228-
if key_mangling:
229-
if not (isinstance(key_mangling, tuple) and \
230-
(len(key_mangling) == 2) and \
231-
isinstance(key_mangling[0], str) and \
232-
isinstance(key_mangling[1], str)):
233-
raise ValueError("key_mangling must be a tuple of two strings")
234-
else:
235-
config_dict = vyos.util.mangle_dict_keys(config_dict, key_mangling[0], key_mangling[1])
236-
else:
237-
config_dict = deepcopy(config_dict)
235+
xmlpath = lpath if get_first_key else lpath[:-1]
238236

239-
return config_dict
237+
if not key_mangling:
238+
conf_dict = vyos.xml.multi_to_list(xmlpath, conf_dict)
239+
return conf_dict
240+
241+
if no_multi_convert is False:
242+
conf_dict = vyos.xml.multi_to_list(xmlpath, conf_dict)
243+
244+
if not (isinstance(key_mangling, tuple) and \
245+
(len(key_mangling) == 2) and \
246+
isinstance(key_mangling[0], str) and \
247+
isinstance(key_mangling[1], str)):
248+
raise ValueError("key_mangling must be a tuple of two strings")
249+
250+
conf_dict = vyos.util.mangle_dict_keys(conf_dict, key_mangling[0], key_mangling[1])
251+
252+
return conf_dict
240253

241254
def is_multi(self, path):
242255
"""

python/vyos/configdiff.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,8 @@ class ConfigDiff(object):
8282
"""
8383
def __init__(self, config, key_mangling=None):
8484
self._level = config.get_level()
85-
self._session_config_dict = config.get_cached_dict()
86-
self._effective_config_dict = config.get_cached_dict(effective=True)
85+
self._session_config_dict = config.get_cached_root_dict(effective=False)
86+
self._effective_config_dict = config.get_cached_root_dict(effective=True)
8787
self._key_mangling = key_mangling
8888

8989
# mirrored from Config; allow path arguments relative to level

python/vyos/xml/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ def defaults(lpath, flat=False):
5151
return load_configuration().defaults(lpath, flat)
5252

5353

54+
def multi_to_list(lpath, conf):
55+
return load_configuration().multi_to_list(lpath, conf)
56+
57+
5458
if __name__ == '__main__':
5559
print(defaults(['service'], flat=True))
5660
print(defaults(['service'], flat=False))

python/vyos/xml/definition.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,23 @@ def _flatten(inside, index, d):
281281

282282
return _flatten(lpath, len(lpath), d)
283283

284+
def multi_to_list(self, lpath, conf):
285+
r = {}
286+
for k in conf:
287+
# key mangling could also be done here
288+
# it would prevent two parsing of the config tree
289+
# under = k.replace('-','_')
290+
under = k
291+
fpath = lpath + [k]
292+
if isinstance(conf[k],dict):
293+
r[under] = self.multi_to_list(fpath, conf[k])
294+
continue
295+
value = conf[k]
296+
if self.is_multi(fpath) and not isinstance(value, list):
297+
value = [value]
298+
r[under] = value
299+
return r
300+
284301
# from functools import lru_cache
285302
# @lru_cache(maxsize=100)
286303
# XXX: need to use cachetool instead - for later

0 commit comments

Comments
 (0)