diff --git a/cmd/kubeadm/.import-restrictions b/cmd/kubeadm/.import-restrictions index f32afb82499..4c184a87482 100644 --- a/cmd/kubeadm/.import-restrictions +++ b/cmd/kubeadm/.import-restrictions @@ -112,15 +112,7 @@ "github.com/coreos/etcd/pkg/tlsutil", "github.com/coreos/etcd/pkg/transport", "github.com/davecgh/go-spew/spew", - "github.com/docker/distribution/digestset", "github.com/docker/distribution/reference", - "github.com/docker/docker/api", - "github.com/docker/docker/client", - "github.com/docker/docker/pkg/term", - "github.com/docker/go-connections/nat", - "github.com/docker/go-connections/sockets", - "github.com/docker/go-connections/tlsconfig", - "github.com/docker/go-units", "github.com/docker/libnetwork/ipvs", "github.com/godbus/dbus", "github.com/gogo/protobuf/proto", diff --git a/cmd/kubeadm/app/util/system/BUILD b/cmd/kubeadm/app/util/system/BUILD index eb403878543..f47bca5eebe 100644 --- a/cmd/kubeadm/app/util/system/BUILD +++ b/cmd/kubeadm/app/util/system/BUILD @@ -25,8 +25,6 @@ go_library( deps = [ "//staging/src/k8s.io/apimachinery/pkg/util/errors:go_default_library", "//vendor/github.com/blang/semver:go_default_library", - "//vendor/github.com/docker/docker/api/types:go_default_library", - "//vendor/github.com/docker/docker/client:go_default_library", "//vendor/github.com/pkg/errors:go_default_library", "//vendor/k8s.io/klog:go_default_library", ], @@ -44,7 +42,6 @@ go_test( embed = [":go_default_library"], tags = ["e2e"], deps = [ - "//vendor/github.com/docker/docker/api/types:go_default_library", "//vendor/github.com/pkg/errors:go_default_library", "//vendor/github.com/stretchr/testify/assert:go_default_library", ], diff --git a/cmd/kubeadm/app/util/system/docker_validator.go b/cmd/kubeadm/app/util/system/docker_validator.go index 7eea21296d9..4131bbb2f83 100644 --- a/cmd/kubeadm/app/util/system/docker_validator.go +++ b/cmd/kubeadm/app/util/system/docker_validator.go @@ -17,11 +17,10 @@ limitations under the License. package system import ( - "context" + "encoding/json" + "os/exec" "regexp" - "github.com/docker/docker/api/types" - "github.com/docker/docker/client" "github.com/pkg/errors" ) @@ -32,6 +31,14 @@ type DockerValidator struct { Reporter Reporter } +// dockerInfo holds a local subset of the Info struct from +// github.com/docker/docker/api/types. +// The JSON output from 'docker info' should map to this struct. +type dockerInfo struct { + Driver string `json:"Driver"` + ServerVersion string `json:"ServerVersion"` +} + // Name is part of the system.Validator interface. func (d *DockerValidator) Name() string { return "docker" @@ -51,18 +58,28 @@ func (d *DockerValidator) Validate(spec SysSpec) (error, error) { return nil, nil } - c, err := client.NewClient(dockerEndpoint, "", nil, nil) + // Run 'docker info' with a JSON output and unmarshal it into a dockerInfo object + info := dockerInfo{} + out, err := exec.Command("docker", "info", "--format", "{{json .}}").CombinedOutput() if err != nil { - return nil, errors.Wrap(err, "failed to create docker client") + return nil, errors.Errorf(`failed executing "docker info --format '{{json .}}'"\noutput: %s\nerror: %v`, string(out), err) } - info, err := c.Info(context.Background()) - if err != nil { - return nil, errors.Wrap(err, "failed to get docker info") + if err := d.unmarshalDockerInfo(out, &info); err != nil { + return nil, err } + + // validate the resulted docker info object against the spec return d.validateDockerInfo(spec.RuntimeSpec.DockerSpec, info) } -func (d *DockerValidator) validateDockerInfo(spec *DockerSpec, info types.Info) (error, error) { +func (d *DockerValidator) unmarshalDockerInfo(b []byte, info *dockerInfo) error { + if err := json.Unmarshal(b, &info); err != nil { + return errors.Wrap(err, "could not unmarshal the JSON output of 'docker info'") + } + return nil +} + +func (d *DockerValidator) validateDockerInfo(spec *DockerSpec, info dockerInfo) (error, error) { // Validate docker version. matched := false for _, v := range spec.Version { diff --git a/cmd/kubeadm/app/util/system/docker_validator_test.go b/cmd/kubeadm/app/util/system/docker_validator_test.go index 765aa0cb80e..132c3b9cb37 100644 --- a/cmd/kubeadm/app/util/system/docker_validator_test.go +++ b/cmd/kubeadm/app/util/system/docker_validator_test.go @@ -17,9 +17,9 @@ limitations under the License. package system import ( + "reflect" "testing" - "github.com/docker/docker/api/types" "github.com/stretchr/testify/assert" ) @@ -33,61 +33,61 @@ func TestValidateDockerInfo(t *testing.T) { } for _, test := range []struct { name string - info types.Info + info dockerInfo err bool warn bool }{ { name: "unsupported Docker version 1.12.1", - info: types.Info{Driver: "driver_2", ServerVersion: "1.12.1"}, + info: dockerInfo{Driver: "driver_2", ServerVersion: "1.12.1"}, err: true, warn: false, }, { name: "unsupported driver", - info: types.Info{Driver: "bad_driver", ServerVersion: "1.13.1"}, + info: dockerInfo{Driver: "bad_driver", ServerVersion: "1.13.1"}, err: true, warn: false, }, { name: "valid Docker version 1.13.1", - info: types.Info{Driver: "driver_1", ServerVersion: "1.13.1"}, + info: dockerInfo{Driver: "driver_1", ServerVersion: "1.13.1"}, err: false, warn: false, }, { name: "valid Docker version 17.03.0-ce", - info: types.Info{Driver: "driver_2", ServerVersion: "17.03.0-ce"}, + info: dockerInfo{Driver: "driver_2", ServerVersion: "17.03.0-ce"}, err: false, warn: false, }, { name: "valid Docker version 17.06.0-ce", - info: types.Info{Driver: "driver_2", ServerVersion: "17.06.0-ce"}, + info: dockerInfo{Driver: "driver_2", ServerVersion: "17.06.0-ce"}, err: false, warn: false, }, { name: "valid Docker version 17.09.0-ce", - info: types.Info{Driver: "driver_2", ServerVersion: "17.09.0-ce"}, + info: dockerInfo{Driver: "driver_2", ServerVersion: "17.09.0-ce"}, err: false, warn: false, }, { name: "valid Docker version 18.06.0-ce", - info: types.Info{Driver: "driver_2", ServerVersion: "18.06.0-ce"}, + info: dockerInfo{Driver: "driver_2", ServerVersion: "18.06.0-ce"}, err: false, warn: false, }, { name: "valid Docker version 18.09.1-ce", - info: types.Info{Driver: "driver_2", ServerVersion: "18.09.1-ce"}, + info: dockerInfo{Driver: "driver_2", ServerVersion: "18.09.1-ce"}, err: false, warn: false, }, { name: "Docker version 19.01.0 is not in the list of validated versions", - info: types.Info{Driver: "driver_2", ServerVersion: "19.01.0"}, + info: dockerInfo{Driver: "driver_2", ServerVersion: "19.01.0"}, err: false, warn: true, }, @@ -107,3 +107,41 @@ func TestValidateDockerInfo(t *testing.T) { }) } } + +func TestUnmarshalDockerInfo(t *testing.T) { + v := &DockerValidator{} + + testCases := []struct { + name string + input string + expectedInfo dockerInfo + expectedError bool + }{ + { + name: "valid: expected dockerInfo is valid", + input: `{ "Driver":"foo", "ServerVersion":"bar" }`, + expectedInfo: dockerInfo{Driver: "foo", ServerVersion: "bar"}, + }, + { + name: "invalid: the JSON input is not valid", + input: `{ "Driver":"foo"`, + expectedError: true, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + var err error + info := dockerInfo{} + if err = v.unmarshalDockerInfo([]byte(tc.input), &info); (err != nil) != tc.expectedError { + t.Fatalf("failed unmarshaling; expected error: %v, got: %v, error: %v", tc.expectedError, (err != nil), err) + } + if err != nil { + return + } + if !reflect.DeepEqual(tc.expectedInfo, info) { + t.Fatalf("dockerInfo do not match, expected: %#v, got: %#v", tc.expectedInfo, info) + } + }) + } +}