diff --git a/pkg/kubelet/dockertools/docker.go b/pkg/kubelet/dockertools/docker.go index bb030743f77..04115703c9d 100644 --- a/pkg/kubelet/dockertools/docker.go +++ b/pkg/kubelet/dockertools/docker.go @@ -104,7 +104,7 @@ type dockerContainerCommandRunner struct { var dockerAPIVersionWithExec = []uint{1, 15} // Returns the major and minor version numbers of docker server. -func (d *dockerContainerCommandRunner) getDockerServerVersion() ([]uint, error) { +func (d *dockerContainerCommandRunner) GetDockerServerVersion() ([]uint, error) { env, err := d.client.Version() if err != nil { return nil, fmt.Errorf("failed to get docker server version - %v", err) @@ -127,7 +127,7 @@ func (d *dockerContainerCommandRunner) getDockerServerVersion() ([]uint, error) } func (d *dockerContainerCommandRunner) nativeExecSupportExists() (bool, error) { - version, err := d.getDockerServerVersion() + version, err := d.GetDockerServerVersion() if err != nil { return false, err } @@ -626,4 +626,5 @@ func parseImageName(image string) (string, string) { type ContainerCommandRunner interface { RunInContainer(containerID string, cmd []string) ([]byte, error) + GetDockerServerVersion() ([]uint, error) } diff --git a/pkg/kubelet/dockertools/docker_test.go b/pkg/kubelet/dockertools/docker_test.go index 8609036ae1b..5108fbc4b14 100644 --- a/pkg/kubelet/dockertools/docker_test.go +++ b/pkg/kubelet/dockertools/docker_test.go @@ -123,7 +123,7 @@ func TestContainerManifestNaming(t *testing.T) { func TestGetDockerServerVersion(t *testing.T) { fakeDocker := &FakeDockerClient{VersionInfo: docker.Env{"Client version=1.2", "Server version=1.1.3", "Server API version=1.15"}} runner := dockerContainerCommandRunner{fakeDocker} - version, err := runner.getDockerServerVersion() + version, err := runner.GetDockerServerVersion() if err != nil { t.Errorf("got error while getting docker server version - %s", err) } diff --git a/pkg/kubelet/kubelet.go b/pkg/kubelet/kubelet.go index fe5cd4890ad..f24f9383f3f 100644 --- a/pkg/kubelet/kubelet.go +++ b/pkg/kubelet/kubelet.go @@ -1362,20 +1362,12 @@ func (kl *Kubelet) syncLoop(updates <-chan PodUpdate, handler SyncHandler) { } // Returns Docker version for this Kubelet. -func (kl *Kubelet) GetDockerVersion() (string, error) { +func (kl *Kubelet) GetDockerVersion() ([]uint, error) { if kl.dockerClient == nil { - return "", fmt.Errorf("No Docker client") + return nil, fmt.Errorf("no Docker client") } - env, err := kl.dockerClient.Version() - if err != nil { - return "", err - } - for _, entry := range *env { - if strings.HasPrefix(entry, "Version=") { - return strings.Split(entry, "=")[1], nil - } - } - return "", fmt.Errorf("Docker version unknown") + dockerRunner := dockertools.NewDockerContainerCommandRunner(kl.dockerClient) + return dockerRunner.GetDockerServerVersion() } // GetKubeletContainerLogs returns logs from the container diff --git a/pkg/kubelet/kubelet_test.go b/pkg/kubelet/kubelet_test.go index b3b44cb4c49..c7130b15bde 100644 --- a/pkg/kubelet/kubelet_test.go +++ b/pkg/kubelet/kubelet_test.go @@ -1367,6 +1367,10 @@ func (f *fakeContainerCommandRunner) RunInContainer(id string, cmd []string) ([] return []byte{}, f.E } +func (f *fakeContainerCommandRunner) GetDockerServerVersion() ([]uint, error) { + return nil, nil +} + func TestRunInContainerNoSuchPod(t *testing.T) { fakeCommandRunner := fakeContainerCommandRunner{} kubelet, fakeDocker := newTestKubelet(t) diff --git a/pkg/kubelet/server.go b/pkg/kubelet/server.go index fdcb402072e..6ac65dc280f 100644 --- a/pkg/kubelet/server.go +++ b/pkg/kubelet/server.go @@ -63,7 +63,7 @@ func ListenAndServeKubeletServer(host HostInterface, address net.IP, port uint, type HostInterface interface { GetContainerInfo(podFullName string, uid types.UID, containerName string, req *info.ContainerInfoRequest) (*info.ContainerInfo, error) GetRootInfo(req *info.ContainerInfoRequest) (*info.ContainerInfo, error) - GetDockerVersion() (string, error) + GetDockerVersion() ([]uint, error) GetMachineInfo() (*info.MachineInfo, error) GetBoundPods() ([]api.BoundPod, error) GetPodByName(namespace, name string) (*api.BoundPod, bool) @@ -109,16 +109,33 @@ func (s *Server) error(w http.ResponseWriter, err error) { http.Error(w, fmt.Sprintf("Internal Error: %v", err), http.StatusInternalServerError) } +func isValidDockerVersion(ver []uint) (bool, string) { + minAllowedVersion := []uint{1, 3, 0} + for i := 0; i < len(ver) && i < len(minAllowedVersion); i++ { + if ver[i] != minAllowedVersion[i] { + if ver[i] < minAllowedVersion[i] { + versions := make([]string, len(ver)) + for i, v := range(ver) { + versions[i] = fmt.Sprint(v) + } + return false, strings.Join(versions, ".") + } + return true, "" + } + } + return true, "" +} + // handleHealthz handles /healthz request and checks Docker version func (s *Server) handleHealthz(w http.ResponseWriter, req *http.Request) { - version, err := s.host.GetDockerVersion() + versions, err := s.host.GetDockerVersion() if err != nil { w.WriteHeader(http.StatusInternalServerError) w.Write([]byte("unknown Docker version")) return } - const minDockerVersion = "1.3.0" - if version < minDockerVersion { + valid, version := isValidDockerVersion(versions) + if !valid { w.WriteHeader(http.StatusInternalServerError) msg := "Docker version is too old (" + version + ")" w.Write([]byte(msg)) diff --git a/pkg/kubelet/server_test.go b/pkg/kubelet/server_test.go index 2dd2f45e46c..32c5f9967e9 100644 --- a/pkg/kubelet/server_test.go +++ b/pkg/kubelet/server_test.go @@ -42,7 +42,7 @@ type fakeKubelet struct { boundPodsFunc func() ([]api.BoundPod, error) logFunc func(w http.ResponseWriter, req *http.Request) runFunc func(podFullName string, uid types.UID, containerName string, cmd []string) ([]byte, error) - dockerVersionFunc func() (string, error) + dockerVersionFunc func() ([]uint, error) containerLogsFunc func(podFullName, containerName, tail string, follow bool, stdout, stderr io.Writer) error } @@ -62,7 +62,7 @@ func (fk *fakeKubelet) GetRootInfo(req *info.ContainerInfoRequest) (*info.Contai return fk.rootInfoFunc(req) } -func (fk *fakeKubelet) GetDockerVersion() (string, error) { +func (fk *fakeKubelet) GetDockerVersion() ([]uint, error) { return fk.dockerVersionFunc() }