diff --git a/grpc.go b/grpc.go index d914cfdeb5006c366e584f4f2d83ce1ab1127ee8..1302161630c3da8efd745e93f8ff89e16079bb36 100644 --- a/grpc.go +++ b/grpc.go @@ -104,11 +104,7 @@ func (s server) CreatePlugin(req *pb.CreateRequest, stream pb.Csbi_CreatePluginS if err != nil { return handleRPCError(labels, err) } - err = buildPlugin(d.ID.String()) - if err != nil { - return handleRPCError(labels, err) - } - file, err := os.Open(filepath.Join(d.ID.String(), "plugin.so")) + file, err := os.Open(filepath.Join(d.ID.String(), "gostructs.go")) if err != nil { return handleRPCError(labels, err) } diff --git a/templates.go b/templates.go index ad71ef198da4bcee29f56db8c82de33cddfaf124..ec0811d3276b0cea51d13d4a72d7f54d7248f5e4 100644 --- a/templates.go +++ b/templates.go @@ -1,10 +1,6 @@ package csbi -import ( - "html/template" - - "github.com/openconfig/ygot/ygen" -) +import "github.com/openconfig/ygot/ygen" var pluginStruct = ygen.GoStructCodeSnippet{ StructName: "Csbi", @@ -13,55 +9,30 @@ var pluginStruct = ygen.GoStructCodeSnippet{ id uuid.UUID }`, Methods: ` -func (sbi *Csbi) SbiIdentifier() string { - return "plugin sbi" +// SbiIdentifier returns the identifier as a +func (csbi *Csbi) SbiIdentifier() string { + return "csbi" } -func (sbi *Csbi) SetNode(schema *yang.Entry, root interface{}, path *gpb.Path, val interface{}, opts ...ytypes.SetNodeOpt) error { - log.WithFields(log.Fields{ - "schema": schema.Name, - "path": path, - "val": val, - "opts": opts, - }).Trace("entering SetNode()") +// SetNode injects schema specific model representation to the transport. +// Needed for type assertion. +func (csbi *Csbi) SetNode(schema *yang.Entry, root interface{}, path *gpb.Path, val interface{}, opts ...ytypes.SetNodeOpt) error { return ytypes.SetNode(schema, root.(*Device), path, val, opts...) } -func (sbi *Csbi) Schema() *ytypes.Schema { - schema, err := Schema() - sbi.schema = schema - if err != nil { - log.Fatal(err) - } - return schema -} - -func (sbi *Csbi) ID() uuid.UUID { - return sbi.id -} - -func (sbi *Csbi) Type() spb.Type { - return spb.Type_CONTAINERISED -} - -func (sbi *Csbi) Unmarshal(bytes []byte, fields []string, goStruct ygot.ValidatedGoStruct, opt ...ytypes.UnmarshalOpt) error { - log.WithFields(log.Fields{}).Trace("entering Unmarshal()") - return unmarshal(sbi.Schema(), bytes, fields, goStruct, opt...) +// Unmarshal injects schema specific model representation to the transport. +// Needed for type assertion. +func (csbi *Csbi) Unmarshal(bytes []byte, path *gpb.Path, goStruct ygot.ValidatedGoStruct, opt ...ytypes.UnmarshalOpt) error { + return unmarshal(csbi.Schema(), bytes, path, goStruct, opt...) } -// unmarshal parses gNMI response to a go struct. -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)) } }() - log.WithFields(log.Fields{ - "schema": schema.RootSchema().Name, - "fields": fields, - "bytes": len(bytes), - "opts": opt, - }).Trace("entering unmarshal()") // Load SBI definition root, err := ygot.DeepCopy(schema.Root) @@ -70,94 +41,58 @@ func unmarshal(schema *ytypes.Schema, bytes []byte, fields []string, goStruct yg } validatedDeepCopy, ok := root.(ygot.ValidatedGoStruct) if !ok { - return fmt.Errorf("no validated go struct") + return &errors.ErrInvalidTypeAssertion{} } - ygot.BuildEmptyTree(validatedDeepCopy) - log.Trace("built empty tree") - - var fieldStruct ygot.ValidatedGoStruct - if len(fields) != 0 { - log.Trace("fetching fields") - fieldStruct, err = getField(validatedDeepCopy, fields) - if err != nil { - return err - } - } else { - log.Trace("using root struct") - 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 := Unmarshal(bytes, fieldStruct, opt...); err != nil { + if err := Unmarshal(bytes, validatedCreatedNode, opt...); err != nil { return err } - ygot.PruneEmptyBranches(validatedDeepCopy) - log.Trace("pruned empty branches") - log.Trace("merging structs...") - return ygot.MergeStructInto(goStruct, 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)) - } - }() - log.WithFields(log.Fields{ - "fields": fields, - }).Trace("getting field") - f := fields[0] - log.Tracef("field name: %v", f) - 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 { - log.Trace("fetching fields") - return getField(outStruct, fields[1:]) +// Schema is holding the default OpenConfig schema for minimal compatibility +// to gosdn interfaces +func (csbi *Csbi) Schema() *ytypes.Schema { + schema, err := Schema() + csbi.schema = schema + if err != nil { + log.Fatal(err) } - return outStruct, nil + return schema +} + +// ID returns the Southbound's UUID +func (csbi *Csbi) ID() uuid.UUID { + return csbi.id +} + +// Type returns the Southbound's type +func (csbi *Csbi) Type() spb.Type { + return spb.Type_CONTAINERISED }`, } const pluginImportAmendmend = ` + "code.fbi.h-da.de/danet/gosdn/nucleus/errors" spb "code.fbi.h-da.de/danet/api/go/gosdn/southbound" "github.com/google/uuid" - "github.com/openconfig/ygot/util" + log "github.com/sirupsen/logrus" ) var PluginSymbol Csbi ` - -var templater *template.Template - -const pluginGoModTemplate = `module << .ModuleName >> - -go << .GoVersion >> - -require (<<range $element := .Dependencies>> - <<$element.Name>> v<<$element.Version>> -<<end>>) -` - -// Module represents a Go module entry in go.mod. Name and version needed. -type Module struct { - Name string `json:"name"` - Version string `json:"version"` -} - -// GoMod represents a go.mod file used for templates. -type GoMod struct { - ModuleName string `json:"name"` - GoVersion string `json:"go_version"` - Dependencies []Module `json:"dependencies"` -} diff --git a/write.go b/write.go index 2b37cfe08e0a85bc0693506180ff9a94c5e0b865..d3233ae76d61b2c476cfbf58393c9a333a91a6a5 100644 --- a/write.go +++ b/write.go @@ -3,9 +3,7 @@ package csbi import ( "bytes" "context" - "encoding/json" "fmt" - "html/template" "io/fs" "net" "os" @@ -93,11 +91,7 @@ func writeCsbi(ctx context.Context, code *ygen.GeneratedGoCode, path string) err } func writePlugin(code *ygen.GeneratedGoCode, path string) error { - err := writeCode(path, code) - if err != nil { - return err - } - return writeGoMod(path) + return writeCode(path, code) } func copyFile(path, filename string) error { @@ -153,29 +147,3 @@ func writeCode(path string, code *ygen.GeneratedGoCode) error { } return nil } -func writeGoMod(path string) error { - // Read dependencies from JSON file - deps, err := os.ReadFile(filepath.Join("resources", "plugin_deps.json")) - if err != nil { - return err - } - module := GoMod{} - if err := json.Unmarshal(deps, &module); err != nil { - return err - } - - // Create go.mod in destination directory and write template - file := filepath.Join(path, "go.mod") - goMod, err := os.OpenFile(file, os.O_CREATE|os.O_WRONLY, 0755) - if err != nil { - return err - } - defer goMod.Sync() - - templater := template.New("goMod").Delims("<<", ">>") - _, err = templater.Parse(pluginGoModTemplate) - if err != nil { - return err - } - return templater.Execute(goMod, module) -}