WIP - Suggesting changes (take2)

    This is not yet completed, still working on things. Eventually the plan
    is to provide the following changes

    - restructure repo to be more aligned with https://github.com/golang-standards/project-layout
    - add k8s probes
    - modifications (golang range loops, etc) to follow some golang
    practices

Change-Id: I6922cbc00b5ef17ceab183aba00a7fc59ab46480
diff --git a/cmd/ofagent/config.go b/cmd/ofagent/config.go
new file mode 100644
index 0000000..1ced4e8
--- /dev/null
+++ b/cmd/ofagent/config.go
@@ -0,0 +1,114 @@
+/*
+   Copyright 2019 the original author or authors.
+
+   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 main
+
+import (
+	"flag"
+	"time"
+)
+
+type Config struct {
+	OFControllerEndPoint      string
+	VolthaApiEndPoint         string
+	LogLevel                  string
+	Banner                    bool
+	Version                   bool
+	ProbeEndPoint             string
+	CpuProfile                string
+	MemProfile                string
+	DeviceListRefreshInterval time.Duration
+	ConnectionRetryDelay      time.Duration
+	ConnectionMaxRetries      int
+}
+
+func parseCommandLineArguments() (*Config, error) {
+	config := Config{}
+
+	flag.BoolVar(&(config.Banner),
+		"banner",
+		true,
+		"display application banner on startup")
+	flag.BoolVar(&(config.Version),
+		"version",
+		false,
+		"display application version and exit")
+	flag.StringVar(&(config.OFControllerEndPoint),
+		"controller",
+		"onos-openflow:6653",
+		"connection to the OF controller specified as host:port")
+	flag.StringVar(&(config.OFControllerEndPoint),
+		"O",
+		"onos-openflow:6653",
+		"(short) connection to the OF controller specified as host:port")
+	flag.StringVar(&(config.VolthaApiEndPoint),
+		"voltha",
+		"voltha-api-server:50060",
+		"connection to the VOLTHA API server specified as host:port")
+	flag.StringVar(&(config.VolthaApiEndPoint),
+		"A",
+		"voltha-api-server:50060",
+		"(short) connection to the VOLTHA API server specified as host:port")
+	flag.StringVar(&(config.ProbeEndPoint),
+		"probe",
+		":8080",
+		"address and port on which to listen for k8s live and ready probe requests")
+	flag.StringVar(&(config.ProbeEndPoint),
+		"P",
+		":8080",
+		"(short) address and port on which to listen for k8s live and ready probe requests")
+	flag.StringVar(&(config.LogLevel),
+		"loglevel",
+		"WARN",
+		"initial log level setting, overriden by any value set in configuration store")
+	flag.StringVar(&(config.LogLevel),
+		"L",
+		"WARN",
+		"(short) initial log level setting, overriden by any value set in configuration store")
+	flag.StringVar(&(config.CpuProfile),
+		"cpuprofile",
+		"",
+		"write cpu profile to 'file' if specified")
+	flag.StringVar(&(config.MemProfile),
+		"memprofile",
+		"",
+		"write memory profile to 'file' if specified")
+	flag.DurationVar(&(config.ConnectionRetryDelay),
+		"cd",
+		3*time.Second,
+		"(short) delay to wait before connection establishment retries")
+	flag.DurationVar(&(config.ConnectionRetryDelay),
+		"connnection-delay",
+		3*time.Second,
+		"delay to wait before connection establishment retries")
+	flag.IntVar(&(config.ConnectionMaxRetries),
+		"mr",
+		0,
+		"(short) number of retries when attempting to estblish a connection, 0 is unlimted")
+	flag.IntVar(&(config.ConnectionMaxRetries),
+		"connnection-retries",
+		0,
+		"number of retries when attempting to estblish a connection, 0 is unlimted")
+	flag.DurationVar(&(config.DeviceListRefreshInterval),
+		"dri",
+		1*time.Minute,
+		"(short) interval between attempts to synchronize devices from voltha to ofagent")
+	flag.DurationVar(&(config.DeviceListRefreshInterval),
+		"device-refresh-interval",
+		1*time.Minute,
+		"interval between attempts to synchronize devices from voltha to ofagent")
+
+	return &config, nil
+}
diff --git a/cmd/ofagent/main.go b/cmd/ofagent/main.go
new file mode 100644
index 0000000..cd03674
--- /dev/null
+++ b/cmd/ofagent/main.go
@@ -0,0 +1,130 @@
+/*
+   Copyright 2019 the original author or authors.
+
+   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 main
+
+import (
+	"context"
+	"flag"
+	"fmt"
+	"github.com/opencord/ofagent-go/internal/pkg/ofagent"
+	"github.com/opencord/voltha-lib-go/v2/pkg/log"
+	"github.com/opencord/voltha-lib-go/v2/pkg/probe"
+	"github.com/opencord/voltha-lib-go/v2/pkg/version"
+	"os"
+	"strings"
+)
+
+func printBanner() {
+	fmt.Println(`   ___  _____ _                    _   `)
+	fmt.Println(`  / _ \|  ___/ \   __ _  ___ _ __ | |_ `)
+	fmt.Println(` | | | | |_ / _ \ / _' |/ _ \ '_ \| __|`)
+	fmt.Println(` | |_| |  _/ ___ \ (_| |  __/ | | | |_ `)
+	fmt.Println(`  \___/|_|/_/   \_\__, |\___|_| |_|\__|`)
+	fmt.Println(`                  |___/                `)
+}
+
+func printVersion() {
+	fmt.Println("OFAgent")
+	fmt.Println(version.VersionInfo.String("  "))
+}
+
+func main() {
+
+	config, _ := parseCommandLineArguments()
+	flag.Parse()
+
+	if config.Version {
+		printVersion()
+		os.Exit(0)
+	}
+
+	if config.Banner {
+		printBanner()
+	}
+
+	log.SetLogLevel(log.DebugLevel)
+	log.SetDefaultLogger(log.JSON, log.DebugLevel,
+		log.Fields{
+			"component": "ofagent",
+		})
+
+	logLevel := log.WarnLevel
+	switch strings.ToLower(config.LogLevel) {
+	case "fatal":
+		logLevel = log.FatalLevel
+	case "error":
+		logLevel = log.ErrorLevel
+	case "warn":
+		logLevel = log.WarnLevel
+	case "info":
+		logLevel = log.InfoLevel
+	case "debug":
+		logLevel = log.DebugLevel
+	default:
+		log.Warn("unrecognized-log-level",
+			log.Fields{
+				"msg":       "Unrecognized log level setting defaulting to 'WARN'",
+				"component": "ofagent",
+				"value":     config.LogLevel,
+			})
+		config.LogLevel = "WARN"
+		logLevel = log.FatalLevel
+	}
+	log.SetDefaultLogger(log.JSON, logLevel,
+		log.Fields{
+			"component": "ofagent",
+		})
+	log.SetAllLogLevel(logLevel)
+
+	log.Infow("ofagent-startup-configuration",
+		log.Fields{
+			"configuration": fmt.Sprintf("%+v", *config),
+		})
+
+	_, err := log.AddPackage(log.JSON, logLevel, nil)
+	if err != nil {
+		log.Errorw("unable-to-register-package-to-the-log-map", log.Fields{"error": err})
+	}
+
+	/*
+	 * Create and start the liveness and readiness container management probes. This
+	 * is done in the main function so just in case the main starts multiple other
+	 * objects there can be a single probe end point for the process.
+	 */
+	p := &probe.Probe{}
+	go p.ListenAndServe(config.ProbeEndPoint)
+
+	/*
+	 * Create a context which to start the services used by the applicaiton
+	 * and attach the probe to that context
+	 */
+	ctx := context.WithValue(context.Background(), probe.ProbeContextKey, p)
+
+	ofa, err := ofagent.NewOFAgent(&ofagent.OFAgent{
+		OFControllerEndPoint:      config.OFControllerEndPoint,
+		VolthaApiEndPoint:         config.VolthaApiEndPoint,
+		DeviceListRefreshInterval: config.DeviceListRefreshInterval,
+		ConnectionMaxRetries:      config.ConnectionMaxRetries,
+		ConnectionRetryDelay:      config.ConnectionRetryDelay,
+	})
+	if err != nil {
+		log.Fatalw("failed-to-create-ofagent",
+			log.Fields{
+				"error": err})
+	}
+	ofa.Run(ctx)
+}