Comments (15)
Only the most obvious conversions are in the defaults but you are supposed to create your own Node implementations that implement node.Node and then use strategy like nodeutil.Extend to base all your custom Nodes on
https://github.com/freeconf/yang/blob/master/nodeutil/extend.go
type YourBaseNode struct {
...
}
func (b *YourBaseNode) OnField(..) {
switch r.Meta().Type().Ident() {
case "Addr":
// custom impl
Then use YourBaseNode much like nodeutil.Extend is used.
https://github.com/freeconf/examples/blob/master/basics/mgmt.go#L19
Having said all this, if there is a 100% no brainer to put as default...
from yang.
I think my main issue is that the Node-Interface for maps contains too much magic, especially with Next/OnNext and Child/OnChild. It takes hours of browsing through the source (especiall nodeutil.reflect) to understand what you are supposed to do with these interface calls.
Most likely the main issue for me is that the map I am trying to connect to restconf doesn't contain pointers, it contains references. Which should be fine for read only access (writing would need more custom code), but I think nodeutil.ReflectChild() cannot handle this kind of map at all. Which means you have to do most of the Node-calls by hand and there is not enough example code how to do it.
from yang.
from yang.
I think a great start would be to extend the "car" example with a custom "map" implementation... it already has a array/slice one, but the map one is quite different.
from yang.
Would you think about applying the following change? It would at least (as far as I can tell) allow read access to all Objects in Go that support the fmt.Stringer interface.
diff --git a/nodeutil/reflect.go b/nodeutil/reflect.go
index 512945c..8292adc 100644
--- a/nodeutil/reflect.go
+++ b/nodeutil/reflect.go
@@ -490,8 +490,13 @@ func ReadFieldWithFieldName(fieldName string, m meta.Leafable, ptrVal reflect.Va
fieldVal = fieldVal.Slice(0, fieldVal.Len())
}
+ innerFieldVal := fieldVal.Interface()
switch dt.Format() {
case val.FmtString:
+ stringer, ok := innerFieldVal.(fmt.Stringer)
+ if ok {
+ return val.String(stringer.String()), nil
+ }
s := fieldVal.String()
if len(s) == 0 {
return nil, nil
from yang.
Verified this already works
https://github.com/freeconf/yang/blob/master/nodeutil/reflect_test.go#L236
from yang.
Doesn't work for me...
I use a struct with netip.Prefix elements... when I switch off the patch above, I have to overwrite the nodeutil.ReflectChild behavior, otherwise I get this (overwritten for originator, not for destination).
{"destination":"\u003cnetip.Prefix Value\u003e","originator":"2.3.4.5"}
Maybe this happens because netip.Prefix is a struct, not a native type? If you think it would help, I can write up a small selfcontained test that demonstrates this.
from yang.
I got my patch for nodeutil/reflect.go even simpler... it seems fmt.Sprint() handles conversion to strings better than "Value.String()".
diff --git a/nodeutil/reflect.go b/nodeutil/reflect.go
index 512945c..71ce106 100644
--- a/nodeutil/reflect.go
+++ b/nodeutil/reflect.go
@@ -492,7 +492,7 @@ func ReadFieldWithFieldName(fieldName string, m meta.Leafable, ptrVal reflect.Va
switch dt.Format() {
case val.FmtString:
- s := fieldVal.String()
+ s := fmt.Sprint(fieldVal.Interface())
if len(s) == 0 {
return nil, nil
}
This gives me the proper output for netip.Prefix in a struct.
from yang.
from yang.
Okay, I tried to boil the test down a bit...
func main() {
yangPath := source.Path("./cmd/restconf/yang")
type TestContainer struct {
Destination netip.Prefix
Originator netip.Addr
}
type TestData struct {
Root *TestContainer
}
td := TestData{
Root: &TestContainer{
Destination: netip.MustParsePrefix("10.0.0.0/8"),
Originator: netip.MustParseAddr("192.168.1.1"),
},
}
d := device.New(yangPath)
if err := d.Add("simple", nodeutil.ReflectChild(&td)); err != nil {
panic(err)
}
srv := restconf.NewServer(d)
defer srv.Close()
err := d.ApplyStartupConfig(strings.NewReader(`
{
"fc-restconf" : {
"web": {
"port" : ":9080"
},
"debug" : true
}
}`))
if err != nil {
return
}
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
<-c
}
module simple {
namespace "de.fraunhofer.fkie/kom/rhn/simple";
prefix "simple";
description "test yang tree";
revision 0;
container root {
leaf destination {
type string;
}
leaf originator {
type string;
}
}
}
Without my patch the http call http://127.0.0.1:9080/restconf/data/simple:root
gives me
{"destination":"\u003cnetip.Prefix Value\u003e","originator":"\u003cnetip.Addr Value\u003e"}
with my patch it gives me
{"destination":"10.0.0.0/8","originator":"192.168.1.1"}
I hope this will help to track down the problem. Most likely the test can be condensed even more, but I still having trouble with parts of freeconf's API.
from yang.
After looking through the go reflection API for a bit I came up with this patch, which should not slow down normal strings:
diff --git a/nodeutil/reflect.go b/nodeutil/reflect.go
index 512945c..8c0c5b6 100644
--- a/nodeutil/reflect.go
+++ b/nodeutil/reflect.go
@@ -492,7 +492,12 @@ func ReadFieldWithFieldName(fieldName string, m meta.Leafable, ptrVal reflect.Va
switch dt.Format() {
case val.FmtString:
- s := fieldVal.String()
+ var s string
+ if fieldVal.Type().Kind() == reflect.String {
+ s = fieldVal.String()
+ } else {
+ s = fmt.Sprint(fieldVal.Interface())
+ }
if len(s) == 0 {
return nil, nil
}
The problem is in fieldVal.String()
call... it calls a subfunction called stringNonString()
for something not "Kind == string", which leads to the bad output.
from yang.
from yang.
netip.Prefix and netip.Addr is part of Go 1.18 or later
(edit)
func (p Prefix) String() string { ... }
func (ip Addr) String() string { ... }
from yang.
from yang.
thank you for accepting the change, I will update my local repository.
I know that this doesn't help with writing, but I have a few other ideas how to extend Freeconf/Yang a bit to make it easier for everyone to hook in data structures without doing a full custom handler. But I first want to look at the "low hanging fruits"... and in my case, I don't need write access... I am using Restconf as a powerful "query"-language to probe the internal data of a routing agent, so large parts (not all) of my data is read-only anyways.
Being able to handle more datatypes out of the box should be good for all users. But next time I find an example about something that doesn't work and how to fix it I will try to include a selfcontained example into my first post in the issue.
from yang.
Related Issues (20)
- Renaming of struct fields doesn't apply during replace operation? HOT 7
- Yang loader gets blocked for for an invalid yang file. HOT 1
- Panic in freeconf/yang library when import is missing HOT 1
- No support for mutiple bases for identityref type. HOT 1
- Derived bases of identities are not as expected when muti-level imports are done HOT 4
- [Question] Is Default() method syntax changed intentionally? Is this correct if leaf has value other than string. HOT 3
- Panic in freeconf/yang library if two leaf nodes has the same name. HOT 1
- Panic when 'config:true' is added in yang HOT 3
- Config substatment is not supported under choice statement HOT 1
- Augmenting is failing if target node is any substatment under a choice HOT 7
- Failing to augment if taget node is choice and data to be augmented also is choice HOT 3
- No error thrown is when a duplicate node is added to container using augment. HOT 1
- No error is thrown if cases inside a choice contains child nodes with same name. HOT 2
- Leaf of type union wrongly inherits default and units from typedef HOT 3
- Fraction-digits is not inherited through typedef HOT 2
- Panic when 'config:true' is added inside a choicecase in yang HOT 2
- bit information for 'bits' datatype is not found if a typedef is used. HOT 3
- 'Config'=false setting from parent/grand-parents not getting inherited to data nodes under a choice HOT 4
- Issue with setting default value for list and leaf-list using refine HOT 4
- Setting default value through typedef for leaf-list generates panic HOT 7
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from yang.