diff --git a/cmd/gnmi-capabilities/capabilities.go b/cmd/gnmi-capabilities/capabilities.go index 54601b8a7ede5805a0d1a3ad633424020a8fc736..cabad2624ac914da3829e5f03fe98ee89bc06d38 100644 --- a/cmd/gnmi-capabilities/capabilities.go +++ b/cmd/gnmi-capabilities/capabilities.go @@ -11,13 +11,14 @@ import ( ) func main() { - cfg := &gnmi.Config{ - Addr: "[2003:e6:1722:fed0:0:242:ac11:5]:6030", + cfg := gnmi.Config{ + Addr: "portainer.danet.fbi.h-da.de:6030", Username: "admin", Password: "arista", Encoding: gpb.Encoding_JSON_IETF, } - transport, err := nucleus.NewGnmiTransport(cfg) + opts := &nucleus.GnmiTransportOptions{Config: cfg} + transport, err := nucleus.NewGnmiTransport(opts) if err != nil { log.Error(err) } diff --git a/cmd/gnmi-set/set.go b/cmd/gnmi-set/set.go index 2e5a2ee693a92049a51a65643c153a345350496a..d80ced7378110c9a6c2ac43da4320b02ca9b89a1 100644 --- a/cmd/gnmi-set/set.go +++ b/cmd/gnmi-set/set.go @@ -17,10 +17,11 @@ func main() { } opts := &nucleus.GnmiTransportOptions{ - - Addr: a, - Username: "admin", - Password: "arista", + Config: gnmi.Config{ + Addr: a, + Username: "admin", + Password: "arista", + }, } t, err := nucleus.NewGnmiTransport(opts) if err != nil { diff --git a/cmd/gnmi-telemetry/telemetry.go b/cmd/gnmi-telemetry/telemetry.go index fc61043ec99297a6a344ffc94da5b3baf8ce43eb..fc686a0792552273e701886d7c6bf0394a05c8d7 100644 --- a/cmd/gnmi-telemetry/telemetry.go +++ b/cmd/gnmi-telemetry/telemetry.go @@ -5,6 +5,7 @@ import ( "code.fbi.h-da.de/cocsn/gosdn/nucleus" "context" "fmt" + "github.com/google/uuid" gpb "github.com/openconfig/gnmi/proto/gnmi" log "github.com/sirupsen/logrus" "os" @@ -17,14 +18,16 @@ func main() { log.SetLevel(log.DebugLevel) sbi := &nucleus.OpenConfig{} - device, err := nucleus.NewDevice("gnmi", sbi, + device, err := nucleus.NewDevice(sbi, &nucleus.GnmiTransportOptions{ - Addr: "portainer.danet.fbi.h-da.de:6030", - Username: "admin", - Password: "arista", + Config: gnmi.Config{ + Addr: "portainer.danet.fbi.h-da.de:6030", + Username: "admin", + Password: "arista", + Encoding: gpb.Encoding_JSON_IETF, + }, SetNode: sbi.SetNode(), RespChan: make(chan *gpb.SubscribeResponse), - Encoding: gpb.Encoding_JSON_IETF, }) if err != nil { log.Debug(err) @@ -32,8 +35,6 @@ func main() { pnd, err := nucleus.NewPND("openconfig", "a simple openconfig PND", uuid.New(), sbi) if err != nil { log.Fatal(err) - } - log.Fatal(err) } if err := pnd.AddDevice(device); err != nil { log.Fatal(err) diff --git a/cmd/gnmi/gnmi.go b/cmd/gnmi/gnmi.go index 050c89d8f5c38e430562fc73eb2d1e813351d495..da82fb20a4e5a0b256840282c77697e82024b6d3 100644 --- a/cmd/gnmi/gnmi.go +++ b/cmd/gnmi/gnmi.go @@ -1,7 +1,9 @@ package main import ( + "code.fbi.h-da.de/cocsn/gosdn/forks/goarista/gnmi" "code.fbi.h-da.de/cocsn/gosdn/nucleus" + "github.com/google/uuid" gpb "github.com/openconfig/gnmi/proto/gnmi" log "github.com/sirupsen/logrus" ) @@ -12,16 +14,18 @@ import ( */ func main() { - log.SetLevel(log.DebugLevel) sbi := &nucleus.OpenConfig{} - device, err := nucleus.NewDevice("gnmi", sbi, - &nucleus.GnmiTransportOptions{ + opts := &nucleus.GnmiTransportOptions{ + Config: gnmi.Config{ Addr: "portainer.danet.fbi.h-da.de:6030", Username: "admin", Password: "arista", - SetNode: sbi.SetNode(), Encoding: gpb.Encoding_JSON_IETF, - }) + }, + SetNode: sbi.SetNode(), + } + log.SetLevel(log.DebugLevel) + device, err := nucleus.NewDevice(sbi, opts) if err != nil { log.Debug(err) } diff --git a/forks/goarista/gnmi/client.go b/forks/goarista/gnmi/client.go index 4ed4998b8ce935504fe9a1ae8928b8d4c6ffdacd..f9ed05b53fcd4852b7f5fa4c61d40e25c3688532 100644 --- a/forks/goarista/gnmi/client.go +++ b/forks/goarista/gnmi/client.go @@ -9,7 +9,6 @@ import ( "crypto/tls" "crypto/x509" "errors" - "flag" "fmt" "math" "net" @@ -82,59 +81,6 @@ type SubscribeOptions struct { Target string } -// ParseFlags reads arguments from stdin and returns a populated Config object and a list of -// paths to subscribe to -func ParseFlags() (*Config, []string) { - // flags - var ( - addrsFlag = flag.String("addrs", "localhost:6030", - "Comma-separated list of addresses of OpenConfig gRPC servers. The address 'HOSTNAME' "+ - "is replaced by the current hostname.") - - caFileFlag = flag.String("cafile", "", - "Path to server TLS certificate file") - - certFileFlag = flag.String("certfile", "", - "Path to ciena TLS certificate file") - - keyFileFlag = flag.String("keyfile", "", - "Path to ciena TLS private key file") - - passwordFlag = flag.String("password", "", - "Password to authenticate with") - - usernameFlag = flag.String("username", "", - "Username to authenticate with") - - tlsFlag = flag.Bool("tls", false, - "Enable TLS") - - compressionFlag = flag.String("compression", "", - "Type of compression to use") - - subscribeFlag = flag.String("subscribe", "", - "Comma-separated list of paths to subscribe to upon connecting to the server") - - token = flag.String("token", "", - "Authentication token") - ) - flag.Parse() - cfg := &Config{ - Addr: *addrsFlag, - CAFile: *caFileFlag, - CertFile: *certFileFlag, - KeyFile: *keyFileFlag, - Password: *passwordFlag, - Username: *usernameFlag, - TLS: *tlsFlag, - Compression: *compressionFlag, - Token: *token, - } - subscriptions := strings.Split(*subscribeFlag, ",") - return cfg, subscriptions - -} - // accessTokenCred implements credentials.PerRPCCredentials, the gRPC // interface for credentials that need to attach security information // to every RPC. diff --git a/nucleus/cli-handling.go b/nucleus/cli-handling.go index bc53846565793b40d2727312cfef025adc1e953d..55136026e9ebd4af850f43e5647b6425f596f86e 100644 --- a/nucleus/cli-handling.go +++ b/nucleus/cli-handling.go @@ -18,6 +18,7 @@ import ( "github.com/spf13/viper" pb "code.fbi.h-da.de/cocsn/gosdn/api/proto" + "code.fbi.h-da.de/cocsn/gosdn/forks/goarista/gnmi" gpb "github.com/openconfig/gnmi/proto/gnmi" log "github.com/sirupsen/logrus" "google.golang.org/grpc" @@ -239,8 +240,16 @@ func (s *server) AddDevice(ctx context.Context, in *pb.AddDeviceRequest) (*pb.Ad return &pb.AddDeviceReply{Message: err.Error()}, err } - newDevice, err := NewDevice(sbi, &GnmiTransportOptions{in.Device.Address, in.Device.Username, - in.Device.Password, sbi.SetNode(), nil, gpb.Encoding_JSON_IETF}) + newDevice, err := NewDevice(sbi, + &GnmiTransportOptions{ + Config: gnmi.Config{ + Addr: in.Device.Address, + Username: in.Device.Username, + Password: in.Device.Password, + Encoding: gpb.Encoding_JSON_IETF, + }, + SetNode: sbi.SetNode(), + }) if err != nil { log.Info(err) return &pb.AddDeviceReply{Message: err.Error()}, err diff --git a/nucleus/device_test.go b/nucleus/device_test.go index 2aed3c2dc7ba89e120c16a6a55bae29aa8b92148..900855346f0d7d4beb2bc39106fc9790af2cb761 100644 --- a/nucleus/device_test.go +++ b/nucleus/device_test.go @@ -14,7 +14,7 @@ func TestDevice_Id(t *testing.T) { GoStruct ygot.GoStruct SBI SouthboundInterface Transport Transport - Uuid uuid.UUID + Uuid uuid.UUID } tests := []struct { name string @@ -24,7 +24,7 @@ func TestDevice_Id(t *testing.T) { { name: "default", fields: fields{ - Uuid: did, + Uuid: did, }, want: did, }, @@ -35,7 +35,7 @@ func TestDevice_Id(t *testing.T) { GoStruct: tt.fields.GoStruct, SBI: tt.fields.SBI, Transport: tt.fields.Transport, - Uuid: tt.fields.Uuid, + Uuid: tt.fields.Uuid, } if got := d.Id(); !reflect.DeepEqual(got, tt.want) { t.Errorf("Id() = %v, want %v", got, tt.want) @@ -47,7 +47,7 @@ func TestDevice_Id(t *testing.T) { func TestNewDevice(t *testing.T) { sbi := &OpenConfig{} type args struct { - sbi SouthboundInterface + sbi SouthboundInterface opts TransportOptions } tests := []struct { @@ -59,32 +59,27 @@ func TestNewDevice(t *testing.T) { { name: "default", args: args{ - sbi: sbi, - opts: &GnmiTransportOptions{ - Addr: "test:///", - Username: "test", - Password: "test", + sbi: sbi, + opts: &GnmiTransportOptions{ + Config: gnmi.Config{ + Addr: "test:///", + Username: "test", + Password: "test", + }, }, }, want: &Device{ GoStruct: &openconfig.Device{}, SBI: sbi, - Uuid: uuid.New(), + Uuid: uuid.New(), Transport: &Gnmi{ - SetNode: nil, - RespChan: nil, - Unmarshal: nil, - Options: &GnmiTransportOptions{ - Addr: "test:///", - Username: "test", - Password: "test", - }, - config: &gnmi.Config{ - Addr: "test:///", - Username: "test", - Password: "test", + Options: &GnmiTransportOptions{ + Config: gnmi.Config{ + Addr: "test:///", + Username: "test", + Password: "test", + }, }, - client: nil, }, }, }, diff --git a/nucleus/gnmi_transport.go b/nucleus/gnmi_transport.go index 4bdef0618499aaa31389c237707a5cadba5a6022..500dd66391cb4ff0207280b395094881303f0e9e 100644 --- a/nucleus/gnmi_transport.go +++ b/nucleus/gnmi_transport.go @@ -12,24 +12,23 @@ import ( ) type Gnmi struct { - SetNode func(schema *yang.Entry, root interface{}, path *gpb.Path, val interface{}, opts ...ytypes.SetNodeOpt) error - RespChan chan *gpb.SubscribeResponse + SetNode func(schema *yang.Entry, root interface{}, path *gpb.Path, val interface{}, opts ...ytypes.SetNodeOpt) error + RespChan chan *gpb.SubscribeResponse Unmarshal func([]byte, []string, interface{}, ...ytypes.UnmarshalOpt) error - Options *GnmiTransportOptions - config *gnmi.Config - client gpb.GNMIClient + Options *GnmiTransportOptions + config *gnmi.Config + client gpb.GNMIClient } func NewGnmiTransport(opts *GnmiTransportOptions) (*Gnmi, error) { - config := createConfig(opts) - c, err := gnmi.Dial(config) + c, err := gnmi.Dial(&opts.Config) if err != nil { return nil, err } return &Gnmi{ SetNode: opts.SetNode, RespChan: opts.RespChan, - config: config, + config: &opts.Config, Options: opts, client: c, }, nil @@ -92,7 +91,7 @@ func (g *Gnmi) Set(ctx context.Context, params ...interface{}) (interface{}, err // Invalid params cause unhealable error ops := make([]*gnmi.Operation, 0) exts := make([]*gnmi_ext.Extension, 0) - for _,p := range params{ + for _, p := range params { switch p.(type) { case *gnmi.Operation: ops = append(ops, p.(*gnmi.Operation)) @@ -224,13 +223,12 @@ func (g *Gnmi) Close() error { type GnmiTransportOptions struct { // all needed gnmi transport parameters - Addr string - Username string - Password string - SetNode func(schema *yang.Entry, root interface{}, path *gpb.Path, + gnmi.Config + + SetNode func(schema *yang.Entry, root interface{}, path *gpb.Path, val interface{}, opts ...ytypes.SetNodeOpt) error - RespChan chan *gpb.SubscribeResponse - Encoding gpb.Encoding + Unmarshal func([]byte, []string, interface{}, ...ytypes.UnmarshalOpt) error + RespChan chan *gpb.SubscribeResponse } func (gto *GnmiTransportOptions) GetAddress() string { diff --git a/nucleus/gnmi_transport_test.go b/nucleus/gnmi_transport_test.go index f53df098a611507d7973a798e1ad28766b4e0ded..54fcf554d79577fda7ecb7e0c7a90ea1d0564f24 100644 --- a/nucleus/gnmi_transport_test.go +++ b/nucleus/gnmi_transport_test.go @@ -86,12 +86,14 @@ func mockTransport() Gnmi { func newGnmiTransportOptions() *GnmiTransportOptions { return &GnmiTransportOptions{ - Username: "test", - Password: "test", - Addr: "localhost:13371", + Config: gnmi.Config{ + Username: "test", + Password: "test", + Addr: "localhost:13371", + Encoding: gpb.Encoding_PROTO, + }, SetNode: nil, RespChan: make(chan *gpb.SubscribeResponse), - Encoding: gpb.Encoding_PROTO, } } @@ -575,8 +577,7 @@ func TestGnmi_getWithRequest(t *testing.T) { func TestNewGnmiTransport(t *testing.T) { type args struct { - opts *GnmiTransportOptions - config *gnmi.Config + opts *GnmiTransportOptions } tests := []struct { name string @@ -587,10 +588,12 @@ func TestNewGnmiTransport(t *testing.T) { { name: "default", args: args{opts: &GnmiTransportOptions{ - Username: "test", - Password: "test", - Addr: "localhost:13371", - Encoding: gpb.Encoding_PROTO, + Config: gnmi.Config{ + Username: "test", + Password: "test", + Addr: "localhost:13371", + Encoding: gpb.Encoding_PROTO, + }, }}, want: &Gnmi{ config: &gnmi.Config{ @@ -605,19 +608,19 @@ func TestNewGnmiTransport(t *testing.T) { }, { name: "unsupported compression", - args: args{config: &gnmi.Config{Compression: "brotli"}}, + args: args{opts: &GnmiTransportOptions{Config: gnmi.Config{Compression: "brotli"}}}, want: nil, wantErr: true, }, { name: "certificate error no key file", - args: args{config: &gnmi.Config{TLS: true, CertFile: "invalid", KeyFile: ""}}, + args: args{opts: &GnmiTransportOptions{Config: gnmi.Config{TLS: true, CertFile: "invalid", KeyFile: ""}}}, want: nil, wantErr: true, }, { name: "certificate error no ca file", - args: args{config: &gnmi.Config{TLS: true, CAFile: "invalid"}}, + args: args{opts: &GnmiTransportOptions{Config: gnmi.Config{TLS: true, CAFile: "invalid"}}}, want: nil, wantErr: true, }, diff --git a/nucleus/integration_test.go b/nucleus/integration_test.go index 9327c47297e341b9daddb7c7708062ede9593924..1f73e3f7ce8c0365729e31cb40398471f2f71106 100644 --- a/nucleus/integration_test.go +++ b/nucleus/integration_test.go @@ -20,10 +20,12 @@ func testSetupIntegration() { } opt = &GnmiTransportOptions{ - Addr: address, - Username: "admin", - Password: "arista", - Encoding: gpb.Encoding_JSON_IETF, + Config: gnmi.Config{ + Addr: address, + Username: "admin", + Password: "arista", + Encoding: gpb.Encoding_JSON_IETF, + }, } } @@ -48,21 +50,23 @@ func TestGnmi_SetIntegration(t *testing.T) { { name: "destination unreachable", fields: fields{opt: &GnmiTransportOptions{ - Addr: "203.0.113.10:6030", + Config: gnmi.Config{ + Addr: "203.0.113.10:6030", + }, }, }, - args: args{ - ctx: context.Background(), + args: args{ + ctx: context.Background(), params: []interface{}{&gnmi.Operation{}}, }, want: nil, wantErr: true, }, { - name: "valid update", - fields: fields{opt: opt}, - args: args{ - ctx: context.Background(), + name: "valid update", + fields: fields{opt: opt}, + args: args{ + ctx: context.Background(), params: []interface{}{ &gnmi.Operation{ Type: "update", @@ -206,7 +210,9 @@ func TestGnmi_CapabilitiesIntegration(t *testing.T) { { name: "destination unreachable", fields: fields{opt: &GnmiTransportOptions{ - Addr: "203.0.113.10:6030", + Config: gnmi.Config{ + Addr: "203.0.113.10:6030", + }, }, }, args: args{ctx: context.Background()},