I’m working on an open-source program that needs to support multiple northbound agents, including ConfD. The problem is that different northbound agents encode YANG data in different ways (e.g. ConfD encodes IPv4 addresses using in_addr structures whereas other programs encode IPv4 addresses using strings).
What I’m trying to do is to normalize all YANG data my program receives into raw strings and then parse this string myself (with the help of libyang to identify the YANG type). This is certainly not very efficient but it simplifies things quite a bit for me.
Looking at the ConfD documentation I found the CONFD_DAEMON_FLAG_STRINGSONLY flag which makes ConfD deliver strings (C_BUF) for all YANG types, but unfortunately this flag is only available in the Data Provider API (I’m using CDB).
I also tried to use confd_val2str() but I found it to be too complicated to use in a generic way (for all possible YANG types). confd_pp_value() on the other hand is super convenient but it doesn’t provide the raw YANG data value (e.g. enum<3> instead of 3).
One solution I thought about is to write a function to convert a confd_value structure to a string myself. It would be similar to confd_pp_value() but without the “pretty” part, only the raw value would be printed. This idea however feels like an overkill to solve a simple problem. I’d appreciate if someone could shed some light on what would be the best way to do what I’m trying to do, any suggestion would be welcome.
Correct - and CONFD_DAEMON_FLAG_STRINGSONLY predates the possibility to do generic value -> string translation in the library via confd_val2str() - i.e. if confd_val2str() had been first, CONFD_DAEMON_FLAG_STRINGSONLY would never have been implemented…
The generiic way is to get the struct confd_type* from the struct confd_cs_node* for the leaf you have a value for, and find the struct confd_cs_node* via the path to the leaf. And you “should” always have that path already, either as the “string path” that you passed to e.g. cdb_get() (use confd_cs_node_cd() to find the node) or as a confd_hkeypath_t* that you received in the iter() callback for cdb_diff_iterate() (use confd_find_cs_node() to find the node). It’s basically just 2 lines of code, e.g.:
It would be quite problematic if it printed “3” - you could have a YANG union of enumeration and e.g. int32, in which case it would be impossible to tell the difference between the 4th enum and the integer 3. (And if you at some point wanted to translate it back to an internal value, it would always be the integer.)
You could implement something like that fairly trivially by using confd_serialize() and then your favorite stringification method on the binary buffer produced - e.g. hex or base64.