Skip to content
Snippets Groups Projects
Commit 630906db authored by Malte Bauch's avatar Malte Bauch
Browse files

Merge branch 'develop' into...

Merge branch 'develop' into 156-a-setrequest-to-change-a-specific-path-of-an-ond-only-works-for-paths-with-string-values
parents 393dcdbb ce85c068
No related branches found
No related tags found
1 merge request!225Draft: Resolve "A SetRequest to change a specific path of an OND only works for paths with string values"
This commit is part of merge request !225. Comments created here will be created in the context of that merge request.
......@@ -23,5 +23,5 @@ type SouthboundInterface interface { // nolint
Schema() *ytypes.Schema
ID() uuid.UUID
Type() spb.Type
Unmarshal([]byte, []string, ygot.ValidatedGoStruct, ...ytypes.UnmarshalOpt) error
Unmarshal([]byte, *gpb.Path, ygot.ValidatedGoStruct, ...ytypes.UnmarshalOpt) error
}
// Code generated by mockery 2.7.5. DO NOT EDIT.
// Code generated by mockery v2.9.4. DO NOT EDIT.
package mocks
......
// Code generated by mockery 2.7.5. DO NOT EDIT.
// Code generated by mockery v2.9.4. DO NOT EDIT.
package mocks
......
// Code generated by mockery 2.7.5. DO NOT EDIT.
// Code generated by mockery v2.9.4. DO NOT EDIT.
package mocks
......@@ -104,7 +104,7 @@ func (_m *SouthboundInterface) Type() gosdnsouthbound.Type {
}
// Unmarshal provides a mock function with given fields: _a0, _a1, _a2, _a3
func (_m *SouthboundInterface) Unmarshal(_a0 []byte, _a1 []string, _a2 ygot.ValidatedGoStruct, _a3 ...ytypes.UnmarshalOpt) error {
func (_m *SouthboundInterface) Unmarshal(_a0 []byte, _a1 *gnmi.Path, _a2 ygot.ValidatedGoStruct, _a3 ...ytypes.UnmarshalOpt) error {
_va := make([]interface{}, len(_a3))
for _i := range _a3 {
_va[_i] = _a3[_i]
......@@ -115,7 +115,7 @@ func (_m *SouthboundInterface) Unmarshal(_a0 []byte, _a1 []string, _a2 ygot.Vali
ret := _m.Called(_ca...)
var r0 error
if rf, ok := ret.Get(0).(func([]byte, []string, ygot.ValidatedGoStruct, ...ytypes.UnmarshalOpt) error); ok {
if rf, ok := ret.Get(0).(func([]byte, *gnmi.Path, ygot.ValidatedGoStruct, ...ytypes.UnmarshalOpt) error); ok {
r0 = rf(_a0, _a1, _a2, _a3...)
} else {
r0 = ret.Error(0)
......
// Code generated by mockery 2.7.5. DO NOT EDIT.
// Code generated by mockery v2.9.4. DO NOT EDIT.
package mocks
......
// Code generated by mockery 2.7.5. DO NOT EDIT.
// Code generated by mockery v2.9.4. DO NOT EDIT.
package mocks
......
// Code generated by mockery 2.7.5. DO NOT EDIT.
// Code generated by mockery v2.9.4. DO NOT EDIT.
package mocks
......
......@@ -63,6 +63,7 @@ func Test_core_Get(t *testing.T) {
name string
args args
want []string
length int
wantErr bool
}{
{
......@@ -70,15 +71,28 @@ func Test_core_Get(t *testing.T) {
args: args{
ctx: context.Background(),
request: &pb.GetRequest{
All: true,
Pid: []string{
pndID,
},
},
},
length: 1,
want: []string{
pndID,
"test",
"test",
},
},
{
name: "getAll",
args: args{
ctx: context.Background(),
request: &pb.GetRequest{
All: true,
},
},
length: 2,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
......@@ -91,13 +105,19 @@ func Test_core_Get(t *testing.T) {
return
}
got := []string{
resp.Pnd[0].Id,
resp.Pnd[0].Name,
resp.Pnd[0].Description,
if tt.name == "default" {
got := []string{
resp.Pnd[0].Id,
resp.Pnd[0].Name,
resp.Pnd[0].Description,
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("core.Get() = %v, want %v", got, tt.want)
}
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("core.Get() = %v, want %v", got, tt.want)
length := len(resp.Pnd)
if tt.length != length {
t.Errorf("core.Get() = %v, want %v", length, tt.length)
}
})
}
......
......@@ -14,7 +14,6 @@ import (
"code.fbi.h-da.de/danet/forks/goarista/gnmi"
"code.fbi.h-da.de/danet/gosdn/nucleus/errors"
"code.fbi.h-da.de/danet/gosdn/nucleus/types"
pathutils "code.fbi.h-da.de/danet/gosdn/nucleus/util/path"
gpb "github.com/openconfig/gnmi/proto/gnmi"
"github.com/openconfig/goyang/pkg/yang"
"github.com/openconfig/ygot/ygot"
......@@ -29,7 +28,7 @@ import (
type Gnmi struct {
SetNode func(schema *yang.Entry, root interface{}, path *gpb.Path, val interface{}, opts ...ytypes.SetNodeOpt) error
RespChan chan *gpb.SubscribeResponse
Unmarshal func([]byte, []string, ygot.ValidatedGoStruct, ...ytypes.UnmarshalOpt) error
Unmarshal func([]byte, *gpb.Path, ygot.ValidatedGoStruct, ...ytypes.UnmarshalOpt) error
Options *tpb.TransportOption
client gpb.GNMIClient
config *gnmi.Config
......@@ -130,7 +129,6 @@ func (g *Gnmi) Type() string {
// root struct. It logs all errors and returns an error containing the number
// off errors encountered during the process.
func (g *Gnmi) ProcessResponse(resp interface{}, root interface{}, s *ytypes.Schema) error {
models := s.SchemaTree
d, ok := root.(ygot.ValidatedGoStruct)
if !ok {
return &errors.ErrInvalidTypeAssertion{}
......@@ -147,16 +145,16 @@ func (g *Gnmi) ProcessResponse(resp interface{}, root interface{}, s *ytypes.Sch
switch val := update.Val.Value.(type) {
case *gpb.TypedValue_JsonVal:
opts := []ytypes.UnmarshalOpt{&ytypes.IgnoreExtraFields{}}
if err := g.Unmarshal(val.JsonVal, pathutils.ToStrings(path), d, opts...); err != nil {
if err := g.Unmarshal(val.JsonVal, path, d, opts...); err != nil {
errs = append(errs, err)
}
case *gpb.TypedValue_JsonIetfVal:
opts := []ytypes.UnmarshalOpt{&ytypes.IgnoreExtraFields{}}
if err := g.Unmarshal(val.JsonIetfVal, pathutils.ToStrings(path), d, opts...); err != nil {
if err := g.Unmarshal(val.JsonIetfVal, path, d, opts...); err != nil {
errs = append(errs, err)
}
default:
schema := models["Device"]
schema := s.RootSchema()
opts := []ytypes.SetNodeOpt{&ytypes.InitMissingElements{}, &ytypes.TolerateJSONInconsistencies{}}
if err := g.SetNode(schema, root, update.Path, update.Val, opts...); err != nil {
errs = append(errs, err)
......
......@@ -234,7 +234,7 @@ func TestGnmi_ProcessResponse(t *testing.T) {
path: "../test/proto/resp-interfaces-interface-arista-ceos",
root: &openconfig.Device{},
},
wantErr: true,
wantErr: false,
},
{
name: "Interfaces Wildcard",
......
package nucleus
import (
"fmt"
"reflect"
"code.fbi.h-da.de/danet/gosdn/nucleus/errors"
spb "code.fbi.h-da.de/danet/api/go/gosdn/southbound"
......@@ -13,7 +10,6 @@ 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"
......@@ -76,13 +72,12 @@ func (oc *OpenConfig) SetNode(schema *yang.Entry, root interface{}, path *gpb.Pa
// Unmarshal injects OpenConfig specific model representation to the transport.
// Needed for type assertion.
func (oc *OpenConfig) Unmarshal(bytes []byte, fields []string, goStruct ygot.ValidatedGoStruct, opt ...ytypes.UnmarshalOpt) error {
return unmarshal(oc.Schema(), bytes, fields, goStruct, opt...)
func (oc *OpenConfig) Unmarshal(bytes []byte, path *gpb.Path, goStruct ygot.ValidatedGoStruct, opt ...ytypes.UnmarshalOpt) error {
return unmarshal(oc.Schema(), bytes, path, goStruct, opt...)
}
// unmarshal parses gNMI response to a go struct. If it's a root level response
// it uses
func unmarshal(schema *ytypes.Schema, bytes []byte, fields []string, goStruct ygot.ValidatedGoStruct, opt ...ytypes.UnmarshalOpt) error {
//unmarshal parses a gNMI response to a go struct.
func unmarshal(schema *ytypes.Schema, bytes []byte, path *gpb.Path, goStruct ygot.ValidatedGoStruct, opt ...ytypes.UnmarshalOpt) error {
defer func() {
if r := recover(); r != nil {
log.Error(r.(error))
......@@ -98,53 +93,26 @@ func unmarshal(schema *ytypes.Schema, bytes []byte, fields []string, goStruct yg
if !ok {
return &errors.ErrInvalidTypeAssertion{}
}
ygot.BuildEmptyTree(validatedDeepCopy)
var fieldStruct ygot.ValidatedGoStruct
if len(fields) != 0 {
fieldStruct, err = getField(validatedDeepCopy, fields)
if err != nil {
return err
}
} else {
fieldStruct = validatedDeepCopy
// returns the node we want to fill with the data contained in 'bytes',
// using the specified 'path'.
createdNode, _, err := ytypes.GetOrCreateNode(schema.RootSchema(), validatedDeepCopy, path)
if err != nil {
return err
}
validatedCreatedNode, ok := createdNode.(ygot.ValidatedGoStruct)
if !ok {
return &errors.ErrInvalidTypeAssertion{}
}
if err := openconfig.Unmarshal(bytes, fieldStruct, opt...); err != nil {
if err := openconfig.Unmarshal(bytes, validatedCreatedNode, opt...); err != nil {
return err
}
ygot.PruneEmptyBranches(validatedDeepCopy)
opts := []ygot.MergeOpt{&ygot.MergeOverwriteExistingFields{}}
return ygot.MergeStructInto(goStruct, validatedDeepCopy, opts...)
}
// getField traverses the GoStruct and returns the field that represents the
// tail of the path
func getField(inStruct ygot.ValidatedGoStruct, fields []string) (ygot.ValidatedGoStruct, error) {
defer func() {
if r := recover(); r != nil {
log.Error(r.(error))
}
}()
f := fields[0]
s := reflect.ValueOf(inStruct)
h := reflect.Indirect(s).FieldByName(f).Interface()
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 {
return getField(outStruct, fields[1:])
}
return outStruct, nil
}
// ID returns the ID of the OpenConfig SBI
func (oc *OpenConfig) ID() uuid.UUID {
return oc.id
......@@ -174,9 +142,9 @@ func (csbi *Csbi) SetNode(schema *yang.Entry, root interface{}, path *gpb.Path,
// Unmarshal injects schema specific model representation to the transport.
// Needed for type assertion.
func (csbi *Csbi) Unmarshal(bytes []byte, fields []string, goStruct ygot.ValidatedGoStruct, opt ...ytypes.UnmarshalOpt) error {
func (csbi *Csbi) Unmarshal(bytes []byte, path *gpb.Path, goStruct ygot.ValidatedGoStruct, opt ...ytypes.UnmarshalOpt) error {
oc := OpenConfig{}
return unmarshal(oc.Schema(), bytes, fields, goStruct, opt...)
return unmarshal(oc.Schema(), bytes, path, goStruct, opt...)
}
// Schema is holding the default OpenConfig schema for minimal compatibility
......
......@@ -6,7 +6,6 @@ import (
spb "code.fbi.h-da.de/danet/api/go/gosdn/southbound"
"code.fbi.h-da.de/danet/gosdn/nucleus/util/path"
"code.fbi.h-da.de/danet/gosdn/nucleus/util/proto"
"code.fbi.h-da.de/danet/yang-models/generated/openconfig"
"github.com/google/uuid"
......@@ -165,10 +164,9 @@ func Test_unmarshal(t *testing.T) {
if err != nil {
t.Error(err)
}
fields := path.ToStrings(resp.Notification[0].Update[0].Path)
bytes := resp.Notification[0].Update[0].Val.GetJsonIetfVal()
oc := NewSBI(spb.Type_OPENCONFIG)
if err := unmarshal(oc.Schema(), bytes, fields, tt.args.goStruct, tt.args.opt...); err != nil {
if err := unmarshal(oc.Schema(), bytes, resp.Notification[0].Update[0].Path, tt.args.goStruct, tt.args.opt...); err != nil {
if !tt.wantErr {
t.Errorf("unmarshal() error = %v, wantErr %v", err, tt.wantErr)
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment