SEBA-688 implement mock gRPC server and unit test the version command

Change-Id: Ia10a8ea5b00ce5d5100f8fffbefba96f234d4b32
diff --git a/commands/command.go b/commands/command.go
index 6d975cf..4a38d5b 100644
--- a/commands/command.go
+++ b/commands/command.go
@@ -22,6 +22,7 @@
 	"github.com/opencord/cordctl/format"
 	"google.golang.org/grpc"
 	"gopkg.in/yaml.v2"
+	"io"
 	"io/ioutil"
 	"log"
 	"os"
@@ -37,6 +38,9 @@
 	OUTPUT_YAML
 )
 
+// Make it easy to override output stream for testing
+var OutputStream io.Writer = os.Stdout
+
 var CharReplacer = strings.NewReplacer("\\t", "\t", "\\n", "\n")
 
 type GrpcConfigSpec struct {
@@ -55,6 +59,7 @@
 	Server   string        `yaml:"server"`
 	Username string        `yaml:"username"`
 	Password string        `yaml:"password"`
+	Protoset string        `yaml:"protoset"`
 	Tls      TlsConfigSpec `yaml:"tls"`
 	Grpc     GrpcConfigSpec
 }
@@ -74,6 +79,7 @@
 	Server   string `short:"s" long:"server" default:"" value-name:"SERVER:PORT" description:"IP/Host and port of XOS"`
 	Username string `short:"u" long:"username" value-name:"USERNAME" default:"" description:"Username to authenticate with XOS"`
 	Password string `short:"p" long:"password" value-name:"PASSWORD" default:"" description:"Password to authenticate with XOS"`
+	Protoset string `long:"protoset" value-name:"FILENAME" description:"Load protobuf definitions from protoset instead of reflection api"`
 	Debug    bool   `short:"d" long:"debug" description:"Enable debug mode"`
 	UseTLS   bool   `long:"tls" description:"Use TLS"`
 	CACert   string `long:"tlscacert" value-name:"CA_CERT_FILE" description:"Trust certs signed only by this CA"`
@@ -133,6 +139,25 @@
 		}
 	}
 
+	// Override from environment
+	//    in particualr, for passing env vars via `go test`
+	env_server, present := os.LookupEnv("CORDCTL_SERVER")
+	if present {
+		GlobalConfig.Server = env_server
+	}
+	env_username, present := os.LookupEnv("CORDCTL_USERNAME")
+	if present {
+		GlobalConfig.Username = env_username
+	}
+	env_password, present := os.LookupEnv("CORDCTL_PASSWORD")
+	if present {
+		GlobalConfig.Password = env_password
+	}
+	env_protoset, present := os.LookupEnv("CORDCTL_PROTOSET")
+	if present {
+		GlobalConfig.Protoset = env_protoset
+	}
+
 	// Override from command line
 	if GlobalOptions.Server != "" {
 		GlobalConfig.Server = GlobalOptions.Server
@@ -143,6 +168,9 @@
 	if GlobalOptions.Password != "" {
 		GlobalConfig.Password = GlobalOptions.Password
 	}
+	if GlobalOptions.Protoset != "" {
+		GlobalConfig.Protoset = GlobalOptions.Protoset
+	}
 
 	// Generate error messages for required settings
 	if GlobalConfig.Server == "" {
@@ -165,19 +193,19 @@
 	if result != nil && result.Data != nil {
 		if result.OutputAs == OUTPUT_TABLE {
 			tableFormat := format.Format(result.Format)
-			tableFormat.Execute(os.Stdout, true, result.Data)
+			tableFormat.Execute(OutputStream, true, result.Data)
 		} else if result.OutputAs == OUTPUT_JSON {
 			asJson, err := json.Marshal(&result.Data)
 			if err != nil {
 				panic(err)
 			}
-			fmt.Printf("%s", asJson)
+			fmt.Fprintf(OutputStream, "%s", asJson)
 		} else if result.OutputAs == OUTPUT_YAML {
 			asYaml, err := yaml.Marshal(&result.Data)
 			if err != nil {
 				panic(err)
 			}
-			fmt.Printf("%s", asYaml)
+			fmt.Fprintf(OutputStream, "%s", asYaml)
 		}
 	}
 }