Repository: kubernetes-csi/csi-driver-nfs (go)

Issue:
provide more driver info in logs
**Is your feature request related to a problem?/Why is this needed**
<!-- A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] -->

**Describe the solution you'd like in detail**
<!-- A clear and concise description of what you want to happen. -->
could refer to https://github.com/kubernetes-csi/csi-driver-smb/blob/a9a2e47b1790b18e722e9d0b4d413c4e8a520507/pkg/smb/smb.go#L54-L58

```
[pod/csi-smb-controller-5dd89b9bf6-vbbzq/smb] DRIVER INFORMATION:
[pod/csi-smb-controller-5dd89b9bf6-vbbzq/smb] -------------------
[pod/csi-smb-controller-5dd89b9bf6-vbbzq/smb] Build Date: "2021-01-09T16:38:17Z"
[pod/csi-smb-controller-5dd89b9bf6-vbbzq/smb] Compiler: gc
[pod/csi-smb-controller-5dd89b9bf6-vbbzq/smb] Driver Name: smb.csi.k8s.io
[pod/csi-smb-controller-5dd89b9bf6-vbbzq/smb] Driver Version: e2e-c091d36a1d9ee8d6026cb06a165bbe49110afcb5
[pod/csi-smb-controller-5dd89b9bf6-vbbzq/smb] Git Commit: c091d36a1d9ee8d6026cb06a165bbe49110afcb5
[pod/csi-smb-controller-5dd89b9bf6-vbbzq/smb] Go Version: go1.15.5
[pod/csi-smb-controller-5dd89b9bf6-vbbzq/smb] Platform: linux/amd64
```

**Describe alternatives you've considered**
<!-- A clear and concise description of any alternative solutions or features you've considered. -->

**Additional context**
<!-- Add any other context or screenshots about the feature request here. -->


Pull request description:
provide more driver info in logs
<!--  Thanks for sending a pull request!  Here are some tips for you:

1. If this is your first time, please read our contributor guidelines: https://git.k8s.io/community/contributors/guide#your-first-contribution and developer guide https://git.k8s.io/community/contributors/devel/development.md#development-guide
2. Follow the instructions for writing a release note: https://git.k8s.io/community/contributors/guide/release-notes.md
3. If the PR is unfinished, see how to mark it: https://git.k8s.io/community/contributors/guide/pull-requests.md#marking-unfinished-pull-requests
-->

**What type of PR is this?**
/kind feature

**What this PR does / why we need it**:
The changes in this PR provides more information about the driver when the driver is started.
 
**Which issue(s) this PR fixes**:
<!--
*Automatically closes linked issue when PR is merged.
Usage: `Fixes #<issue number>`, or `Fixes (paste link of issue)`.
_If PR is about `failing-tests or flakes`, please post the related issues/tests in a comment and do not use `Fixes`_*
-->
Fixes #131 

**Special notes for your reviewer**:

**Does this PR introduce a user-facing change?**:
<!--
If no, just write "NONE" in the release-note block below.
If yes, a release note is required:
Enter your extended release note in the block below. If the PR requires additional action from users switching to the new release, include the string "action required".
-->
```release-note
none
```


Patch:
diff --git a/Makefile b/Makefile
index 0925c8b9..7c171a1c 100644
--- a/Makefile
+++ b/Makefile
@@ -24,9 +24,12 @@ DOCKER_CLI_EXPERIMENTAL = enabled
 export GOPATH GOBIN GO111MODULE DOCKER_CLI_EXPERIMENTAL
 
 include release-tools/build.make
-LDFLAGS = "-X ${PKG}/pkg/nfs.driverVersion=${IMAGE_VERSION} -s -w -extldflags '-static'"
-GIT_COMMIT ?= $(shell git rev-parse HEAD)
-IMAGE_VERSION ?= v3.0.0
+
+GIT_COMMIT = $(shell git rev-parse HEAD)
+BUILD_DATE = $(shell date -u +"%Y-%m-%dT%H:%M:%SZ")
+IMAGE_VERSION = v3.0.0
+LDFLAGS = -X ${PKG}/pkg/nfs.driverVersion=${IMAGE_VERSION} -X ${PKG}/pkg/nfs.gitCommit=${GIT_COMMIT} -X ${PKG}/pkg/nfs.buildDate=${BUILD_DATE}
+EXT_LDFLAGS = -s -w -extldflags "-static"
 # Use a custom version for E2E tests if we are testing in CI
 ifdef CI
 ifndef PUBLISH
@@ -82,7 +85,7 @@ local-k8s-uninstall:
 
 .PHONY: nfs
 nfs:
