diff --git a/pkg/kubelet/container/runtime.go b/pkg/kubelet/container/runtime.go index 9a1590a91e0..5f58e1a4e36 100644 --- a/pkg/kubelet/container/runtime.go +++ b/pkg/kubelet/container/runtime.go @@ -198,6 +198,15 @@ func (c *ContainerID) UnmarshalJSON(data []byte) error { return c.ParseString(string(data)) } +type ContainerStatus string + +const ( + ContainerStatusRunning ContainerStatus = "running" + ContainerStatusExited ContainerStatus = "exited" + // This unknown encompasses all the statuses that we currently don't care. + ContainerStatusUnknown ContainerStatus = "unknown" +) + // Container provides the runtime information for a container, such as ID, hash, // status of the container. type Container struct { @@ -215,6 +224,8 @@ type Container struct { // The timestamp of the creation time of the container. // TODO(yifan): Consider to move it to api.ContainerStatus. Created int64 + // Status is the status of the container. + Status ContainerStatus } // Basic information about a container image. diff --git a/pkg/kubelet/dockertools/convert.go b/pkg/kubelet/dockertools/convert.go index 7f743f5bd35..b55366cf165 100644 --- a/pkg/kubelet/dockertools/convert.go +++ b/pkg/kubelet/dockertools/convert.go @@ -18,6 +18,7 @@ package dockertools import ( "fmt" + "strings" docker "github.com/fsouza/go-dockerclient" kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" @@ -27,6 +28,19 @@ import ( // This file contains helper functions to convert docker API types to runtime // (kubecontainer) types. +func mapStatus(status string) kubecontainer.ContainerStatus { + // Parse the status string in docker.APIContainers. This could break when + // we upgrade docker. + switch { + case strings.HasPrefix(status, "Up"): + return kubecontainer.ContainerStatusRunning + case strings.HasPrefix(status, "Exited"): + return kubecontainer.ContainerStatusExited + default: + return kubecontainer.ContainerStatusUnknown + } +} + // Converts docker.APIContainers to kubecontainer.Container. func toRuntimeContainer(c *docker.APIContainers) (*kubecontainer.Container, error) { if c == nil { @@ -37,12 +51,14 @@ func toRuntimeContainer(c *docker.APIContainers) (*kubecontainer.Container, erro if err != nil { return nil, err } + return &kubecontainer.Container{ ID: kubetypes.DockerID(c.ID).ContainerID(), Name: dockerName.ContainerName, Image: c.Image, Hash: hash, Created: c.Created, + Status: mapStatus(c.Status), }, nil } diff --git a/pkg/kubelet/dockertools/convert_test.go b/pkg/kubelet/dockertools/convert_test.go index acc99f660f2..439100ae41a 100644 --- a/pkg/kubelet/dockertools/convert_test.go +++ b/pkg/kubelet/dockertools/convert_test.go @@ -24,12 +24,31 @@ import ( kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" ) +func TestMapStatus(t *testing.T) { + testCases := []struct { + input string + expected kubecontainer.ContainerStatus + }{ + {input: "Up 5 hours", expected: kubecontainer.ContainerStatusRunning}, + {input: "Exited (0) 2 hours ago", expected: kubecontainer.ContainerStatusExited}, + {input: "Created", expected: kubecontainer.ContainerStatusUnknown}, + {input: "Random string", expected: kubecontainer.ContainerStatusUnknown}, + } + + for i, test := range testCases { + if actual := mapStatus(test.input); actual != test.expected { + t.Errorf("Test[%d]: expected %q, got %q", i, test.expected, actual) + } + } +} + func TestToRuntimeContainer(t *testing.T) { original := &docker.APIContainers{ ID: "ab2cdf", Image: "bar_image", Created: 12345, Names: []string{"/k8s_bar.5678_foo_ns_1234_42"}, + Status: "Up 5 hours", } expected := &kubecontainer.Container{ ID: kubecontainer.ContainerID{"docker", "ab2cdf"}, @@ -37,6 +56,7 @@ func TestToRuntimeContainer(t *testing.T) { Image: "bar_image", Hash: 0x5678, Created: 12345, + Status: kubecontainer.ContainerStatusRunning, } actual, err := toRuntimeContainer(original) diff --git a/pkg/kubelet/dockertools/docker_test.go b/pkg/kubelet/dockertools/docker_test.go index 82cf3cd3ac5..fb7ecd88ad4 100644 --- a/pkg/kubelet/dockertools/docker_test.go +++ b/pkg/kubelet/dockertools/docker_test.go @@ -580,14 +580,16 @@ func TestFindContainersByPod(t *testing.T) { Namespace: "ns", Containers: []*kubecontainer.Container{ { - ID: kubetypes.DockerID("foobar").ContainerID(), - Name: "foobar", - Hash: 0x1234, + ID: kubetypes.DockerID("foobar").ContainerID(), + Name: "foobar", + Hash: 0x1234, + Status: kubecontainer.ContainerStatusUnknown, }, { - ID: kubetypes.DockerID("baz").ContainerID(), - Name: "baz", - Hash: 0x1234, + ID: kubetypes.DockerID("baz").ContainerID(), + Name: "baz", + Hash: 0x1234, + Status: kubecontainer.ContainerStatusUnknown, }, }, }, @@ -597,9 +599,10 @@ func TestFindContainersByPod(t *testing.T) { Namespace: "ns", Containers: []*kubecontainer.Container{ { - ID: kubetypes.DockerID("barbar").ContainerID(), - Name: "barbar", - Hash: 0x1234, + ID: kubetypes.DockerID("barbar").ContainerID(), + Name: "barbar", + Hash: 0x1234, + Status: kubecontainer.ContainerStatusUnknown, }, }, }, @@ -638,19 +641,22 @@ func TestFindContainersByPod(t *testing.T) { Namespace: "ns", Containers: []*kubecontainer.Container{ { - ID: kubetypes.DockerID("foobar").ContainerID(), - Name: "foobar", - Hash: 0x1234, + ID: kubetypes.DockerID("foobar").ContainerID(), + Name: "foobar", + Hash: 0x1234, + Status: kubecontainer.ContainerStatusUnknown, }, { - ID: kubetypes.DockerID("barfoo").ContainerID(), - Name: "barfoo", - Hash: 0x1234, + ID: kubetypes.DockerID("barfoo").ContainerID(), + Name: "barfoo", + Hash: 0x1234, + Status: kubecontainer.ContainerStatusUnknown, }, { - ID: kubetypes.DockerID("baz").ContainerID(), - Name: "baz", - Hash: 0x1234, + ID: kubetypes.DockerID("baz").ContainerID(), + Name: "baz", + Hash: 0x1234, + Status: kubecontainer.ContainerStatusUnknown, }, }, }, @@ -660,9 +666,10 @@ func TestFindContainersByPod(t *testing.T) { Namespace: "ns", Containers: []*kubecontainer.Container{ { - ID: kubetypes.DockerID("barbar").ContainerID(), - Name: "barbar", - Hash: 0x1234, + ID: kubetypes.DockerID("barbar").ContainerID(), + Name: "barbar", + Hash: 0x1234, + Status: kubecontainer.ContainerStatusUnknown, }, }, }, @@ -672,9 +679,10 @@ func TestFindContainersByPod(t *testing.T) { Namespace: "ns", Containers: []*kubecontainer.Container{ { - ID: kubetypes.DockerID("bazbaz").ContainerID(), - Name: "bazbaz", - Hash: 0x1234, + ID: kubetypes.DockerID("bazbaz").ContainerID(), + Name: "bazbaz", + Hash: 0x1234, + Status: kubecontainer.ContainerStatusUnknown, }, }, }, diff --git a/pkg/kubelet/rkt/rkt.go b/pkg/kubelet/rkt/rkt.go index 3b30e6924c0..a302e6a34e0 100644 --- a/pkg/kubelet/rkt/rkt.go +++ b/pkg/kubelet/rkt/rkt.go @@ -793,7 +793,14 @@ func (r *Runtime) GetPods(all bool) ([]*kubecontainer.Pod, error) { var pods []*kubecontainer.Pod for _, u := range units { if strings.HasPrefix(u.Name, kubernetesUnitPrefix) { - if !all && u.SubState != "running" { + var status kubecontainer.ContainerStatus + switch { + case u.SubState == "running": + status = kubecontainer.ContainerStatusRunning + default: + status = kubecontainer.ContainerStatusExited + } + if !all && status != kubecontainer.ContainerStatusRunning { continue } pod, _, err := r.readServiceFile(u.Name)