nso_verify handle leaf-list in 4.5 and identityref (#37393)

NSO verify did not handle leaf-list value verification in 4.5 and
later due to changes made for configuration writing made.

map prefix for identityref types in verification.
This commit is contained in:
Claes Nästén 2018-03-20 11:01:36 +01:00 committed by John R Barker
commit 6308047dc9
4 changed files with 51 additions and 26 deletions

View file

@ -320,15 +320,16 @@ class ValueBuilder(object):
return 'Value<path={0}, state={1}, value={2}>'.format(
self.path, self.state, self.value)
def __init__(self, client):
def __init__(self, client, mode='config'):
self._client = client
self._mode = mode
self._schema_cache = {}
self._module_prefix_map_cache = None
self._values = []
self._values_dirty = False
def build(self, parent, maybe_qname, value, schema=None):
qname, name = self._get_prefix_name(maybe_qname)
qname, name = self.get_prefix_name(maybe_qname)
if name is None:
path = parent
else:
@ -349,16 +350,16 @@ class ValueBuilder(object):
self._add_value(path, State.PRESENT, None, deps)
else:
if maybe_qname is None:
value_type = self._get_type(path)
value_type = self.get_type(path)
else:
value_type = self._get_child_type(parent, qname)
if 'identityref' in value_type:
if isinstance(value, list):
value = [ll_v for ll_v, t_ll_v
in [self._get_prefix_name(v) for v in value]]
in [self.get_prefix_name(v) for v in value]]
else:
value, t_value = self._get_prefix_name(value)
value, t_value = self.get_prefix_name(value)
self._add_value(path, State.SET, value, deps)
elif isinstance(value, dict):
self._build_dict(path, schema, value)
@ -440,7 +441,7 @@ class ValueBuilder(object):
def _build_dict(self, path, schema, value):
keys = schema.get('key', [])
for dict_key, dict_value in value.items():
qname, name = self._get_prefix_name(dict_key)
qname, name = self.get_prefix_name(dict_key)
if dict_key in ('__state', ) or name in keys:
continue
@ -449,16 +450,25 @@ class ValueBuilder(object):
def _build_leaf_list(self, path, schema, value):
deps = schema.get('deps', [])
entry_type = self._get_type(path, schema)
# remove leaf list if treated as a list and then re-create the
# expected list entries.
self._add_value(path, State.ABSENT, None, deps)
entry_type = self.get_type(path, schema)
for entry in value:
if 'identityref' in entry_type:
entry, t_entry = self._get_prefix_name(entry)
entry_path = '{0}{{{1}}}'.format(path, entry)
self._add_value(entry_path, State.PRESENT, None, deps)
if self._mode == 'verify':
for entry in value:
if 'identityref' in entry_type:
entry, t_entry = self.get_prefix_name(entry)
entry_path = '{0}{{{1}}}'.format(path, entry)
if not self._client.exists(entry_path):
self._add_value(entry_path, State.ABSENT, None, deps)
else:
# remove leaf list if treated as a list and then re-create the
# expected list entries.
self._add_value(path, State.ABSENT, None, deps)
for entry in value:
if 'identityref' in entry_type:
entry, t_entry = self.get_prefix_name(entry)
entry_path = '{0}{{{1}}}'.format(path, entry)
self._add_value(entry_path, State.PRESENT, None, deps)
def _build_list(self, path, schema, value):
deps = schema.get('deps', [])
@ -490,7 +500,7 @@ class ValueBuilder(object):
value_type = self._get_child_type(path, key)
if 'identityref' in value_type:
value, t_value = self._get_prefix_name(value)
value, t_value = self.get_prefix_name(value)
key_parts.append(self._quote_key(value))
return ' '.join(key_parts)
@ -533,7 +543,7 @@ class ValueBuilder(object):
self._values.append(ValueBuilder.Value(path, state, value, deps))
self._values_dirty = True
def _get_prefix_name(self, qname):
def get_prefix_name(self, qname):
if not isinstance(qname, (str, unicode)):
return qname, None
if ':' not in qname:
@ -556,9 +566,9 @@ class ValueBuilder(object):
parent_schema = all_schema['data']
meta = all_schema['meta']
schema = self._find_child(parent_path, parent_schema, key)
return self._get_type(parent_path, schema, meta)
return self.get_type(parent_path, schema, meta)
def _get_type(self, path, schema=None, meta=None):
def get_type(self, path, schema=None, meta=None):
if schema is None or meta is None:
all_schema = self._ensure_schema_cached(path)
schema = all_schema['data']
@ -686,7 +696,8 @@ def verify_version_str(version_str, required_versions):
def normalize_value(expected_value, value, key):
if value is None:
return None
if isinstance(expected_value, bool):
if (isinstance(expected_value, bool) and
isinstance(value, (str, unicode))):
return value == 'true'
if isinstance(expected_value, int):
try:

View file

@ -116,7 +116,7 @@ class NsoVerify(object):
violations = []
# build list of values from configured data
value_builder = ValueBuilder(self._client)
value_builder = ValueBuilder(self._client, 'verify')
for key, value in self._data.items():
value_builder.build('', key, value)
@ -146,11 +146,17 @@ class NsoVerify(object):
n_value = normalize_value(
expected_value.value, value, expected_value.path)
if n_value != expected_value.value:
violations.append({
'path': expected_value.path,
'expected-value': expected_value.value,
'value': n_value
})
# if the value comparision fails, try mapping identityref
value_type = value_builder.get_type(expected_value.path)
if value_type is not None and 'identityref' in value_type:
n_value, t_value = self.get_prefix_name(value)
if expected_value.value != n_value:
violations.append({
'path': expected_value.path,
'expected-value': expected_value.value,
'value': n_value
})
else:
raise ModuleFailException(
'value state {0} not supported at {1}'.format(