-	CGO_ENABLED=0 GOOS=linux go build -a -ldflags ${LDFLAGS} -mod vendor -o bin/nfsplugin ./cmd/nfsplugin
+	CGO_ENABLED=0 GOOS=linux go build -a -ldflags "${LDFLAGS} ${EXT_LDFLAGS}" -mod vendor -o bin/nfsplugin ./cmd/nfsplugin
 
 .PHONY: container
 container: nfs
diff --git a/go.mod b/go.mod
index 253ffa7e..a0b1fec8 100644
--- a/go.mod
+++ b/go.mod
@@ -19,6 +19,7 @@ require (
 	k8s.io/klog/v2 v2.4.0
 	k8s.io/kubernetes v1.21.0-alpha.0.0.20201210005053-f58c4d8cd725
 	k8s.io/utils v0.0.0-20201110183641-67b214c5f920
+	sigs.k8s.io/yaml v1.2.0
 )
 
 replace k8s.io/api => k8s.io/api v0.20.0
diff --git a/pkg/nfs/nfs.go b/pkg/nfs/nfs.go
index 32ba2268..f6558c36 100644
--- a/pkg/nfs/nfs.go
+++ b/pkg/nfs/nfs.go
@@ -98,6 +98,12 @@ func NewNodeServer(n *Driver, mounter mount.Interface) *NodeServer {
 }
 
 func (n *Driver) Run(testMode bool) {
+	versionMeta, err := GetVersionYAML()
+	if err != nil {
+		klog.Fatalf("%v", err)
+	}
+	klog.Infof("\nDRIVER INFORMATION:\n-------------------\n%s\n\nStreaming logs below:", versionMeta)
+
 	n.ns = NewNodeServer(n, mount.New(""))
 	s := NewNonBlockingGRPCServer()
 	s.Start(n.endpoint,
diff --git a/pkg/nfs/version.go b/pkg/nfs/version.go
new file mode 100644
index 00000000..1c8a313b
--- /dev/null
+++ b/pkg/nfs/version.go
@@ -0,0 +1,67 @@
+/*
+Copyright 2021 The Kubernetes 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 nfs
+
+import (
+	"fmt"
+	"runtime"
+	"strings"
+
+	"sigs.k8s.io/yaml"
+)
+
+// These are set during build time via -ldflags
+var (
+	driverVersion = "N/A"
+	gitCommit     = "N/A"
+	buildDate     = "N/A"
+)
+
+// VersionInfo holds the version information of the driver
+type VersionInfo struct {
+	DriverName    string `json:"Driver Name"`
+	DriverVersion string `json:"Driver Version"`
+	GitCommit     string `json:"Git Commit"`
+	BuildDate     string `json:"Build Date"`
+	GoVersion     string `json:"Go Version"`
+	Compiler      string `json:"Compiler"`
+	Platform      string `json:"Platform"`
+}
+
+// GetVersion returns the version information of the driver
+func GetVersion() VersionInfo {
+	return VersionInfo{
+		DriverName:    DriverName,
+		DriverVersion: driverVersion,
+		GitCommit:     gitCommit,
+		BuildDate:     buildDate,
+		GoVersion:     runtime.Version(),
+		Compiler:      runtime.Compiler,
+		Platform:      fmt.Sprintf("%s/%s", runtime.GOOS, runtime.GOARCH),
+	}
+}
+
+// GetVersionYAML returns the version information of the driver
+// in YAML format
+func GetVersionYAML() (string, error) {
+	info := GetVersion()
+	marshalled, err := yaml.Marshal(&info)
+	if err != nil {
+		return "", err
+	}
+	return strings.TrimSpace(string(marshalled)), nil
+}
diff --git a/release-tools/README.md b/release-tools/README.md
index 6315a736..60eab2a9 100644
--- a/release-tools/README.md
+++ b/release-tools/README.md
@@ -44,17 +44,10 @@ is the recommended way of maintaining a copy of the rules inside the
 changes also locally, test them and then push them back to the shared
 repository at a later time.
 
-We no longer care about importing the full commit history, so `--squash` should be used
-when submitting a `release-tools` update. Also make sure that the PR for that
-contains the automatically generated commit message in the PR description.
-It contains the list of individual commits that were squashed. The script from
-https://github.com/kubernetes-csi/csi-release-tools/issues/7 can create such
-PRs automatically.
-
 Cheat sheet:
 
-- `git subtree add --squash --prefix=release-tools https://github.com/kubernetes-csi/csi-release-tools.git master` - add release tools to a repo which does not have them yet (only once)
-- `git subtree pull --squash --prefix=release-tools https://github.com/kubernetes-csi/csi-release-tools.git master` - update local copy to latest upstream (whenever upstream changes)
+- `git subtree add --prefix=release-tools https://github.com/kubernetes-csi/csi-release-tools.git master` - add release tools to a repo which does not have them yet (only once)
+- `git subtree pull --prefix=release-tools https://github.com/kubernetes-csi/csi-release-tools.git master` - update local copy to latest upstream (whenever upstream changes)
 - edit, `git commit`, `git subtree push --prefix=release-tools git@github.com:<user>/csi-release-tools.git <my-new-or-existing-branch>` - push to a new branch before submitting a PR
 
 verify-shellcheck.sh
diff --git a/release-tools/boilerplate/boilerplate.py b/release-tools/boilerplate/boilerplate.py
index 5618b9ab..63f74963 100755
--- a/release-tools/boilerplate/boilerplate.py
+++ b/release-tools/boilerplate/boilerplate.py
@@ -19,6 +19,8 @@ from __future__ import print_function
 import argparse
 import difflib
 import glob
+import json
+import mmap
 import os
 import re
 import sys
@@ -31,12 +33,12 @@ parser.add_argument(
     nargs='*')
 
 # Rootdir defaults to the directory **above** the repo-infra dir.
-rootdir = os.path.dirname(__file__) + "./../../"
+rootdir = os.path.dirname(__file__) + "./../../../"
 rootdir = os.path.abspath(rootdir)
 parser.add_argument(
     "--rootdir", default=rootdir, help="root directory to examine")
 
-default_boilerplate_dir = os.path.abspath(os.path.dirname(__file__))
+default_boilerplate_dir = os.path.join(rootdir, "csi-driver-nfs/hack/boilerplate")
 
 parser.add_argument(
     "--boilerplate-dir", default=default_boilerplate_dir)
@@ -197,4 +199,4 @@ def main():
     return 0
 
 if __name__ == "__main__":
-    sys.exit(main())
+    sys.exit(main())
\ No newline at end of file
diff --git a/release-tools/prow.sh b/release-tools/prow.sh
index ec695ec6..d4300550 100755
--- a/release-tools/prow.sh
+++ b/release-tools/prow.sh
@@ -71,7 +71,7 @@ version_to_git () {
     version="$1"
     shift
     case "$version" in
-        latest|master) echo "master";;
+        latest) echo "master";;
         release-*) echo "$version";;
         *) echo "v$version";;
     esac
diff --git a/vendor/modules.txt b/vendor/modules.txt
index bcde69a0..2be794dc 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -742,6 +742,7 @@ sigs.k8s.io/apiserver-network-proxy/konnectivity-client/proto/client
 # sigs.k8s.io/structured-merge-diff/v4 v4.0.2
 sigs.k8s.io/structured-merge-diff/v4/value
 # sigs.k8s.io/yaml v1.2.0
+## explicit
 sigs.k8s.io/yaml
 # k8s.io/api => k8s.io/api v0.20.0
 # k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.20.0


Test patch:
diff --git a/pkg/nfs/version_test.go b/pkg/nfs/version_test.go
new file mode 100644
index 00000000..a1215fdd
--- /dev/null
+++ b/pkg/nfs/version_test.go
@@ -0,0 +1,60 @@
+/*
+Copyright 2021 The Kubernetes 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 nfs
+
+import (
+	"fmt"
+	"reflect"
+	"runtime"
+	"strings"
+	"testing"
+
+	"sigs.k8s.io/yaml"
+)
+
+func TestGetVersion(t *testing.T) {
+	version := GetVersion()
+
+	expected := VersionInfo{
+		DriverName:    DriverName,
+		DriverVersion: "N/A",
+		GitCommit:     "N/A",
+		BuildDate:     "N/A",
+		GoVersion:     runtime.Version(),
+		Compiler:      runtime.Compiler,
+		Platform:      fmt.Sprintf("%s/%s", runtime.GOOS, runtime.GOARCH),
+	}
+
+	if !reflect.DeepEqual(version, expected) {
+		t.Errorf("Unexpected error. \n Expected: %v \n Found: %v", expected, version)
+	}
+
+}
+
+func TestGetVersionYAML(t *testing.T) {
+	resp, err := GetVersionYAML()
+	if err != nil {
+		t.Fatalf("Unexpected error: %v", err)
+	}
+	versionInfo := GetVersion()
+	marshalled, _ := yaml.Marshal(&versionInfo)
+	expected := strings.TrimSpace(string(marshalled))
+
+	if resp != expected {
+		t.Fatalf("Unexpected error. \n Expected:%v\nFound:%v", expected, resp)
+	}
+}