diff --git a/cmd/cmd.go b/cmd/cmd.go new file mode 100644 index 0000000..991d4bf --- /dev/null +++ b/cmd/cmd.go @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (c) 2022-2023 Dell Inc, or its subsidiaries. + +// Package cmd implements the ipsec related CLI commands +package cmd + +import ( + "log" + "os" + + "github.com/opiproject/godpu/cmd/common" + "github.com/opiproject/godpu/cmd/inventory" + "github.com/opiproject/godpu/cmd/ipsec" + "github.com/opiproject/godpu/cmd/network" + "github.com/opiproject/godpu/cmd/storage" + "github.com/spf13/cobra" +) + +// NewCommand handles the cli for evpn, ipsec, invetory and storage +func NewCommand() *cobra.Command { + // + // This is the root command for the CLI + // + + c := &cobra.Command{ + Use: "godpu", + Short: "godpu - DPUs and IPUs cli commands", + Run: func(cmd *cobra.Command, _ []string) { + err := cmd.Help() + if err != nil { + log.Fatalf("[ERROR] %s", err.Error()) + } + os.Exit(1) + }, + } + c.AddCommand(inventory.NewInventoryCommand()) + c.AddCommand(ipsec.NewIPSecCommand()) + c.AddCommand(storage.NewStorageCommand()) + c.AddCommand(network.NewEvpnCommand()) + + flags := c.PersistentFlags() + flags.String(common.AddrCmdLineArg, "localhost:50151", "address of OPI gRPC server") + flags.String(common.TLSFiles, "", "TLS files in client_cert:client_key:ca_cert format.") + + return c +} diff --git a/cmd/storage/common/common.go b/cmd/common/common.go similarity index 88% rename from cmd/storage/common/common.go rename to cmd/common/common.go index 45dc5ac..b2bdbdd 100644 --- a/cmd/storage/common/common.go +++ b/cmd/common/common.go @@ -15,6 +15,9 @@ const AddrCmdLineArg = "addr" // TimeoutCmdLineArg cmdline arg name for timeout const TimeoutCmdLineArg = "timeout" +// TLSFiles cmdline arg name for tls files +const TLSFiles = "tlsfiles" + // PrintResponse prints only response string into stdout without any // additional information func PrintResponse(response string) { diff --git a/cmd/inventory/inventory-get.go b/cmd/inventory/inventory-get.go index 2fe1caf..da3c406 100644 --- a/cmd/inventory/inventory-get.go +++ b/cmd/inventory/inventory-get.go @@ -9,22 +9,25 @@ import ( "log" "time" + "github.com/opiproject/godpu/cmd/common" "github.com/opiproject/godpu/inventory" "github.com/spf13/cobra" ) // NewGetCommand returns the inventory get command func NewGetCommand() *cobra.Command { - var ( - addr string - ) cmd := &cobra.Command{ Use: "get", Aliases: []string{"g"}, Short: "Gets DPU inventory information", Args: cobra.NoArgs, - Run: func(_ *cobra.Command, _ []string) { - invClient, err := inventory.New(addr) + Run: func(c *cobra.Command, _ []string) { + tlsFiles, err := c.Flags().GetString(common.TLSFiles) + cobra.CheckErr(err) + + addr, err := c.Flags().GetString(common.AddrCmdLineArg) + cobra.CheckErr(err) + invClient, err := inventory.New(addr, tlsFiles) if err != nil { log.Fatalf("could create gRPC client: %v", err) } @@ -39,8 +42,6 @@ func NewGetCommand() *cobra.Command { log.Printf("%s", data) }, } - flags := cmd.Flags() - flags.StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") return cmd } diff --git a/cmd/ipsec/ipsec-stats.go b/cmd/ipsec/ipsec-stats.go index a26e91b..f5706f6 100644 --- a/cmd/ipsec/ipsec-stats.go +++ b/cmd/ipsec/ipsec-stats.go @@ -8,27 +8,26 @@ import ( "fmt" "log" + "github.com/opiproject/godpu/cmd/common" "github.com/opiproject/godpu/ipsec" "github.com/spf13/cobra" ) // NewStatsCommand returns the ipsec stats command func NewStatsCommand() *cobra.Command { - var ( - addr string - ) cmd := &cobra.Command{ Use: "stats", Aliases: []string{"c"}, Short: "Queries ipsec statistics", Args: cobra.NoArgs, - Run: func(_ *cobra.Command, _ []string) { + Run: func(c *cobra.Command, _ []string) { + addr, err := c.Flags().GetString(common.AddrCmdLineArg) + cobra.CheckErr(err) + res := ipsec.Stats(addr) fmt.Println(res) }, } - flags := cmd.Flags() - flags.StringVar(&addr, "addr", "localhost:50151", "address or OPI gRPC server") return cmd } diff --git a/cmd/ipsec/ipsec-test.go b/cmd/ipsec/ipsec-test.go index 088c93e..97dc29d 100644 --- a/cmd/ipsec/ipsec-test.go +++ b/cmd/ipsec/ipsec-test.go @@ -7,6 +7,7 @@ package ipsec import ( "fmt" + "github.com/opiproject/godpu/cmd/common" "github.com/opiproject/godpu/ipsec" "github.com/spf13/cobra" ) @@ -14,7 +15,6 @@ import ( // NewTestCommand returns the ipsec tests command func NewTestCommand() *cobra.Command { var ( - addr string pingaddr string ) cmd := &cobra.Command{ @@ -22,13 +22,15 @@ func NewTestCommand() *cobra.Command { Aliases: []string{"c"}, Short: "Test ipsec functionality", Args: cobra.NoArgs, - Run: func(_ *cobra.Command, _ []string) { + Run: func(c *cobra.Command, _ []string) { + addr, err := c.Flags().GetString(common.AddrCmdLineArg) + cobra.CheckErr(err) + res := ipsec.TestIpsec(addr, pingaddr) fmt.Println(res) }, } flags := cmd.Flags() - flags.StringVar(&addr, "addr", "localhost:50151", "address or OPI gRPC server") flags.StringVar(&pingaddr, "pingaddr", "localhost", "address of other tunnel end to Ping") return cmd } diff --git a/cmd/network/evpn-bridge-port.go b/cmd/network/evpn-bridge-port.go index a6ae33c..196b24e 100644 --- a/cmd/network/evpn-bridge-port.go +++ b/cmd/network/evpn-bridge-port.go @@ -11,13 +11,13 @@ import ( "log" "time" + "github.com/opiproject/godpu/cmd/common" "github.com/opiproject/godpu/network" "github.com/spf13/cobra" ) // CreateBridgePort creates an Bridge Port an OPI server func CreateBridgePort() *cobra.Command { - var addr string var name string var mac string var bridgePortType string @@ -27,9 +27,15 @@ func CreateBridgePort() *cobra.Command { Use: "create-bp", Short: "Create a bridge port", Long: "Create a BridgePort with the specified name, MAC address, type, and VLAN IDs", - Run: func(_ *cobra.Command, _ []string) { + Run: func(c *cobra.Command, _ []string) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - evpnClient, err := network.NewBridgePort(addr) + + tlsFiles, err := c.Flags().GetString(common.TLSFiles) + cobra.CheckErr(err) + + addr, err := c.Flags().GetString(common.AddrCmdLineArg) + cobra.CheckErr(err) + evpnClient, err := network.NewBridgePort(addr, tlsFiles) if err != nil { log.Fatalf("could not create gRPC client: %v", err) } @@ -49,7 +55,6 @@ func CreateBridgePort() *cobra.Command { cmd.Flags().StringVar(&mac, "mac", "", "Specify the MAC address") cmd.Flags().StringVarP(&bridgePortType, "type", "t", "", "Specify the type (access or trunk)") cmd.Flags().StringSliceVar(&logicalBridges, "logicalBridges", []string{}, "Specify VLAN IDs (multiple values supported)") - cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") if err := cmd.MarkFlagRequired("mac"); err != nil { log.Fatalf("Error marking flag as required: %v", err) @@ -70,7 +75,6 @@ func CreateBridgePort() *cobra.Command { // DeleteBridgePort delete an Bridge Port an OPI server func DeleteBridgePort() *cobra.Command { - var addr string var name string var allowMissing bool @@ -78,9 +82,16 @@ func DeleteBridgePort() *cobra.Command { Use: "delete-bp", Short: "Delete a bridge port", Long: "Delete a BridgePort with the specified name", - Run: func(_ *cobra.Command, _ []string) { + Run: func(c *cobra.Command, _ []string) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - evpnClient, err := network.NewBridgePort(addr) + + tlsFiles, err := c.Flags().GetString(common.TLSFiles) + cobra.CheckErr(err) + + addr, err := c.Flags().GetString(common.AddrCmdLineArg) + cobra.CheckErr(err) + + evpnClient, err := network.NewBridgePort(addr, tlsFiles) if err != nil { log.Fatalf("could not create gRPC client: %v", err) } @@ -97,23 +108,28 @@ func DeleteBridgePort() *cobra.Command { cmd.Flags().StringVarP(&name, "name", "n", "", "Specify the name of the BridgePort") cmd.Flags().BoolVarP(&allowMissing, "allowMissing", "a", false, "Specify if missing allowed") - cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") return cmd } // GetBridgePort Get Bridge Port details func GetBridgePort() *cobra.Command { - var addr string var name string cmd := &cobra.Command{ Use: "get-bp", Short: "Show details of a bridge port", Long: "Show details of a BridgePort with the specified name", - Run: func(_ *cobra.Command, _ []string) { + Run: func(c *cobra.Command, _ []string) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - evpnClient, err := network.NewBridgePort(addr) + + tlsFiles, err := c.Flags().GetString(common.TLSFiles) + cobra.CheckErr(err) + + addr, err := c.Flags().GetString(common.AddrCmdLineArg) + cobra.CheckErr(err) + + evpnClient, err := network.NewBridgePort(addr, tlsFiles) if err != nil { log.Fatalf("could not create gRPC client: %v", err) } @@ -130,7 +146,6 @@ func GetBridgePort() *cobra.Command { } cmd.Flags().StringVarP(&name, "name", "n", "", "Specify the name of the BridgePort") - cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") if err := cmd.MarkFlagRequired("name"); err != nil { log.Fatalf("Error marking flag as required: %v", err) @@ -140,16 +155,22 @@ func GetBridgePort() *cobra.Command { // ListBridgePorts list all the Bridge Port an OPI server func ListBridgePorts() *cobra.Command { - var addr string var pageSize int32 var pageToken string cmd := &cobra.Command{ Use: "list-bps", Short: "Show details of all bridge ports", - Run: func(_ *cobra.Command, _ []string) { + Run: func(c *cobra.Command, _ []string) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - evpnClient, err := network.NewBridgePort(addr) + + tlsFiles, err := c.Flags().GetString(common.TLSFiles) + cobra.CheckErr(err) + + addr, err := c.Flags().GetString(common.AddrCmdLineArg) + cobra.CheckErr(err) + + evpnClient, err := network.NewBridgePort(addr, tlsFiles) if err != nil { log.Fatalf("could not create gRPC client: %v", err) } @@ -178,13 +199,12 @@ func ListBridgePorts() *cobra.Command { } cmd.Flags().Int32VarP(&pageSize, "pagesize", "s", 0, "Specify page size") cmd.Flags().StringVarP(&pageToken, "pagetoken", "t", "", "Specify the token") - cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") + return cmd } // UpdateBridgePort update the Bridge Port on OPI server func UpdateBridgePort() *cobra.Command { - var addr string var name string var updateMask []string var allowMissing bool @@ -193,9 +213,16 @@ func UpdateBridgePort() *cobra.Command { Use: "update-bp", Short: "Update the bridge port", Long: "updates the Bridge Port with updated mask", - Run: func(_ *cobra.Command, _ []string) { + Run: func(c *cobra.Command, _ []string) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - evpnClient, err := network.NewBridgePort(addr) + + tlsFiles, err := c.Flags().GetString(common.TLSFiles) + cobra.CheckErr(err) + + addr, err := c.Flags().GetString(common.AddrCmdLineArg) + cobra.CheckErr(err) + + evpnClient, err := network.NewBridgePort(addr, tlsFiles) if err != nil { log.Fatalf("could not create gRPC client: %v", err) } @@ -214,6 +241,6 @@ func UpdateBridgePort() *cobra.Command { cmd.Flags().StringVar(&name, "name", "", "name of the Bridge Port") cmd.Flags().StringSliceVar(&updateMask, "update-mask", nil, "update mask") cmd.Flags().BoolVarP(&allowMissing, "allowMissing", "a", false, "allow the missing") - cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") + return cmd } diff --git a/cmd/network/evpn-logical-brige.go b/cmd/network/evpn-logical-brige.go index ffc0ade..91d637a 100644 --- a/cmd/network/evpn-logical-brige.go +++ b/cmd/network/evpn-logical-brige.go @@ -11,13 +11,13 @@ import ( "log" "time" + "github.com/opiproject/godpu/cmd/common" "github.com/opiproject/godpu/network" "github.com/spf13/cobra" ) // CreateLogicalBridge creates an Logical Bridge an OPI server func CreateLogicalBridge() *cobra.Command { - var addr string var name string var vlanID uint32 var vni uint32 @@ -27,10 +27,17 @@ func CreateLogicalBridge() *cobra.Command { Use: "create-lb", Short: "Create a logical bridge", Long: "Create a logical bridge with the specified name, VLAN ID, and VNI", - Run: func(_ *cobra.Command, _ []string) { + Run: func(c *cobra.Command, _ []string) { var vniparam *uint32 ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - evpnClient, err := network.NewLogicalBridge(addr) + + tlsFiles, err := c.Flags().GetString(common.TLSFiles) + cobra.CheckErr(err) + + addr, err := c.Flags().GetString(common.AddrCmdLineArg) + cobra.CheckErr(err) + + evpnClient, err := network.NewLogicalBridge(addr, tlsFiles) if err != nil { log.Fatalf("could create gRPC client: %v", err) } @@ -49,15 +56,11 @@ func CreateLogicalBridge() *cobra.Command { PrintLB(lb) }, } - cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") cmd.Flags().StringVarP(&name, "name", "n", "", "Specify the name of the logical bridge") cmd.Flags().Uint32VarP(&vlanID, "vlan-id", "v", 0, "Specify the VLAN ID") cmd.Flags().Uint32VarP(&vni, "vni", "i", 0, "Specify the VNI") cmd.Flags().StringVar(&vtep, "vtep", "", "VTEP IP address") - if err := cmd.MarkFlagRequired("addr"); err != nil { - log.Fatalf("Error marking flag as required: %v", err) - } if err := cmd.MarkFlagRequired("name"); err != nil { log.Fatalf("Error marking flag as required: %v", err) } @@ -72,7 +75,6 @@ func CreateLogicalBridge() *cobra.Command { // DeleteLogicalBridge deletes an Logical Bridge an OPI server func DeleteLogicalBridge() *cobra.Command { - var addr string var name string var allowMissing bool @@ -80,9 +82,16 @@ func DeleteLogicalBridge() *cobra.Command { Use: "delete-lb", Short: "Delete a logical bridge", Long: "Delete a logical bridge with the specified name", - Run: func(_ *cobra.Command, _ []string) { + Run: func(c *cobra.Command, _ []string) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - evpnClient, err := network.NewLogicalBridge(addr) + + tlsFiles, err := c.Flags().GetString(common.TLSFiles) + cobra.CheckErr(err) + + addr, err := c.Flags().GetString(common.AddrCmdLineArg) + cobra.CheckErr(err) + + evpnClient, err := network.NewLogicalBridge(addr, tlsFiles) if err != nil { log.Fatalf("could not create gRPC client: %v", err) } @@ -99,7 +108,6 @@ func DeleteLogicalBridge() *cobra.Command { cmd.Flags().StringVarP(&name, "name", "n", "", "Specify the name of the BridgePort") cmd.Flags().BoolVarP(&allowMissing, "allowMissing", "a", false, "Specify allow missing") - cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") if err := cmd.MarkFlagRequired("name"); err != nil { log.Fatalf("Error marking flag as required: %v", err) @@ -109,16 +117,22 @@ func DeleteLogicalBridge() *cobra.Command { // GetLogicalBridge get Logical Bridge details from OPI server func GetLogicalBridge() *cobra.Command { - var addr string var name string cmd := &cobra.Command{ Use: "get-lb", Short: "Show details of a logical bridge", Long: "Show details of a logical bridge with the specified name", - Run: func(_ *cobra.Command, _ []string) { + Run: func(c *cobra.Command, _ []string) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - evpnClient, err := network.NewLogicalBridge(addr) + + tlsFiles, err := c.Flags().GetString(common.TLSFiles) + cobra.CheckErr(err) + + addr, err := c.Flags().GetString(common.AddrCmdLineArg) + cobra.CheckErr(err) + + evpnClient, err := network.NewLogicalBridge(addr, tlsFiles) if err != nil { log.Fatalf("could not create gRPC client: %v", err) } @@ -135,7 +149,7 @@ func GetLogicalBridge() *cobra.Command { } cmd.Flags().StringVarP(&name, "name", "n", "", "Specify the name of the BridgePort") - cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") + if err := cmd.MarkFlagRequired("name"); err != nil { log.Fatalf("Error marking flag as required: %v", err) } @@ -145,15 +159,22 @@ func GetLogicalBridge() *cobra.Command { // ListLogicalBridges list all Logical Bridge details from OPI server func ListLogicalBridges() *cobra.Command { - var addr string var pageSize int32 var pageToken string + cmd := &cobra.Command{ Use: "list-lbs", Short: "Show details of all logical bridges", - Run: func(_ *cobra.Command, _ []string) { + Run: func(c *cobra.Command, _ []string) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - evpnClient, err := network.NewLogicalBridge(addr) + + tlsFiles, err := c.Flags().GetString(common.TLSFiles) + cobra.CheckErr(err) + + addr, err := c.Flags().GetString(common.AddrCmdLineArg) + cobra.CheckErr(err) + + evpnClient, err := network.NewLogicalBridge(addr, tlsFiles) if err != nil { log.Fatalf("could not create gRPC client: %v", err) } @@ -184,22 +205,29 @@ func ListLogicalBridges() *cobra.Command { cmd.Flags().Int32VarP(&pageSize, "pagesize", "s", 0, "Specify page size") cmd.Flags().StringVarP(&pageToken, "pagetoken", "t", "", "Specify the token") - cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") + return cmd } // UpdateLogicalBridge update Logical Bridge on OPI server func UpdateLogicalBridge() *cobra.Command { - var addr string var name string var allowMissing bool var updateMask []string + cmd := &cobra.Command{ Use: "update-lb", Short: "update the logical bridge", - Run: func(_ *cobra.Command, _ []string) { + Run: func(c *cobra.Command, _ []string) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - evpnClient, err := network.NewLogicalBridge(addr) + + tlsFiles, err := c.Flags().GetString(common.TLSFiles) + cobra.CheckErr(err) + + addr, err := c.Flags().GetString(common.AddrCmdLineArg) + cobra.CheckErr(err) + + evpnClient, err := network.NewLogicalBridge(addr, tlsFiles) if err != nil { log.Fatalf("could not create gRPC client: %v", err) } @@ -215,7 +243,6 @@ func UpdateLogicalBridge() *cobra.Command { } cmd.Flags().StringVar(&name, "name", "", "name of the logical bridge") cmd.Flags().StringSliceVar(&updateMask, "update-mask", nil, "update mask") - cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") cmd.Flags().BoolVarP(&allowMissing, "allowMissing", "a", false, "Specify allow missing") return cmd diff --git a/cmd/network/evpn-svi.go b/cmd/network/evpn-svi.go index a48f937..2ebe32b 100644 --- a/cmd/network/evpn-svi.go +++ b/cmd/network/evpn-svi.go @@ -11,13 +11,13 @@ import ( "log" "time" + "github.com/opiproject/godpu/cmd/common" "github.com/opiproject/godpu/network" "github.com/spf13/cobra" ) // CreateSVI create svi on OPI server func CreateSVI() *cobra.Command { - var addr string var name string var vrf string var logicalBridge string @@ -30,9 +30,16 @@ func CreateSVI() *cobra.Command { Use: "create-svi", Short: "Create a SVI", Long: "Create an using name, vrf,logical bridges, mac, gateway ip's and enable bgp ", - Run: func(_ *cobra.Command, _ []string) { + Run: func(c *cobra.Command, _ []string) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - evpnClient, err := network.NewSVI(addr) + + tlsFiles, err := c.Flags().GetString(common.TLSFiles) + cobra.CheckErr(err) + + addr, err := c.Flags().GetString(common.AddrCmdLineArg) + cobra.CheckErr(err) + + evpnClient, err := network.NewSVI(addr, tlsFiles) if err != nil { log.Fatalf("could not create gRPC client: %v", err) } @@ -54,7 +61,6 @@ func CreateSVI() *cobra.Command { cmd.Flags().StringSliceVar(&gwIPs, "gw-ips", nil, "List of GW IP addresses") cmd.Flags().BoolVar(&ebgp, "ebgp", false, "Enable eBGP in VRF for tenants connected through this SVI") cmd.Flags().Uint32VarP(&remoteAS, "remote-as", "", 0, "The remote AS") - cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") if err := cmd.MarkFlagRequired("vrf"); err != nil { log.Fatalf("Error marking flag as required: %v", err) @@ -76,16 +82,22 @@ func CreateSVI() *cobra.Command { // DeleteSVI delete the svi on OPI server func DeleteSVI() *cobra.Command { - var addr string var name string var allowMissing bool cmd := &cobra.Command{ Use: "delete-svi", Short: "Delete a SVI", - Run: func(_ *cobra.Command, _ []string) { + Run: func(c *cobra.Command, _ []string) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - evpnClient, err := network.NewSVI(addr) + + tlsFiles, err := c.Flags().GetString(common.TLSFiles) + cobra.CheckErr(err) + + addr, err := c.Flags().GetString(common.AddrCmdLineArg) + cobra.CheckErr(err) + + evpnClient, err := network.NewSVI(addr, tlsFiles) if err != nil { log.Fatalf("could not create gRPC client: %v", err) } @@ -102,7 +114,6 @@ func DeleteSVI() *cobra.Command { cmd.Flags().StringVarP(&name, "name", "n", "", "Specify the name of the BridgePort") cmd.Flags().BoolVarP(&allowMissing, "allowMissing", "a", false, "Specify the name of the BridgePort") - cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") if err := cmd.MarkFlagRequired("name"); err != nil { log.Fatalf("Error marking flag as required: %v", err) @@ -112,15 +123,21 @@ func DeleteSVI() *cobra.Command { // GetSVI get svi details from OPI server func GetSVI() *cobra.Command { - var addr string var name string cmd := &cobra.Command{ Use: "get-svi", Short: "Show details of a SVI", - Run: func(_ *cobra.Command, _ []string) { + Run: func(c *cobra.Command, _ []string) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - evpnClient, err := network.NewSVI(addr) + + tlsFiles, err := c.Flags().GetString(common.TLSFiles) + cobra.CheckErr(err) + + addr, err := c.Flags().GetString(common.AddrCmdLineArg) + cobra.CheckErr(err) + + evpnClient, err := network.NewSVI(addr, tlsFiles) if err != nil { log.Fatalf("could not create gRPC client: %v", err) } @@ -136,7 +153,6 @@ func GetSVI() *cobra.Command { } cmd.Flags().StringVarP(&name, "name", "n", "", "Specify the name of the BridgePort") - cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") if err := cmd.MarkFlagRequired("name"); err != nil { log.Fatalf("Error marking flag as required: %v", err) @@ -146,16 +162,22 @@ func GetSVI() *cobra.Command { // ListSVIs get all the svi's from OPI server func ListSVIs() *cobra.Command { - var addr string var pageSize int32 var pageToken string cmd := &cobra.Command{ Use: "list-svis", Short: "Show details of all SVIs", - Run: func(_ *cobra.Command, _ []string) { + Run: func(c *cobra.Command, _ []string) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - evpnClient, err := network.NewSVI(addr) + + tlsFiles, err := c.Flags().GetString(common.TLSFiles) + cobra.CheckErr(err) + + addr, err := c.Flags().GetString(common.AddrCmdLineArg) + cobra.CheckErr(err) + + evpnClient, err := network.NewSVI(addr, tlsFiles) if err != nil { log.Fatalf("could not create gRPC client: %v", err) } @@ -185,13 +207,12 @@ func ListSVIs() *cobra.Command { cmd.Flags().Int32VarP(&pageSize, "pageSize", "s", 0, "Specify the name of the BridgePort") cmd.Flags().StringVarP(&pageToken, "pageToken", "p", "", "Specify the page token") - cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") + return cmd } // UpdateSVI update the svi on OPI server func UpdateSVI() *cobra.Command { - var addr string var name string var updateMask []string var allowMissing bool @@ -199,9 +220,16 @@ func UpdateSVI() *cobra.Command { cmd := &cobra.Command{ Use: "update-svi", Short: "update the SVI", - Run: func(_ *cobra.Command, _ []string) { + Run: func(c *cobra.Command, _ []string) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - evpnClient, err := network.NewSVI(addr) + + tlsFiles, err := c.Flags().GetString(common.TLSFiles) + cobra.CheckErr(err) + + addr, err := c.Flags().GetString(common.AddrCmdLineArg) + cobra.CheckErr(err) + + evpnClient, err := network.NewSVI(addr, tlsFiles) if err != nil { log.Fatalf("could not create gRPC client: %v", err) } @@ -216,8 +244,8 @@ func UpdateSVI() *cobra.Command { PrintSvi(svi) }, } - cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") cmd.Flags().StringSliceVar(&updateMask, "update-mask", nil, "update mask") cmd.Flags().BoolVarP(&allowMissing, "allowMissing", "a", false, "allow the missing") + return cmd } diff --git a/cmd/network/evpn-vrf.go b/cmd/network/evpn-vrf.go index 5f5e0a3..2941c2a 100644 --- a/cmd/network/evpn-vrf.go +++ b/cmd/network/evpn-vrf.go @@ -11,25 +11,31 @@ import ( "log" "time" + "github.com/opiproject/godpu/cmd/common" "github.com/opiproject/godpu/network" "github.com/spf13/cobra" ) // CreateVRF Create vrf on OPI Server func CreateVRF() *cobra.Command { - var addr string var name string var vni uint32 var loopback string var vtep string - cmd := &cobra.Command{ Use: "create-vrf", Short: "Create a VRF", - Run: func(_ *cobra.Command, _ []string) { + Run: func(c *cobra.Command, _ []string) { var vniparam *uint32 ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - evpnClient, err := network.NewVRF(addr) + + tlsFiles, err := c.Flags().GetString(common.TLSFiles) + cobra.CheckErr(err) + + addr, err := c.Flags().GetString(common.AddrCmdLineArg) + cobra.CheckErr(err) + + evpnClient, err := network.NewVRF(addr, tlsFiles) if err != nil { log.Fatalf("could not create gRPC client: %v", err) } @@ -50,7 +56,6 @@ func CreateVRF() *cobra.Command { cmd.Flags().Uint32VarP(&vni, "vni", "v", 0, "Must be unique ") cmd.Flags().StringVar(&loopback, "loopback", "", "Loopback IP address") cmd.Flags().StringVar(&vtep, "vtep", "", "VTEP IP address") - cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") if err := cmd.MarkFlagRequired("loopback"); err != nil { log.Fatalf("Error marking flag as required: %v", err) @@ -60,16 +65,21 @@ func CreateVRF() *cobra.Command { // DeleteVRF update the vrf on OPI server func DeleteVRF() *cobra.Command { - var addr string var name string var allowMissing bool - cmd := &cobra.Command{ Use: "delete-vrf", Short: "Delete a VRF", - Run: func(_ *cobra.Command, _ []string) { + Run: func(c *cobra.Command, _ []string) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - evpnClient, err := network.NewVRF(addr) + + tlsFiles, err := c.Flags().GetString(common.TLSFiles) + cobra.CheckErr(err) + + addr, err := c.Flags().GetString(common.AddrCmdLineArg) + cobra.CheckErr(err) + + evpnClient, err := network.NewVRF(addr, tlsFiles) if err != nil { log.Fatalf("could not create gRPC client: %v", err) } @@ -86,22 +96,25 @@ func DeleteVRF() *cobra.Command { cmd.Flags().StringVarP(&name, "name", "n", "", "Specify the name of the BridgePort") cmd.Flags().BoolVarP(&allowMissing, "allowMissing", "a", false, "Specify the name of the BridgePort") - cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") - return cmd } // GetVRF get vrf details from OPI server func GetVRF() *cobra.Command { - var addr string var name string - cmd := &cobra.Command{ Use: "get-vrf", Short: "Show details of a VRF", - Run: func(_ *cobra.Command, _ []string) { + Run: func(c *cobra.Command, _ []string) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - evpnClient, err := network.NewVRF(addr) + + tlsFiles, err := c.Flags().GetString(common.TLSFiles) + cobra.CheckErr(err) + + addr, err := c.Flags().GetString(common.AddrCmdLineArg) + cobra.CheckErr(err) + + evpnClient, err := network.NewVRF(addr, tlsFiles) if err != nil { log.Fatalf("could not create gRPC client: %v", err) } @@ -119,8 +132,6 @@ func GetVRF() *cobra.Command { } cmd.Flags().StringVarP(&name, "name", "n", "", "Specify the name of the vrf") - cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") - if err := cmd.MarkFlagRequired("name"); err != nil { log.Fatalf("Error marking flag as required: %v", err) } @@ -129,16 +140,21 @@ func GetVRF() *cobra.Command { // ListVRFs list all vrf's with details from OPI server func ListVRFs() *cobra.Command { - var addr string var pageSize int32 var pageToken string - cmd := &cobra.Command{ Use: "list-vrfs", Short: "Show details of all Vrfs", - Run: func(_ *cobra.Command, _ []string) { + Run: func(c *cobra.Command, _ []string) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - evpnClient, err := network.NewVRF(addr) + + tlsFiles, err := c.Flags().GetString(common.TLSFiles) + cobra.CheckErr(err) + + addr, err := c.Flags().GetString(common.AddrCmdLineArg) + cobra.CheckErr(err) + + evpnClient, err := network.NewVRF(addr, tlsFiles) if err != nil { log.Fatalf("could not create gRPC client: %v", err) } @@ -167,23 +183,26 @@ func ListVRFs() *cobra.Command { } cmd.Flags().Int32VarP(&pageSize, "pagesize", "s", 0, "Specify page size") cmd.Flags().StringVarP(&pageToken, "pagetoken", "t", "", "Specify the token") - cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") return cmd } // UpdateVRF update the vrf on OPI server func UpdateVRF() *cobra.Command { - var addr string var name string var updateMask []string var allowMissing bool - cmd := &cobra.Command{ Use: "update-vrf", Short: "update the VRF", - Run: func(_ *cobra.Command, _ []string) { + Run: func(c *cobra.Command, _ []string) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - evpnClient, err := network.NewVRF(addr) + tlsFiles, err := c.Flags().GetString(common.TLSFiles) + cobra.CheckErr(err) + + addr, err := c.Flags().GetString(common.AddrCmdLineArg) + cobra.CheckErr(err) + + evpnClient, err := network.NewVRF(addr, tlsFiles) if err != nil { log.Fatalf("could not create gRPC client: %v", err) } @@ -198,10 +217,8 @@ func UpdateVRF() *cobra.Command { PrintVrf(vrf) }, } - cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") cmd.Flags().StringVarP(&name, "name", "n", "", "Specify the name of the vrf") cmd.Flags().StringSliceVar(&updateMask, "update-mask", nil, "update mask") cmd.Flags().BoolVarP(&allowMissing, "allowMissing", "a", false, "allow the missing") - return cmd } diff --git a/cmd/storage/backend/nvme_controller.go b/cmd/storage/backend/nvme_controller.go index ece917b..885e6a3 100644 --- a/cmd/storage/backend/nvme_controller.go +++ b/cmd/storage/backend/nvme_controller.go @@ -9,7 +9,7 @@ import ( "fmt" "strings" - "github.com/opiproject/godpu/cmd/storage/common" + "github.com/opiproject/godpu/cmd/common" backendclient "github.com/opiproject/godpu/storage/backend" pb "github.com/opiproject/opi-api/storage/v1alpha1/gen/go" "github.com/spf13/cobra" @@ -31,7 +31,10 @@ func newCreateNvmeControllerCommand() *cobra.Command { timeout, err := c.Flags().GetDuration(common.TimeoutCmdLineArg) cobra.CheckErr(err) - client, err := backendclient.New(addr) + tlsFiles, err := c.Flags().GetString(common.TLSFiles) + cobra.CheckErr(err) + + client, err := backendclient.New(addr, tlsFiles) cobra.CheckErr(err) ctx, cancel := context.WithTimeout(context.Background(), timeout) @@ -64,6 +67,7 @@ func newCreateNvmeControllerCommand() *cobra.Command { func newDeleteNvmeControllerCommand() *cobra.Command { name := "" allowMissing := false + cmd := &cobra.Command{ Use: "controller", Aliases: []string{"c"}, @@ -76,7 +80,10 @@ func newDeleteNvmeControllerCommand() *cobra.Command { timeout, err := c.Flags().GetDuration(common.TimeoutCmdLineArg) cobra.CheckErr(err) - client, err := backendclient.New(addr) + tlsFiles, err := c.Flags().GetString(common.TLSFiles) + cobra.CheckErr(err) + + client, err := backendclient.New(addr, tlsFiles) cobra.CheckErr(err) ctx, cancel := context.WithTimeout(context.Background(), timeout) @@ -97,6 +104,7 @@ func newDeleteNvmeControllerCommand() *cobra.Command { func newGetNvmeControllerCommand() *cobra.Command { name := "" + cmd := &cobra.Command{ Use: "controller", Aliases: []string{"c"}, @@ -109,7 +117,10 @@ func newGetNvmeControllerCommand() *cobra.Command { timeout, err := c.Flags().GetDuration(common.TimeoutCmdLineArg) cobra.CheckErr(err) - client, err := backendclient.New(addr) + tlsFiles, err := c.Flags().GetString(common.TLSFiles) + cobra.CheckErr(err) + + client, err := backendclient.New(addr, tlsFiles) cobra.CheckErr(err) ctx, cancel := context.WithTimeout(context.Background(), timeout) diff --git a/cmd/storage/backend/nvme_path.go b/cmd/storage/backend/nvme_path.go index 79e1bb2..c12c37e 100644 --- a/cmd/storage/backend/nvme_path.go +++ b/cmd/storage/backend/nvme_path.go @@ -8,7 +8,7 @@ import ( "context" "net" - "github.com/opiproject/godpu/cmd/storage/common" + "github.com/opiproject/godpu/cmd/common" backendclient "github.com/opiproject/godpu/storage/backend" "github.com/spf13/cobra" "google.golang.org/protobuf/encoding/protojson" @@ -39,6 +39,7 @@ func newCreateNvmePathTCPCommand() *cobra.Command { controller := "" var ip net.IP var port uint16 + cmd := &cobra.Command{ Use: "tcp", Aliases: []string{"t"}, @@ -51,7 +52,10 @@ func newCreateNvmePathTCPCommand() *cobra.Command { timeout, err := c.Flags().GetDuration(common.TimeoutCmdLineArg) cobra.CheckErr(err) - client, err := backendclient.New(addr) + tlsFiles, err := c.Flags().GetString(common.TLSFiles) + cobra.CheckErr(err) + + client, err := backendclient.New(addr, tlsFiles) cobra.CheckErr(err) ctx, cancel := context.WithTimeout(context.Background(), timeout) @@ -83,6 +87,7 @@ func newCreateNvmePathPcieCommand() *cobra.Command { id := "" controller := "" bdf := "" + cmd := &cobra.Command{ Use: "pcie", Aliases: []string{"p"}, @@ -95,7 +100,10 @@ func newCreateNvmePathPcieCommand() *cobra.Command { timeout, err := c.Flags().GetDuration(common.TimeoutCmdLineArg) cobra.CheckErr(err) - client, err := backendclient.New(addr) + tlsFiles, err := c.Flags().GetString(common.TLSFiles) + cobra.CheckErr(err) + + client, err := backendclient.New(addr, tlsFiles) cobra.CheckErr(err) ctx, cancel := context.WithTimeout(context.Background(), timeout) @@ -120,6 +128,7 @@ func newCreateNvmePathPcieCommand() *cobra.Command { func newDeleteNvmePathCommand() *cobra.Command { name := "" + allowMissing := false cmd := &cobra.Command{ Use: "path", @@ -133,7 +142,10 @@ func newDeleteNvmePathCommand() *cobra.Command { timeout, err := c.Flags().GetDuration(common.TimeoutCmdLineArg) cobra.CheckErr(err) - client, err := backendclient.New(addr) + tlsFiles, err := c.Flags().GetString(common.TLSFiles) + cobra.CheckErr(err) + + client, err := backendclient.New(addr, tlsFiles) cobra.CheckErr(err) ctx, cancel := context.WithTimeout(context.Background(), timeout) @@ -154,6 +166,7 @@ func newDeleteNvmePathCommand() *cobra.Command { func newGetNvmePathCommand() *cobra.Command { name := "" + cmd := &cobra.Command{ Use: "path", Aliases: []string{"p"}, @@ -166,7 +179,10 @@ func newGetNvmePathCommand() *cobra.Command { timeout, err := c.Flags().GetDuration(common.TimeoutCmdLineArg) cobra.CheckErr(err) - client, err := backendclient.New(addr) + tlsFiles, err := c.Flags().GetString(common.TLSFiles) + cobra.CheckErr(err) + + client, err := backendclient.New(addr, tlsFiles) cobra.CheckErr(err) ctx, cancel := context.WithTimeout(context.Background(), timeout) @@ -180,7 +196,6 @@ func newGetNvmePathCommand() *cobra.Command { } cmd.Flags().StringVar(&name, "name", "", "name of path to get") - cobra.CheckErr(cmd.MarkFlagRequired("name")) return cmd diff --git a/cmd/storage/frontend/nvme_controller.go b/cmd/storage/frontend/nvme_controller.go index 0b79a9e..c3f5944 100644 --- a/cmd/storage/frontend/nvme_controller.go +++ b/cmd/storage/frontend/nvme_controller.go @@ -8,7 +8,7 @@ import ( "context" "net" - "github.com/opiproject/godpu/cmd/storage/common" + "github.com/opiproject/godpu/cmd/common" frontendclient "github.com/opiproject/godpu/storage/frontend" "github.com/spf13/cobra" ) @@ -36,6 +36,7 @@ func newCreateNvmeControllerTCPCommand() *cobra.Command { subsystem := "" var ip net.IP var port uint16 + cmd := &cobra.Command{ Use: "tcp", Aliases: []string{"t"}, @@ -48,7 +49,10 @@ func newCreateNvmeControllerTCPCommand() *cobra.Command { timeout, err := c.Flags().GetDuration(common.TimeoutCmdLineArg) cobra.CheckErr(err) - client, err := frontendclient.New(addr) + tlsFiles, err := c.Flags().GetString(common.TLSFiles) + cobra.CheckErr(err) + + client, err := frontendclient.New(addr, tlsFiles) cobra.CheckErr(err) ctx, cancel := context.WithTimeout(context.Background(), timeout) @@ -79,6 +83,7 @@ func newCreateNvmeControllerPcieCommand() *cobra.Command { var port uint var pf uint var vf uint + cmd := &cobra.Command{ Use: "pcie", Aliases: []string{"p"}, @@ -91,7 +96,10 @@ func newCreateNvmeControllerPcieCommand() *cobra.Command { timeout, err := c.Flags().GetDuration(common.TimeoutCmdLineArg) cobra.CheckErr(err) - client, err := frontendclient.New(addr) + tlsFiles, err := c.Flags().GetString(common.TLSFiles) + cobra.CheckErr(err) + + client, err := frontendclient.New(addr, tlsFiles) cobra.CheckErr(err) ctx, cancel := context.WithTimeout(context.Background(), timeout) @@ -120,6 +128,7 @@ func newCreateNvmeControllerPcieCommand() *cobra.Command { func newDeleteNvmeControllerCommand() *cobra.Command { name := "" allowMissing := false + cmd := &cobra.Command{ Use: "controller", Aliases: []string{"c"}, @@ -132,7 +141,10 @@ func newDeleteNvmeControllerCommand() *cobra.Command { timeout, err := c.Flags().GetDuration(common.TimeoutCmdLineArg) cobra.CheckErr(err) - client, err := frontendclient.New(addr) + tlsFiles, err := c.Flags().GetString(common.TLSFiles) + cobra.CheckErr(err) + + client, err := frontendclient.New(addr, tlsFiles) cobra.CheckErr(err) ctx, cancel := context.WithTimeout(context.Background(), timeout) diff --git a/cmd/storage/frontend/nvme_namespace.go b/cmd/storage/frontend/nvme_namespace.go index f581add..9251d0a 100644 --- a/cmd/storage/frontend/nvme_namespace.go +++ b/cmd/storage/frontend/nvme_namespace.go @@ -7,7 +7,7 @@ package frontend import ( "context" - "github.com/opiproject/godpu/cmd/storage/common" + "github.com/opiproject/godpu/cmd/common" frontendclient "github.com/opiproject/godpu/storage/frontend" "github.com/spf13/cobra" ) @@ -16,6 +16,7 @@ func newCreateNvmeNamespaceCommand() *cobra.Command { id := "" subsystem := "" volume := "" + cmd := &cobra.Command{ Use: "namespace", Aliases: []string{"n"}, @@ -28,7 +29,10 @@ func newCreateNvmeNamespaceCommand() *cobra.Command { timeout, err := c.Flags().GetDuration(common.TimeoutCmdLineArg) cobra.CheckErr(err) - client, err := frontendclient.New(addr) + tlsFiles, err := c.Flags().GetString(common.TLSFiles) + cobra.CheckErr(err) + + client, err := frontendclient.New(addr, tlsFiles) cobra.CheckErr(err) ctx, cancel := context.WithTimeout(context.Background(), timeout) @@ -54,6 +58,7 @@ func newCreateNvmeNamespaceCommand() *cobra.Command { func newDeleteNvmeNamespaceCommand() *cobra.Command { name := "" allowMissing := false + cmd := &cobra.Command{ Use: "namespace", Aliases: []string{"d"}, @@ -66,7 +71,10 @@ func newDeleteNvmeNamespaceCommand() *cobra.Command { timeout, err := c.Flags().GetDuration(common.TimeoutCmdLineArg) cobra.CheckErr(err) - client, err := frontendclient.New(addr) + tlsFiles, err := c.Flags().GetString(common.TLSFiles) + cobra.CheckErr(err) + + client, err := frontendclient.New(addr, tlsFiles) cobra.CheckErr(err) ctx, cancel := context.WithTimeout(context.Background(), timeout) diff --git a/cmd/storage/frontend/nvme_subsystem.go b/cmd/storage/frontend/nvme_subsystem.go index 0ea38b1..3df6919 100644 --- a/cmd/storage/frontend/nvme_subsystem.go +++ b/cmd/storage/frontend/nvme_subsystem.go @@ -7,7 +7,7 @@ package frontend import ( "context" - "github.com/opiproject/godpu/cmd/storage/common" + "github.com/opiproject/godpu/cmd/common" frontendclient "github.com/opiproject/godpu/storage/frontend" "github.com/spf13/cobra" ) @@ -16,6 +16,7 @@ func newCreateNvmeSubsystemCommand() *cobra.Command { id := "" nqn := "" hostnqn := "" + cmd := &cobra.Command{ Use: "subsystem", Aliases: []string{"s"}, @@ -28,7 +29,10 @@ func newCreateNvmeSubsystemCommand() *cobra.Command { timeout, err := c.Flags().GetDuration(common.TimeoutCmdLineArg) cobra.CheckErr(err) - client, err := frontendclient.New(addr) + tlsFiles, err := c.Flags().GetString(common.TLSFiles) + cobra.CheckErr(err) + + client, err := frontendclient.New(addr, tlsFiles) cobra.CheckErr(err) ctx, cancel := context.WithTimeout(context.Background(), timeout) @@ -53,6 +57,7 @@ func newCreateNvmeSubsystemCommand() *cobra.Command { func newDeleteNvmeSubsystemCommand() *cobra.Command { name := "" allowMissing := false + cmd := &cobra.Command{ Use: "subsystem", Aliases: []string{"s"}, @@ -65,7 +70,10 @@ func newDeleteNvmeSubsystemCommand() *cobra.Command { timeout, err := c.Flags().GetDuration(common.TimeoutCmdLineArg) cobra.CheckErr(err) - client, err := frontendclient.New(addr) + tlsFiles, err := c.Flags().GetString(common.TLSFiles) + cobra.CheckErr(err) + + client, err := frontendclient.New(addr, tlsFiles) cobra.CheckErr(err) ctx, cancel := context.WithTimeout(context.Background(), timeout) diff --git a/cmd/storage/frontend/virtio_blk.go b/cmd/storage/frontend/virtio_blk.go index b1abb7e..c8bd60a 100644 --- a/cmd/storage/frontend/virtio_blk.go +++ b/cmd/storage/frontend/virtio_blk.go @@ -7,7 +7,7 @@ package frontend import ( "context" - "github.com/opiproject/godpu/cmd/storage/common" + "github.com/opiproject/godpu/cmd/common" frontendclient "github.com/opiproject/godpu/storage/frontend" "github.com/spf13/cobra" ) @@ -19,6 +19,7 @@ func newCreateVirtioBlkCommand() *cobra.Command { var pf uint var vf uint var maxIoQPS uint + cmd := &cobra.Command{ Use: "blk", Aliases: []string{"b"}, @@ -31,7 +32,10 @@ func newCreateVirtioBlkCommand() *cobra.Command { timeout, err := c.Flags().GetDuration(common.TimeoutCmdLineArg) cobra.CheckErr(err) - client, err := frontendclient.New(addr) + tlsFiles, err := c.Flags().GetString(common.TLSFiles) + cobra.CheckErr(err) + + client, err := frontendclient.New(addr, tlsFiles) cobra.CheckErr(err) ctx, cancel := context.WithTimeout(context.Background(), timeout) @@ -61,6 +65,7 @@ func newCreateVirtioBlkCommand() *cobra.Command { func newDeleteVirtioBlkCommand() *cobra.Command { name := "" allowMissing := false + cmd := &cobra.Command{ Use: "blk", Aliases: []string{"b"}, @@ -73,7 +78,10 @@ func newDeleteVirtioBlkCommand() *cobra.Command { timeout, err := c.Flags().GetDuration(common.TimeoutCmdLineArg) cobra.CheckErr(err) - client, err := frontendclient.New(addr) + tlsFiles, err := c.Flags().GetString(common.TLSFiles) + cobra.CheckErr(err) + + client, err := frontendclient.New(addr, tlsFiles) cobra.CheckErr(err) ctx, cancel := context.WithTimeout(context.Background(), timeout) diff --git a/cmd/storage/storage.go b/cmd/storage/storage.go index 12829b7..f4f9d6f 100644 --- a/cmd/storage/storage.go +++ b/cmd/storage/storage.go @@ -7,8 +7,8 @@ package storage import ( "time" + "github.com/opiproject/godpu/cmd/common" "github.com/opiproject/godpu/cmd/storage/backend" - "github.com/opiproject/godpu/cmd/storage/common" "github.com/opiproject/godpu/cmd/storage/frontend" "github.com/spf13/cobra" ) @@ -27,7 +27,6 @@ func NewStorageCommand() *cobra.Command { } flags := cmd.PersistentFlags() - flags.String(common.AddrCmdLineArg, "localhost:50151", "address of OPI gRPC server") flags.Duration(common.TimeoutCmdLineArg, 10*time.Second, "timeout for a cmd") cmd.AddCommand(newStorageCreateCommand()) diff --git a/cmd/storage/test.go b/cmd/storage/test.go index 9148fb6..e74e2a9 100644 --- a/cmd/storage/test.go +++ b/cmd/storage/test.go @@ -9,7 +9,7 @@ import ( "context" "log" - "github.com/opiproject/godpu/cmd/storage/common" + "github.com/opiproject/godpu/cmd/common" "github.com/opiproject/godpu/grpc" "github.com/opiproject/godpu/storage/test" "github.com/spf13/cobra" @@ -155,7 +155,7 @@ func runTests( } // Set up a connection to the server. - client, err := grpc.New(addr) + client, err := grpc.New(addr, "") if err != nil { log.Fatalf("error creating new client: %v", err) } diff --git a/docker-compose.yml b/docker-compose.yml index 0b52d3b..f9b73e9 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -142,7 +142,7 @@ services: - NET_ADMIN networks: - opi - command: /opi-evpn-bridge -grpc_port=50151 -http_port=8082 -redis_addr="redis:6379" -frr_addr="frr" + command: /opi-evpn-bridge --grpcport=50151 --httpport=8082 --dbaddress="redis:6379" --database=redis healthcheck: test: grpcurl -plaintext localhost:50151 list || exit 1 depends_on: diff --git a/grpc/client.go b/grpc/client.go index a933bc3..3f4f3f3 100644 --- a/grpc/client.go +++ b/grpc/client.go @@ -6,6 +6,7 @@ package grpc import ( "errors" + "fmt" "log" "google.golang.org/grpc" @@ -13,8 +14,9 @@ import ( ) type clientImpl struct { - addr string // address of OPI gRPC server - d Dialler + addr string // address of OPI gRPC server + d Dialler + tlsfile string } // Dialler defines the function type that creates a gRPC connection @@ -29,12 +31,12 @@ type Connector interface { } // New returns a new gRPC connector for the server at the given address -func New(address string) (Connector, error) { - return NewWithDialler(address, grpc.Dial) +func New(address string, tlsfile string) (Connector, error) { + return NewWithDialler(address, grpc.Dial, tlsfile) } // NewWithDialler returns a new gRPC client for the server at the given address using the gRPC dialler provided -func NewWithDialler(address string, d Dialler) (Connector, error) { +func NewWithDialler(address string, d Dialler, tls string) (Connector, error) { if len(address) == 0 { return nil, errors.New("cannot use empty address") } @@ -44,13 +46,36 @@ func NewWithDialler(address string, d Dialler) (Connector, error) { } return clientImpl{ - addr: address, - d: d, + addr: address, + d: d, + tlsfile: tls, }, nil } // NewConn creates a new gRPC connection func (c clientImpl) NewConn() (grpc.ClientConnInterface, Closer, error) { + log.Println("files", c.tlsfile) + if c.tlsfile != "" { + config, err := ParseTLSFiles(c.tlsfile) + if err != nil { + return nil, nil, fmt.Errorf("failed to parse TLS files: %v", err) + } + option, err := SetupTLSCredentials(config) + if err != nil { + return nil, nil, fmt.Errorf("failed to setup TLS credentials: %v", err) + } + conn, err := c.d(c.addr, grpc.WithTransportCredentials(option)) + if err != nil { + return nil, nil, err + } + closer := func() { + err := conn.Close() + if err != nil { + log.Fatalf("did not close connection: %v", err) + } + } + return conn, closer, nil + } conn, err := c.d(c.addr, grpc.WithTransportCredentials(insecure.NewCredentials())) if err != nil { return nil, nil, err diff --git a/grpc/client_test.go b/grpc/client_test.go index 3527b77..927128e 100644 --- a/grpc/client_test.go +++ b/grpc/client_test.go @@ -23,7 +23,7 @@ var _ = Describe("gRPC", func() { Context("using a non-empty address", func() { BeforeEach(func() { addr = "localhost:1234" - c, err = grpcOpi.New(addr) + c, err = grpcOpi.New(addr, "") }) It("should return a client", func() { @@ -36,7 +36,7 @@ var _ = Describe("gRPC", func() { Context("and specifying a valid dialler", func() { BeforeEach(func() { dialler = diallerNoError - c, err = grpcOpi.NewWithDialler(addr, dialler) + c, err = grpcOpi.NewWithDialler(addr, dialler, "") }) It("should return a client", func() { @@ -49,7 +49,7 @@ var _ = Describe("gRPC", func() { Context("and specifying an invalid dialler", func() { BeforeEach(func() { dialler = nil - c, err = grpcOpi.NewWithDialler(addr, dialler) + c, err = grpcOpi.NewWithDialler(addr, dialler, "") }) It("should not return a client", func() { @@ -64,7 +64,7 @@ var _ = Describe("gRPC", func() { Context("using an empty address", func() { BeforeEach(func() { addr = "" - c, err = grpcOpi.New(addr) + c, err = grpcOpi.New(addr, "") }) It("should not return a client", func() { @@ -77,7 +77,7 @@ var _ = Describe("gRPC", func() { Context("and specifying a valid dialler", func() { BeforeEach(func() { dialler = diallerNoError - c, err = grpcOpi.NewWithDialler(addr, dialler) + c, err = grpcOpi.NewWithDialler(addr, dialler, "") }) It("should not return a client", func() { @@ -91,7 +91,7 @@ var _ = Describe("gRPC", func() { Context("and specifying an invalid dialler", func() { BeforeEach(func() { dialler = nil - c, err = grpcOpi.NewWithDialler(addr, dialler) + c, err = grpcOpi.NewWithDialler(addr, dialler, "") }) It("should not return a client", func() { @@ -116,7 +116,7 @@ var _ = Describe("gRPC", func() { Context("and a connection can be created", func() { BeforeEach(func() { dialler = diallerNoError - c, _ := grpcOpi.NewWithDialler(addr, dialler) + c, _ := grpcOpi.NewWithDialler(addr, dialler, "") conn, closer, err = c.NewConn() }) @@ -136,7 +136,7 @@ var _ = Describe("gRPC", func() { Context("and a connection cannot be created", func() { BeforeEach(func() { dialler = diallerWithError - c, _ := grpcOpi.NewWithDialler(addr, dialler) + c, _ := grpcOpi.NewWithDialler(addr, dialler, "") conn, closer, err = c.NewConn() }) diff --git a/grpc/tls.go b/grpc/tls.go new file mode 100644 index 0000000..74704d8 --- /dev/null +++ b/grpc/tls.go @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2023 Intel Corporation + +// Package grpc contains utility functions +package grpc + +import ( + "crypto/tls" + "crypto/x509" + "errors" + "fmt" + "log" + "os" + "strings" + + "google.golang.org/grpc/credentials" +) + +// TLSConfig contains information required to enable TLS for gRPC client. +type TLSConfig struct { + ClientCertPath string + ClientKeyPath string + CaCertPath string +} + +// ParseTLSFiles parses a string containing server certificate, +// server key and CA certificate separated by `:` +func ParseTLSFiles(tlsFiles string) (TLSConfig, error) { + files := strings.Split(tlsFiles, ":") + + numOfFiles := len(files) + if numOfFiles != 3 { + return TLSConfig{}, errors.New("wrong number of path entries provided." + + "Expect :: are provided separated by `:`") + } + + tls := TLSConfig{} + + const emptyPathErr = "empty %s path is not allowed" + tls.ClientCertPath = files[0] + if tls.ClientCertPath == "" { + return TLSConfig{}, fmt.Errorf(emptyPathErr, "server cert") + } + + tls.ClientKeyPath = files[1] + if tls.ClientKeyPath == "" { + return TLSConfig{}, fmt.Errorf(emptyPathErr, "server key") + } + + tls.CaCertPath = files[2] + if tls.CaCertPath == "" { + return TLSConfig{}, fmt.Errorf(emptyPathErr, "CA cert") + } + + return tls, nil +} + +// SetupTLSCredentials returns a service options to enable TLS for gRPC client +func SetupTLSCredentials(config TLSConfig) (credentials.TransportCredentials, error) { + return setupTLSCredentials(config, tls.LoadX509KeyPair, os.ReadFile) +} + +func setupTLSCredentials(config TLSConfig, + loadX509KeyPair func(string, string) (tls.Certificate, error), + readFile func(string) ([]byte, error), +) (credentials.TransportCredentials, error) { + clientCert, err := loadX509KeyPair(config.ClientCertPath, config.ClientKeyPath) + if err != nil { + return nil, err + } + c := &tls.Config{ + Certificates: []tls.Certificate{clientCert}, + MinVersion: tls.VersionTLS12, + CipherSuites: []uint16{ + tls.TLS_AES_256_GCM_SHA384, + tls.TLS_AES_128_GCM_SHA256, + tls.TLS_CHACHA20_POLY1305_SHA256, + tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + }, + } + + c.RootCAs = x509.NewCertPool() + log.Println("Loading client ca certificate:", config.CaCertPath) + + clientCaCert, err := readFile(config.CaCertPath) + if err != nil { + return nil, fmt.Errorf("failed to read certificate: %v. error: %v", config.CaCertPath, err) + } + + if !c.RootCAs.AppendCertsFromPEM(clientCaCert) { + return nil, fmt.Errorf("failed to add client CA's certificate: %v", config.CaCertPath) + } + + return credentials.NewTLS(c), nil +} diff --git a/inventory/client.go b/inventory/client.go index ca5bef6..2d541ce 100644 --- a/inventory/client.go +++ b/inventory/client.go @@ -28,8 +28,8 @@ type InvClient interface { } // New creates an inventory client for use with OPI server at the given address -func New(addr string) (InvClient, error) { - c, err := grpcOpi.New(addr) +func New(addr string, tls string) (InvClient, error) { + c, err := grpcOpi.New(addr, tls) if err != nil { return nil, err } diff --git a/inventory/client_test.go b/inventory/client_test.go index e712d3b..0487c6b 100644 --- a/inventory/client_test.go +++ b/inventory/client_test.go @@ -31,7 +31,7 @@ var _ = Describe("Inventory", func() { Context("using a non-empty address", func() { BeforeEach(func() { addr = "localhost:1234" - c, err = inventory.New(addr) + c, err = inventory.New(addr, "") }) It("should return a client", func() { @@ -45,7 +45,7 @@ var _ = Describe("Inventory", func() { Context("using an empty address", func() { BeforeEach(func() { addr = "" - c, err = inventory.New(addr) + c, err = inventory.New(addr, "") }) It("should not return a client", func() { diff --git a/main.go b/main.go index 9711cfb..fc877a6 100644 --- a/main.go +++ b/main.go @@ -6,41 +6,13 @@ package main import ( "log" - "os" - "github.com/opiproject/godpu/cmd/inventory" - "github.com/opiproject/godpu/cmd/ipsec" - "github.com/opiproject/godpu/cmd/network" - "github.com/opiproject/godpu/cmd/storage" - "github.com/spf13/cobra" + "github.com/opiproject/godpu/cmd" ) func main() { - command := newCommand() + command := cmd.NewCommand() if err := command.Execute(); err != nil { log.Fatalf("[ERROR] %s", err.Error()) } } - -func newCommand() *cobra.Command { - // - // This is the root command for the CLI - // - - c := &cobra.Command{ - Use: "godpu", - Short: "godpu - DPUs and IPUs cli commands", - Run: func(cmd *cobra.Command, _ []string) { - err := cmd.Help() - if err != nil { - log.Fatalf("[ERROR] %s", err.Error()) - } - os.Exit(1) - }, - } - c.AddCommand(inventory.NewInventoryCommand()) - c.AddCommand(ipsec.NewIPSecCommand()) - c.AddCommand(storage.NewStorageCommand()) - c.AddCommand(network.NewEvpnCommand()) - return c -} diff --git a/network/evpn.go b/network/evpn.go index bbdeb44..bbd7c5c 100644 --- a/network/evpn.go +++ b/network/evpn.go @@ -77,8 +77,8 @@ func resourceIDToFullName(container string, resourceID string) string { } // NewLogicalBridge creates an evpn Logical Bridge client for use with OPI server at the given address -func NewLogicalBridge(addr string) (EvpnClient, error) { - c, err := grpcOpi.New(addr) +func NewLogicalBridge(addr string, tls string) (EvpnClient, error) { + c, err := grpcOpi.New(addr, tls) if err != nil { return nil, err } @@ -106,8 +106,8 @@ func NewLogicalBridgeWithArgs(c grpcOpi.Connector, getter PbEvpnLogicalBridgeCli } // NewBridgePort creates an evpn Bridge Port client for use with OPI server at the given address -func NewBridgePort(addr string) (EvpnClient, error) { - c, err := grpcOpi.New(addr) +func NewBridgePort(addr string, tls string) (EvpnClient, error) { + c, err := grpcOpi.New(addr, tls) if err != nil { return nil, err } @@ -135,8 +135,8 @@ func NewBridgePortWithArgs(c grpcOpi.Connector, getter PbEvpnBridgePortClientGet } // NewVRF creates an evpn VRF client for use with OPI server at the given address -func NewVRF(addr string) (EvpnClient, error) { - c, err := grpcOpi.New(addr) +func NewVRF(addr string, tls string) (EvpnClient, error) { + c, err := grpcOpi.New(addr, tls) if err != nil { return nil, err } @@ -164,8 +164,8 @@ func NewVRFWithArgs(c grpcOpi.Connector, getter PbEvpnVRFClientGetter) (EvpnClie } // NewSVI creates an evpn SVI client for use with OPI server at the given address -func NewSVI(addr string) (EvpnClient, error) { - c, err := grpcOpi.New(addr) +func NewSVI(addr string, tls string) (EvpnClient, error) { + c, err := grpcOpi.New(addr, tls) if err != nil { return nil, err } diff --git a/network/evpn_test.go b/network/evpn_test.go index 5542626..1c858bc 100644 --- a/network/evpn_test.go +++ b/network/evpn_test.go @@ -29,7 +29,7 @@ func TestNewLogicalBridge(t *testing.T) { for testName, tt := range tests { t.Run(testName, func(t *testing.T) { - client, err := NewLogicalBridge(tt.address) + client, err := NewLogicalBridge(tt.address, "") if (err != nil) == !tt.wantErr { t.Errorf("expected err: %v, received: %v", tt.wantErr, err) } @@ -60,7 +60,7 @@ func TestNewBridgePort(t *testing.T) { for testName, tt := range tests { t.Run(testName, func(t *testing.T) { - client, err := NewBridgePort(tt.address) + client, err := NewBridgePort(tt.address, "") if (err != nil) == !tt.wantErr { t.Errorf("expected err: %v, received: %v", tt.wantErr, err) } @@ -91,7 +91,7 @@ func TestNewVRF(t *testing.T) { for testName, tt := range tests { t.Run(testName, func(t *testing.T) { - client, err := NewVRF(tt.address) + client, err := NewVRF(tt.address, "") if (err != nil) == !tt.wantErr { t.Errorf("expected err: %v, received: %v", tt.wantErr, err) } @@ -122,7 +122,7 @@ func TestNewSVI(t *testing.T) { for testName, tt := range tests { t.Run(testName, func(t *testing.T) { - client, err := NewSVI(tt.address) + client, err := NewSVI(tt.address, "") if (err != nil) == !tt.wantErr { t.Errorf("expected err: %v, received: %v", tt.wantErr, err) } diff --git a/storage/backend/client.go b/storage/backend/client.go index f4e155f..2609861 100644 --- a/storage/backend/client.go +++ b/storage/backend/client.go @@ -20,8 +20,8 @@ type Client struct { } // New creates a new instance of Client -func New(addr string) (*Client, error) { - connector, err := grpcOpi.New(addr) +func New(addr string, tls string) (*Client, error) { + connector, err := grpcOpi.New(addr, tls) if err != nil { return nil, err } diff --git a/storage/backend/client_test.go b/storage/backend/client_test.go index 385826a..ead31e2 100644 --- a/storage/backend/client_test.go +++ b/storage/backend/client_test.go @@ -28,7 +28,7 @@ func TestNewClient(t *testing.T) { for testName, tt := range tests { t.Run(testName, func(t *testing.T) { - client, err := New(tt.address) + client, err := New(tt.address, "") if (err != nil) == !tt.wantErr { t.Errorf("expected err: %v, received: %v", tt.wantErr, err) } diff --git a/storage/frontend/client.go b/storage/frontend/client.go index 15b80ff..e65ec02 100644 --- a/storage/frontend/client.go +++ b/storage/frontend/client.go @@ -24,8 +24,8 @@ type Client struct { } // New creates a new instance of Client -func New(addr string) (*Client, error) { - connector, err := grpcOpi.New(addr) +func New(addr string, tls string) (*Client, error) { + connector, err := grpcOpi.New(addr, tls) if err != nil { return nil, err } diff --git a/storage/frontend/client_test.go b/storage/frontend/client_test.go index 7e6d0a7..0f32fa6 100644 --- a/storage/frontend/client_test.go +++ b/storage/frontend/client_test.go @@ -28,7 +28,7 @@ func TestNewClient(t *testing.T) { for testName, tt := range tests { t.Run(testName, func(t *testing.T) { - client, err := New(tt.address) + client, err := New(tt.address, "") if (err != nil) == !tt.wantErr { t.Errorf("expected err: %v, received: %v", tt.wantErr, err) }