Skip to content

Commit bbaef48

Browse files
authored
feat: check correct docker version is installed (#2647)
1 parent caa8c6a commit bbaef48

File tree

2 files changed

+71
-12
lines changed

2 files changed

+71
-12
lines changed

internal/util/cmdutil/cmdutil.go

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,13 @@ import (
3535
)
3636

3737
const (
38-
StackTraceOnErrors = "COBRA_STACK_TRACE_ON_ERRORS"
39-
trueString = "true"
40-
Stdout = "stdout"
41-
Unwrap = "unwrap"
42-
dockerVersionTimeout time.Duration = 5 * time.Second
43-
FunctionsCatalogURL = "https://catalog.kpt.dev/catalog-v2.json"
38+
StackTraceOnErrors = "COBRA_STACK_TRACE_ON_ERRORS"
39+
trueString = "true"
40+
Stdout = "stdout"
41+
Unwrap = "unwrap"
42+
dockerVersionTimeout time.Duration = 5 * time.Second
43+
FunctionsCatalogURL = "https://catalog.kpt.dev/catalog-v2.json"
44+
minSupportedDockerVersion string = "v20.10.0"
4445
)
4546

4647
// FixDocs replaces instances of old with new in the docs for c
@@ -88,22 +89,39 @@ func ResolveAbsAndRelPaths(path string) (string, string, error) {
8889
return relPath, absPath, nil
8990
}
9091

91-
// DockerCmdAvailable runs `docker ps` to check that the docker command is
92-
// available, and returns an error with installation instructions if it is not
92+
// DockerCmdAvailable runs `docker version` to check that the docker command is
93+
// available and is a supported version. Returns an error with installation
94+
// instructions if it is not
9395
func DockerCmdAvailable() error {
9496
suggestedText := `docker must be running to use this command
9597
To install docker, follow the instructions at https://docs.docker.com/get-docker/.
9698
`
97-
buffer := &bytes.Buffer{}
99+
cmdOut := &bytes.Buffer{}
98100

99101
ctx, cancel := context.WithTimeout(context.Background(), dockerVersionTimeout)
100102
defer cancel()
101-
cmd := exec.CommandContext(ctx, "docker", "version")
102-
cmd.Stderr = buffer
103+
cmd := exec.CommandContext(ctx, "docker", "version", "--format", "{{.Client.Version}}")
104+
cmd.Stdout = cmdOut
103105
err := cmd.Run()
104-
if err != nil {
106+
if err != nil || cmdOut.String() == "" {
105107
return fmt.Errorf("%s", suggestedText)
106108
}
109+
return isSupportedDockerVersion(strings.TrimSuffix(cmdOut.String(), "\n"))
110+
}
111+
112+
// isSupportedDockerVersion returns an error if a given docker version is invalid
113+
// or is less than minSupportedDockerVersion
114+
func isSupportedDockerVersion(v string) error {
115+
suggestedText := fmt.Sprintf(`docker client version must be %s or greater`, minSupportedDockerVersion)
116+
// docker version output does not have a leading v which is required by semver, so we prefix it
117+
currentDockerVersion := fmt.Sprintf("v%s", v)
118+
if !semver.IsValid(currentDockerVersion) {
119+
return fmt.Errorf("%s: found invalid version %s", suggestedText, currentDockerVersion)
120+
}
121+
// if currentDockerVersion is less than minDockerClientVersion, compare returns +1
122+
if semver.Compare(minSupportedDockerVersion, currentDockerVersion) > 0 {
123+
return fmt.Errorf("%s: found %s", suggestedText, currentDockerVersion)
124+
}
107125
return nil
108126
}
109127

internal/util/cmdutil/cmdutil_test.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"testing"
2424

2525
"github.com/stretchr/testify/assert"
26+
"github.com/stretchr/testify/require"
2627
"sigs.k8s.io/kustomize/kyaml/kio"
2728
)
2829

@@ -352,3 +353,43 @@ func TestListImages(t *testing.T) {
352353
sort.Strings(result)
353354
assert.Equal(t, []string{"apply-setters:v0.1.1", "gatekeeper:v0.2.1"}, result)
354355
}
356+
357+
func TestIsSupportedDockerVersion(t *testing.T) {
358+
tests := []struct {
359+
name string
360+
inputV string
361+
errMsg string
362+
}{
363+
{
364+
name: "greater than min version",
365+
inputV: "20.10.1",
366+
},
367+
{
368+
name: "equal to min version",
369+
inputV: "20.10.0",
370+
},
371+
{
372+
name: "less than min version",
373+
inputV: "20.9.1",
374+
errMsg: "docker client version must be v20.10.0 or greater: found v20.9.1",
375+
},
376+
{
377+
name: "invalid semver",
378+
inputV: "20..12.1",
379+
errMsg: "docker client version must be v20.10.0 or greater: found invalid version v20..12.1",
380+
},
381+
}
382+
for _, tt := range tests {
383+
tt := tt
384+
t.Run(tt.name, func(t *testing.T) {
385+
require := require.New(t)
386+
err := isSupportedDockerVersion(tt.inputV)
387+
if tt.errMsg != "" {
388+
require.NotNil(err)
389+
require.Contains(err.Error(), tt.errMsg)
390+
} else {
391+
require.NoError(err)
392+
}
393+
})
394+
}
395+
}

0 commit comments

Comments
 (0)