From a7bdc7c6c043f2d6c6a5dafcbdfeff6ba33e7cdb Mon Sep 17 00:00:00 2001
From: Martin Stiemerling <mls.ietf@gmail.com>
Date: Fri, 25 Sep 2020 17:40:05 +0200
Subject: [PATCH] gosdn-cli with working command selection. Stubs mostly for
 grpc calls.

---
 gosdn-cli/gosdn-cli.go | 125 +++++++++++++++++++++++++++++++++++++++--
 1 file changed, 120 insertions(+), 5 deletions(-)

diff --git a/gosdn-cli/gosdn-cli.go b/gosdn-cli/gosdn-cli.go
index 1c15073d8..da4cf1750 100644
--- a/gosdn-cli/gosdn-cli.go
+++ b/gosdn-cli/gosdn-cli.go
@@ -3,10 +3,13 @@ package main
 import (
 	pb "code.fbi.h-da.de/cocsn/gosdn/cliInterface"
 	"context"
+	"fmt"
+	"github.com/rivo/tview"
 	"google.golang.org/grpc"
 	"log"
 	"os"
 	"time"
+	"flag"
 )
 
 const (
@@ -14,16 +17,110 @@ const (
 	defaultName = "gosdn-cli"
 )
 
-// Based on the helloworld example of grpc.io
+// Based on the helloworld example of grpc.io -- thx!
+
+const refreshInterval = 500 * time.Millisecond
+
+var (
+	view *tview.Modal
+	app  *tview.Application
+)
+
+type cliClientConfig struct {
+	goSDNCLIAddr4 *string
+	goSDNCLIPort4 *int
+	interactive *bool
+	goSDNCommand *string
+}
+
+type commandOptions struct {
+	name string
+	description string
+	command func(conn *grpc.ClientConn) ()
+}
+
+var commandList = map[string] commandOptions {
+	"hello": {"hello", "test connection to goSDN controller", goSDNSayHello},
+	"shutdown": {"shutdown", "request goSDN controller to shutdown", goSDNShutdown},
+	"testdb" :  {"testdb", "test all database connections", goSDNTestDB},
+}
+
+/*
+	gosdn-cli allows to mode of operations:
+	- interactive: text GUI to operate goSDN
+    - non-interactive: basic CLI without text GUI
+ */
 
 func main() {
+	// This holds the basic configuration for gosdn-cli
+	var myConfiguration = new(cliClientConfig)
+
+	myConfiguration.goSDNCLIAddr4 = flag.String("cliServerAddr", "127.0.0.1", "The IPv4 Address of the grpcCLI.")
+	myConfiguration.goSDNCLIPort4 = flag.Int("cliServerPort", 55055, "The port number of the grpcCLI")
+	myConfiguration.interactive = flag.Bool("interactive", false, "interactive: text gui or just not")
+	var printCommandList = flag.Bool("commandlist", false, "interactive: print command list")
+	myConfiguration.goSDNCommand = flag.String("command", "", "-command: <your command> ; show commands with -commandlist")
+
+	flag.Parse()
+
+	// Print complete command list and exit
+	if (*printCommandList == true) {
+		for _, element := range commandList {
+			fmt.Println(element.name + "\t" + element.description)
+		}
+		os.Exit(0)
+	}
+
+	log.Println("Starting " + defaultName + " to access the goSDN controller")
+	// Prepare string with socket for connection to the goSDN controller
+	goSDNSocketAddress := fmt.Sprintf("%s:%d", *myConfiguration.goSDNCLIAddr4, *myConfiguration.goSDNCLIPort4)
+
+	log.Println("Connecting to the goSDN server at: " + goSDNSocketAddress)
 	// Set up a connection to the server.
 	address := "localhost:55055"
+
 	conn, err := grpc.Dial(address, grpc.WithInsecure(), grpc.WithBlock())
 	if err != nil {
 		log.Fatalf("did not connect: %v", err)
 	}
 	defer conn.Close()
+	log.Println(("Connected to " + conn.Target()))
+
+	// Check for non-interactive or interactive mode
+	if(*myConfiguration.interactive == false) {
+		log.Println("starting in non-interactive mode")
+		// Lookup command or die
+		_, found := commandList[*myConfiguration.goSDNCommand]
+		if(found) {
+			// Excecute desired command
+			commandList[*myConfiguration.goSDNCommand].command(conn)
+		} else {
+			log.Fatalf("Your desired command %s is not available", commandList[*myConfiguration.goSDNCommand].name)
+			os.Exit(1)
+		}
+
+	} else {
+		log.Println("starting in interactive mode -- do not use yet")
+		os.Exit(1)
+
+		app = tview.NewApplication().EnableMouse(true)
+
+		flex := tview.NewFlex().
+			AddItem(tview.NewBox().SetBorder(true).SetTitle("Command List"), 0, 1, false).
+			AddItem(tview.NewFlex().SetDirection(tview.FlexRow).
+				AddItem(tview.NewBox().SetBorder(true).SetTitle("Top"), 0, 1, false).
+				AddItem(tview.NewBox().SetBorder(true).SetTitle("Middle (3 x height of Top)"), 0, 3, false).
+				AddItem(tview.NewBox().SetBorder(true).SetTitle("Bottom (5 rows)"), 5, 1, false), 0, 2, false)
+
+		if err := app.SetRoot(flex, true).Run(); err != nil {
+			panic(err)
+		}
+	}
+}
+
+
+func goSDNSayHello (conn *grpc.ClientConn) {
+
 	c := pb.NewGreeterClient(conn)
 
 	// Contact the server and print out its response.
@@ -35,13 +132,31 @@ func main() {
 	defer cancel()
 	r, err := c.SayHello(ctx, &pb.HelloRequest{Name: name})
 	if err != nil {
-		log.Fatalf("could not greet: %v", err)
+		log.Fatalf("could not say hello: %v", err)
 	}
 	log.Printf("Greeting: %s", r.GetMessage())
 
-	r2, err := c.Shutdown(ctx, &pb.ShutdownRequest{Name: name})
+
+}
+
+func goSDNShutdown (conn *grpc.ClientConn) {
+
+	c := pb.NewGreeterClient(conn)
+
+	// Contact the server and print out its response.
+	name := defaultName
+	if len(os.Args) > 1 {
+		name = os.Args[1]
+	}
+	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
+	defer cancel()
+	r, err := c.Shutdown(ctx, &pb.ShutdownRequest{Name: name})
 	if err != nil {
-		log.Fatalf("could not greet: %v", err)
+		log.Fatalf("could not request shutdown: %v", err)
 	}
-	log.Printf("Greeting: %s", r2.GetMessage())
+	log.Printf("Greeting: %s", r.GetMessage())
 }
+
+func goSDNTestDB(conn *grpc.ClientConn){
+	// TODO: fill with code
+}
\ No newline at end of file
-- 
GitLab