mirror of https://github.com/k3s-io/k3s
Merge pull request #6004 from yifan-gu/ref_manager
kubelet: Move container reference manager to pkg/kubelet/container.pull/6/head
commit
1cad0df268
|
@ -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
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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))
|
||||
|
|
Loading…
Reference in New Issue