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

process response can process partial paths now

parent 6577c6f6
No related branches found
No related tags found
1 merge request!173Process response overhaul
...@@ -4,8 +4,8 @@ go 1.16 ...@@ -4,8 +4,8 @@ go 1.16
require ( require (
code.fbi.h-da.de/cocsn/api v0.2.2 code.fbi.h-da.de/cocsn/api v0.2.2
code.fbi.h-da.de/cocsn/gosdn v0.0.3-0.20210622103523-1af2dd83f700 code.fbi.h-da.de/cocsn/gosdn v0.0.3-0.20210622104649-6577c6f645b1
code.fbi.h-da.de/cocsn/gosdn/interfaces v0.0.0-20210622103523-1af2dd83f700 code.fbi.h-da.de/cocsn/gosdn/interfaces v0.0.0-20210622104649-6577c6f645b1
code.fbi.h-da.de/cocsn/yang-models v0.0.7 code.fbi.h-da.de/cocsn/yang-models v0.0.7
github.com/google/uuid v1.2.0 github.com/google/uuid v1.2.0
github.com/openconfig/gnmi v0.0.0-20210527163611-d3a3e30199da github.com/openconfig/gnmi v0.0.0-20210527163611-d3a3e30199da
......
This diff is collapsed.
...@@ -4,7 +4,7 @@ go 1.16 ...@@ -4,7 +4,7 @@ go 1.16
require ( require (
code.fbi.h-da.de/cocsn/api v0.2.2 code.fbi.h-da.de/cocsn/api v0.2.2
code.fbi.h-da.de/cocsn/gosdn/interfaces v0.0.0-20210621161319-e9316e4c2a92 code.fbi.h-da.de/cocsn/gosdn/interfaces v0.0.0-20210622104649-6577c6f645b1
code.fbi.h-da.de/cocsn/yang-models v0.0.7 code.fbi.h-da.de/cocsn/yang-models v0.0.7
github.com/aristanetworks/goarista v0.0.0-20201120222254-94a892eb0c6a github.com/aristanetworks/goarista v0.0.0-20201120222254-94a892eb0c6a
github.com/docker/docker v20.10.6+incompatible github.com/docker/docker v20.10.6+incompatible
......
This diff is collapsed.
...@@ -22,11 +22,15 @@ func NewDevice(name string, opt *tpb.TransportOption, sbi southbound.SouthboundI ...@@ -22,11 +22,15 @@ func NewDevice(name string, opt *tpb.TransportOption, sbi southbound.SouthboundI
name = namesgenerator.GetRandomName(0) name = namesgenerator.GetRandomName(0)
} }
root, err := ygot.DeepCopy(sbi.Schema().Root)
if err != nil {
return nil, err
}
if opt.Csbi { if opt.Csbi {
return &CsbiDevice{ return &CsbiDevice{
CommonDevice: CommonDevice{ CommonDevice: CommonDevice{
UUID: uuid.New(), UUID: uuid.New(),
GoStruct: sbi.Schema().Root, GoStruct: root,
sbi: sbi, sbi: sbi,
transport: t, transport: t,
name: name, name: name,
...@@ -36,7 +40,7 @@ func NewDevice(name string, opt *tpb.TransportOption, sbi southbound.SouthboundI ...@@ -36,7 +40,7 @@ func NewDevice(name string, opt *tpb.TransportOption, sbi southbound.SouthboundI
return &CommonDevice{ return &CommonDevice{
UUID: uuid.New(), UUID: uuid.New(),
GoStruct: sbi.Schema().Root, GoStruct: root,
sbi: sbi, sbi: sbi,
transport: t, transport: t,
name: name, name: name,
......
...@@ -3,6 +3,7 @@ package nucleus ...@@ -3,6 +3,7 @@ package nucleus
import ( import (
"context" "context"
"reflect" "reflect"
"strings"
"code.fbi.h-da.de/cocsn/gosdn/interfaces/southbound" "code.fbi.h-da.de/cocsn/gosdn/interfaces/southbound"
...@@ -35,7 +36,7 @@ var opmap = map[ppb.ApiOperation]string{ ...@@ -35,7 +36,7 @@ var opmap = map[ppb.ApiOperation]string{
type Gnmi struct { type Gnmi struct {
SetNode func(schema *yang.Entry, root interface{}, path *gpb.Path, val interface{}, opts ...ytypes.SetNodeOpt) error SetNode func(schema *yang.Entry, root interface{}, path *gpb.Path, val interface{}, opts ...ytypes.SetNodeOpt) error
RespChan chan *gpb.SubscribeResponse RespChan chan *gpb.SubscribeResponse
Unmarshal func([]byte, []string, interface{}, ...ytypes.UnmarshalOpt) error Unmarshal func([]byte, []string, ygot.ValidatedGoStruct, ...ytypes.UnmarshalOpt) error
Options *tpb.TransportOption Options *tpb.TransportOption
client gpb.GNMIClient client gpb.GNMIClient
config *gnmi.Config config *gnmi.Config
...@@ -227,15 +228,37 @@ func (g *Gnmi) Type() string { ...@@ -227,15 +228,37 @@ func (g *Gnmi) Type() string {
// ProcessResponse takes a gNMI response and serializes the contents to the root struct. // ProcessResponse takes a gNMI response and serializes the contents to the root struct.
func (g *Gnmi) ProcessResponse(resp interface{}, root interface{}, s *ytypes.Schema) error { func (g *Gnmi) ProcessResponse(resp interface{}, root interface{}, s *ytypes.Schema) error {
models := s.SchemaTree models := s.SchemaTree
r := resp.(*gpb.GetResponse) d, ok := root.(ygot.ValidatedGoStruct)
if !ok {
return &errors.ErrInvalidTypeAssertion{}
}
r, ok := resp.(*gpb.GetResponse)
if !ok {
return &errors.ErrInvalidTypeAssertion{}
}
rn := r.Notification rn := r.Notification
for _, msg := range rn { for _, msg := range rn {
for _, update := range msg.Update { for _, update := range msg.Update {
path := update.Path path := update.Path
val, ok := update.Val.Value.(*gpb.TypedValue_JsonVal) val, ok := update.Val.Value.(*gpb.TypedValue_JsonVal)
if ok { if ok {
buf := strings.Builder{}
for _,e := range path.Elem {
key := strings.Title(e.Name)
buf.WriteString(key)
buf.WriteString("_")
}
filter := buf.String()
filter = strings.TrimSuffix(filter,"_")
keys := make([]string, 0)
for k := range models {
if strings.Contains(k, filter) {
keys = append(keys, k)
}
}
//TODO: Fetch field by name
opts := []ytypes.UnmarshalOpt{&ytypes.IgnoreExtraFields{}} opts := []ytypes.UnmarshalOpt{&ytypes.IgnoreExtraFields{}}
return g.Unmarshal(val.JsonVal, pathutils.ToStrings(path), root, opts...) return g.Unmarshal(val.JsonVal, pathutils.ToStrings(path), d, opts...)
} }
// TODO(mk): Evaluate hardcoded model key // TODO(mk): Evaluate hardcoded model key
schema := models["Device"] schema := models["Device"]
......
...@@ -10,7 +10,6 @@ import ( ...@@ -10,7 +10,6 @@ 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"
...@@ -67,57 +66,57 @@ func (oc *OpenConfig) SetNode() func(schema *yang.Entry, root interface{}, path ...@@ -67,57 +66,57 @@ func (oc *OpenConfig) SetNode() func(schema *yang.Entry, root interface{}, path
// Unmarshal injects OpenConfig specific model representation to the transport. // Unmarshal injects OpenConfig specific model representation to the transport.
// Needed for type assertion. // Needed for type assertion.
func (oc *OpenConfig) Unmarshal() func([]byte, []string, ygot.GoStruct, ...ytypes.UnmarshalOpt) error { func (oc *OpenConfig) Unmarshal() func([]byte, []string, ygot.ValidatedGoStruct, ...ytypes.UnmarshalOpt) error {
return unmarshal return unmarshal
} }
// unmarshal parses a root or 1st level gNMI response to a go struct // unmarshal parses a root or 1st level gNMI response to a go struct
// Named return to return appropriate recover error func unmarshal(bytes []byte, fields []string, goStruct ygot.ValidatedGoStruct, opt ...ytypes.UnmarshalOpt) error {
func unmarshal(bytes []byte, fields []string, goStruct ygot.GoStruct, opt ...ytypes.UnmarshalOpt) (err error) { defer func() {
ygot.BuildEmptyTree(goStruct) if r := recover(); r != nil {
return openconfig.Unmarshal(bytes, goStruct.(*openconfig.Device), opt...) log.Error(r.(error))
}
}()
switch l := len(fields); l {
case 0:
return openconfig.Unmarshal(bytes, goStruct.(*openconfig.Device), opt...)
default:
}
var c ygot.ValidatedGoStruct
// Load SBI definition
d := openconfig.Device{}
ygot.BuildEmptyTree(&d)
c = getField(&d, fields)
if err := openconfig.Unmarshal(bytes, c, opt...); err != nil {
return err
}
if err := ygot.MergeStructInto(goStruct, &d); err != nil {
return err
}
return nil
} }
// iter walks down the provided paths and initializes the ygot.GoStruct. It only works for // iter walks down the provided paths and initializes the ygot.GoStruct. It only works for
// the root level. Named returns to return appropriate recover error // the root level.
// TODO(mk): Fix deeper layers // TODO(mk): Fix deeper layers
func iter(a ygot.GoStruct, fields []string) (b ygot.GoStruct, f string, err error) { func getField(inStruct ygot.ValidatedGoStruct, fields []string) ygot.ValidatedGoStruct {
defer func() { defer func() {
if r := recover(); r != nil { if r := recover(); r != nil {
err = r.(error) log.Error(r.(error))
} }
}() }()
var c ygot.GoStruct f := fields[0]
var configStruct reflect.Value s := reflect.ValueOf(inStruct)
f = fields[0] h := reflect.Indirect(s).FieldByName(f).Interface()
s := reflect.ValueOf(a).Elem() outStruct := h.(ygot.ValidatedGoStruct)
h := s.FieldByName(f)
configStruct = reflect.New(h.Type())
// Pointer of field needs to be initialized.
// Very convoluted russian doll trick
// https://stackoverflow.com/a/57469950/4378176
// https://golang.org/src/encoding/json/decode.go?s#L474
// TODO(mk): Prettify
p2 := configStruct.Elem()
// If we have KeyHelperGoStruct we need make and modify map instead of plain struct
if p2.Kind() == reflect.Map {
p2.Set(reflect.MakeMap(p2.Type()))
configStruct.Elem().Set(p2)
if err := util.InsertIntoMapStructField(a, f, "", p2); err != nil {
panic(err)
}
} else {
configStruct.Elem().Set(reflect.New(p2.Type().Elem()))
b = configStruct.Elem().Interface().(ygot.GoStruct)
}
if len(fields) > 1 { if len(fields) > 1 {
c, _, _ = iter(b, fields[1:]) outStruct = getField(outStruct, fields[1:])
} else { } else {
return return outStruct
} }
reflect.ValueOf(b).Elem().FieldByName(f).Set(reflect.ValueOf(c)) return outStruct
return
} }
// ID returns the ID of the OpenConfig SBI // ID returns the ID of the OpenConfig SBI
...@@ -145,7 +144,7 @@ func (csbi *Csbi) SetNode() func(schema *yang.Entry, root interface{}, path *gpb ...@@ -145,7 +144,7 @@ func (csbi *Csbi) SetNode() func(schema *yang.Entry, root interface{}, path *gpb
// Unmarshal injects OpenConfig specific model representation to the transport. // Unmarshal injects OpenConfig specific model representation to the transport.
// Needed for type assertion. // Needed for type assertion.
func (csbi *Csbi) Unmarshal() func([]byte, []string, ygot.GoStruct, ...ytypes.UnmarshalOpt) error { func (csbi *Csbi) Unmarshal() func([]byte, []string, ygot.ValidatedGoStruct, ...ytypes.UnmarshalOpt) error {
return unmarshal return unmarshal
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment