]>
git.proxmox.com Git - mirror_frr.git/blob - tests/topotests/munet/config.py
1 # -*- coding: utf-8 eval: (blacken-mode 1) -*-
2 # SPDX-License-Identifier: GPL-2.0-or-later
4 # June 25 2022, Christian Hopps <chopps@gmail.com>
6 # Copyright (c) 2021-2022, LabN Consulting, L.L.C.
8 """A module that defines common configuration utility functions."""
11 from collections
.abc
import Iterable
12 from copy
import deepcopy
13 from typing
import overload
16 def find_with_kv(lst
, k
, v
):
19 if k
in e
and e
[k
] == v
:
24 def find_all_with_kv(lst
, k
, v
):
28 if k
in e
and e
[k
] == v
:
33 def find_matching_net_config(name
, cconf
, oconf
):
34 p
= find_all_with_kv(oconf
.get("connections", {}), "to", name
)
38 rname
= cconf
.get("remote-name", None)
42 return find_with_kv(p
, "name", rname
)
45 def merge_using_key(a
, b
, k
):
46 # First get a dict of indexes in `a` for the key value of `k` in objects of `a`
48 mi
= {o
[k
]: i
for i
, o
in enumerate(m
)}
59 def list_to_dict_with_key(lst
, k
):
60 """Convert a YANG styl list of objects to dict of objects.
62 This function converts a YANG style list of objects (dictionaries) to a plain python
63 dictionary of objects (dictionaries). The value for the supplied key for each
64 object is used to store the object in the new diciontary.
66 This only works for lists of objects which are keyed on a single contained value.
69 lst: a *list* of python dictionary objects.
70 k: the key value contained in each dictionary object in the list.
73 A dictionary of objects (dictionaries).
75 return {x
[k
]: x
for x
in (lst
if lst
else [])}
78 def config_to_dict_with_key(c
, ck
, k
):
79 """Convert the config item from a list of objects to dict.
81 Use :py:func:`list_to_dict_with_key` to convert the list of objects
82 at ``c[ck]`` to a dict of the objects using the key ``k``.
86 ck: The key identifying the list of objects from ``c``.
87 k: The key to pass to :py:func:`list_to_dict_with_key`.
90 A dictionary of objects (dictionaries).
92 c
[ck
] = list_to_dict_with_key(c
.get(ck
, []), k
)
97 def config_subst(config
: str, **kwargs
) -> str:
102 def config_subst(config
: Iterable
, **kwargs
) -> Iterable
:
106 def config_subst(config
: Iterable
, **kwargs
) -> Iterable
:
107 if isinstance(config
, str):
108 if "%RUNDIR%/%NAME%" in config
:
109 config
= config
.replace("%RUNDIR%/%NAME%", "%RUNDIR%")
111 "config '%RUNDIR%/%NAME%' should be changed to '%RUNDIR%' only, "
112 "converting automatically for now."
114 for name
, value
in kwargs
.items():
115 config
= config
.replace(f
"%{name.upper()}%", str(value
))
116 elif isinstance(config
, Iterable
):
118 return {k
: config_subst(config
[k
], **kwargs
) for k
in config
}
119 except (KeyError, TypeError):
120 return [config_subst(x
, **kwargs
) for x
in config
]
124 def value_merge_deepcopy(s1
, s2
):
125 """Merge values using deepcopy.
127 Create a deepcopy of the result of merging the values from dicts ``s1`` and ``s2``.
128 If a key exists in both ``s1`` and ``s2`` the value from ``s2`` is used."
131 for k
, v
in s1
.items():
133 d
[k
] = deepcopy(s2
[k
])
139 def merge_kind_config(kconf
, config
):
140 mergekeys
= kconf
.get("merge", [])
141 config
= deepcopy(config
)
142 new
= deepcopy(kconf
)
147 if k
not in mergekeys
:
149 elif isinstance(new
[k
], list):
150 new
[k
].extend(config
[k
])
151 elif isinstance(new
[k
], dict):
152 new
[k
] = {**new
[k
], **config
[k
]}
161 def cli_opt_list(option_list
):
164 if isinstance(option_list
, str):
165 return [x
for x
in option_list
.split(",") if x
]
166 return [x
for x
in option_list
if x
]
169 def name_in_cli_opt_str(name
, option_list
):
170 ol
= cli_opt_list(option_list
)
171 return name
in ol
or "all" in ol
174 class ConfigOptionsProxy
:
175 """Proxy options object to fill in for any missing pytest config."""
178 """An object that returns None for any attribute access."""
180 def __getattr__(self
, attr
):
183 def __init__(self
, pytestconfig
=None):
184 if isinstance(pytestconfig
, ConfigOptionsProxy
):
185 self
.config
= pytestconfig
.config
186 self
.option
= self
.config
.option
188 self
.config
= pytestconfig
190 self
.option
= self
.config
.option
192 self
.option
= ConfigOptionsProxy
.DefNoneObject()
194 def getoption(self
, opt
, default
=None):
199 value
= self
.config
.getoption(opt
)
200 return value
if value
is not None else default
204 def get_option(self
, opt
, default
=None):
205 return self
.getoption(opt
, default
)
207 def get_option_list(self
, opt
):
208 value
= self
.get_option(opt
, "")
209 return cli_opt_list(value
)
211 def name_in_option_list(self
, name
, opt
):
212 optlist
= self
.get_option_list(opt
)
213 return "all" in optlist
or name
in optlist