Inject and report version info

Build system injects version and environment
information similar to voltha-go builds.

Reports version via command line arg or via
"adapters" api call.

Change-Id: Ib21de7faac0d36c86a80c6d2f574c6e052b96459
diff --git a/Gopkg.lock b/Gopkg.lock
index 4b1d426..9f8532c 100644
--- a/Gopkg.lock
+++ b/Gopkg.lock
@@ -216,7 +216,7 @@
 
 [[projects]]
   branch = "master"
-  digest = "1:493092a7b59aec01e27d25e3cc4e833c59de8d19c845611a612387592a2b7ff9"
+  digest = "1:6b91ad0847f5e2ff260d4867b6fa723f6b80f797f87f49ce185d083c4f801289"
   name = "github.com/opencord/voltha-go"
   packages = [
     "adapters",
@@ -224,6 +224,7 @@
     "common/log",
     "common/ponresourcemanager",
     "common/techprofile",
+    "common/version",
     "db/kvstore",
     "db/model",
     "kafka",
@@ -439,6 +440,7 @@
     "github.com/opencord/voltha-go/common/log",
     "github.com/opencord/voltha-go/common/ponresourcemanager",
     "github.com/opencord/voltha-go/common/techprofile",
+    "github.com/opencord/voltha-go/common/version",
     "github.com/opencord/voltha-go/db/kvstore",
     "github.com/opencord/voltha-go/db/model",
     "github.com/opencord/voltha-go/kafka",
diff --git a/Makefile b/Makefile
index 9ccda96..b3fd408 100644
--- a/Makefile
+++ b/Makefile
@@ -20,25 +20,37 @@
 # Variables
 VERSION                  ?= $(shell cat ./VERSION)
 
+DOCKER_LABEL_VCS_DIRTY     = false
+ifneq ($(shell git ls-files --others --modified --exclude-standard 2>/dev/null | wc -l | sed -e 's/ //g'),0)
+    DOCKER_LABEL_VCS_DIRTY = true
+endif
 ## Docker related
+DOCKER_EXTRA_ARGS        ?=
 DOCKER_REGISTRY          ?=
 DOCKER_REPOSITORY        ?=
-DOCKER_BUILD_ARGS        ?=
 DOCKER_TAG               ?= ${VERSION}
 GOADAPTER_IMAGENAME      := ${DOCKER_REGISTRY}${DOCKER_REPOSITORY}voltha-openolt-adapter:${DOCKER_TAG}-go
 PYTHONADAPTER_IMAGENAME  := ${DOCKER_REGISTRY}${DOCKER_REPOSITORY}voltha-openolt-adapter:${DOCKER_TAG}-py
 ADAPTER_IMAGENAME        := ${DOCKER_REGISTRY}${DOCKER_REPOSITORY}voltha-openolt-adapter:${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_BUILD_DATE  ?= $(shell date -u "+%Y-%m-%dT%H:%M:%SZ")
-DOCKER_LABEL_COMMIT_DATE = $(shell git show -s --format=%cd --date=iso-strict HEAD)
+DOCKER_LABEL_VCS_URL       ?= $(shell git remote get-url $(shell git remote))
+DOCKER_LABEL_VCS_REF       = $(shell git rev-parse HEAD)
+DOCKER_LABEL_BUILD_DATE    ?= $(shell date -u "+%Y-%m-%dT%H:%M:%SZ")
+DOCKER_LABEL_COMMIT_DATE   = $(shell git show -s --format=%cd --date=iso-strict HEAD)
 
-ifeq ($(shell git ls-files --others --modified --exclude-standard 2>/dev/null | wc -l | sed -e 's/ //g'),0)
-  DOCKER_LABEL_VCS_REF = $(shell git rev-parse HEAD)
-else
-  DOCKER_LABEL_VCS_REF = $(shell git rev-parse HEAD)+dirty
-endif
+DOCKER_BUILD_ARGS ?= \
+	${DOCKER_EXTRA_ARGS} \
+	--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}" \
+	--build-arg org_opencord_vcs_dirty="${DOCKER_LABEL_VCS_DIRTY}"
+
+DOCKER_BUILD_ARGS_LOCAL ?= ${DOCKER_BUILD_ARGS} \
+	--build-arg LOCAL_PYVOLTHA=${LOCAL_PYVOLTHA} \
+	--build-arg LOCAL_PROTOS=${LOCAL_PROTOS}
 
 .PHONY: docker-build openolt_go openolt_python local-protos local-volthago local-pyvoltha
 
@@ -111,26 +123,10 @@
 docker-build: openolt_go openolt_python
 
 openolt_go: local-protos local-volthago
-	docker build $(DOCKER_BUILD_ARGS) \
-    -t ${GOADAPTER_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 docker/Dockerfile.openolt .
+	docker build $(DOCKER_BUILD_ARGS) -t ${GOADAPTER_IMAGENAME} -f docker/Dockerfile.openolt .
 
 openolt_python: local-protos local-pyvoltha
-	docker build $(DOCKER_BUILD_ARGS) \
-    -t ${PYTHONADAPTER_IMAGENAME} \
-    --build-arg LOCAL_PYVOLTHA=$(LOCAL_PYVOLTHA) \
-    --build-arg LOCAL_PROTOS=$(LOCAL_PROTOS) \
-    --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 python/docker/Dockerfile.openolt_adapter python
+	docker build $(DOCKER_BUILD_ARGS_LOCAL) -t ${PYTHONADAPTER_IMAGENAME} -f python/docker/Dockerfile.openolt_adapter python
 
 	# Current default image gets the base DOCKER_TAG
 	docker tag ${PYTHONADAPTER_IMAGENAME} ${ADAPTER_IMAGENAME}
diff --git a/config/config.go b/config/config.go
index 0a47ef2..17d270b 100644
--- a/config/config.go
+++ b/config/config.go
@@ -26,40 +26,42 @@
 
 // Open OLT default constants
 const (
-	EtcdStoreName           = "etcd"
-	defaultInstanceid       = "openOlt001"
-	defaultKafkaadapterhost = "127.0.0.1"
-	defaultKafkaadapterport = 9092
-	defaultKafkaclusterhost = "127.0.0.1"
-	defaultKafkaclusterport = 9094
-	defaultKvstoretype      = EtcdStoreName
-	defaultKvstoretimeout   = 5 //in seconds
-	defaultKvstorehost      = "127.0.0.1"
-	defaultKvstoreport      = 2379 // Consul = 8500; Etcd = 2379
-	defaultLoglevel         = 0
-	defaultBanner           = false
-	defaultTopic            = "openolt"
-	defaultCoretopic        = "rwcore"
-	defaultOnunumber        = 1
+	EtcdStoreName             = "etcd"
+	defaultInstanceid         = "openOlt001"
+	defaultKafkaadapterhost   = "127.0.0.1"
+	defaultKafkaadapterport   = 9092
+	defaultKafkaclusterhost   = "127.0.0.1"
+	defaultKafkaclusterport   = 9094
+	defaultKvstoretype        = EtcdStoreName
+	defaultKvstoretimeout     = 5 //in seconds
+	defaultKvstorehost        = "127.0.0.1"
+	defaultKvstoreport        = 2379 // Consul = 8500; Etcd = 2379
+	defaultLoglevel           = 0
+	defaultBanner             = false
+	defaultDisplayVersionOnly = false
+	defaultTopic              = "openolt"
+	defaultCoretopic          = "rwcore"
+	defaultOnunumber          = 1
 )
 
 // AdapterFlags represents the set of configurations used by the read-write adaptercore service
 type AdapterFlags struct {
 	// Command line parameters
-	InstanceID       string
-	KafkaAdapterHost string
-	KafkaAdapterPort int
-	KafkaClusterHost string
-	KafkaClusterPort int
-	KVStoreType      string
-	KVStoreTimeout   int // in seconds
-	KVStoreHost      string
-	KVStorePort      int
-	Topic            string
-	CoreTopic        string
-	LogLevel         int
-	OnuNumber        int
-	Banner           bool
+	InstanceID         string
+	KafkaAdapterHost   string
+	KafkaAdapterPort   int
+	KafkaClusterHost   string
+	KafkaClusterPort   int
+	KVStoreType        string
+	KVStoreTimeout     int // in seconds
+	KVStoreHost        string
+	KVStorePort        int
+	Topic              string
+	CoreTopic          string
+	LogLevel           int
+	OnuNumber          int
+	Banner             bool
+	DisplayVersionOnly bool
 }
 
 func init() {
@@ -69,20 +71,21 @@
 // NewAdapterFlags returns a new RWCore config
 func NewAdapterFlags() *AdapterFlags {
 	var adapterFlags = AdapterFlags{ // Default values
-		InstanceID:       defaultInstanceid,
-		KafkaAdapterHost: defaultKafkaadapterhost,
-		KafkaAdapterPort: defaultKafkaadapterport,
-		KafkaClusterHost: defaultKafkaclusterhost,
-		KafkaClusterPort: defaultKafkaclusterport,
-		KVStoreType:      defaultKvstoretype,
-		KVStoreTimeout:   defaultKvstoretimeout,
-		KVStoreHost:      defaultKvstorehost,
-		KVStorePort:      defaultKvstoreport,
-		Topic:            defaultTopic,
-		CoreTopic:        defaultCoretopic,
-		LogLevel:         defaultLoglevel,
-		OnuNumber:        defaultOnunumber,
-		Banner:           defaultBanner,
+		InstanceID:         defaultInstanceid,
+		KafkaAdapterHost:   defaultKafkaadapterhost,
+		KafkaAdapterPort:   defaultKafkaadapterport,
+		KafkaClusterHost:   defaultKafkaclusterhost,
+		KafkaClusterPort:   defaultKafkaclusterport,
+		KVStoreType:        defaultKvstoretype,
+		KVStoreTimeout:     defaultKvstoretimeout,
+		KVStoreHost:        defaultKvstorehost,
+		KVStorePort:        defaultKvstoreport,
+		Topic:              defaultTopic,
+		CoreTopic:          defaultCoretopic,
+		LogLevel:           defaultLoglevel,
+		OnuNumber:          defaultOnunumber,
+		Banner:             defaultBanner,
+		DisplayVersionOnly: defaultDisplayVersionOnly,
 	}
 	return &adapterFlags
 }
@@ -127,7 +130,10 @@
 	flag.IntVar(&(so.OnuNumber), "onu_number", defaultOnunumber, help)
 
 	help = fmt.Sprintf("Show startup banner log lines")
-	flag.BoolVar(&so.Banner, "banner", defaultBanner, help)
+	flag.BoolVar(&(so.Banner), "banner", defaultBanner, help)
+
+	help = fmt.Sprintf("Show version information and exit")
+	flag.BoolVar(&(so.DisplayVersionOnly), "version", defaultDisplayVersionOnly, help)
 
 	flag.Parse()
 
diff --git a/docker/Dockerfile.openolt b/docker/Dockerfile.openolt
index a0a2554..d7cc1dc 100644
--- a/docker/Dockerfile.openolt
+++ b/docker/Dockerfile.openolt
@@ -33,8 +33,24 @@
 COPY vendor ./vendor
 COPY *.go ./
 
+ARG org_label_schema_version=unknown
+ARG org_label_schema_vcs_url=unknown
+ARG org_label_schema_vcs_ref=unknown
+ARG org_label_schema_build_date=unknown
+ARG org_opencord_vcs_commit_date=unknown
+ARG org_opencord_vcs_dirty=unknown
+
 # Build openolt
-RUN go build -o /build/openolt
+SHELL ["/bin/ash", "-o", "pipefail", "-c"]
+RUN go build -o /build/openolt \
+	-ldflags \
+	"-X github.com/opencord/voltha-openolt-adapter/vendor/github.com/opencord/voltha-go/common/version.version=$org_label_schema_version \
+	 -X github.com/opencord/voltha-openolt-adapter/vendor/github.com/opencord/voltha-go/common/version.vcsRef=$org_label_schema_vcs_ref  \
+	 -X github.com/opencord/voltha-openolt-adapter/vendor/github.com/opencord/voltha-go/common/version.vcsDirty=$org_opencord_vcs_dirty \
+	 -X github.com/opencord/voltha-openolt-adapter/vendor/github.com/opencord/voltha-go/common/version.goVersion=$(go version 2>&1 | sed -E  's/.*go([0-9]+\.[0-9]+\.[0-9]+).*/\1/g') \
+	 -X github.com/opencord/voltha-openolt-adapter/vendor/github.com/opencord/voltha-go/common/version.os=$(go env GOHOSTOS) \
+	 -X github.com/opencord/voltha-openolt-adapter/vendor/github.com/opencord/voltha-go/common/version.arch=$(go env GOHOSTARCH) \
+	 -X github.com/opencord/voltha-openolt-adapter/vendor/github.com/opencord/voltha-go/common/version.buildTime=$org_label_schema_build_date"
 
 # -------------
 # Image creation stage
@@ -53,6 +69,7 @@
 ARG org_label_schema_vcs_ref=unknown
 ARG org_label_schema_build_date=unknown
 ARG org_opencord_vcs_commit_date=unknown
+ARG org_opencord_vcs_dirty=unknown
 
 LABEL org.label-schema.schema-version=1.0 \
       org.label-schema.name=voltha-openolt-adapter-go \
@@ -60,4 +77,5 @@
       org.label-schema.vcs-url=$org_label_schema_vcs_url \
       org.label-schema.vcs-ref=$org_label_schema_vcs_ref \
       org.label-schema.build-date=$org_label_schema_build_date \
-      org.opencord.vcs-commit-date=$org_opencord_vcs_commit_date
+      org.opencord.vcs-commit-date=$org_opencord_vcs_commit_date \
+      org.opencord.vcs-dirty=$org_opencord_vcs_dirty
diff --git a/main.go b/main.go
index 519aedb..1a9b411 100644
--- a/main.go
+++ b/main.go
@@ -24,6 +24,7 @@
 	"github.com/opencord/voltha-go/adapters"
 	com "github.com/opencord/voltha-go/adapters/common"
 	"github.com/opencord/voltha-go/common/log"
+	"github.com/opencord/voltha-go/common/version"
 	"github.com/opencord/voltha-go/db/kvstore"
 	"github.com/opencord/voltha-go/kafka"
 	ac "github.com/opencord/voltha-openolt-adapter/adaptercore"
@@ -230,7 +231,8 @@
 func (a *adapter) registerWithCore(retries int) error {
 	log.Info("registering-with-core")
 	adapterDescription := &voltha.Adapter{Id: "openolt", // Unique name for the device type
-		Vendor: "simulation Enterprise Inc"}
+		Vendor:  "VOLTHA OpenOLT",
+		Version: version.VersionInfo.Version}
 	types := []*voltha.DeviceType{{Id: "openolt",
 		Adapter:                     "openolt", // Name of the adapter that handles device type
 		AcceptsBulkFlowUpdate:       false,     // Currently openolt adapter does not support bulk flow handling
@@ -295,6 +297,11 @@
 	fmt.Println("                                              ")
 }
 
+func printVersion() {
+	fmt.Println("VOLTHA OpenOLT Adapter")
+	fmt.Println(version.VersionInfo.String("  "))
+}
+
 func main() {
 	start := time.Now()
 
@@ -317,6 +324,12 @@
 
 	defer log.CleanUp()
 
+	// Print version / build information and exit
+	if cf.DisplayVersionOnly {
+		printVersion()
+		return
+	}
+
 	// Print banner if specified
 	if cf.Banner {
 		printBanner()
diff --git a/vendor/github.com/opencord/voltha-go/common/version/version.go b/vendor/github.com/opencord/voltha-go/common/version/version.go
new file mode 100644
index 0000000..49c0b10
--- /dev/null
+++ b/vendor/github.com/opencord/voltha-go/common/version/version.go
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2019-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.
+ */
+package version
+
+import (
+	"fmt"
+	"strings"
+)
+
+// Default build-time variable.
+// These values can (should) be overridden via ldflags when built with
+// `make`
+var (
+	version   = "unknown-version"
+	goVersion = "unknown-goversion"
+	vcsRef    = "unknown-vcsref"
+	vcsDirty  = "unknown-vcsdirty"
+	buildTime = "unknown-buildtime"
+	os        = "unknown-os"
+	arch      = "unknown-arch"
+)
+
+type VersionInfoType struct {
+	Version   string `json:"version"`
+	GoVersion string `json:"goversion"`
+	VcsRef    string `json:"vcsref"`
+	VcsDirty  string `json:"vcsdirty"`
+	BuildTime string `json:"buildtime"`
+	Os        string `json:"os"`
+	Arch      string `json:"arch"`
+}
+
+var VersionInfo VersionInfoType
+
+func init() {
+	VersionInfo = VersionInfoType{
+		Version:   version,
+		VcsRef:    vcsRef,
+		VcsDirty:  vcsDirty,
+		GoVersion: goVersion,
+		Os:        os,
+		Arch:      arch,
+		BuildTime: buildTime,
+	}
+}
+
+func (v VersionInfoType) String(indent string) string {
+	builder := strings.Builder{}
+
+	builder.WriteString(fmt.Sprintf("%sVersion:      %s\n", indent, VersionInfo.Version))
+	builder.WriteString(fmt.Sprintf("%sGoVersion:    %s\n", indent, VersionInfo.GoVersion))
+	builder.WriteString(fmt.Sprintf("%sVCS Ref:      %s\n", indent, VersionInfo.VcsRef))
+	builder.WriteString(fmt.Sprintf("%sVCS Dirty:    %s\n", indent, VersionInfo.VcsDirty))
+	builder.WriteString(fmt.Sprintf("%sBuilt:        %s\n", indent, VersionInfo.BuildTime))
+	builder.WriteString(fmt.Sprintf("%sOS/Arch:      %s/%s\n", indent, VersionInfo.Os, VersionInfo.Arch))
+	return builder.String()
+}