diff --git a/pkg/kubelet/container_reference_manager.go b/pkg/kubelet/container/container_reference_manager.go similarity index 63% rename from pkg/kubelet/container_reference_manager.go rename to pkg/kubelet/container/container_reference_manager.go index 811e9d74b39..c6ba09b8f06 100644 --- a/pkg/kubelet/container_reference_manager.go +++ b/pkg/kubelet/container/container_reference_manager.go @@ -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 diff --git a/pkg/kubelet/container/container_reference_manager_test.go b/pkg/kubelet/container/container_reference_manager_test.go new file mode 100644 index 00000000000..3739a52e77c --- /dev/null +++ b/pkg/kubelet/container/container_reference_manager_test.go @@ -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) + } + } +} diff --git a/pkg/kubelet/kubelet.go b/pkg/kubelet/kubelet.go index efa748edb2f..96dc93059a6 100644 --- a/pkg/kubelet/kubelet.go +++ b/pkg/kubelet/kubelet.go @@ -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) diff --git a/pkg/kubelet/kubelet_test.go b/pkg/kubelet/kubelet_test.go index bef220876f2..9892f2fe323 100644 --- a/pkg/kubelet/kubelet_test.go +++ b/pkg/kubelet/kubelet_test.go @@ -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 diff --git a/pkg/kubelet/probe_test.go b/pkg/kubelet/probe_test.go index 10fc272203d..5f12124d805 100644 --- a/pkg/kubelet/probe_test.go +++ b/pkg/kubelet/probe_test.go @@ -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(), } } diff --git a/pkg/kubelet/runonce_test.go b/pkg/kubelet/runonce_test.go index 7a0f4e6c501..80517937cb4 100644 --- a/pkg/kubelet/runonce_test.go +++ b/pkg/kubelet/runonce_test.go @@ -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))