corenova / yang-js

YANG parser and composer
Apache License 2.0
56 stars 18 forks source link

Got some trouble during updating yang-js to the latest version #84

Closed quantang closed 5 years ago

quantang commented 5 years ago

Hello @saintkepha,

I just got back on YANG schema related work and want to update my yang-js library to the latest version. However, I am not sure whether I am using it in the wrong way, as my code cannot work with the latest version.

Could you help me take a look where would be the problem?

Here is what my code looks like before:

        const schema = path.resolve(
            vistaSchemasDirectory,
            './schemas/topology-injector/at-network-topology-v1.yang',
        );

        const model = Yang.import(schema)
            .bind({
                'feature(AMF)': () => {},
                'feature(VLAN)': () => {},
            })
            .eval()
            .access('ietf-network'));

        model.set({
            'ietf-network:networks': {},
        });

My expectation is it will initialize my model with the 'ietf-network:networks' attribute, which is the root of my data. However, when I try to call the get() function, it always returns empty.

Here is my sample data structure:

{
    "ietf-network:networks": {
        "network": [{
            "network-types": {
                "ietf-l2-topology:l2-network": {},
                "at-network-topology-v1:at-network": {}
            },
            "network-id": "local.area.atmf",  // the id of the network, which should be global unique in all plugins
                                              // so the plugin name must be the suffix of the network id.
            "ietf-l2-topology:l2-network-attributes": {
                "name": "local"  // the name of the network, which will be displayed to the users.
            },
            "at-network-topology-v1:at-network-attributes": {
                "source": "atmf"  // indicate which plugin provides this network to Vista Base
            },
            "node": [{
                "node-id": "Master",  // the id of the node, such as hostname, mac address
                                      // or anything "unique in the current network"
                "ietf-l2-topology:l2-node-attributes": {
                    "name": "Master",  // the hostname of the node
                    "sys-mac-address": "ec:cd:6d:ef:f7:37",
                    "management-address": ["172.31.0.251"]
                },
                "at-network-topology-v1:node-primary-attributes": {
                    "device-type": "switch",  // the icon type of the node in a map or a detail page
                    "status": "normal",  // the status of the node, such as critical, offline and abnormal.
                },
                "at-network-topology-v1:node-extra-attributes": [{
                    "name": "model",
                    "display-name": "MODEL",
                    "value": "AT-x930-28GSTX",
                    "priority": "high"
                }, {
                    "name": "serial",
                    "display-name": "SERIAL",
                    "value": "A04881A151300002",
                    "priority": "low"
                }],
                "ietf-network-topology:termination-point": [{
                    "tp-id": "sa12"
                }]
            }, {
                "node-id": "3",
                "ietf-l2-topology:l2-node-attributes": {
                    "name": "3",
                    "sys-mac-address": "00:00:cd:37:0a:de",
                    "management-address": ["172.31.2.61"]
                },
                "ietf-network-topology:termination-point": [{
                    "tp-id": "sa12"
                }]
            }],
            "ietf-network-topology:link": [{
                "link-id": "Master:sa12-3:sa12",  // the id of the link, which could be anything unique in the current network
                "source": {
                    "source-node": "Master",  // the "node-id" of the source node
                    "source-tp": "sa12"       // the "tp-id" of the souce node termination point
                },
                "destination": {
                    "dest-node": "3",         // the "node-id" of the destination node
                    "dest-tp": "sa12"         // the "tp-id" of the destination node termination point
                }
            }]
        }]
    }
}

Any idea? Cheers.

sekur commented 5 years ago

Hi @quantang

I don't see any issues with your code so I'll try to replicate that pattern.

But I do have some suggestions on how you can condense the logic.

For one, the latest yang-js does not require a function for binding.

You can simply do something like:

const model = Yang.import(schema).bind({
  'feature(AMF)': true,
  'feature(VLAN)': true
}).eval({
  'ietf-network:network': {}
});

