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

using reflection to identify top-level device field

parent 133467fa
Branches
Tags
2 merge requests!106Resolve "Job Failed #240443",!90Develop
Pipeline #66482 passed with warnings
......@@ -16,7 +16,7 @@ import (
func main() {
log.SetLevel(log.DebugLevel)
sbi := &nucleus.AristaOC{}
sbi := &nucleus.Arista{}
device := nucleus.Device{
GoStruct: sbi.Schema().Root,
......
......@@ -2,6 +2,7 @@ package nucleus
import (
"code.fbi.h-da.de/cocsn/gosdn/forks/goarista/gnmi"
"code.fbi.h-da.de/cocsn/gosdn/nucleus/util"
"context"
gpb "github.com/openconfig/gnmi/proto/gnmi"
"testing"
......@@ -106,25 +107,34 @@ func TestGnmi_CapabilitiesIntegration(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
}
t.Run("Test GNMI Capabilities", func(t *testing.T){
cfg := &gnmi.Config{
Addr: address,
Username: "admin",
Password: "arista",
Encoding: gpb.Encoding_JSON_IETF,
respones := map[string]*gpb.CapabilityResponse{
"../test/cap-resp-arista-ceos": {},
}
transport,err := NewGnmiTransport(cfg)
if err != nil {
t.Error(err)
}
resp, err := transport.Capabilities(context.Background())
if err != nil {
t.Error(err)
}
if resp == nil {
t.Error("resp is nil")
for k,v := range respones {
if err := util.Read(k, v); err != nil {
t.Errorf("error parsing %v: %v", k, err)
}
t.Run("Test GNMI Capabilities", func(t *testing.T) {
cfg := &gnmi.Config{
Addr: address,
Username: "admin",
Password: "arista",
Encoding: gpb.Encoding_JSON_IETF,
}
transport, err := NewGnmiTransport(cfg)
if err != nil {
t.Error(err)
}
resp, err := transport.Capabilities(context.Background())
if err != nil {
t.Error(err)
}
if resp != v {
t.Error("resp is nil")
}
})
}
})
}
func TestPndImplementation_RequestAllIntegration(t *testing.T) {
......
......@@ -3,11 +3,13 @@ package nucleus
import (
"code.fbi.h-da.de/cocsn/yang-models/generated/arista"
"code.fbi.h-da.de/cocsn/yang-models/generated/openconfig"
log "github.com/golang/glog"
"github.com/google/uuid"
gpb "github.com/openconfig/gnmi/proto/gnmi"
"github.com/openconfig/goyang/pkg/yang"
"github.com/openconfig/ygot/ygot"
"github.com/openconfig/ygot/ytypes"
log "github.com/sirupsen/logrus"
"reflect"
)
// SouthboundInterface provides an
......@@ -47,6 +49,7 @@ func (oc *OpenConfig) SbiIdentifier() string {
func (oc *OpenConfig) Schema() *ytypes.Schema {
schema, err := openconfig.Schema()
oc.schema = schema
if err != nil {
log.Fatal(err)
}
......@@ -65,6 +68,34 @@ func (oc *OpenConfig) SetNode() func(schema *yang.Entry, root interface{}, path
}
}
// Unmarshal injects OpenConfig specific model
// representation to the transport.
// Needed for type assertion.
func (oc *OpenConfig) Unmarshal() func([]byte, string, interface{}, ...ytypes.UnmarshalOpt) error {
return func(bytes []byte, path string, goStruct interface{}, opt ...ytypes.UnmarshalOpt) error {
// Load SBI definition
d := openconfig.Device{}
s := reflect.ValueOf(&d).Elem()
h := s.FieldByName("Interfaces")
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: Prettify (mk)
p2 := configStruct.Elem()
configStruct.Elem().Set(reflect.New(p2.Type().Elem()))
c := configStruct.Elem().Interface().(ygot.GoStruct)
if err := oc.schema.Unmarshal(bytes, c, opt...); err != nil {
return err
}
reflect.ValueOf(goStruct.(*openconfig.Device)).Elem().FieldByName("Interfaces").Set(reflect.ValueOf(c))
return nil
}
}
func (oc *OpenConfig) Id() uuid.UUID {
return oc.id
}
......@@ -72,7 +103,7 @@ func (oc *OpenConfig) Id() uuid.UUID {
// deprecated
// Use for prototyping only.
// Use OpenConfig instead
type AristaOC struct {
type Arista struct {
// deprecated
transport Transport
......@@ -80,26 +111,27 @@ type AristaOC struct {
id uuid.UUID
}
func (oc *AristaOC) Id() uuid.UUID {
func (oc *Arista) Id() uuid.UUID {
return oc.id
}
func (oc *AristaOC) SbiIdentifier() string {
func (oc *Arista) SbiIdentifier() string {
return "arista"
}
func (oc *AristaOC) Schema() *ytypes.Schema {
func (oc *Arista) Schema() *ytypes.Schema {
schema, err := arista.Schema()
if err != nil {
log.Fatal(err)
}
oc.schema = schema
return schema
}
// SetNode injects AristaOC specific model
// SetNode injects Arista specific model
// representation to the transport.
// Needed for type assertion.
func (oc *AristaOC) SetNode() func(schema *yang.Entry, root interface{}, path *gpb.Path, val interface{}, opts ...ytypes.SetNodeOpt) error {
func (oc *Arista) SetNode() func(schema *yang.Entry, root interface{}, path *gpb.Path, val interface{}, opts ...ytypes.SetNodeOpt) error {
return func(schema *yang.Entry, root interface{}, path *gpb.Path, val interface{}, opts ...ytypes.SetNodeOpt) error {
if err := ytypes.SetNode(schema, root.(*arista.Device), path, val, opts...); err != nil {
return err
......@@ -107,3 +139,17 @@ func (oc *AristaOC) SetNode() func(schema *yang.Entry, root interface{}, path *g
return nil
}
}
// Unmarshal injects Arista specific model
// representation to the transport.
// Needed for type assertion.
func (oc *Arista) Unmarshal() func([]byte, interface{}, ...ytypes.UnmarshalOpt) error {
return func(bytes []byte, goStruct interface{}, opt ...ytypes.UnmarshalOpt) error {
ifaces := &arista.OpenconfigInterfaces_Interfaces{}
if err := oc.schema.Unmarshal(bytes, ifaces, opt...); err != nil {
return err
}
goStruct.(*arista.Device).Interfaces = ifaces
return nil
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment