Merge pull request #6004 from yifan-gu/ref_manager

kubelet: Move container reference manager to pkg/kubelet/container.
pull/6/head
Victor Marmol 2015-03-26 13:04:34 -07:00
commit 1cad0df268
6 changed files with 100 additions and 74 deletions

View File

@ -1,5 +1,5 @@
/*
Copyright 2014 Google Inc. All rights reserved.
Copyright 2015 Google Inc. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -14,34 +14,35 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package kubelet
package container
import (
"fmt"
"sync"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
)
// ContainerRefManager manages the references for the containers.
// RefManager manages the references for the containers.
// The references are used for reporting events such as creation,
// failure, etc. This manager is thread-safe, no locks are necessary
// for the caller.
type ContainerRefManager struct {
type RefManager struct {
sync.RWMutex
// TODO(yifan): To use strong type.
containerIDToRef map[string]*api.ObjectReference
}
// newContainerRefManager creates and returns a container reference manager
// NewRefManager creates and returns a container reference manager
// with empty contents.
func newContainerRefManager() *ContainerRefManager {
c := ContainerRefManager{}
func NewRefManager() *RefManager {
c := RefManager{}
c.containerIDToRef = make(map[string]*api.ObjectReference)
return &c
}
// SetRef stores a reference to a pod's container, associating it with the given container id.
func (c *ContainerRefManager) SetRef(id string, ref *api.ObjectReference) {
// SetRef stores a reference to a pod's container, associating it with the given container ID.
func (c *RefManager) SetRef(id string, ref *api.ObjectReference) {
c.Lock()
defer c.Unlock()
c.containerIDToRef[id] = ref
@ -50,29 +51,45 @@ func (c *ContainerRefManager) SetRef(id string, ref *api.ObjectReference) {
// ClearRef forgets the given container id and its associated container reference.
// TODO(yifan): This is currently never called. Consider to remove this function,
// or figure out when to clear the references.
func (c *ContainerRefManager) ClearRef(id string) {
func (c *RefManager) ClearRef(id string) {
c.Lock()
defer c.Unlock()
delete(c.containerIDToRef, id)
}
// GetRef returns the container reference of the given id, or (nil, false) if none is stored.
func (c *ContainerRefManager) GetRef(id string) (ref *api.ObjectReference, ok bool) {
// GetRef returns the container reference of the given ID, or (nil, false) if none is stored.
func (c *RefManager) GetRef(id string) (ref *api.ObjectReference, ok bool) {
c.RLock()
defer c.RUnlock()
ref, ok = c.containerIDToRef[id]
return ref, ok
}
// fieldPath returns a fieldPath locating container within pod.
// Returns an error if the container isn't part of the pod.
func fieldPath(pod *api.Pod, container *api.Container) (string, error) {
for i := range pod.Spec.Containers {
here := &pod.Spec.Containers[i]
if here.Name == container.Name {
if here.Name == "" {
return fmt.Sprintf("spec.containers[%d]", i), nil
} else {
return fmt.Sprintf("spec.containers{%s}", here.Name), nil
}
}
}
return "", fmt.Errorf("container %#v not found in pod %#v", container, pod)
}
// GenerateContainerRef returns an *api.ObjectReference which references the given container within the
// given pod. Returns an error if the reference can't be constructed or the container doesn't
// actually belong to the pod.
// TODO: Pods that came to us by static config or over HTTP have no selfLink set, which makes
// this fail and log an error. Figure out how we want to identify these pods to the rest of the
// system.
// TODO(yifan): Revisit this function later, for current case, it does not need to use ContainerRefManager
// as a receiver, and does not need to be exported.
func (c *ContainerRefManager) GenerateContainerRef(pod *api.Pod, container *api.Container) (*api.ObjectReference, error) {
// TODO(yifan): Revisit this function later, for current case it does not need to use RefManager
// as a receiver.
func (c *RefManager) GenerateContainerRef(pod *api.Pod, container *api.Container) (*api.ObjectReference, error) {
fieldPath, err := fieldPath(pod, container)
if err != nil {
// TODO: figure out intelligent way to refer to containers that we implicitly

View File

@ -0,0 +1,61 @@
/*
Copyright 2015 Google Inc. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package container
import (
"testing"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
)
func TestFieldPath(t *testing.T) {
pod := &api.Pod{Spec: api.PodSpec{Containers: []api.Container{
{Name: "foo"},
{Name: "bar"},
{Name: ""},
{Name: "baz"},
}}}
table := map[string]struct {
pod *api.Pod
container *api.Container
path string
success bool
}{
"basic": {pod, &api.Container{Name: "foo"}, "spec.containers{foo}", true},
"basic2": {pod, &api.Container{Name: "baz"}, "spec.containers{baz}", true},
"emptyName": {pod, &api.Container{Name: ""}, "spec.containers[2]", true},
"basicSamePointer": {pod, &pod.Spec.Containers[0], "spec.containers{foo}", true},
"missing": {pod, &api.Container{Name: "qux"}, "", false},
}
for name, item := range table {
res, err := fieldPath(item.pod, item.container)
if item.success == false {
if err == nil {
t.Errorf("%v: unexpected non-error", name)
}
continue
}
if err != nil {
t.Errorf("%v: unexpected error: %v", name, err)
continue
}
if e, a := item.path, res; e != a {
t.Errorf("%v: wanted %v, got %v", name, e, a)
}
}
}

View File

@ -218,7 +218,7 @@ func NewMainKubelet(
rootDirectory: rootDirectory,
resyncInterval: resyncInterval,
podInfraContainerImage: podInfraContainerImage,
containerRefManager: newContainerRefManager(),
containerRefManager: kubecontainer.NewRefManager(),
runner: dockertools.NewDockerContainerCommandRunner(dockerClient),
httpClient: &http.Client{},
pullQPS: pullQPS,
@ -296,7 +296,7 @@ type Kubelet struct {
// Needed to report events for containers belonging to deleted/modified pods.
// Tracks references for reporting events
containerRefManager *ContainerRefManager
containerRefManager *kubecontainer.RefManager
// Optional, defaults to simple Docker implementation
dockerPuller dockertools.DockerPuller
@ -668,22 +668,6 @@ func (kl *Kubelet) runHandler(podFullName string, uid types.UID, container *api.
return actionHandler.Run(podFullName, uid, container, handler)
}
// fieldPath returns a fieldPath locating container within pod.
// Returns an error if the container isn't part of the pod.
func fieldPath(pod *api.Pod, container *api.Container) (string, error) {
for i := range pod.Spec.Containers {
here := &pod.Spec.Containers[i]
if here.Name == container.Name {
if here.Name == "" {
return fmt.Sprintf("spec.containers[%d]", i), nil
} else {
return fmt.Sprintf("spec.containers{%s}", here.Name), nil
}
}
}
return "", fmt.Errorf("container %#v not found in pod %#v", container, pod)
}
// Run a single container from a pod. Returns the docker container ID
func (kl *Kubelet) runContainer(pod *api.Pod, container *api.Container, podVolumes volumeMap, netMode, ipcMode string) (id dockertools.DockerID, err error) {
ref, err := kl.containerRefManager.GenerateContainerRef(pod, container)

View File

@ -110,7 +110,7 @@ func newTestKubelet(t *testing.T) *TestKubelet {
kubelet.cadvisor = mockCadvisor
podManager, fakeMirrorClient := newFakePodManager()
kubelet.podManager = podManager
kubelet.containerRefManager = newContainerRefManager()
kubelet.containerRefManager = kubecontainer.NewRefManager()
return &TestKubelet{kubelet, fakeDocker, mockCadvisor, fakeKubeClient, waitGroup, fakeMirrorClient}
}
@ -1265,44 +1265,6 @@ func TestMakePortsAndBindings(t *testing.T) {
}
}
func TestFieldPath(t *testing.T) {
pod := &api.Pod{Spec: api.PodSpec{Containers: []api.Container{
{Name: "foo"},
{Name: "bar"},
{Name: ""},
{Name: "baz"},
}}}
table := map[string]struct {
pod *api.Pod
container *api.Container
path string
success bool
}{
"basic": {pod, &api.Container{Name: "foo"}, "spec.containers{foo}", true},
"basic2": {pod, &api.Container{Name: "baz"}, "spec.containers{baz}", true},
"emptyName": {pod, &api.Container{Name: ""}, "spec.containers[2]", true},
"basicSamePointer": {pod, &pod.Spec.Containers[0], "spec.containers{foo}", true},
"missing": {pod, &api.Container{Name: "qux"}, "", false},
}
for name, item := range table {
res, err := fieldPath(item.pod, item.container)
if item.success == false {
if err == nil {
t.Errorf("%v: unexpected non-error", name)
}
continue
}
if err != nil {
t.Errorf("%v: unexpected error: %v", name, err)
continue
}
if e, a := item.path, res; e != a {
t.Errorf("%v: wanted %v, got %v", name, e, a)
}
}
}
type errorTestingDockerClient struct {
dockertools.FakeDockerClient
listContainersError error

View File

@ -22,6 +22,7 @@ import (
"time"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
kubecontainer "github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/container"
"github.com/GoogleCloudPlatform/kubernetes/pkg/probe"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util/exec"
@ -153,7 +154,7 @@ func makeTestKubelet(result probe.Result, err error) *Kubelet {
err: err,
},
},
containerRefManager: newContainerRefManager(),
containerRefManager: kubecontainer.NewRefManager(),
}
}

View File

@ -25,6 +25,7 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/client/record"
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/cadvisor"
kubecontainer "github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/container"
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/dockertools"
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/network"
docker "github.com/fsouza/go-dockerclient"
@ -79,7 +80,7 @@ func TestRunOnce(t *testing.T) {
cadvisor: cadvisor,
nodeLister: testNodeLister{},
statusManager: newStatusManager(nil),
containerRefManager: newContainerRefManager(),
containerRefManager: kubecontainer.NewRefManager(),
}
kb.networkPlugin, _ = network.InitNetworkPlugin([]network.NetworkPlugin{}, "", network.NewFakeHost(nil))