networktocode / ntc-rosetta

The missing bridge between industry standard CLIs and YANG
https://ntc-rosetta.readthedocs.io/en/latest/index.html
Apache License 2.0
103 stars 23 forks source link

Exception when list key is an identityref #46

Open marcushoff opened 3 years ago

marcushoff commented 3 years ago

First of all: Cool project! I'm implementing demo parsers and translators for VyOS. When creating the translator for openconfig-system I get an exception when implementing: /system/logging/console/selectors/selector/facility It's the list key and it's an identityref and I think that's causing the problem. I also think it might be in Yangson, but I'm not 100% sure.

The exception is thrown here: ` tests/models/test_models.py:133: in translate config = device.translate(candidate, replace=mode == "replace") ntc_rosetta/drivers/base.py:103: in translate return translator.process() /usr/local/lib/python3.6/site-packages/yangify/translator/init.py:618: in process self._process_container() /usr/local/lib/python3.6/site-packages/yangify/translator/init.py:445: in _process_container self._process_container_node(c) /usr/local/lib/python3.6/site-packages/yangify/translator/init.py:426: in _process_container_node attr._process_container() /usr/local/lib/python3.6/site-packages/yangify/translator/init.py:445: in _process_container self._process_container_node(c) /usr/local/lib/python3.6/site-packages/yangify/translator/init.py:426: in _process_container_node attr._process_container() /usr/local/lib/python3.6/site-packages/yangify/translator/init.py:445: in _process_container self._process_container_node(c) /usr/local/lib/python3.6/site-packages/yangify/translator/init.py:426: in _process_container_node attr._process_container() /usr/local/lib/python3.6/site-packages/yangify/translator/init.py:445: in _process_container self._process_container_node(c) /usr/local/lib/python3.6/site-packages/yangify/translator/init.py:426: in _process_container_node attr._process_container() /usr/local/lib/python3.6/site-packages/yangify/translator/init.py:447: in _process_container self._process_container_node(child) /usr/local/lib/python3.6/site-packages/yangify/translator/init.py:428: in _process_container_node attr._process_list() /usr/local/lib/python3.6/site-packages/yangify/translator/init.py:517: in _process_list if not self._obj_changed(element_path) and not self.yy.replace: /usr/local/lib/python3.6/site-packages/yangify/translator/init.py:231: in _obj_changed candidate = self.yy.candidate.goto(irt).value /usr/local/lib/python3.6/site-packages/yangson/instance.py:306: in goto inst = sel.goto_step(inst) /usr/local/lib/python3.6/site-packages/yangson/instance.py:996: in goto_step return inst.look_up(**self.parse_keys(inst.schema_node))


self = <yangson.instance.EntryKeys object at 0x7f7c85ad4cf8>, sn = <yangson.schemanode.ListNode object at 0x7f7c86526908>

def parse_keys(self, sn: "DataNode") -> Dict[InstanceName, ScalarValue]:
    """Parse key dictionary in the context of a schema node.

    Args:
        sn: Schema node corresponding to a list.
    """
    res = {}
    for k in self.keys:
        knod = sn.get_data_child(*k)
        if knod is None:
            raise NonexistentSchemaNode(sn.qual_name, *k)
        kval = knod.type.parse_value(self.keys[k])
        if kval is None:
          raise InvalidKeyValue(self.keys[k])

E yangson.exceptions.InvalidKeyValue: ('AUTH', 'openconfig-system')

/usr/local/lib/python3.6/site-packages/yangson/instance.py:964: InvalidKeyValue `

The data.json: { "openconfig-system:system": { "logging": { "console": { "selectors": { "selector": [ { "facility": "AUTH", "severity": "ALERT", "config": { "facility": "AUTH", "severity": "ALERT" } } ] } } } } }

What happens is that when the translater is creating the candidate from the json, it stores 'facility' as a tuple, because it's an identityref. Then when we're translating it expects the list key to be a string, from which it can create a tuple, but it's already a tuple and fails.