SEBA-902 mock testing of redfish importer;
Remove hardcoded addresses and replace with config file / cmdline;
Support hostnames in importer as alternative to ip addresses;
Treat response 204 as success

Change-Id: I17e8e585e388c501c02867ce952bbe1fa9b09668
diff --git a/demo_test/Dockerfile b/demo_test/Dockerfile
new file mode 100644
index 0000000..efd6ce9
--- /dev/null
+++ b/demo_test/Dockerfile
@@ -0,0 +1,62 @@
+# copyright 2018-present Open Networking Foundation
+#
+# 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.
+
+FROM golang:1.12 AS build-env
+SHELL ["/bin/bash", "-o",  "pipefail", "-c"]
+RUN /bin/true | cat
+RUN apt-get update && apt-get install --no-install-recommends -y --allow-downgrades \
+	git=1:2.20.1-2+deb10u1 \
+	gcc=4:8.3.0-1 \
+	curl=7.64.0-4 \
+	unzip=6.0-23+deb10u1
+# Install these prereqs now so they get built into a container layer and cached
+# TODO: Revisit once demo-test implements mod=vendor
+RUN go get -v google.golang.org/grpc \
+	&& go get -v github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway \
+	&& go get -v github.com/golang/protobuf/protoc-gen-go \
+	&& go get github.com/sirupsen/logrus \
+	&& go get github.com/Shopify/sarama
+# Install protoc, same steps as in main importer dockerfile
+ENV PROTOC_VERSION="3.7.0"
+ENV PROTOC_SHA256SUM="a1b8ed22d6dc53c5b8680a6f1760a305b33ef471bece482e92728f00ba2a2969"
+RUN curl -L -o /tmp/protoc-${PROTOC_VERSION}-linux-x86_64.zip https://github.com/google/protobuf/releases/download/v${PROTOC_VERSION}/protoc-${PROTOC_VERSION}-linux-x86_64.zip \
+ && mkdir /tmp/protoc3 \
+ && echo "$PROTOC_SHA256SUM  /tmp/protoc-${PROTOC_VERSION}-linux-x86_64.zip" | sha256sum -c - \
+ && unzip /tmp/protoc-${PROTOC_VERSION}-linux-x86_64.zip -d /tmp/protoc3 \
+ && mv /tmp/protoc3/bin/* /usr/local/bin/ \
+ && mv /tmp/protoc3/include/* /usr/local/include/
+RUN mkdir /app
+COPY . /app/
+WORKDIR /app
+ENV GO111MODULE=on
+ENV PROTOC_VERSION="3.7.0"
+ENV PROTOC_SHA256SUM="a1b8ed22d6dc53c5b8680a6f1760a305b33ef471bece482e92728f00ba2a2969"
+
+WORKDIR /app/demo_test
+RUN make prereq
+RUN make proto/importer.pb.go
+# Note: "make demotest" produces an executable that throws "No such file" errors. Investigate.
+RUN GO111MODULE=on CGO_ENABLED=0 GOOS=linux go build -o demotest .
+
+# Also build the client, as having it inside the container may facilitate testing without
+# having to setup port forwardin
+WORKDIR /app/demo_test/functional_test
+RUN GO111MODULE=on CGO_ENABLED=0 GOOS=linux go build -o dm .
+
+FROM alpine:3.9.4
+WORKDIR /app/demo_test
+COPY --from=build-env /app/demo_test/demotest .
+COPY --from=build-env /app/demo_test/functional_test/dm .
+ENTRYPOINT ["./demotest"]
+
diff --git a/demo_test/Makefile b/demo_test/Makefile
index 4296147..4ceae91 100644
--- a/demo_test/Makefile
+++ b/demo_test/Makefile
@@ -12,6 +12,26 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+# Configure shell
+SHELL = bash -eu -o pipefail
+
+# Variables
+VERSION                  ?= $(shell cat ../VERSION)
+CONTAINER_NAME           ?= redfish-importer-demotest
+
+## Docker related
+DOCKER_REGISTRY          ?=
+DOCKER_REPOSITORY        ?=
+DOCKER_BUILD_ARGS        ?=
+DOCKER_TAG               ?= ${VERSION}
+DOCKER_IMAGENAME         := ${DOCKER_REGISTRY}${DOCKER_REPOSITORY}${CONTAINER_NAME}:${DOCKER_TAG}
+
+## Docker labels. Only set ref and commit date if committed
+DOCKER_LABEL_VCS_URL     ?= $(shell git remote get-url $(shell git remote))
+DOCKER_LABEL_VCS_REF     ?= $(shell git diff-index --quiet HEAD -- && git rev-parse HEAD || echo "unknown")
+DOCKER_LABEL_COMMIT_DATE ?= $(shell git diff-index --quiet HEAD -- && git show -s --format=%cd --date=iso-strict HEAD || echo "unknown" )
+DOCKER_LABEL_BUILD_DATE  ?= $(shell date -u "+%Y-%m-%dT%H:%M:%SZ")
+
 prereq:
 	go get -v google.golang.org/grpc
 	go get -v github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway
@@ -22,10 +42,22 @@
 demotest: prereq proto/importer.pb.go
 	go build -i -v -o $@
 
-
 proto/importer.pb.go: ../proto/importer.proto
 	mkdir -p proto
 	protoc --proto_path=../proto \
 	-I${GOPATH}/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \
 	--go_out=plugins=grpc:proto/ \
 	../proto/importer.proto
+
+docker-build:
+	docker build $(DOCKER_BUILD_ARGS) \
+	-t ${DOCKER_IMAGENAME} \
+	--build-arg org_label_schema_version="${VERSION}" \
+	--build-arg org_label_schema_vcs_url="${DOCKER_LABEL_VCS_URL}" \
+	--build-arg org_label_schema_vcs_ref="${DOCKER_LABEL_VCS_REF}" \
+	--build-arg org_label_schema_build_date="${DOCKER_LABEL_BUILD_DATE}" \
+	--build-arg org_opencord_vcs_commit_date="${DOCKER_LABEL_COMMIT_DATE}" \
+	-f Dockerfile ..
+
+docker-push:
+	docker push ${DOCKER_IMAGENAME}
diff --git a/demo_test/config.go b/demo_test/config.go
new file mode 100644
index 0000000..e8bd589
--- /dev/null
+++ b/demo_test/config.go
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+ *
+ * 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.
+ */
+
+// Implements global configuration for demotest
+package main
+
+import (
+	"fmt"
+	flags "github.com/jessevdk/go-flags"
+	"gopkg.in/yaml.v2"
+	"io/ioutil"
+	"log"
+	"os"
+	"path"
+	"path/filepath"
+	"strings"
+)
+
+type OutputType uint8
+
+type GlobalConfigSpec struct {
+	Kafka    string `yaml:"kafka"`
+	Local    string `yaml:"local"`
+	Importer string `yaml:"importer"`
+}
+
+var (
+	CharReplacer = strings.NewReplacer("\\t", "\t", "\\n", "\n")
+
+	GlobalConfig = GlobalConfigSpec{
+		Kafka:    "kafka_ip.sh",
+		Local:    ":9999",
+		Importer: "localhost:31085",
+	}
+
+	GlobalCommandOptions = make(map[string]map[string]string)
+
+	GlobalOptions struct {
+		Config   string `short:"c" long:"config" env:"PROXYCONFIG" value-name:"FILE" default:"" description:"Location of proxy config file"`
+		Kafka    string `short:"k" long:"kafka" default:"" value-name:"SERVER:PORT" description:"IP/Host and port of Kafka"`
+		Importer string `short:"i" long:"importer" default:"" value-name:"SERVER:PORT" description:"IP/Host and port of Importer"`
+		Local    string `short:"l" long:"local" default:"" value-name:"SERVER:PORT" description:"IP/Host and port to listen on"`
+	}
+
+	Debug = log.New(os.Stdout, "DEBUG: ", 0)
+	Info  = log.New(os.Stdout, "INFO: ", 0)
+	Warn  = log.New(os.Stderr, "WARN: ", 0)
+	Error = log.New(os.Stderr, "ERROR: ", 0)
+)
+
+func ParseCommandLine() {
+	parser := flags.NewNamedParser(path.Base(os.Args[0]),
+		flags.HelpFlag|flags.PassDoubleDash|flags.PassAfterNonOption)
+	_, err := parser.AddGroup("Global Options", "", &GlobalOptions)
+	if err != nil {
+		panic(err)
+	}
+
+	_, err = parser.ParseArgs(os.Args[1:])
+	if err != nil {
+		_, ok := err.(*flags.Error)
+		if ok {
+			real := err.(*flags.Error)
+			if real.Type == flags.ErrHelp {
+				os.Stdout.WriteString(err.Error() + "\n")
+				os.Exit(0)
+			}
+		}
+
+		fmt.Fprintf(os.Stderr, "%s: %s\n", os.Args[0], err.Error())
+
+		os.Exit(1)
+	}
+}
+
+func ProcessGlobalOptions() {
+	if len(GlobalOptions.Config) == 0 {
+		home, err := os.UserHomeDir()
+		if err != nil {
+			Warn.Printf("Unable to discover the user's home directory: %s", err)
+			home = "~"
+		}
+		GlobalOptions.Config = filepath.Join(home, ".redfish-importer", "demotest-config")
+	}
+
+	if info, err := os.Stat(GlobalOptions.Config); err == nil && !info.IsDir() {
+		configFile, err := ioutil.ReadFile(GlobalOptions.Config)
+		if err != nil {
+			Error.Fatalf("Unable to read the configuration file '%s': %s",
+				GlobalOptions.Config, err.Error())
+		}
+		if err = yaml.Unmarshal(configFile, &GlobalConfig); err != nil {
+			Error.Fatalf("Unable to parse the configuration file '%s': %s",
+				GlobalOptions.Config, err.Error())
+		}
+	}
+
+	if GlobalOptions.Kafka != "" {
+		GlobalConfig.Kafka = GlobalOptions.Kafka
+	}
+	if GlobalOptions.Local != "" {
+		GlobalConfig.Local = GlobalOptions.Local
+	}
+	if GlobalOptions.Importer != "" {
+		GlobalConfig.Importer = GlobalOptions.Importer
+	}
+}
+
+func ShowGlobalOptions() {
+	log.Printf("Configuration:")
+	log.Printf("    Kafka: %v", GlobalConfig.Kafka)
+	log.Printf("    Listen Address: %v", GlobalConfig.Local)
+}
diff --git a/demo_test/functional_test/test_cli.go b/demo_test/functional_test/test_cli.go
index 3a1bc95..81cfe07 100644
--- a/demo_test/functional_test/test_cli.go
+++ b/demo_test/functional_test/test_cli.go
@@ -19,16 +19,32 @@
 import "bufio"
 import "os"
 import "strings"