It's possible the .access is resolving something unintended? But you don't need to access a specific module in order to set the data. As long as the datapath is in one of the "schema" import dependency chain, it should do what you expect.

BTW, latest yang-js also creates a parent Store instance attached to the model so you can also check the model.store to see if it got applied there.

Another possibility is that ietf-network module actually isn't one of the import dependencies of the at-network-topology-v1.yang?

Before, we used to allow .access() to get to the "store" which was attached to the Model class constructor. But this is no longer the case. Each Yang.import or such are disconnected from each other and there is no longer a Singleton Store where all models live.

Take a look at Store.coffee for how to work with multiple peer modules.

sekur commented 5 years ago

Just realized new Store isn't well documented. Should make it into .litcoffee at some point...

Here's an example:

const store = new Store('my-awesome-store');
store.add(Yang.import('ietf-network').bind({ }));
store.add(Yang.import('some-other')));
store.set({
  // data for any of the schemas you've added
});

Hope this helps.

This pattern allows you to evaluate the same schema against different data without clobbering shared module dependencies.

quantang commented 5 years ago

Hi @saintkepha,

I tried it in some different ways and found something interesting:

        const store = new Yang.Store());
        store.add(
            Yang.import(schema)
            // .bind({
            //     'feature(AMF)': () => {},
            // }),
        );
        store.set({
            'ietf-network:networks': {},
        });

        console.log('model:', store.in('ietf-network:networks').toJSON());
        console.log('store:', store.toJSON());

Any idea?

Here is the error:

 2019-02-22 16:01:50+1300: YangService:initialize { Error: issue executing registered function binding during get(): this.binding.call is not a function
     at Model.Property.error (/home/quant/Projects_bak/vistamanager/node_modules/yang-js/lib/property.js:435:15)
     at Model.Property.get (/home/quant/Projects_bak/vistamanager/node_modules/yang-js/lib/property.js:273:24)
     at Model.<anonymous> (/home/quant/Projects_bak/vistamanager/node_modules/yang-js/lib/property.js:479:25)
     at Model.Property.toJSON (/home/quant/Projects_bak/vistamanager/node_modules/yang-js/lib/property.js:481:10)
     at Store.toJSON (/home/quant/Projects_bak/vistamanager/node_modules/yang-js/lib/store.js:113:22)
     at Function.YangService.loadYangSchema (/home/quant/Projects_bak/vistamanager/dist/yang/yangService.js:88:37)
     at Function.<anonymous> (/home/quant/Projects_bak/vistamanager/dist/yang/yangService.js:67:30)
     at step (/home/quant/Projects_bak/vistamanager/dist/yang/yangService.js:32:23)
     at Object.next (/home/quant/Projects_bak/vistamanager/dist/yang/yangService.js:13:53)
     at /home/quant/Projects_bak/vistamanager/dist/yang/yangService.js:7:71
     at new Promise (<anonymous>)
     at __awaiter (/home/quant/Projects_bak/vistamanager/dist/yang/yangService.js:3:12)
     at Function.YangService.initialize (/home/quant/Projects_bak/vistamanager/dist/yang/yangService.js:63:16)
     at new YangService (/home/quant/Projects_bak/vistamanager/dist/yang/yangService.js:57:25)
     at new AmfYangDelegate (/home/quant/Projects_bak/vistamanager/dist/yang/amfYangDelegate.js:44:28)
     at new GuestDeviceDelegate (/home/quant/Projects_bak/vistamanager/dist/data/topologyRepo/guestDeviceDelegate.js:49:28)
   uri: undefined,
   src:
    { name: 'at-network-topology-v1',
      kind: 'module',
      xpath: '/',
      schema:
       { 'yang-version': '1',
         namespace: 'urn:atl:params:xml:ns:yang:at-network-topology',
         prefix: 'atnt',
         import: [Object],
         organization: 'Allied Telesis',
         description:
          'This module define the model for the Allied Telesis network topology.',
         revision: [Object],
         typedef: [Object],
         feature: [Object],
         grouping: [Object],
         augment: [Object] },
      active: true,
      changed: true,
      readonly: false },
   ctx:
    TypeError: this.binding.call is not a function
        at Model.Property.get (/home/quant/Projects_bak/vistamanager/node_modules/yang-js/lib/property.js:270:33)
        at Model.<anonymous> (/home/quant/Projects_bak/vistamanager/node_modules/yang-js/lib/property.js:479:25)
        at Model.Property.toJSON (/home/quant/Projects_bak/vistamanager/node_modules/yang-js/lib/property.js:481:10)
        at Store.toJSON (/home/quant/Projects_bak/vistamanager/node_modules/yang-js/lib/store.js:113:22)
        at Function.YangService.loadYangSchema (/home/quant/Projects_bak/vistamanager/dist/yang/yangService.js:88:37)
        at Function.<anonymous> (/home/quant/Projects_bak/vistamanager/dist/yang/yangService.js:67:30)
        at step (/home/quant/Projects_bak/vistamanager/dist/yang/yangService.js:32:23)
        at Object.next (/home/quant/Projects_bak/vistamanager/dist/yang/yangService.js:13:53)
        at /home/quant/Projects_bak/vistamanager/dist/yang/yangService.js:7:71
        at new Promise (<anonymous>)
        at __awaiter (/home/quant/Projects_bak/vistamanager/dist/yang/yangService.js:3:12)
        at Function.YangService.initialize (/home/quant/Projects_bak/vistamanager/dist/yang/yangService.js:63:16)
        at new YangService (/home/quant/Projects_bak/vistamanager/dist/yang/yangService.js:57:25)
        at new AmfYangDelegate (/home/quant/Projects_bak/vistamanager/dist/yang/amfYangDelegate.js:44:28)
        at new GuestDeviceDelegate (/home/quant/Projects_bak/vistamanager/dist/data/topologyRepo/guestDeviceDelegate.js:49:28)
        at new MongoTopologyRepository (/home/quant/Projects_bak/vistamanager/dist/data/mongoTopologyRepository.js:384:34) }
