From e48f925bda648d00b2691c64227fd70e42a748a3 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Fri, 7 Apr 2017 17:08:54 +0200 Subject: [PATCH 1/2] Fix tini version parsing Invalid version strings for the init (tini) binary were still accepted, which lead to (e.g.) "hello world" Being used as "vhello world" This makes the version parsing slightly stricter Signed-off-by: Sebastiaan van Stijn Upstream-commit: 984d99e19cd5fbc6889528c9588f4875e3c40cc5 Component: engine --- components/engine/daemon/info_unix.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/engine/daemon/info_unix.go b/components/engine/daemon/info_unix.go index e60a06a006..ddbd7523d5 100644 --- a/components/engine/daemon/info_unix.go +++ b/components/engine/daemon/info_unix.go @@ -69,7 +69,7 @@ func (daemon *Daemon) FillPlatformInfo(v *types.Info, sysInfo *sysinfo.SysInfo) v.InitCommit.Expected = dockerversion.InitCommitID[0:len(v.InitCommit.ID)] } } - if v.InitCommit.ID == "" && len(parts) >= 1 { + if v.InitCommit.ID == "" && strings.HasPrefix(parts[0], "tini version") { vs := strings.TrimPrefix(parts[0], "tini version ") v.InitCommit.ID = "v" + vs } From 36c4c391578fbbbb799685caa4cf11532722ac26 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Wed, 29 Mar 2017 13:44:14 +0200 Subject: [PATCH 2/2] Refactor "init" version parsing, and add unit-test Signed-off-by: Sebastiaan van Stijn Upstream-commit: 72eddf4258db8c10b145ded188d13c50e4a5530b Component: engine --- components/engine/daemon/info_unix.go | 50 ++++++++++++--------- components/engine/daemon/info_unix_test.go | 52 ++++++++++++++++++++++ 2 files changed, 80 insertions(+), 22 deletions(-) create mode 100644 components/engine/daemon/info_unix_test.go diff --git a/components/engine/daemon/info_unix.go b/components/engine/daemon/info_unix.go index ddbd7523d5..56437acdb0 100644 --- a/components/engine/daemon/info_unix.go +++ b/components/engine/daemon/info_unix.go @@ -11,6 +11,7 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/dockerversion" "github.com/docker/docker/pkg/sysinfo" + "github.com/pkg/errors" ) // FillPlatformInfo fills the platform related info. @@ -54,32 +55,37 @@ func (daemon *Daemon) FillPlatformInfo(v *types.Info, sysInfo *sysinfo.SysInfo) v.RuncCommit.ID = "N/A" } - v.InitCommit.Expected = dockerversion.InitCommitID if rv, err := exec.Command(DefaultInitBinary, "--version").Output(); err == nil { - // examples of how Tini outputs version info: - // "tini version 0.13.0 - git.949e6fa" - // "tini version 0.13.2" - parts := strings.Split(strings.TrimSpace(string(rv)), " - ") + ver, err := parseInitVersion(string(rv)) - v.InitCommit.ID = "" - if v.InitCommit.ID == "" && len(parts) >= 2 { - gitParts := strings.Split(parts[1], ".") - if len(gitParts) == 2 && gitParts[0] == "git" { - v.InitCommit.ID = gitParts[1] - v.InitCommit.Expected = dockerversion.InitCommitID[0:len(v.InitCommit.ID)] - } - } - if v.InitCommit.ID == "" && strings.HasPrefix(parts[0], "tini version") { - vs := strings.TrimPrefix(parts[0], "tini version ") - v.InitCommit.ID = "v" + vs - } - - if v.InitCommit.ID == "" { - logrus.Warnf("failed to retrieve %s version: unknown output format: %s", DefaultInitBinary, string(rv)) - v.InitCommit.ID = "N/A" + if err != nil { + logrus.Warnf("failed to retrieve %s version: %s", DefaultInitBinary, err) } + v.InitCommit = ver } else { - logrus.Warnf("failed to retrieve %s version", DefaultInitBinary) + logrus.Warnf("failed to retrieve %s version: %s", DefaultInitBinary, err) v.InitCommit.ID = "N/A" } } + +// parseInitVersion parses a Tini version string, and extracts the version. +func parseInitVersion(v string) (types.Commit, error) { + version := types.Commit{ID: "", Expected: dockerversion.InitCommitID} + 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)] + } + } + if version.ID == "" && strings.HasPrefix(parts[0], "tini version ") { + version.ID = "v" + strings.TrimPrefix(parts[0], "tini version ") + } + if version.ID == "" { + version.ID = "N/A" + return version, errors.Errorf("unknown output format: %s", v) + } + return version, nil +} diff --git a/components/engine/daemon/info_unix_test.go b/components/engine/daemon/info_unix_test.go new file mode 100644 index 0000000000..ef36c40e39 --- /dev/null +++ b/components/engine/daemon/info_unix_test.go @@ -0,0 +1,52 @@ +// +build !windows + +package daemon + +import ( + "testing" + + "github.com/docker/docker/api/types" + "github.com/docker/docker/dockerversion" + "github.com/stretchr/testify/assert" +) + +func TestParseInitVersion(t *testing.T) { + tests := []struct { + version string + result types.Commit + invalid bool + }{ + { + version: "tini version 0.13.0 - git.949e6fa", + result: types.Commit{ID: "949e6fa", Expected: dockerversion.InitCommitID[0:7]}, + }, { + version: "tini version 0.13.0\n", + result: types.Commit{ID: "v0.13.0", Expected: dockerversion.InitCommitID}, + }, { + version: "tini version 0.13.2", + result: types.Commit{ID: "v0.13.2", Expected: dockerversion.InitCommitID}, + }, { + version: "tini version0.13.2", + result: types.Commit{ID: "N/A", Expected: dockerversion.InitCommitID}, + invalid: true, + }, { + version: "", + result: types.Commit{ID: "N/A", Expected: dockerversion.InitCommitID}, + invalid: true, + }, { + version: "hello world", + result: types.Commit{ID: "N/A", Expected: dockerversion.InitCommitID}, + invalid: true, + }, + } + + for _, test := range tests { + ver, err := parseInitVersion(string(test.version)) + if test.invalid { + assert.Error(t, err) + } else { + assert.NoError(t, err) + } + assert.Equal(t, test.result, ver) + } +}