Skip to content

Commit

Permalink
Add GetContainers in docker manager
Browse files Browse the repository at this point in the history
This function is part of the container runtime interface, so docker should
support it.

This change also adds some basic unit tests in manager_test.go. We should
start migrating docker specific tests from kubelet_test to manager_test.go.
  • Loading branch information
yujuhong committed Apr 29, 2015
1 parent ee27094 commit 959b3f5
Show file tree
Hide file tree
Showing 2 changed files with 152 additions and 20 deletions.
94 changes: 74 additions & 20 deletions pkg/kubelet/dockertools/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -635,6 +635,67 @@ func makeCapabilites(capAdd []api.CapabilityType, capDrop []api.CapabilityType)
return addCaps, dropCaps
}

// A helper function to get the KubeletContainerName and hash from a docker
// container.
func getDockerContainerNameInfo(c *docker.APIContainers) (*KubeletContainerName, uint64, error) {
if len(c.Names) == 0 {
return nil, 0, fmt.Errorf("cannot parse empty docker container name: %#v", c.Names)
}
dockerName, hash, err := ParseDockerName(c.Names[0])
if err != nil {
return nil, 0, fmt.Errorf("parse docker container name %q error: %v", c.Names[0], err)
}
return dockerName, hash, nil
}

// Converts docker.APIContainers to kubecontainer.Container.
func convertDockerToRuntimeContainer(c *docker.APIContainers) (*kubecontainer.Container, error) {
dockerName, hash, err := getDockerContainerNameInfo(c)
if err != nil {
return nil, err
}
return &kubecontainer.Container{
ID: types.UID(c.ID),
Name: dockerName.ContainerName,
Image: c.Image,
Hash: hash,
Created: c.Created,
}, nil
}

// Get pod UID, name, and namespace by examining the container names.
func getPodInfoFromContainer(c *docker.APIContainers) (types.UID, string, string, error) {
dockerName, _, err := getDockerContainerNameInfo(c)
if err != nil {
return types.UID(""), "", "", err
}
name, namespace, err := kubecontainer.ParsePodFullName(dockerName.PodFullName)
if err != nil {
return types.UID(""), "", "", fmt.Errorf("parse pod full name %q error: %v", dockerName.PodFullName, err)
}
return dockerName.PodUID, name, namespace, nil
}

// GetContainers returns a list of running containers if |all| is false;
// otherwise, it returns all containers.
func (dm *DockerManager) GetContainers(all bool) ([]*kubecontainer.Container, error) {
containers, err := GetKubeletDockerContainers(dm.client, all)
if err != nil {
return nil, err
}
// Convert DockerContainers to []*kubecontainer.Container
result := make([]*kubecontainer.Container, 0, len(containers))
for _, c := range containers {
converted, err := convertDockerToRuntimeContainer(c)
if err != nil {
glog.Errorf("Error examining the container: %v", err)
continue
}
result = append(result, converted)
}
return result, nil
}

func (dm *DockerManager) GetPods(all bool) ([]*kubecontainer.Pod, error) {
pods := make(map[types.UID]*kubecontainer.Pod)
var result []*kubecontainer.Pod
Expand All @@ -646,35 +707,28 @@ func (dm *DockerManager) GetPods(all bool) ([]*kubecontainer.Pod, error) {

// Group containers by pod.
for _, c := range containers {
if len(c.Names) == 0 {
glog.Warningf("Cannot parse empty docker container name: %#v", c.Names)
converted, err := convertDockerToRuntimeContainer(c)
if err != nil {
glog.Errorf("Error examining the container: %v", err)
continue
}
dockerName, hash, err := ParseDockerName(c.Names[0])

podUID, podName, podNamespace, err := getPodInfoFromContainer(c)
if err != nil {
glog.Warningf("Parse docker container name %q error: %v", c.Names[0], err)
glog.Errorf("Error examining the container: %v", err)
continue
}
pod, found := pods[dockerName.PodUID]

pod, found := pods[podUID]
if !found {
name, namespace, err := kubecontainer.ParsePodFullName(dockerName.PodFullName)
if err != nil {
glog.Warningf("Parse pod full name %q error: %v", dockerName.PodFullName, err)
continue
}
pod = &kubecontainer.Pod{
ID: dockerName.PodUID,
Name: name,
Namespace: namespace,
ID: podUID,
Name: podName,
Namespace: podNamespace,
}
pods[dockerName.PodUID] = pod
pods[podUID] = pod
}
pod.Containers = append(pod.Containers, &kubecontainer.Container{
ID: types.UID(c.ID),
Name: dockerName.ContainerName,
Hash: hash,
Created: c.Created,
})
pod.Containers = append(pod.Containers, converted)
}

// Convert map to list.
Expand Down
78 changes: 78 additions & 0 deletions pkg/kubelet/dockertools/manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,38 @@ limitations under the License.
package dockertools

import (
"reflect"
"testing"

"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/client/record"
kubecontainer "github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/container"
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/network"
"github.com/GoogleCloudPlatform/kubernetes/pkg/types"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
"github.com/fsouza/go-dockerclient"
)

func NewFakeDockerManager() (*DockerManager, *FakeDockerClient) {
fakeDocker := &FakeDockerClient{Errors: make(map[string]error), RemovedImages: util.StringSet{}}
fakeRecorder := &record.FakeRecorder{}
readinessManager := kubecontainer.NewReadinessManager()
containerRefManager := kubecontainer.NewRefManager()
networkPlugin, _ := network.InitNetworkPlugin([]network.NetworkPlugin{}, "", network.NewFakeHost(nil))

dockerManager := NewDockerManager(
fakeDocker,
fakeRecorder,
readinessManager,
containerRefManager,
PodInfraContainerImage,
0, 0, "",
kubecontainer.FakeOS{},
networkPlugin)

return dockerManager, fakeDocker
}

func TestSetEntrypointAndCommand(t *testing.T) {
cases := []struct {
name string
Expand Down Expand Up @@ -87,3 +113,55 @@ func TestSetEntrypointAndCommand(t *testing.T) {
}
}
}

func TestConvertDockerToRuntimeContainer(t *testing.T) {
dockerContainer := &docker.APIContainers{
ID: "ab2cdf",
Image: "bar_image",
Created: 12345,
Names: []string{"/k8s_bar.5678_foo_ns_1234_42"},
}
expected := &kubecontainer.Container{
ID: types.UID("ab2cdf"),
Name: "bar",
Image: "bar_image",
Hash: 0x5678,
Created: 12345,
}

actual, err := convertDockerToRuntimeContainer(dockerContainer)
if err != nil {
t.Fatalf("unexpected error %v", err)
}
if !reflect.DeepEqual(expected, actual) {
t.Errorf("expected %#v, got %#v", expected, actual)
}
}

func TestGetContainers(t *testing.T) {
manager, fakeDocker := NewFakeDockerManager()
containers := []docker.APIContainers{
{
ID: "1234",
Names: []string{"/k8s_foo_qux_new_1234_42"},
},
{
ID: "5678",
Names: []string{"/k8s_bar_qux_new_5678_42"},
},
}
expected := util.NewStringSet([]string{"foo", "bar"}...)
fakeDocker.ContainerList = containers
actualContainers, err := manager.GetContainers(false)
if err != nil {
t.Fatalf("unexpected error %v", err)
}

actual := util.NewStringSet()
for _, c := range actualContainers {
actual.Insert(c.Name)
}
if !reflect.DeepEqual(expected.List(), actual.List()) {
t.Errorf("expected %#v, got %#v", expected.List(), actual.List())
}
}

0 comments on commit 959b3f5

Please sign in to comment.