openconfig/gnmi

How to properely marshal a gNMI struct to string?

hellt opened this issue · 4 comments

hellt commented

Hi,
I am trying to log a gNMI proto message contents before sending it off to the target, I thought I could use the following:

import (
	"github.com/openconfig/gnmi/proto/gnmi"
	"google.golang.org/protobuf/encoding/prototext"
)
req := &gnmi.GetRequest{
	UseModels: make([]*gnmi.ModelData, 0),
	Path:      make([]*gnmi.Path, 0),
	Encoding:  gnmi.Encoding(encodingVal),
}
logger.Printf("sending gNMI GetRequest: '%s'", prototext.MarshalOptions{Multiline: false}.Format(req))

but unfortunately prototext marshaller fails to recognize (?) all of the fields for this GetRequest, since the output contains only the path information:

2020/06/11 09:08:14.938045 sending gNMI GetRequest: 'path:{elem:{name:"state"} elem:{name:"system"} elem:{name:"version"}}'

By default, marshalling to textproto will leave out fields that are set to their default value. This will be the case when you set encoding to JSON``, or leave an empty set of fields in use_modelsorpath`.

Please see the small program here that demonstrates this:

package main

import (
	"fmt"

	gpb "github.com/openconfig/gnmi/proto/gnmi"
	"github.com/openconfig/ygot/ygot"
	"google.golang.org/protobuf/encoding/prototext"
)

func main() {
	// Prints an empty message
	p := &gpb.GetRequest{Path: []*gpb.Path{}}
	fmt.Printf("%s\n", prototext.Format(p))

	// Prints a populated Path field.
	if pp, err := ygot.StringToStructuredPath("/interfaces/interface[name=eth0]/state/oper-status"); err == nil {
		p.Path = []*gpb.Path{pp}
	}
	fmt.Printf("%s\n", prototext.Format(p))

	// Doesn't print the encoding field
	p.Encoding = gpb.Encoding_JSON
	fmt.Printf("%s\n", prototext.Format(p))

	// Prints the encoding field
	p.Encoding = gpb.Encoding_ASCII
	fmt.Printf("%s\n", prototext.Format(p))
}
hellt commented

Thanks @robshakir !

  1. Am I correct that JSON for encoding is considered to be default because it is mapped to int32 0, as well as DataType ALL is mapped to 0
  2. If 1 is correct, is it though true , that on the wire the default value for, say, JSON encoding which is 0 will be still encoded as a slice of bytes when sent over the grpc channel?
  1. Yes, the 0 value of an enumeration is its default value. This is described here.

  2. The encoding seen by marshalling to textproto is not what is used on the wire -- you can find the full details of the binary encoding here.

hellt commented

Closing, since there is no option to override default behavior of the text marshaller