SEBA-580 Add bash completion;
Add Git Dirty to version;
Add config comamnd

Change-Id: I847dc309a41d74d80e427106bcc839b8db3f9a2c
diff --git a/commands/command.go b/commands/command.go
index 9741e51..6a8d663 100644
--- a/commands/command.go
+++ b/commands/command.go
@@ -111,16 +111,12 @@
 	Server string `yaml:"server"`
 }
 
-func NewConnection() (*grpc.ClientConn, error) {
+func ProcessGlobalOptions() {
 	if len(GlobalOptions.Config) == 0 {
-		home := os.Getenv("HOME")
-		// TODO: Replace after Jenkins updated to go 1.12
-		/*
-			home, err := os.UserHomeDir()
-			if err != nil {
-				log.Printf("Unable to discover they users home directory: %s\n", err)
-			}
-		*/
+		home, err := os.UserHomeDir()
+		if err != nil {
+			log.Printf("Unable to discover the users home directory: %s\n", err)
+		}
 		GlobalOptions.Config = fmt.Sprintf("%s/.cord/config", home)
 	}
 
@@ -147,6 +143,19 @@
 		GlobalConfig.Password = GlobalOptions.Password
 	}
 
+	if GlobalConfig.Server == "" {
+		log.Fatal("Server is not set. Please update config file or use the -s option")
+	}
+	if GlobalConfig.Username == "" {
+		log.Fatal("Username is not set. Please update config file or use the -u option")
+	}
+	if GlobalConfig.Password == "" {
+		log.Fatal("Password is not set. Please update config file or use the -p option")
+	}
+}
+
+func NewConnection() (*grpc.ClientConn, error) {
+	ProcessGlobalOptions()
 	return grpc.Dial(GlobalConfig.Server, grpc.WithInsecure())
 }
 
diff --git a/commands/completion.go b/commands/completion.go
new file mode 100644
index 0000000..67c7ad3
--- /dev/null
+++ b/commands/completion.go
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2019-present Ciena Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package commands
+
+import (
+	"fmt"
+	flags "github.com/jessevdk/go-flags"
+	"github.com/opencord/cordctl/completion"
+)
+
+type BashOptions struct{}
+
+type CompletionOptions struct {
+	BashOptions `command:"bash"`
+}
+
+func RegisterCompletionCommands(parent *flags.Parser) {
+	parent.AddCommand("completion", "generate shell compleition", "Commands to generate shell completion information", &CompletionOptions{})
+}
+
+func (options *BashOptions) Execute(args []string) error {
+	fmt.Println(completion.Bash)
+	return nil
+}
diff --git a/commands/config.go b/commands/config.go
new file mode 100644
index 0000000..81875a5
--- /dev/null
+++ b/commands/config.go
@@ -0,0 +1,60 @@
+/*
+ * Portions copyright 2019-present Open Networking Foundation
+ * Original copyright 2019-present Ciena Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package commands
+
+import (
+	"fmt"
+	flags "github.com/jessevdk/go-flags"
+	"gopkg.in/yaml.v2"
+)
+
+const copyrightNotice = `
+# Portions copyright 2019-present Open Networking Foundation
+# Original copyright 2019-present Ciena Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+`
+
+type ConfigOptions struct {
+}
+
+func RegisterConfigCommands(parent *flags.Parser) {
+	parent.AddCommand("config", "generate cordctl configuration", "Commands to generate cordctl configuration", &ConfigOptions{})
+}
+
+func (options *ConfigOptions) Execute(args []string) error {
+	//GlobalConfig
+	ProcessGlobalOptions()
+	b, err := yaml.Marshal(GlobalConfig)
+	if err != nil {
+		return err
+	}
+	fmt.Println(copyrightNotice)
+	fmt.Println(string(b))
+	return nil
+}
diff --git a/commands/models.go b/commands/models.go
index 92a7b2c..f7a1963 100644
--- a/commands/models.go
+++ b/commands/models.go
@@ -31,13 +31,15 @@
 	DEFAULT_MODEL_AVAILABLE_FORMAT = "{{ . }}"
 )
 
+type ModelNameString string
+
 type ModelList struct {
 	OutputOptions
 	ShowHidden      bool `long:"showhidden" description:"Show hidden fields in default output"`
 	ShowFeedback    bool `long:"showfeedback" description:"Show feedback fields in default output"`
 	ShowBookkeeping bool `long:"showbookkeeping" description:"Show bookkeeping fields in default output"`
 	Args            struct {
-		ModelName string
+		ModelName ModelNameString
 	} `positional-args:"yes" required:"yes"`
 }
 
@@ -100,12 +102,12 @@
 
 	defer conn.Close()
 
-	err = CheckModelName(descriptor, options.Args.ModelName)
+	err = CheckModelName(descriptor, string(options.Args.ModelName))
 	if err != nil {
 		return err
 	}
 
-	method := "xos.xos/List" + options.Args.ModelName
+	method := "xos.xos/List" + string(options.Args.ModelName)
 
 	ctx, cancel := context.WithTimeout(context.Background(), GlobalConfig.Grpc.Timeout)
 	defer cancel()
@@ -195,3 +197,26 @@
 	GenerateOutput(&result)
 	return nil
 }
+
+func (modelName *ModelNameString) Complete(match string) []flags.Completion {
+	conn, descriptor, err := InitReflectionClient()
+	if err != nil {
+		return nil
+	}
+
+	defer conn.Close()
+
+	models, err := GetModelNames(descriptor)
+	if err != nil {
+		return nil
+	}
+
+	list := make([]flags.Completion, 0)
+	for k := range models {
+		if strings.HasPrefix(k, match) {
+			list = append(list, flags.Completion{Item: k})
+		}
+	}
+
+	return list
+}
diff --git a/commands/version.go b/commands/version.go
index 9cc8b05..4af5a8a 100644
--- a/commands/version.go
+++ b/commands/version.go
@@ -29,6 +29,7 @@
 	Version   string `json:"version"`
 	GoVersion string `json:"goversion"`
 	GitCommit string `json:"gitcommit"`
+	GitDirty  string `json:"gitdirty"`
 	BuildTime string `json:"buildtime"`
 	Os        string `json:"os"`
 	Arch      string `json:"arch"`
@@ -59,6 +60,7 @@
 		Version:   version.Version,
 		GoVersion: version.GoVersion,
 		GitCommit: version.GitCommit,
+		GitDirty:  version.GitDirty,
 		Os:        version.Os,
 		Arch:      version.Arch,
 		BuildTime: version.BuildTime,
@@ -81,6 +83,7 @@
  Version         {{.Client.Version}}
  Go version:     {{.Client.GoVersion}}
  Git commit:     {{.Client.GitCommit}}
+ Git dirty:      {{.Client.GitDirty}}
  Built:          {{.Client.BuildTime}}
  OS/Arch:        {{.Client.Os}}/{{.Client.Arch}}