Merge pull request #37974 from thaJeztah/add_more_component_versions

Add containerd, runc, and docker-init versions to /version
This commit is contained in:
Yong Tang 2019-01-14 21:09:00 -08:00 committed by GitHub
commit 508e5f7b70
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 171 additions and 43 deletions

View file

@ -118,6 +118,7 @@ func (daemon *Daemon) SystemVersion() types.Version {
v.Platform.Name = dockerversion.PlatformName
daemon.fillPlatformVersion(&v)
return v
}

View file

@ -6,6 +6,7 @@ import (
"context"
"fmt"
"os/exec"
"path/filepath"
"strings"
"github.com/docker/docker/api/types"
@ -32,17 +33,11 @@ func (daemon *Daemon) fillPlatformInfo(v *types.Info, sysInfo *sysinfo.SysInfo)
defaultRuntimeBinary := daemon.configStore.GetRuntime(v.DefaultRuntime).Path
if rv, err := exec.Command(defaultRuntimeBinary, "--version").Output(); err == nil {
parts := strings.Split(strings.TrimSpace(string(rv)), "\n")
if len(parts) == 3 {
parts = strings.Split(parts[1], ": ")
if len(parts) == 2 {
v.RuncCommit.ID = strings.TrimSpace(parts[1])
}
}
if v.RuncCommit.ID == "" {
logrus.Warnf("failed to retrieve %s version: unknown output format: %s", defaultRuntimeBinary, string(rv))
if _, commit, err := parseRuncVersion(string(rv)); err != nil {
logrus.Warnf("failed to parse %s version: %v", defaultRuntimeBinary, err)
v.RuncCommit.ID = "N/A"
} else {
v.RuncCommit.ID = commit
}
} else {
logrus.Warnf("failed to retrieve %s version: %v", defaultRuntimeBinary, err)
@ -64,14 +59,19 @@ func (daemon *Daemon) fillPlatformInfo(v *types.Info, sysInfo *sysinfo.SysInfo)
// value as "ID" to prevent clients from reporting a version-mismatch
v.ContainerdCommit.Expected = v.ContainerdCommit.ID
// TODO is there still a need to check the expected version for tini?
// if not, we can change this, and just set "Expected" to v.InitCommit.ID
v.InitCommit.Expected = dockerversion.InitCommitID
defaultInitBinary := daemon.configStore.GetInitPath()
if rv, err := exec.Command(defaultInitBinary, "--version").Output(); err == nil {
ver, err := parseInitVersion(string(rv))
if err != nil {
logrus.Warnf("failed to retrieve %s version: %s", defaultInitBinary, err)
if _, commit, err := parseInitVersion(string(rv)); err != nil {
logrus.Warnf("failed to parse %s version: %s", defaultInitBinary, err)
v.InitCommit.ID = "N/A"
} else {
v.InitCommit.ID = commit
v.InitCommit.Expected = dockerversion.InitCommitID[0:len(commit)]
}
v.InitCommit = ver
} else {
logrus.Warnf("failed to retrieve %s version: %s", defaultInitBinary, err)
v.InitCommit.ID = "N/A"
@ -115,6 +115,53 @@ func (daemon *Daemon) fillPlatformInfo(v *types.Info, sysInfo *sysinfo.SysInfo)
}
}
func (daemon *Daemon) fillPlatformVersion(v *types.Version) {
if rv, err := daemon.containerd.Version(context.Background()); err == nil {
v.Components = append(v.Components, types.ComponentVersion{
Name: "containerd",
Version: rv.Version,
Details: map[string]string{
"GitCommit": rv.Revision,
},
})
}
defaultRuntime := daemon.configStore.GetDefaultRuntimeName()
defaultRuntimeBinary := daemon.configStore.GetRuntime(defaultRuntime).Path
if rv, err := exec.Command(defaultRuntimeBinary, "--version").Output(); err == nil {
if ver, commit, err := parseRuncVersion(string(rv)); err != nil {
logrus.Warnf("failed to parse %s version: %v", defaultRuntimeBinary, err)
} else {
v.Components = append(v.Components, types.ComponentVersion{
Name: defaultRuntime,
Version: ver,
Details: map[string]string{
"GitCommit": commit,
},
})
}
} else {
logrus.Warnf("failed to retrieve %s version: %v", defaultRuntimeBinary, err)
}
defaultInitBinary := daemon.configStore.GetInitPath()
if rv, err := exec.Command(defaultInitBinary, "--version").Output(); err == nil {
if ver, commit, err := parseInitVersion(string(rv)); err != nil {
logrus.Warnf("failed to parse %s version: %s", defaultInitBinary, err)
} else {
v.Components = append(v.Components, types.ComponentVersion{
Name: filepath.Base(defaultInitBinary),
Version: ver,
Details: map[string]string{
"GitCommit": commit,
},
})
}
} else {
logrus.Warnf("failed to retrieve %s version: %s", defaultInitBinary, err)
}
}
func fillDriverWarnings(v *types.Info) {
for _, pair := range v.DriverStatus {
if pair[0] == "Data loop file" {
@ -149,24 +196,52 @@ func getBackingFs(v *types.Info) string {
return ""
}
// parseInitVersion parses a Tini version string, and extracts the version.
func parseInitVersion(v string) (types.Commit, error) {
version := types.Commit{ID: "", Expected: dockerversion.InitCommitID}
// parseInitVersion parses a Tini version string, and extracts the "version"
// and "git commit" from the output.
//
// Output example from `docker-init --version`:
//
// tini version 0.18.0 - git.fec3683
func parseInitVersion(v string) (version string, commit string, err error) {
parts := strings.Split(strings.TrimSpace(v), " - ")
if len(parts) >= 2 {
gitParts := strings.Split(parts[1], ".")
if len(gitParts) == 2 && gitParts[0] == "git" {
version.ID = gitParts[1]
version.Expected = dockerversion.InitCommitID[0:len(version.ID)]
commit = gitParts[1]
}
}
if version.ID == "" && strings.HasPrefix(parts[0], "tini version ") {
version.ID = "v" + strings.TrimPrefix(parts[0], "tini version ")
if strings.HasPrefix(parts[0], "tini version ") {
version = strings.TrimPrefix(parts[0], "tini version ")
}
if version.ID == "" {
version.ID = "N/A"
return version, errors.Errorf("unknown output format: %s", v)
if version == "" && commit == "" {
err = errors.Errorf("unknown output format: %s", v)
}
return version, nil
return version, commit, err
}
// parseRuncVersion parses the output of `runc --version` and extracts the
// "version" and "git commit" from the output.
//
// Output example from `runc --version`:
//
// runc version 1.0.0-rc5+dev
// commit: 69663f0bd4b60df09991c08812a60108003fa340
// spec: 1.0.0
func parseRuncVersion(v string) (version string, commit string, err error) {
lines := strings.Split(strings.TrimSpace(v), "\n")
for _, line := range lines {
if strings.HasPrefix(line, "runc version") {
version = strings.TrimSpace(strings.TrimPrefix(line, "runc version"))
continue
}
if strings.HasPrefix(line, "commit:") {
commit = strings.TrimSpace(strings.TrimPrefix(line, "commit:"))
continue
}
}
if version == "" && commit == "" {
err = errors.Errorf("unknown output format: %s", v)
}
return version, commit, err
}

View file

@ -5,49 +5,99 @@ package daemon // import "github.com/docker/docker/daemon"
import (
"testing"
"github.com/docker/docker/api/types"
"github.com/docker/docker/dockerversion"
"gotest.tools/assert"
is "gotest.tools/assert/cmp"
)
func TestParseInitVersion(t *testing.T) {
tests := []struct {
output string
version string
result types.Commit
commit string
invalid bool
}{
{
version: "tini version 0.13.0 - git.949e6fa",
result: types.Commit{ID: "949e6fa", Expected: dockerversion.InitCommitID[0:7]},
output: "tini version 0.13.0 - git.949e6fa",
version: "0.13.0",
commit: "949e6fa",
}, {
version: "tini version 0.13.0\n",
result: types.Commit{ID: "v0.13.0", Expected: dockerversion.InitCommitID},
output: "tini version 0.13.0\n",
version: "0.13.0",
}, {
version: "tini version 0.13.2",
result: types.Commit{ID: "v0.13.2", Expected: dockerversion.InitCommitID},
output: "tini version 0.13.2",
version: "0.13.2",
}, {
version: "tini version0.13.2",
result: types.Commit{ID: "N/A", Expected: dockerversion.InitCommitID},
output: "tini version0.13.2",
invalid: true,
}, {
version: "",
result: types.Commit{ID: "N/A", Expected: dockerversion.InitCommitID},
output: "",
invalid: true,
}, {
version: "hello world",
result: types.Commit{ID: "N/A", Expected: dockerversion.InitCommitID},
output: "hello world",
invalid: true,
},
}
for _, test := range tests {
ver, err := parseInitVersion(string(test.version))
version, commit, err := parseInitVersion(string(test.output))
if test.invalid {
assert.Check(t, is.ErrorContains(err, ""))
} else {
assert.Check(t, err)
}
assert.Check(t, is.DeepEqual(test.result, ver))
assert.Equal(t, test.version, version)
assert.Equal(t, test.commit, commit)
}
}
func TestParseRuncVersion(t *testing.T) {
tests := []struct {
output string
version string
commit string
invalid bool
}{
{
output: `
runc version 1.0.0-rc5+dev
commit: 69663f0bd4b60df09991c08812a60108003fa340
spec: 1.0.0
`,
version: "1.0.0-rc5+dev",
commit: "69663f0bd4b60df09991c08812a60108003fa340",
},
{
output: `
runc version 1.0.0-rc5+dev
spec: 1.0.0
`,
version: "1.0.0-rc5+dev",
},
{
output: `
commit: 69663f0bd4b60df09991c08812a60108003fa340
spec: 1.0.0
`,
commit: "69663f0bd4b60df09991c08812a60108003fa340",
},
{
output: "",
invalid: true,
},
{
output: "hello world",
invalid: true,
},
}
for _, test := range tests {
version, commit, err := parseRuncVersion(string(test.output))
if test.invalid {
assert.Check(t, is.ErrorContains(err, ""))
} else {
assert.Check(t, err)
}
assert.Equal(t, test.version, version)
assert.Equal(t, test.commit, commit)
}
}

View file

@ -9,5 +9,7 @@ import (
func (daemon *Daemon) fillPlatformInfo(v *types.Info, sysInfo *sysinfo.SysInfo) {
}
func (daemon *Daemon) fillPlatformVersion(v *types.Version) {}
func fillDriverWarnings(v *types.Info) {
}