Skip to content
Snippets Groups Projects
Commit f511b020 authored by Manuel Kieweg's avatar Manuel Kieweg
Browse files

better error handling

parent 9281c78b
No related branches found
No related tags found
1 merge request!173Process response overhaul
......@@ -16,3 +16,4 @@ documentation/design/*.pdf
restconf/bin/bin
test/.terraform.local/
configs/gosdn.toml
debug.test
\ No newline at end of file
package nucleus
import (
"code.fbi.h-da.de/cocsn/gosdn/nucleus/errors"
"fmt"
"reflect"
"code.fbi.h-da.de/cocsn/gosdn/nucleus/errors"
spb "code.fbi.h-da.de/cocsn/api/go/gosdn/southbound"
"code.fbi.h-da.de/cocsn/gosdn/interfaces/southbound"
......@@ -11,6 +13,7 @@ import (
"github.com/google/uuid"
gpb "github.com/openconfig/gnmi/proto/gnmi"
"github.com/openconfig/goyang/pkg/yang"
"github.com/openconfig/ygot/util"
"github.com/openconfig/ygot/ygot"
"github.com/openconfig/ygot/ytypes"
log "github.com/sirupsen/logrus"
......@@ -73,21 +76,19 @@ func (oc *OpenConfig) Unmarshal() func([]byte, []string, ygot.ValidatedGoStruct,
// unmarshal parses gNMI response to a go struct. If it's a root level response
// it uses
func (oc *OpenConfig)unmarshal(bytes []byte, fields []string, goStruct ygot.ValidatedGoStruct, opt ...ytypes.UnmarshalOpt) error {
func (oc *OpenConfig) unmarshal(bytes []byte, fields []string, goStruct ygot.ValidatedGoStruct, opt ...ytypes.UnmarshalOpt) error {
defer func() {
if r := recover(); r != nil {
log.Error(r.(error))
}
}()
switch l := len(fields); l {
case 0:
if len(fields) == 0 {
return openconfig.Unmarshal(bytes, goStruct.(*openconfig.Device), opt...)
default:
}
var c ygot.ValidatedGoStruct
// Load SBI definition
root, err := ygot.DeepCopy(oc.schema.Root)
root, err := ygot.DeepCopy(oc.Schema().Root)
if err != nil {
return err
}
......@@ -96,7 +97,10 @@ func (oc *OpenConfig)unmarshal(bytes []byte, fields []string, goStruct ygot.Vali
return &errors.ErrInvalidTypeAssertion{}
}
ygot.BuildEmptyTree(d)
c = getField(d, fields)
c, err = getField(d, fields)
if err != nil {
return err
}
if err := openconfig.Unmarshal(bytes, c, opt...); err != nil {
return err
......@@ -110,7 +114,7 @@ func (oc *OpenConfig)unmarshal(bytes []byte, fields []string, goStruct ygot.Vali
// getField traverses the GoStruct and returns the field that represents the
// tail of the path
func getField(inStruct ygot.ValidatedGoStruct, fields []string) ygot.ValidatedGoStruct {
func getField(inStruct ygot.ValidatedGoStruct, fields []string) (ygot.ValidatedGoStruct, error) {
defer func() {
if r := recover(); r != nil {
log.Error(r.(error))
......@@ -119,13 +123,18 @@ func getField(inStruct ygot.ValidatedGoStruct, fields []string) ygot.ValidatedGo
f := fields[0]
s := reflect.ValueOf(inStruct)
h := reflect.Indirect(s).FieldByName(f).Interface()
outStruct := h.(ygot.ValidatedGoStruct)
outStruct, ok := h.(ygot.ValidatedGoStruct)
if !ok {
t := reflect.TypeOf(h)
if !(util.IsTypeStruct(t) || util.IsTypeStructPtr(t)) {
return nil, fmt.Errorf("cannot process entry of type %v, request longer or shorter path", t)
}
return nil, fmt.Errorf("expected ValidatedGoStruct got %v", t)
}
if len(fields) > 1 {
outStruct = getField(outStruct, fields[1:])
} else {
return outStruct
return getField(outStruct, fields[1:])
}
return outStruct
return outStruct, nil
}
// ID returns the ID of the OpenConfig SBI
......
......@@ -4,6 +4,8 @@ import (
"reflect"
"testing"
spb "code.fbi.h-da.de/cocsn/api/go/gosdn/southbound"
"code.fbi.h-da.de/cocsn/gosdn/interfaces/transport"
"code.fbi.h-da.de/cocsn/gosdn/nucleus/util/path"
......@@ -11,6 +13,7 @@ import (
"code.fbi.h-da.de/cocsn/yang-models/generated/openconfig"
"github.com/google/uuid"
gpb "github.com/openconfig/gnmi/proto/gnmi"
"github.com/openconfig/ygot/ygot"
"github.com/openconfig/ygot/ytypes"
)
......@@ -105,7 +108,7 @@ func TestOpenConfig_Schema(t *testing.T) {
func Test_unmarshal(t *testing.T) {
type args struct {
path string
goStruct interface{}
goStruct ygot.ValidatedGoStruct
opt []ytypes.UnmarshalOpt
}
tests := []struct {
......@@ -114,7 +117,7 @@ func Test_unmarshal(t *testing.T) {
wantErr bool
}{
{
name: "fail",
name: "interfaces-interface w/o opts",
args: args{
goStruct: &openconfig.Device{},
path: "../test/proto/resp-interfaces-interface-arista-ceos",
......@@ -122,36 +125,36 @@ func Test_unmarshal(t *testing.T) {
wantErr: true,
},
{
name: "root w/opts",
name: "interfaces w/opts",
args: args{
path: "../test/proto/resp-full-node-arista-ceos",
path: "../test/proto/resp-interfaces-arista-ceos",
goStruct: &openconfig.Device{},
opt: []ytypes.UnmarshalOpt{&ytypes.IgnoreExtraFields{}},
},
wantErr: false,
},
{
name: "root w/o opts",
name: "interfaces w/o opts",
args: args{
path: "../test/proto/resp-full-node-arista-ceos",
path: "../test/proto/resp-interfaces-arista-ceos",
goStruct: &openconfig.Device{},
opt: nil,
},
wantErr: true,
},
{
name: "interfaces w/opts",
name: "root w/opts",
args: args{
path: "../test/proto/resp-interfaces-arista-ceos",
path: "../test/proto/resp-full-node-arista-ceos",
goStruct: &openconfig.Device{},
opt: []ytypes.UnmarshalOpt{&ytypes.IgnoreExtraFields{}},
},
wantErr: false,
},
{
name: "interfaces w/o opts",
name: "root w/o opts",
args: args{
path: "../test/proto/resp-interfaces-arista-ceos",
path: "../test/proto/resp-full-node-arista-ceos",
goStruct: &openconfig.Device{},
opt: nil,
},
......@@ -167,8 +170,13 @@ func Test_unmarshal(t *testing.T) {
}
fields := path.ToStrings(resp.Notification[0].Update[0].Path)
bytes := resp.Notification[0].Update[0].Val.GetJsonIetfVal()
if err := unmarshal(bytes, fields, tt.args.goStruct, tt.args.opt...); (err != nil) != tt.wantErr {
t.Errorf("unmarshal() error = %v, wantErr %v", err, tt.wantErr)
sbi := NewSBI(spb.Type_OPENCONFIG)
oc := sbi.(*OpenConfig)
if err := oc.unmarshal(bytes, fields, tt.args.goStruct, tt.args.opt...); err != nil {
if !tt.wantErr {
t.Errorf("unmarshal() error = %v, wantErr %v", err, tt.wantErr)
}
return
}
if tt.args.goStruct.(*openconfig.Device).Interfaces == nil && tt.args.opt != nil {
t.Errorf("unmarshal() error: field Interfaces must not be nil")
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment