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