api: generalize version information to any platform component

This change adds a Platform struct with a Name field and a general
Components field to the Version API type. This will allow API
consumers to show version information for the whole platform and
it will allow API providers to set the versions for the various
components of the platform.

All changes here are backwards compatible.

Signed-off-by: Tibor Vass <tibor@docker.com>
diff --git a/Makefile b/Makefile
index 3298815..6f5145a 100644
--- a/Makefile
+++ b/Makefile
@@ -53,7 +53,8 @@
 	-e http_proxy \
 	-e https_proxy \
 	-e no_proxy \
-	-e VERSION
+	-e VERSION \
+	-e PLATFORM
 # note: we _cannot_ add "-e DOCKER_BUILDTAGS" here because even if it's unset in the shell, that would shadow the "ENV DOCKER_BUILDTAGS" set in our Dockerfile, which is very important for our official builds
 
 # to allow `make BIND_DIR=. shell` or `make BIND_DIR= test`
diff --git a/api/server/router/system/system_routes.go b/api/server/router/system/system_routes.go
index 8f6aecd..535956d 100644
--- a/api/server/router/system/system_routes.go
+++ b/api/server/router/system/system_routes.go
@@ -6,7 +6,6 @@
 	"net/http"
 	"time"
 
-	"github.com/docker/docker/api"
 	"github.com/docker/docker/api/server/httputils"
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/api/types/events"
@@ -65,7 +64,6 @@
 
 func (s *systemRouter) getVersion(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
 	info := s.backend.SystemVersion()
-	info.APIVersion = api.DefaultVersion
 
 	return httputils.WriteJSON(w, http.StatusOK, info)
 }
diff --git a/api/types/types.go b/api/types/types.go
index f7ac772..7814e6b 100644
--- a/api/types/types.go
+++ b/api/types/types.go
@@ -107,9 +107,21 @@
 	Experimental bool
 }
 
+// ComponentVersion describes the version information for a specific component.
+type ComponentVersion struct {
+	Name    string
+	Version string
+	Details map[string]string `json:",omitempty"`
+}
+
 // Version contains response of Engine API:
 // GET "/version"
 type Version struct {
+	Platform   struct{ Name string } `json:",omitempty"`
+	Components []ComponentVersion    `json:",omitempty"`
+
+	// The following fields are deprecated, they relate to the Engine component and are kept for backwards compatibility
+
 	Version       string
 	APIVersion    string `json:"ApiVersion"`
 	MinAPIVersion string `json:"MinAPIVersion,omitempty"`
diff --git a/daemon/info.go b/daemon/info.go
index b14e7ba..bbb027e 100644
--- a/daemon/info.go
+++ b/daemon/info.go
@@ -154,24 +154,46 @@
 
 // SystemVersion returns version information about the daemon.
 func (daemon *Daemon) SystemVersion() types.Version {
-	v := types.Version{
-		Version:       dockerversion.Version,
-		GitCommit:     dockerversion.GitCommit,
-		MinAPIVersion: api.MinVersion,
-		GoVersion:     runtime.Version(),
-		Os:            runtime.GOOS,
-		Arch:          runtime.GOARCH,
-		BuildTime:     dockerversion.BuildTime,
-		Experimental:  daemon.configStore.Experimental,
-	}
-
 	kernelVersion := "<unknown>"
 	if kv, err := kernel.GetKernelVersion(); err != nil {
 		logrus.Warnf("Could not get kernel version: %v", err)
 	} else {
 		kernelVersion = kv.String()
 	}
-	v.KernelVersion = kernelVersion
+
+	v := types.Version{
+		Components: []types.ComponentVersion{
+			{
+				Name:    "Engine",
+				Version: dockerversion.Version,
+				Details: map[string]string{
+					"GitCommit":     dockerversion.GitCommit,
+					"ApiVersion":    api.DefaultVersion,
+					"MinAPIVersion": api.MinVersion,
+					"GoVersion":     runtime.Version(),
+					"Os":            runtime.GOOS,
+					"Arch":          runtime.GOARCH,
+					"BuildTime":     dockerversion.BuildTime,
+					"KernelVersion": kernelVersion,
+					"Experimental":  fmt.Sprintf("%t", daemon.configStore.Experimental),
+				},
+			},
+		},
+
+		// Populate deprecated fields for older clients
+		Version:       dockerversion.Version,
+		GitCommit:     dockerversion.GitCommit,
+		APIVersion:    api.DefaultVersion,
+		MinAPIVersion: api.MinVersion,
+		GoVersion:     runtime.Version(),
+		Os:            runtime.GOOS,
+		Arch:          runtime.GOARCH,
+		BuildTime:     dockerversion.BuildTime,
+		KernelVersion: kernelVersion,
+		Experimental:  daemon.configStore.Experimental,
+	}
+
+	v.Platform.Name = dockerversion.PlatformName
 
 	return v
 }
diff --git a/dockerversion/version_lib.go b/dockerversion/version_lib.go
index 33f77d3..72f4893 100644
--- a/dockerversion/version_lib.go
+++ b/dockerversion/version_lib.go
@@ -13,4 +13,5 @@
 	ContainerdCommitID string = "library-import"
 	RuncCommitID       string = "library-import"
 	InitCommitID       string = "library-import"
+	PlatformName       string = ""
 )
diff --git a/hack/make/.go-autogen b/hack/make/.go-autogen
index b68e3a7..850c3ec 100644
--- a/hack/make/.go-autogen
+++ b/hack/make/.go-autogen
@@ -18,6 +18,7 @@
 	BuildTime          string = "$BUILDTIME"
 	IAmStatic          string = "${IAMSTATIC:-true}"
 	ContainerdCommitID string = "${CONTAINERD_COMMIT}"
+	PlatformName       string = "${PLATFORM}"
 )
 
 // AUTOGENERATED FILE; see /go/src/github.com/docker/docker/hack/make/.go-autogen