+import "log"
 
 func main() {
+	if len(os.Args) <= 1 {
+		log.Printf("Syntax: ./dm <arguments>")
+		os.Exit(-1)
+	}
+
 	// connect to this socket
 	cmdstr := strings.Join(os.Args[1:], " ")
-	conn, _ := net.Dial("tcp", "127.0.0.1:9999")
+	conn, err := net.Dial("tcp", "127.0.0.1:9999")
+	if err != nil {
+		log.Printf("Error opening connection: %v", err)
+		os.Exit(-1)
+	}
+
 	// send to socket
 	fmt.Fprintf(conn, cmdstr+"\n")
 
 	// listen for reply
-	message, _ := bufio.NewReader(conn).ReadString(';')
+	message, err := bufio.NewReader(conn).ReadString(';')
+	if err != nil {
+		log.Printf("Error reading result: %v", err)
+		os.Exit(-1)
+	}
+
 	message = strings.TrimSuffix(message, ";")
 	fmt.Print(message)
 }
diff --git a/demo_test/test.go b/demo_test/test.go
index 438ae74..8d929a0 100644
--- a/demo_test/test.go
+++ b/demo_test/test.go
@@ -41,7 +41,6 @@
 	"alert":  "Alert",
 	"update": "Update"}
 
-var default_address string = "localhost:31085"
 var importerTopic = "importer"
 var DataConsumer sarama.Consumer
 