sekur commented 5 years ago

Hmm it's an interesting issue since Store simply calls model.toJSON() and attaches key/value to a new empty object. There must be something wrong with how feature elements are treated - it must be trying to get() and using the binding as a getter function. I'll take a closer look shortly.

Best, Peter On Thu, Feb 21, 2019 at 7:08 PM Quan Tang notifications@github.com wrote:

Hi @saintkepha https://github.com/saintkepha,

I tried it in some different ways and found something interesting:

    const store = new Yang.Store());
    store.add(
        Yang.import(schema)
        // .bind({
        //     'feature(AMF)': () => {},
        // }),
    );
    store.set({
        'ietf-network:networks': {},
    });

    console.log('model:', store.in('ietf-network:networks').toJSON());
    console.log('store:', store.toJSON());
  • If the bind() function is skipped, both the console.log will look good (except the feature related data is missing).
  • If the bind() function is called, the second console.log will be an error. No matter I pass the feature(AMF) with a function or true value.

Any idea?

Here is the error:

2019-02-22 16:01:50+1300: YangService:initialize { Error: issue executing registered function binding during get(): this.binding.call is not a function at Model.Property.error (/home/quant/Projects_bak/vistamanager/node_modules/yang-js/lib/property.js:435:15) at Model.Property.get (/home/quant/Projects_bak/vistamanager/node_modules/yang-js/lib/property.js:273:24) at Model. (/home/quant/Projects_bak/vistamanager/node_modules/yang-js/lib/property.js:479:25) at Model.Property.toJSON (/home/quant/Projects_bak/vistamanager/node_modules/yang-js/lib/property.js:481:10) at Store.toJSON (/home/quant/Projects_bak/vistamanager/node_modules/yang-js/lib/store.js:113:22) at Function.YangService.loadYangSchema (/home/quant/Projects_bak/vistamanager/dist/yang/yangService.js:88:37) at Function. (/home/quant/Projects_bak/vistamanager/dist/yang/yangService.js:67:30) at step (/home/quant/Projects_bak/vistamanager/dist/yang/yangService.js:32:23) at Object.next (/home/quant/Projects_bak/vistamanager/dist/yang/yangService.js:13:53) at /home/quant/Projects_bak/vistamanager/dist/yang/yangService.js:7:71 at new Promise () at awaiter (/home/quant/Projects_bak/vistamanager/dist/yang/yangService.js:3:12) at Function.YangService.initialize (/home/quant/Projects_bak/vistamanager/dist/yang/yangService.js:63:16) at new YangService (/home/quant/Projects_bak/vistamanager/dist/yang/yangService.js:57:25) at new AmfYangDelegate (/home/quant/Projects_bak/vistamanager/dist/yang/amfYangDelegate.js:44:28) at new GuestDeviceDelegate (/home/quant/Projects_bak/vistamanager/dist/data/topologyRepo/guestDeviceDelegate.js:49:28) uri: undefined, src: { name: 'at-network-topology-v1', kind: 'module', xpath: '/', schema: { 'yang-version': '1', namespace: 'urn:atl:params:xml:ns:yang:at-network-topology', prefix: 'atnt', import: [Object], organization: 'Allied Telesis', description: 'This module define the model for the Allied Telesis network topology.', revision: [Object], typedef: [Object], feature: [Object], grouping: [Object], augment: [Object] }, active: true, changed: true, readonly: false }, ctx: TypeError: this.binding.call is not a function at Model.Property.get (/home/quant/Projects_bak/vistamanager/node_modules/yang-js/lib/property.js:270:33) at Model. (/home/quant/Projects_bak/vistamanager/node_modules/yang-js/lib/property.js:479:25) at Model.Property.toJSON (/home/quant/Projects_bak/vistamanager/node_modules/yang-js/lib/property.js:481:10) at Store.toJSON (/home/quant/Projects_bak/vistamanager/node_modules/yang-js/lib/store.js:113:22) at Function.YangService.loadYangSchema (/home/quant/Projects_bak/vistamanager/dist/yang/yangService.js:88:37) at Function. (/home/quant/Projects_bak/vistamanager/dist/yang/yangService.js:67:30) at step (/home/quant/Projects_bak/vistamanager/dist/yang/yangService.js:32:23) at Object.next (/home/quant/Projects_bak/vistamanager/dist/yang/yangService.js:13:53) at /home/quant/Projects_bak/vistamanager/dist/yang/yangService.js:7:71 at new Promise () at awaiter (/home/quant/Projects_bak/vistamanager/dist/yang/yangService.js:3:12) at Function.YangService.initialize (/home/quant/Projects_bak/vistamanager/dist/yang/yangService.js:63:16) at new YangService (/home/quant/Projects_bak/vistamanager/dist/yang/yangService.js:57:25) at new AmfYangDelegate (/home/quant/Projects_bak/vistamanager/dist/yang/amfYangDelegate.js:44:28) at new GuestDeviceDelegate (/home/quant/Projects_bak/vistamanager/dist/data/topologyRepo/guestDeviceDelegate.js:49:28) at new MongoTopologyRepository (/home/quant/Projects_bak/vistamanager/dist/data/mongoTopologyRepository.js:384:34) }

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/corenova/yang-js/issues/84#issuecomment-466257331, or mute the thread https://github.com/notifications/unsubscribe-auth/AA6KbGN1PNjrzx3H6YRgyCrZAHVUMf2zks5vP18WgaJpZM4bGjuL .

-- Peter Lee Chief Executive Officer Corenova Technologies, Inc. +1-310-400-6450 linkedin.com/in/peter-k-lee

sekur commented 5 years ago

I believe this issue should be resolved... Please reopen if not the case.