@@ -95,20 +94,24 @@
 }
 
 func kafkainit() {
-	cmd := exec.Command("/bin/sh", "kafka_ip.sh")
 	var kafkaIP string
-	var out bytes.Buffer
-	cmd.Stdout = &out
-	err := cmd.Run()
-	if err != nil {
-		logrus.Info(err)
-		os.Exit(1)
+	if GlobalConfig.Kafka == "kafka_ip.sh" {
+		cmd := exec.Command("/bin/sh", "kafka_ip.sh")
+		var out bytes.Buffer
+		cmd.Stdout = &out
+		err := cmd.Run()
+		if err != nil {
+			logrus.Info(err)
+			os.Exit(1)
+		}
+		kafkaIP = out.String()
+		kafkaIP = strings.TrimSuffix(kafkaIP, "\n")
+		kafkaIP = kafkaIP + ":9092"
+		logrus.Infof("IP address of kafka-cord-0:%s", kafkaIP)
+	} else {
+		kafkaIP = GlobalConfig.Kafka
 	}
 
-	kafkaIP = out.String()
-	kafkaIP = strings.TrimSuffix(kafkaIP, "\n")
-	kafkaIP = kafkaIP + ":9092"
-	logrus.Infof("IP address of kafka-cord-0:%s", kafkaIP)
 	config := sarama.NewConfig()
 	config.Consumer.Return.Errors = true
 	master, err := sarama.NewConsumer([]string{kafkaIP}, config)
@@ -119,20 +122,25 @@
 
 	go topicListener(&importerTopic, master)
 }
+
 func main() {
+	ParseCommandLine()
+	ProcessGlobalOptions()
+	ShowGlobalOptions()
+
 	http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
 	logrus.Info("Launching server...")
 	logrus.Info("kafkaInit starting")
 	kafkainit()
 
-	ln, err := net.Listen("tcp", ":9999")
+	ln, err := net.Listen("tcp", GlobalConfig.Local)
 	if err != nil {
 		fmt.Println("could not listen")
 		logrus.Fatalf("did not listen: %v", err)
 	}
 	defer ln.Close()
 
-	conn, err = grpc.Dial(default_address, grpc.WithInsecure())
+	conn, err = grpc.Dial(GlobalConfig.Importer, grpc.WithInsecure())
 	if err != nil {
 		logrus.Fatalf("did not connect: %v", err)
 	}