kubelet: revamp the pod/container naming scheme

There are two main goals for this change.

 1. Fix the naming scheme in kubelet so that it accepts DNS subdomain
    name/namespaces correctly (#4920). The design is discussed in #3453.

 2. Prepare for syncing the static pods back to the apiserver(#4090). This
    includes

  - Eliminate the source component in the internal full pod name (#4922). Pods
    no longer need sources as they will all be sync'd via apiserver.

  - Changing the naming scheme for the static (file-, http-, and etcd-based)
    pods such that they are distinguishable when syncing back to the apiserver.

The changes includes:
  *	name = <pod.Name>-<hostname>
  * namespace = <cluster_namespace> (i.e. "default" for now).
  * container_name = k8s_<contianer_name>.<hash_of_container>_<pod_name>_<namespace>_<uid>_<random>

Note that this is not backward-compatible, meaning the kubelet won't recognize
existing running containers using the old naming scheme.
pull/6/head
Yu-Ju Hong 2015-02-26 12:27:14 -08:00
parent 32fd331e73
commit fe70be9261
14 changed files with 265 additions and 248 deletions

View File

@ -18,6 +18,7 @@ package config
import (
"fmt"
"os"
"reflect"
"sync"
@ -206,7 +207,7 @@ func (s *podStorage) merge(source string, change interface{}) (adds, updates, de
filtered := filterInvalidPods(update.Pods, source, s.recorder)
for _, ref := range filtered {
name := podUniqueName(ref)
name := kubelet.GetPodFullName(ref)
if existing, found := pods[name]; found {
if !reflect.DeepEqual(existing.Spec, ref.Spec) {
// this is an update
@ -229,7 +230,7 @@ func (s *podStorage) merge(source string, change interface{}) (adds, updates, de
case kubelet.REMOVE:
glog.V(4).Infof("Removing a pod %v", update)
for _, value := range update.Pods {
name := podUniqueName(&value)
name := kubelet.GetPodFullName(&value)
if existing, found := pods[name]; found {
// this is a delete
delete(pods, name)
@ -248,7 +249,7 @@ func (s *podStorage) merge(source string, change interface{}) (adds, updates, de
filtered := filterInvalidPods(update.Pods, source, s.recorder)
for _, ref := range filtered {
name := podUniqueName(ref)
name := kubelet.GetPodFullName(ref)
if existing, found := oldPods[name]; found {
pods[name] = existing
if !reflect.DeepEqual(existing.Spec, ref.Spec) {
@ -306,7 +307,7 @@ func filterInvalidPods(pods []api.BoundPod, source string, recorder record.Event
// If validation fails, don't trust it any further -
// even Name could be bad.
} else {
name := podUniqueName(pod)
name := kubelet.GetPodFullName(pod)
if names.Has(name) {
errlist = append(errlist, apierrs.NewFieldDuplicate("name", pod.Name))
} else {
@ -349,12 +350,6 @@ func (s *podStorage) MergedState() interface{} {
return pods
}
// podUniqueName returns a value for a given pod that is unique across a source,
// which is the combination of namespace and name.
func podUniqueName(pod *api.BoundPod) string {
return fmt.Sprintf("%s.%s", pod.Name, pod.Namespace)
}
func bestPodIdentString(pod *api.BoundPod) string {
namespace := pod.Namespace
if namespace == "" {
@ -366,3 +361,11 @@ func bestPodIdentString(pod *api.BoundPod) string {
}
return fmt.Sprintf("%s.%s", name, namespace)
}
func GeneratePodName(name string) (string, error) {
hostname, err := os.Hostname() //TODO: kubelet name would be better
if err != nil {
return "", err
}
return fmt.Sprintf("%s-%s", name, hostname), nil
}

View File

@ -108,11 +108,8 @@ func eventToPods(ev watch.Event) ([]api.BoundPod, error) {
}
for _, pod := range boundPods.Items {
// Backwards compatibility with old api servers
// TODO: Remove this after 1.0 release.
if len(pod.Namespace) == 0 {
pod.Namespace = api.NamespaceDefault
}
// Always overrides the namespace provided by the etcd event.
pod.Namespace = kubelet.NamespaceDefault
pods = append(pods, pod)
}

View File

@ -102,8 +102,14 @@ func TestEventToPods(t *testing.T) {
},
},
pods: []api.BoundPod{
{ObjectMeta: api.ObjectMeta{UID: "111", Name: "foo", Namespace: "foo"}, Spec: api.PodSpec{}},
{ObjectMeta: api.ObjectMeta{UID: "222", Name: "bar", Namespace: "bar"}, Spec: api.PodSpec{}},
{
ObjectMeta: api.ObjectMeta{UID: "111", Name: "foo", Namespace: kubelet.NamespaceDefault},
Spec: api.PodSpec{},
},
{
ObjectMeta: api.ObjectMeta{UID: "222", Name: "bar", Namespace: kubelet.NamespaceDefault},
Spec: api.PodSpec{},
},
},
fail: false,
},
@ -116,7 +122,9 @@ func TestEventToPods(t *testing.T) {
},
},
pods: []api.BoundPod{
{ObjectMeta: api.ObjectMeta{UID: "111", Name: "foo", Namespace: "default"}, Spec: api.PodSpec{}},
{
ObjectMeta: api.ObjectMeta{UID: "111", Name: "foo", Namespace: kubelet.NamespaceDefault},
Spec: api.PodSpec{}},
},
fail: false,
},

View File

@ -21,7 +21,6 @@ import (
"crypto/md5"
"encoding/hex"
"fmt"
"hash/adler32"
"io/ioutil"
"os"
"path/filepath"
@ -186,17 +185,16 @@ func extractFromFile(filename string) (api.BoundPod, error) {
// completely deprecate ContainerManifest.
if len(pod.Name) == 0 {
pod.Name = string(pod.UID)
glog.V(5).Infof("Generated Name %q for UID %q from file %s", pod.Name, pod.UID, filename)
}
if len(pod.Namespace) == 0 {
hasher := adler32.New()
fmt.Fprint(hasher, filename)
// TODO: file-<sum>.hostname would be better, if DNS subdomains
// are allowed for namespace (some places only allow DNS
// labels).
pod.Namespace = fmt.Sprintf("file-%08x-%s", hasher.Sum32(), hostname)
glog.V(5).Infof("Generated namespace %q for pod %q from file %s", pod.Namespace, pod.Name, filename)
if pod.Name, err = GeneratePodName(pod.Name); err != nil {
return pod, err
}
glog.V(5).Infof("Generated Name %q for UID %q from file %s", pod.Name, pod.UID, filename)
// Always overrides the namespace provided by the file.
pod.Namespace = kubelet.NamespaceDefault
glog.V(5).Infof("Using namespace %q for pod %q from file %s", pod.Namespace, pod.Name, filename)
// TODO(dchen1107): BoundPod is not type of runtime.Object. Once we allow kubelet talks
// about Pod directly, we can use SelfLinker defined in package: latest
// Currently just simply follow the same format in resthandler.go

View File

@ -54,8 +54,9 @@ func ExampleManifestAndPod(id string) (v1beta1.ContainerManifest, api.BoundPod)
}
expectedPod := api.BoundPod{
ObjectMeta: api.ObjectMeta{
Name: id,
UID: types.UID(id),
Name: id,
UID: types.UID(id),
Namespace: kubelet.NamespaceDefault,
},
Spec: api.PodSpec{
Containers: []api.Container{
@ -131,27 +132,30 @@ func TestReadFromFile(t *testing.T) {
update := got.(kubelet.PodUpdate)
expected := CreatePodUpdate(kubelet.SET, kubelet.FileSource, api.BoundPod{
ObjectMeta: api.ObjectMeta{
Name: "test",
Name: "",
UID: "12345",
Namespace: "",
Namespace: kubelet.NamespaceDefault,
SelfLink: "",
},
Spec: api.PodSpec{Containers: []api.Container{{Image: "test/image"}}},
})
if !strings.HasPrefix(update.Pods[0].Name, "test-") {
t.Errorf("Unexpected name: %s", update.Pods[0].Name)
}
// There's no way to provide namespace in ContainerManifest, so
// it will be defaulted.
if !strings.HasPrefix(update.Pods[0].ObjectMeta.Namespace, "file-") {
t.Errorf("Unexpected namespace: %s", update.Pods[0].ObjectMeta.Namespace)
if update.Pods[0].Namespace != kubelet.NamespaceDefault {
t.Errorf("Unexpected namespace: %s", update.Pods[0].Namespace)
}
update.Pods[0].ObjectMeta.Namespace = ""
// SelfLink depends on namespace.
if !strings.HasPrefix(update.Pods[0].ObjectMeta.SelfLink, "/api/") {
t.Errorf("Unexpected selflink: %s", update.Pods[0].ObjectMeta.SelfLink)
if !strings.HasPrefix(update.Pods[0].SelfLink, "/api/") {
t.Errorf("Unexpected selflink: %s", update.Pods[0].SelfLink)
}
update.Pods[0].ObjectMeta.SelfLink = ""
// Reset the fileds that we don't want to compare.
update.Pods[0].Name = ""
update.Pods[0].SelfLink = ""
if !api.Semantic.DeepDerivative(expected, update) {
t.Fatalf("Expected %#v, Got %#v", expected, update)
}
@ -179,7 +183,7 @@ func TestReadFromFileWithoutID(t *testing.T) {
ObjectMeta: api.ObjectMeta{
Name: "",
UID: "12345",
Namespace: "",
Namespace: kubelet.NamespaceDefault,
SelfLink: "",
},
Spec: api.PodSpec{Containers: []api.Container{{Image: "test/image"}}},
@ -188,10 +192,9 @@ func TestReadFromFileWithoutID(t *testing.T) {
if len(update.Pods[0].ObjectMeta.Name) == 0 {
t.Errorf("Name did not get defaulted")
}
update.Pods[0].ObjectMeta.Name = ""
update.Pods[0].ObjectMeta.Namespace = ""
update.Pods[0].ObjectMeta.SelfLink = ""
// Reset the fileds that we don't want to compare.
update.Pods[0].Name = ""
update.Pods[0].SelfLink = ""
if !api.Semantic.DeepDerivative(expected, update) {
t.Fatalf("Expected %#v, Got %#v", expected, update)
}
@ -218,17 +221,17 @@ func TestReadV1Beta2FromFile(t *testing.T) {
update := got.(kubelet.PodUpdate)
expected := CreatePodUpdate(kubelet.SET, kubelet.FileSource, api.BoundPod{
ObjectMeta: api.ObjectMeta{
Name: "test",
Name: "",
UID: "12345",
Namespace: "",
Namespace: kubelet.NamespaceDefault,
SelfLink: "",
},
Spec: api.PodSpec{Containers: []api.Container{{Image: "test/image"}}},
})
update.Pods[0].ObjectMeta.Namespace = ""
update.Pods[0].ObjectMeta.SelfLink = ""
// Reset the fileds that we don't want to compare.
update.Pods[0].Name = ""
update.Pods[0].SelfLink = ""
if !api.Semantic.DeepDerivative(expected, update) {
t.Fatalf("Expected %#v, Got %#v", expected, update)
}
@ -252,8 +255,8 @@ func TestReadFromFileWithDefaults(t *testing.T) {
select {
case got := <-ch:
update := got.(kubelet.PodUpdate)
if update.Pods[0].ObjectMeta.UID == "" {
t.Errorf("Unexpected UID: %s", update.Pods[0].ObjectMeta.UID)
if update.Pods[0].UID == "" {
t.Errorf("Unexpected UID: %s", update.Pods[0].UID)
}
case <-time.After(time.Second):
@ -337,12 +340,16 @@ func TestExtractFromDir(t *testing.T) {
update := (<-ch).(kubelet.PodUpdate)
for i := range update.Pods {
update.Pods[i].Namespace = "foobar"
// Pod name is generated with hash and is unique. Skip the comparision
// here by setting it to a simple value.
update.Pods[i].Name = manifests[i].ID
update.Pods[i].SelfLink = ""
}
expected := CreatePodUpdate(kubelet.SET, kubelet.FileSource, pods...)
for i := range expected.Pods {
expected.Pods[i].Namespace = "foobar"
// Pod name is generated with hash and is unique. Skip the comparision
// here by setting it to a simple value.
expected.Pods[i].Name = manifests[i].ID
}
sort.Sort(sortedPods(update.Pods))
sort.Sort(sortedPods(expected.Pods))
@ -351,7 +358,7 @@ func TestExtractFromDir(t *testing.T) {
}
for i := range update.Pods {
if errs := validation.ValidateBoundPod(&update.Pods[i]); len(errs) != 0 {
t.Errorf("Expected no validation errors on %#v, Got %#v", update.Pods[i], errs)
t.Errorf("Expected no validation errors on %#v, Got %q", update.Pods[i], errs)
}
}
}

View File

@ -22,7 +22,6 @@ import (
"crypto/md5"
"encoding/hex"
"fmt"
"hash/adler32"
"io/ioutil"
"net/http"
"time"
@ -92,7 +91,9 @@ func (s *sourceURL) extractFromURL() error {
return singleErr
}
// It parsed!
applyDefaults(&pod, s.url)
if err = applyDefaults(&pod, s.url); err != nil {
return err
}
s.updates <- kubelet.PodUpdate{[]api.BoundPod{pod}, kubelet.SET, kubelet.HTTPSource}
return nil
}
@ -114,7 +115,9 @@ func (s *sourceURL) extractFromURL() error {
// Assume it parsed.
for i := range pods.Items {
pod := &pods.Items[i]
applyDefaults(pod, s.url)
if err = applyDefaults(pod, s.url); err != nil {
return err
}
}
s.updates <- kubelet.PodUpdate{pods.Items, kubelet.SET, kubelet.HTTPSource}
return nil
@ -180,7 +183,7 @@ func tryDecodeList(data []byte) (parsed bool, manifests []v1beta1.ContainerManif
return true, manifests, pods, nil
}
func applyDefaults(pod *api.BoundPod, url string) {
func applyDefaults(pod *api.BoundPod, url string) error {
if len(pod.UID) == 0 {
hasher := md5.New()
fmt.Fprintf(hasher, "url:%s", url)
@ -190,14 +193,18 @@ func applyDefaults(pod *api.BoundPod, url string) {
}
// This is required for backward compatibility, and should be removed once we
// completely deprecate ContainerManifest.
var err error
if len(pod.Name) == 0 {
pod.Name = string(pod.UID)
glog.V(5).Infof("Generate Name %q from UID %q from URL %s", pod.Name, pod.UID, url)
}
if len(pod.Namespace) == 0 {
hasher := adler32.New()
fmt.Fprint(hasher, url)
pod.Namespace = fmt.Sprintf("url-%08x", hasher.Sum32())
glog.V(5).Infof("Generated namespace %q for pod %q from URL %s", pod.Namespace, pod.Name, url)
pod.Name, err = GeneratePodName(pod.Name)
if err != nil {
return err
}
glog.V(5).Infof("Generated Name %q for UID %q from URL %s", pod.Name, pod.UID, url)
// Always overrides the namespace.
pod.Namespace = kubelet.NamespaceDefault
glog.V(5).Infof("Using namespace %q for pod %q from URL %s", pod.Namespace, pod.Name, url)
return nil
}

View File

@ -19,7 +19,7 @@ package config
import (
"encoding/json"
"net/http/httptest"
"strings"
"os"
"testing"
"time"
@ -117,6 +117,8 @@ func TestExtractInvalidManifest(t *testing.T) {
}
func TestExtractFromHTTP(t *testing.T) {
hostname, _ := os.Hostname()
var testCases = []struct {
desc string
manifests interface{}
@ -131,7 +133,7 @@ func TestExtractFromHTTP(t *testing.T) {
api.BoundPod{
ObjectMeta: api.ObjectMeta{
UID: "111",
Name: "foo",
Name: "foo" + "-" + hostname,
Namespace: "foobar",
},
Spec: api.PodSpec{
@ -153,7 +155,7 @@ func TestExtractFromHTTP(t *testing.T) {
api.BoundPod{
ObjectMeta: api.ObjectMeta{
UID: "111",
Name: "111",
Name: "111" + "-" + hostname,
Namespace: "foobar",
},
Spec: api.PodSpec{
@ -171,7 +173,7 @@ func TestExtractFromHTTP(t *testing.T) {
api.BoundPod{
ObjectMeta: api.ObjectMeta{
UID: "111",
Name: "foo",
Name: "foo" + "-" + hostname,
Namespace: "foobar",
},
Spec: api.PodSpec{
@ -198,7 +200,7 @@ func TestExtractFromHTTP(t *testing.T) {
api.BoundPod{
ObjectMeta: api.ObjectMeta{
UID: "111",
Name: "foo",
Name: "foo" + "-" + hostname,
Namespace: "foobar",
},
Spec: api.PodSpec{
@ -214,7 +216,7 @@ func TestExtractFromHTTP(t *testing.T) {
api.BoundPod{
ObjectMeta: api.ObjectMeta{
UID: "222",
Name: "bar",
Name: "bar" + "-" + hostname,
Namespace: "foobar",
},
Spec: api.PodSpec{
@ -234,6 +236,7 @@ func TestExtractFromHTTP(t *testing.T) {
expected: CreatePodUpdate(kubelet.SET, kubelet.HTTPSource),
},
}
for _, testCase := range testCases {
data, err := json.Marshal(testCase.manifests)
if err != nil {
@ -256,8 +259,8 @@ func TestExtractFromHTTP(t *testing.T) {
for i := range update.Pods {
// There's no way to provide namespace in ContainerManifest, so
// it will be defaulted.
if !strings.HasPrefix(update.Pods[i].ObjectMeta.Namespace, "url-") {
t.Errorf("Unexpected namespace: %s", update.Pods[0].ObjectMeta.Namespace)
if update.Pods[i].Namespace != kubelet.NamespaceDefault {
t.Errorf("Unexpected namespace: %s", update.Pods[0].Namespace)
}
update.Pods[i].ObjectMeta.Namespace = "foobar"
}

View File

@ -719,11 +719,11 @@ func ParseDockerName(name string) (podFullName string, podUID types.UID, contain
if len(parts) == 0 || parts[0] != containerNamePrefix {
return
}
if len(parts) < 5 {
if len(parts) < 6 {
// We have at least 5 fields. We may have more in the future.
// Anything with less fields than this is not something we can
// manage.
glog.Warningf("found a container with the %q prefix, but too few fields (%d): ", containerNamePrefix, len(parts), name)
glog.Warningf("found a container with the %q prefix, but too few fields (%d): %q", containerNamePrefix, len(parts), name)
return
}
@ -739,11 +739,10 @@ func ParseDockerName(name string) (podFullName string, podUID types.UID, contain
}
// Pod fullname.
podFullName = parts[2]
podFullName = parts[2] + "_" + parts[3]
// Pod UID.
podUID = types.UID(parts[3])
podUID = types.UID(parts[4])
return
}

View File

@ -54,11 +54,11 @@ func TestGetContainerID(t *testing.T) {
fakeDocker.ContainerList = []docker.APIContainers{
{
ID: "foobar",
Names: []string{"/k8s_foo_qux_1234_42"},
Names: []string{"/k8s_foo_qux_ns_1234_42"},
},
{
ID: "barbar",
Names: []string{"/k8s_bar_qux_2565_42"},
Names: []string{"/k8s_bar_qux_ns_2565_42"},
},
}
fakeDocker.Container = &docker.Container{
@ -73,7 +73,7 @@ func TestGetContainerID(t *testing.T) {
t.Errorf("Expected %#v, Got %#v", fakeDocker.ContainerList, dockerContainers)
}
verifyCalls(t, fakeDocker, []string{"list"})
dockerContainer, found, _ := dockerContainers.FindPodContainer("qux", "", "foo")
dockerContainer, found, _ := dockerContainers.FindPodContainer("qux_ns", "", "foo")
if dockerContainer == nil || !found {
t.Errorf("Failed to find container %#v", dockerContainer)
}
@ -91,7 +91,7 @@ func verifyPackUnpack(t *testing.T, podNamespace, podUID, podName, containerName
hasher := adler32.New()
util.DeepHashObject(hasher, *container)
computedHash := uint64(hasher.Sum32())
podFullName := fmt.Sprintf("%s.%s", podName, podNamespace)
podFullName := fmt.Sprintf("%s_%s", podName, podNamespace)
name := BuildDockerName(types.UID(podUID), podFullName, container)
returnedPodFullName, returnedUID, returnedContainerName, hash := ParseDockerName(name)
if podFullName != returnedPodFullName || podUID != string(returnedUID) || containerName != returnedContainerName || computedHash != hash {
@ -111,8 +111,8 @@ func TestContainerManifestNaming(t *testing.T) {
container := &api.Container{Name: "container"}
podName := "foo"
podNamespace := "test"
name := fmt.Sprintf("k8s_%s_%s.%s_%s_42", container.Name, podName, podNamespace, podUID)
podFullName := fmt.Sprintf("%s.%s", podName, podNamespace)
name := fmt.Sprintf("k8s_%s_%s_%s_%s_42", container.Name, podName, podNamespace, podUID)
podFullName := fmt.Sprintf("%s_%s", podName, podNamespace)
returnedPodFullName, returnedPodUID, returnedContainerName, hash := ParseDockerName(name)
if returnedPodFullName != podFullName || string(returnedPodUID) != podUID || returnedContainerName != container.Name || hash != 0 {
@ -463,15 +463,15 @@ func TestFindContainersByPod(t *testing.T) {
DockerContainers{
"foobar": &docker.APIContainers{
ID: "foobar",
Names: []string{"/k8s_foo_qux_1234_42"},
Names: []string{"/k8s_foo_qux_ns_1234_42"},
},
"barbar": &docker.APIContainers{
ID: "barbar",
Names: []string{"/k8s_foo_qux_1234_42"},
Names: []string{"/k8s_foo_qux_ns_1234_42"},
},
"baz": &docker.APIContainers{
ID: "baz",
Names: []string{"/k8s_foo_qux_1234_42"},
Names: []string{"/k8s_foo_qux_ns_1234_42"},
},
},
types.UID("1234"),
@ -479,15 +479,15 @@ func TestFindContainersByPod(t *testing.T) {
DockerContainers{
"foobar": &docker.APIContainers{
ID: "foobar",
Names: []string{"/k8s_foo_qux_1234_42"},
Names: []string{"/k8s_foo_qux_ns_1234_42"},
},
"barbar": &docker.APIContainers{
ID: "barbar",
Names: []string{"/k8s_foo_qux_1234_42"},
Names: []string{"/k8s_foo_qux_ns_1234_42"},
},
"baz": &docker.APIContainers{
ID: "baz",
Names: []string{"/k8s_foo_qux_1234_42"},
Names: []string{"/k8s_foo_qux_ns_1234_42"},
},
},
},
@ -495,15 +495,15 @@ func TestFindContainersByPod(t *testing.T) {
DockerContainers{
"foobar": &docker.APIContainers{
ID: "foobar",
Names: []string{"/k8s_foo_qux_1234_42"},
Names: []string{"/k8s_foo_qux_ns_1234_42"},
},
"barbar": &docker.APIContainers{
ID: "barbar",
Names: []string{"/k8s_foo_qux_2343_42"},
Names: []string{"/k8s_foo_qux_ns_2343_42"},
},
"baz": &docker.APIContainers{
ID: "baz",
Names: []string{"/k8s_foo_qux_1234_42"},
Names: []string{"/k8s_foo_qux_ns_1234_42"},
},
},
types.UID("1234"),
@ -511,11 +511,11 @@ func TestFindContainersByPod(t *testing.T) {
DockerContainers{
"foobar": &docker.APIContainers{
ID: "foobar",
Names: []string{"/k8s_foo_qux_1234_42"},
Names: []string{"/k8s_foo_qux_ns_1234_42"},
},
"baz": &docker.APIContainers{
ID: "baz",
Names: []string{"/k8s_foo_qux_1234_42"},
Names: []string{"/k8s_foo_qux_ns_1234_42"},
},
},
},
@ -523,15 +523,15 @@ func TestFindContainersByPod(t *testing.T) {
DockerContainers{
"foobar": &docker.APIContainers{
ID: "foobar",
Names: []string{"/k8s_foo_qux_1234_42"},
Names: []string{"/k8s_foo_qux_ns_1234_42"},
},
"barbar": &docker.APIContainers{
ID: "barbar",
Names: []string{"/k8s_foo_qux_2343_42"},
Names: []string{"/k8s_foo_qux_ns_2343_42"},
},
"baz": &docker.APIContainers{
ID: "baz",
Names: []string{"/k8s_foo_qux_1234_42"},
Names: []string{"/k8s_foo_qux_ns_1234_42"},
},
},
types.UID("5678"),
@ -542,7 +542,7 @@ func TestFindContainersByPod(t *testing.T) {
DockerContainers{
"foobar": &docker.APIContainers{
ID: "foobar",
Names: []string{"/k8s_foo_qux_1234_42"},
Names: []string{"/k8s_foo_qux_ns_1234_42"},
},
"barbar": &docker.APIContainers{
ID: "barbar",
@ -550,7 +550,7 @@ func TestFindContainersByPod(t *testing.T) {
},
"baz": &docker.APIContainers{
ID: "baz",
Names: []string{"/k8s_foo_qux_5678_42"},
Names: []string{"/k8s_foo_qux_ns_5678_42"},
},
},
types.UID("5678"),
@ -558,7 +558,7 @@ func TestFindContainersByPod(t *testing.T) {
DockerContainers{
"baz": &docker.APIContainers{
ID: "baz",
Names: []string{"/k8s_foo_qux_5678_42"},
Names: []string{"/k8s_foo_qux_ns_5678_42"},
},
},
},
@ -566,23 +566,23 @@ func TestFindContainersByPod(t *testing.T) {
DockerContainers{
"foobar": &docker.APIContainers{
ID: "foobar",
Names: []string{"/k8s_foo_qux_1234_42"},
Names: []string{"/k8s_foo_qux_ns_1234_42"},
},
"barbar": &docker.APIContainers{
ID: "barbar",
Names: []string{"/k8s_foo_abc_5678_42"},
Names: []string{"/k8s_foo_abc_ns_5678_42"},
},
"baz": &docker.APIContainers{
ID: "baz",
Names: []string{"/k8s_foo_qux_5678_42"},
Names: []string{"/k8s_foo_qux_ns_5678_42"},
},
},
"",
"abc",
"abc_ns",
DockerContainers{
"barbar": &docker.APIContainers{
ID: "barbar",
Names: []string{"/k8s_foo_abc_5678_42"},
Names: []string{"/k8s_foo_abc_ns_5678_42"},
},
},
},

View File

@ -1404,6 +1404,7 @@ func (kl *Kubelet) SyncPods(allPods []api.BoundPod, podSyncTypes map[types.UID]m
glog.V(4).Infof("Skipping deletes, sources aren't ready yet.")
return nil
}
// Kill any containers we don't need.
killed := []string{}
for ix := range dockerContainers {
@ -1413,6 +1414,7 @@ func (kl *Kubelet) SyncPods(allPods []api.BoundPod, podSyncTypes map[types.UID]m
// syncPod() will handle this one.
continue
}
pc := podContainer{podFullName, uid, containerName}
if _, ok := desiredContainers[pc]; !ok {
glog.V(1).Infof("Killing unwanted container %+v", pc)

View File

@ -396,22 +396,21 @@ func TestSyncPodsDoesNothing(t *testing.T) {
fakeDocker.ContainerList = []docker.APIContainers{
{
// format is // k8s_<container-id>_<pod-fullname>_<pod-uid>_<random>
Names: []string{"/k8s_bar." + strconv.FormatUint(dockertools.HashContainer(&container), 16) + "_foo.new.test_12345678_0"},
Names: []string{"/k8s_bar." + strconv.FormatUint(dockertools.HashContainer(&container), 16) + "_foo_new_12345678_0"},
ID: "1234",
},
{
// pod infra container
Names: []string{"/k8s_POD_foo.new.test_12345678_0"},
Names: []string{"/k8s_POD_foo_new_12345678_0"},
ID: "9876",
},
}
kubelet.pods = []api.BoundPod{
{
ObjectMeta: api.ObjectMeta{
UID: "12345678",
Name: "foo",
Namespace: "new",
Annotations: map[string]string{ConfigSourceAnnotationKey: "test"},
UID: "12345678",
Name: "foo",
Namespace: "new",
},
Spec: api.PodSpec{
Containers: []api.Container{
@ -439,10 +438,9 @@ func TestSyncPodsWithTerminationLog(t *testing.T) {
kubelet.pods = []api.BoundPod{
{
ObjectMeta: api.ObjectMeta{
UID: "12345678",
Name: "foo",
Namespace: "new",
Annotations: map[string]string{ConfigSourceAnnotationKey: "test"},
UID: "12345678",
Name: "foo",
Namespace: "new",
},
Spec: api.PodSpec{
Containers: []api.Container{
@ -486,10 +484,9 @@ func TestSyncPodsCreatesNetAndContainer(t *testing.T) {
kubelet.pods = []api.BoundPod{
{
ObjectMeta: api.ObjectMeta{
UID: "12345678",
Name: "foo",
Namespace: "new",
Annotations: map[string]string{ConfigSourceAnnotationKey: "test"},
UID: "12345678",
Name: "foo",
Namespace: "new",
},
Spec: api.PodSpec{
Containers: []api.Container{
@ -521,8 +518,8 @@ func TestSyncPodsCreatesNetAndContainer(t *testing.T) {
}
if len(fakeDocker.Created) != 2 ||
!matchString(t, "k8s_POD\\.[a-f0-9]+_foo.new.test_", fakeDocker.Created[0]) ||
!matchString(t, "k8s_bar\\.[a-f0-9]+_foo.new.test_", fakeDocker.Created[1]) {
!matchString(t, "k8s_POD\\.[a-f0-9]+_foo_new_", fakeDocker.Created[0]) ||
!matchString(t, "k8s_bar\\.[a-f0-9]+_foo_new_", fakeDocker.Created[1]) {
t.Errorf("Unexpected containers created %v", fakeDocker.Created)
}
fakeDocker.Unlock()
@ -537,10 +534,9 @@ func TestSyncPodsCreatesNetAndContainerPullsImage(t *testing.T) {
kubelet.pods = []api.BoundPod{
{
ObjectMeta: api.ObjectMeta{
UID: "12345678",
Name: "foo",
Namespace: "new",
Annotations: map[string]string{ConfigSourceAnnotationKey: "test"},
UID: "12345678",
Name: "foo",
Namespace: "new",
},
Spec: api.PodSpec{
Containers: []api.Container{
@ -566,8 +562,8 @@ func TestSyncPodsCreatesNetAndContainerPullsImage(t *testing.T) {
}
if len(fakeDocker.Created) != 2 ||
!matchString(t, "k8s_POD\\.[a-f0-9]+_foo.new.test_", fakeDocker.Created[0]) ||
!matchString(t, "k8s_bar\\.[a-f0-9]+_foo.new.test_", fakeDocker.Created[1]) {
!matchString(t, "k8s_POD\\.[a-f0-9]+_foo_new_", fakeDocker.Created[0]) ||
!matchString(t, "k8s_bar\\.[a-f0-9]+_foo_new_", fakeDocker.Created[1]) {
t.Errorf("Unexpected containers created %v", fakeDocker.Created)
}
fakeDocker.Unlock()
@ -578,17 +574,16 @@ func TestSyncPodsWithPodInfraCreatesContainer(t *testing.T) {
fakeDocker.ContainerList = []docker.APIContainers{
{
// pod infra container
Names: []string{"/k8s_POD_foo.new.test_12345678_0"},
Names: []string{"/k8s_POD_foo_new_12345678_0"},
ID: "9876",
},
}
kubelet.pods = []api.BoundPod{
{
ObjectMeta: api.ObjectMeta{
UID: "12345678",
Name: "foo",
Namespace: "new",
Annotations: map[string]string{ConfigSourceAnnotationKey: "test"},
UID: "12345678",
Name: "foo",
Namespace: "new",
},
Spec: api.PodSpec{
Containers: []api.Container{
@ -609,7 +604,7 @@ func TestSyncPodsWithPodInfraCreatesContainer(t *testing.T) {
fakeDocker.Lock()
if len(fakeDocker.Created) != 1 ||
!matchString(t, "k8s_bar\\.[a-f0-9]+_foo.new.test_", fakeDocker.Created[0]) {
!matchString(t, "k8s_bar\\.[a-f0-9]+_foo_new_", fakeDocker.Created[0]) {
t.Errorf("Unexpected containers created %v", fakeDocker.Created)
}
fakeDocker.Unlock()
@ -622,17 +617,16 @@ func TestSyncPodsWithPodInfraCreatesContainerCallsHandler(t *testing.T) {
fakeDocker.ContainerList = []docker.APIContainers{
{
// pod infra container
Names: []string{"/k8s_POD_foo.new.test_12345678_0"},
Names: []string{"/k8s_POD_foo_new_12345678_0"},
ID: "9876",
},
}
kubelet.pods = []api.BoundPod{
{
ObjectMeta: api.ObjectMeta{
UID: "12345678",
Name: "foo",
Namespace: "new",
Annotations: map[string]string{ConfigSourceAnnotationKey: "test"},
UID: "12345678",
Name: "foo",
Namespace: "new",
},
Spec: api.PodSpec{
Containers: []api.Container{
@ -664,7 +658,7 @@ func TestSyncPodsWithPodInfraCreatesContainerCallsHandler(t *testing.T) {
fakeDocker.Lock()
if len(fakeDocker.Created) != 1 ||
!matchString(t, "k8s_bar\\.[a-f0-9]+_foo.new.test_", fakeDocker.Created[0]) {
!matchString(t, "k8s_bar\\.[a-f0-9]+_foo_new_", fakeDocker.Created[0]) {
t.Errorf("Unexpected containers created %v", fakeDocker.Created)
}
fakeDocker.Unlock()
@ -678,17 +672,16 @@ func TestSyncPodsDeletesWithNoPodInfraContainer(t *testing.T) {
fakeDocker.ContainerList = []docker.APIContainers{
{
// format is // k8s_<container-id>_<pod-fullname>_<pod-uid>
Names: []string{"/k8s_bar_foo.new.test_12345678_0"},
Names: []string{"/k8s_bar_foo_new_12345678_0"},
ID: "1234",
},
}
kubelet.pods = []api.BoundPod{
{
ObjectMeta: api.ObjectMeta{
UID: "12345678",
Name: "foo",
Namespace: "new",
Annotations: map[string]string{ConfigSourceAnnotationKey: "test"},
UID: "12345678",
Name: "foo",
Namespace: "new",
},
Spec: api.PodSpec{
Containers: []api.Container{
@ -727,12 +720,12 @@ func TestSyncPodsDeletesWhenSourcesAreReady(t *testing.T) {
fakeDocker.ContainerList = []docker.APIContainers{
{
// the k8s prefix is required for the kubelet to manage the container
Names: []string{"/k8s_foo_bar.new.test_12345678_42"},
Names: []string{"/k8s_foo_bar_new_12345678_42"},
ID: "1234",
},
{
// pod infra container
Names: []string{"/k8s_POD_foo.new.test_12345678_42"},
Names: []string{"/k8s_POD_foo_new_12345678_42"},
ID: "9876",
},
}
@ -767,12 +760,12 @@ func TestSyncPodsDeletes(t *testing.T) {
fakeDocker.ContainerList = []docker.APIContainers{
{
// the k8s prefix is required for the kubelet to manage the container
Names: []string{"/k8s_foo_bar.new.test_12345678_42"},
Names: []string{"/k8s_foo_bar_new_12345678_42"},
ID: "1234",
},
{
// pod infra container
Names: []string{"/k8s_POD_foo.new.test_12345678_42"},
Names: []string{"/k8s_POD_foo_new_12345678_42"},
ID: "9876",
},
{
@ -805,26 +798,25 @@ func TestSyncPodDeletesDuplicate(t *testing.T) {
dockerContainers := dockertools.DockerContainers{
"1234": &docker.APIContainers{
// the k8s prefix is required for the kubelet to manage the container
Names: []string{"/k8s_foo_bar.new.test_12345678_1111"},
Names: []string{"/k8s_foo_bar_new_12345678_1111"},
ID: "1234",
},
"9876": &docker.APIContainers{
// pod infra container
Names: []string{"/k8s_POD_bar.new.test_12345678_2222"},
Names: []string{"/k8s_POD_bar_new_12345678_2222"},
ID: "9876",
},
"4567": &docker.APIContainers{
// Duplicate for the same container.
Names: []string{"/k8s_foo_bar.new.test_12345678_3333"},
Names: []string{"/k8s_foo_bar_new_12345678_3333"},
ID: "4567",
},
}
bound := api.BoundPod{
ObjectMeta: api.ObjectMeta{
UID: "12345678",
Name: "bar",
Namespace: "new",
Annotations: map[string]string{ConfigSourceAnnotationKey: "test"},
UID: "12345678",
Name: "bar",
Namespace: "new",
},
Spec: api.PodSpec{
Containers: []api.Container{
@ -850,21 +842,20 @@ func TestSyncPodBadHash(t *testing.T) {
dockerContainers := dockertools.DockerContainers{
"1234": &docker.APIContainers{
// the k8s prefix is required for the kubelet to manage the container
Names: []string{"/k8s_bar.1234_foo.new.test_12345678_42"},
Names: []string{"/k8s_bar.1234_foo_new_12345678_42"},
ID: "1234",
},
"9876": &docker.APIContainers{
// pod infra container
Names: []string{"/k8s_POD_foo.new.test_12345678_42"},
Names: []string{"/k8s_POD_foo_new_12345678_42"},
ID: "9876",
},
}
bound := api.BoundPod{
ObjectMeta: api.ObjectMeta{
UID: "12345678",
Name: "foo",
Namespace: "new",
Annotations: map[string]string{ConfigSourceAnnotationKey: "test"},
UID: "12345678",
Name: "foo",
Namespace: "new",
},
Spec: api.PodSpec{
Containers: []api.Container{
@ -899,21 +890,20 @@ func TestSyncPodUnhealthy(t *testing.T) {
dockerContainers := dockertools.DockerContainers{
"1234": &docker.APIContainers{
// the k8s prefix is required for the kubelet to manage the container
Names: []string{"/k8s_bar_foo.new.test_12345678_42"},
Names: []string{"/k8s_bar_foo_new_12345678_42"},
ID: "1234",
},
"9876": &docker.APIContainers{
// pod infra container
Names: []string{"/k8s_POD_foo.new.test_12345678_42"},
Names: []string{"/k8s_POD_foo_new_12345678_42"},
ID: "9876",
},
}
bound := api.BoundPod{
ObjectMeta: api.ObjectMeta{
UID: "12345678",
Name: "foo",
Namespace: "new",
Annotations: map[string]string{ConfigSourceAnnotationKey: "test"},
UID: "12345678",
Name: "foo",
Namespace: "new",
},
Spec: api.PodSpec{
Containers: []api.Container{
@ -1234,11 +1224,11 @@ func TestGetContainerInfo(t *testing.T) {
ID: containerID,
// pod id: qux
// container id: foo
Names: []string{"/k8s_foo_qux_1234_42"},
Names: []string{"/k8s_foo_qux_ns_1234_42"},
},
}
stats, err := kubelet.GetContainerInfo("qux", "", "foo", cadvisorReq)
stats, err := kubelet.GetContainerInfo("qux_ns", "", "foo", cadvisorReq)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
@ -1308,11 +1298,11 @@ func TestGetContainerInfoWhenCadvisorFailed(t *testing.T) {
ID: containerID,
// pod id: qux
// container id: foo
Names: []string{"/k8s_foo_qux_uuid_1234"},
Names: []string{"/k8s_foo_qux_ns_uuid_1234"},
},
}
stats, err := kubelet.GetContainerInfo("qux", "uuid", "foo", cadvisorReq)
stats, err := kubelet.GetContainerInfo("qux_ns", "uuid", "foo", cadvisorReq)
if stats != nil {
t.Errorf("non-nil stats on error")
}
@ -1367,7 +1357,7 @@ func TestGetContainerInfoWithNoContainers(t *testing.T) {
kubelet.cadvisorClient = mockCadvisor
kubelet.dockerClient = &errorTestingDockerClient{listContainersError: nil}
stats, err := kubelet.GetContainerInfo("qux", "", "foo", nil)
stats, err := kubelet.GetContainerInfo("qux_ns", "", "foo", nil)
if err == nil {
t.Errorf("Expected error from cadvisor client, got none")
}
@ -1388,12 +1378,12 @@ func TestGetContainerInfoWithNoMatchingContainers(t *testing.T) {
containerList := []docker.APIContainers{
{
ID: "fakeId",
Names: []string{"/k8s_bar_qux_1234_42"},
Names: []string{"/k8s_bar_qux_ns_1234_42"},
},
}
kubelet.dockerClient = &errorTestingDockerClient{listContainersError: nil, containerList: containerList}
stats, err := kubelet.GetContainerInfo("qux", "", "foo", nil)
stats, err := kubelet.GetContainerInfo("qux_ns", "", "foo", nil)
if err == nil {
t.Errorf("Expected error from cadvisor client, got none")
}
@ -1479,7 +1469,7 @@ func TestRunInContainer(t *testing.T) {
fakeDocker.ContainerList = []docker.APIContainers{
{
ID: containerID,
Names: []string{"/k8s_" + containerName + "_" + podName + "." + podNamespace + ".test_12345678_42"},
Names: []string{"/k8s_" + containerName + "_" + podName + "_" + podNamespace + "_12345678_42"},
},
}
@ -1487,10 +1477,9 @@ func TestRunInContainer(t *testing.T) {
_, err := kubelet.RunInContainer(
GetPodFullName(&api.BoundPod{
ObjectMeta: api.ObjectMeta{
UID: "12345678",
Name: podName,
Namespace: podNamespace,
Annotations: map[string]string{ConfigSourceAnnotationKey: "test"},
UID: "12345678",
Name: podName,
Namespace: podNamespace,
},
}),
"",
@ -1520,7 +1509,7 @@ func TestRunHandlerExec(t *testing.T) {
fakeDocker.ContainerList = []docker.APIContainers{
{
ID: containerID,
Names: []string{"/k8s_" + containerName + "_" + podName + "." + podNamespace + "_12345678_42"},
Names: []string{"/k8s_" + containerName + "_" + podName + "_" + podNamespace + "_12345678_42"},
},
}
@ -1534,7 +1523,7 @@ func TestRunHandlerExec(t *testing.T) {
},
},
}
err := kubelet.runHandler(podName+"."+podNamespace, "", &container, container.Lifecycle.PostStart)
err := kubelet.runHandler(podName+"_"+podNamespace, "", &container, container.Lifecycle.PostStart)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
@ -1576,7 +1565,7 @@ func TestRunHandlerHttp(t *testing.T) {
},
},
}
err := kubelet.runHandler(podName+"."+podNamespace, "", &container, container.Lifecycle.PostStart)
err := kubelet.runHandler(podName+"_"+podNamespace, "", &container, container.Lifecycle.PostStart)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
@ -1624,16 +1613,15 @@ func TestSyncPodEventHandlerFails(t *testing.T) {
dockerContainers := dockertools.DockerContainers{
"9876": &docker.APIContainers{
// pod infra container
Names: []string{"/k8s_POD_foo.new.test_12345678_42"},
Names: []string{"/k8s_POD_foo_new_12345678_42"},
ID: "9876",
},
}
bound := api.BoundPod{
ObjectMeta: api.ObjectMeta{
UID: "12345678",
Name: "foo",
Namespace: "new",
Annotations: map[string]string{ConfigSourceAnnotationKey: "test"},
UID: "12345678",
Name: "foo",
Namespace: "new",
},
Spec: api.PodSpec{
Containers: []api.Container{
@ -1675,17 +1663,17 @@ func TestKubeletGarbageCollection(t *testing.T) {
containers: []docker.APIContainers{
{
// pod infra container
Names: []string{"/k8s_POD_foo.new.test_.deadbeef_42"},
Names: []string{"/k8s_POD_foo_new_.deadbeef_42"},
ID: "1876",
},
{
// pod infra container
Names: []string{"/k8s_POD_foo.new.test_.deadbeef_42"},
Names: []string{"/k8s_POD_foo_new_.deadbeef_42"},
ID: "2876",
},
{
// pod infra container
Names: []string{"/k8s_POD_foo.new.test_.deadbeef_42"},
Names: []string{"/k8s_POD_foo_new_.deadbeef_42"},
ID: "3876",
},
},
@ -1705,22 +1693,22 @@ func TestKubeletGarbageCollection(t *testing.T) {
containers: []docker.APIContainers{
{
// pod infra container
Names: []string{"/k8s_POD_foo.new.test_.deadbeef_42"},
Names: []string{"/k8s_POD_foo_new_.deadbeef_42"},
ID: "1876",
},
{
// pod infra container
Names: []string{"/k8s_POD_foo.new.test_.deadbeef_42"},
Names: []string{"/k8s_POD_foo_new_.deadbeef_42"},
ID: "2876",
},
{
// pod infra container
Names: []string{"/k8s_POD_foo.new.test_.deadbeef_42"},
Names: []string{"/k8s_POD_foo_new_.deadbeef_42"},
ID: "3876",
},
{
// pod infra container
Names: []string{"/k8s_POD_foo.new.test_.deadbeef_42"},
Names: []string{"/k8s_POD_foo_new_.deadbeef_42"},
ID: "4876",
},
},
@ -1747,7 +1735,7 @@ func TestKubeletGarbageCollection(t *testing.T) {
containers: []docker.APIContainers{
{
// pod infra container
Names: []string{"/k8s_POD_foo.new.test_.deadbeef_42"},
Names: []string{"/k8s_POD_foo_new_.deadbeef_42"},
ID: "1876",
},
},
@ -1757,32 +1745,32 @@ func TestKubeletGarbageCollection(t *testing.T) {
containers: []docker.APIContainers{
{
// pod infra container
Names: []string{"/k8s_POD_foo2.new.test_.beefbeef_40"},
Names: []string{"/k8s_POD_foo2_new_.beefbeef_40"},
ID: "1706",
},
{
// pod infra container
Names: []string{"/k8s_POD_foo2.new.test_.beefbeef_40"},
Names: []string{"/k8s_POD_foo2_new_.beefbeef_40"},
ID: "2706",
},
{
// pod infra container
Names: []string{"/k8s_POD_foo2.new.test_.beefbeef_40"},
Names: []string{"/k8s_POD_foo2_new_.beefbeef_40"},
ID: "3706",
},
{
// pod infra container
Names: []string{"/k8s_POD_foo.new.test_.deadbeef_42"},
Names: []string{"/k8s_POD_foo_new_.deadbeef_42"},
ID: "1876",
},
{
// pod infra container
Names: []string{"/k8s_POD_foo.new.test_.deadbeef_42"},
Names: []string{"/k8s_POD_foo_new_.deadbeef_42"},
ID: "2876",
},
{
// pod infra container
Names: []string{"/k8s_POD_foo.new.test_.deadbeef_42"},
Names: []string{"/k8s_POD_foo_new_.deadbeef_42"},
ID: "3876",
},
},
@ -1991,10 +1979,9 @@ func TestSyncPodsWithPullPolicy(t *testing.T) {
err := kubelet.SyncPods([]api.BoundPod{
{
ObjectMeta: api.ObjectMeta{
UID: "12345678",
Name: "foo",
Namespace: "new",
Annotations: map[string]string{ConfigSourceAnnotationKey: "test"},
UID: "12345678",
Name: "foo",
Namespace: "new",
},
Spec: api.PodSpec{
Containers: []api.Container{
@ -2790,16 +2777,15 @@ func TestExecInContainerNoSuchContainer(t *testing.T) {
fakeDocker.ContainerList = []docker.APIContainers{
{
ID: "notfound",
Names: []string{"/k8s_notfound_" + podName + "." + podNamespace + ".test_12345678_42"},
Names: []string{"/k8s_notfound_" + podName + "_" + podNamespace + "_12345678_42"},
},
}
err := kubelet.ExecInContainer(
GetPodFullName(&api.BoundPod{ObjectMeta: api.ObjectMeta{
UID: "12345678",
Name: podName,
Namespace: podNamespace,
Annotations: map[string]string{ConfigSourceAnnotationKey: "test"},
UID: "12345678",
Name: podName,
Namespace: podNamespace,
}}),
"",
containerID,
@ -2848,16 +2834,15 @@ func TestExecInContainer(t *testing.T) {
fakeDocker.ContainerList = []docker.APIContainers{
{
ID: containerID,
Names: []string{"/k8s_" + containerID + "_" + podName + "." + podNamespace + ".test_12345678_42"},
Names: []string{"/k8s_" + containerID + "_" + podName + "_" + podNamespace + "_12345678_42"},
},
}
err := kubelet.ExecInContainer(
GetPodFullName(&api.BoundPod{ObjectMeta: api.ObjectMeta{
UID: "12345678",
Name: podName,
Namespace: podNamespace,
Annotations: map[string]string{ConfigSourceAnnotationKey: "test"},
UID: "12345678",
Name: podName,
Namespace: podNamespace,
}}),
"",
containerID,
@ -2926,16 +2911,15 @@ func TestPortForwardNoSuchContainer(t *testing.T) {
fakeDocker.ContainerList = []docker.APIContainers{
{
ID: "notfound",
Names: []string{"/k8s_notfound_" + podName + "." + podNamespace + ".test_12345678_42"},
Names: []string{"/k8s_notfound_" + podName + "_" + podNamespace + "_12345678_42"},
},
}
err := kubelet.PortForward(
GetPodFullName(&api.BoundPod{ObjectMeta: api.ObjectMeta{
UID: "12345678",
Name: podName,
Namespace: podNamespace,
Annotations: map[string]string{ConfigSourceAnnotationKey: "test"},
UID: "12345678",
Name: podName,
Namespace: podNamespace,
}}),
"",
port,
@ -2966,20 +2950,19 @@ func TestPortForward(t *testing.T) {
fakeDocker.ContainerList = []docker.APIContainers{
{
ID: infraContainerID,
Names: []string{"/k8s_" + kubelet.podInfraContainerImage + "_" + podName + "." + podNamespace + ".test_12345678_42"},
Names: []string{"/k8s_" + kubelet.podInfraContainerImage + "_" + podName + "_" + podNamespace + "_12345678_42"},
},
{
ID: containerID,
Names: []string{"/k8s_" + containerID + "_" + podName + "." + podNamespace + ".test_12345678_42"},
Names: []string{"/k8s_" + containerID + "_" + podName + "_" + podNamespace + "_12345678_42"},
},
}
err := kubelet.PortForward(
GetPodFullName(&api.BoundPod{ObjectMeta: api.ObjectMeta{
UID: "12345678",
Name: podName,
Namespace: podNamespace,
Annotations: map[string]string{ConfigSourceAnnotationKey: "test"},
UID: "12345678",
Name: podName,
Namespace: podNamespace,
}}),
"",
port,

View File

@ -76,7 +76,7 @@ func TestRunOnce(t *testing.T) {
}
podContainers := []docker.APIContainers{
{
Names: []string{"/k8s_bar." + strconv.FormatUint(dockertools.HashContainer(&api.Container{Name: "bar"}), 16) + "_foo.new.test_12345678_42"},
Names: []string{"/k8s_bar." + strconv.FormatUint(dockertools.HashContainer(&api.Container{Name: "bar"}), 16) + "_foo_new_12345678_42"},
ID: "1234",
Status: "running",
},
@ -130,10 +130,9 @@ func TestRunOnce(t *testing.T) {
results, err := kb.runOnce([]api.BoundPod{
{
ObjectMeta: api.ObjectMeta{
UID: "12345678",
Name: "foo",
Namespace: "new",
Annotations: map[string]string{ConfigSourceAnnotationKey: "test"},
UID: "12345678",
Name: "foo",
Namespace: "new",
},
Spec: api.PodSpec{
Containers: []api.Container{

View File

@ -129,9 +129,6 @@ func newServerTest() *serverTestFramework {
ObjectMeta: api.ObjectMeta{
Namespace: namespace,
Name: name,
Annotations: map[string]string{
ConfigSourceAnnotationKey: "etcd",
},
},
}, true
},
@ -157,6 +154,14 @@ func readResp(resp *http.Response) (string, error) {
return string(body), err
}
// A helper function to return the correct pod name.
func getPodName(name, namespace string) string {
if namespace == "" {
namespace = NamespaceDefault
}
return name + "_" + namespace
}
func TestPodStatus(t *testing.T) {
fw := newServerTest()
expected := api.PodStatus{
@ -165,7 +170,7 @@ func TestPodStatus(t *testing.T) {
},
}
fw.fakeKubelet.statusFunc = func(name string) (api.PodStatus, error) {
if name == "goodpod.default.etcd" {
if name == "goodpod_default" {
return expected, nil
}
return api.PodStatus{}, fmt.Errorf("bad pod %s", name)
@ -191,7 +196,7 @@ func TestContainerInfo(t *testing.T) {
fw := newServerTest()
expectedInfo := &info.ContainerInfo{}
podID := "somepod"
expectedPodID := "somepod" + ".default.etcd"
expectedPodID := getPodName(podID, "")
expectedContainerName := "goodcontainer"
fw.fakeKubelet.containerInfoFunc = func(podID string, uid types.UID, containerName string, req *info.ContainerInfoRequest) (*info.ContainerInfo, error) {
if podID != expectedPodID || containerName != expectedContainerName {
@ -220,7 +225,7 @@ func TestContainerInfoWithUidNamespace(t *testing.T) {
expectedInfo := &info.ContainerInfo{}
podID := "somepod"
expectedNamespace := "custom"
expectedPodID := "somepod" + "." + expectedNamespace + ".etcd"
expectedPodID := getPodName(podID, expectedNamespace)
expectedContainerName := "goodcontainer"
expectedUid := "9b01b80f-8fb4-11e4-95ab-4200af06647"
fw.fakeKubelet.containerInfoFunc = func(podID string, uid types.UID, containerName string, req *info.ContainerInfoRequest) (*info.ContainerInfo, error) {
@ -344,7 +349,7 @@ func TestServeRunInContainer(t *testing.T) {
output := "foo bar"
podNamespace := "other"
podName := "foo"
expectedPodName := podName + "." + podNamespace + ".etcd"
expectedPodName := getPodName(podName, podNamespace)
expectedContainerName := "baz"
expectedCommand := "ls -a"
fw.fakeKubelet.runFunc = func(podFullName string, uid types.UID, containerName string, cmd []string) ([]byte, error) {
@ -384,7 +389,7 @@ func TestServeRunInContainerWithUID(t *testing.T) {
output := "foo bar"
podNamespace := "other"
podName := "foo"
expectedPodName := podName + "." + podNamespace + ".etcd"
expectedPodName := getPodName(podName, podNamespace)
expectedUID := "7e00838d_-_3523_-_11e4_-_8421_-_42010af0a720"
expectedContainerName := "baz"
expectedCommand := "ls -a"
@ -509,9 +514,6 @@ func setPodByNameFunc(fw *serverTestFramework, namespace, pod, container string)
ObjectMeta: api.ObjectMeta{
Namespace: namespace,
Name: pod,
Annotations: map[string]string{
ConfigSourceAnnotationKey: "etcd",
},
},
Spec: api.PodSpec{
Containers: []api.Container{
@ -548,7 +550,7 @@ func TestContainerLogs(t *testing.T) {
output := "foo bar"
podNamespace := "other"
podName := "foo"
expectedPodName := podName + ".other.etcd"
expectedPodName := getPodName(podName, podNamespace)
expectedContainerName := "baz"
expectedTail := ""
expectedFollow := false
@ -575,7 +577,7 @@ func TestContainerLogsWithTail(t *testing.T) {
output := "foo bar"
podNamespace := "other"
podName := "foo"
expectedPodName := podName + ".other.etcd"
expectedPodName := getPodName(podName, podNamespace)
expectedContainerName := "baz"
expectedTail := "5"
expectedFollow := false
@ -602,7 +604,7 @@ func TestContainerLogsWithFollow(t *testing.T) {
output := "foo bar"
podNamespace := "other"
podName := "foo"
expectedPodName := podName + ".other.etcd"
expectedPodName := getPodName(podName, podNamespace)
expectedContainerName := "baz"
expectedTail := ""
expectedFollow := true
@ -693,7 +695,7 @@ func TestServeExecInContainer(t *testing.T) {
podNamespace := "other"
podName := "foo"
expectedPodName := podName + "." + podNamespace + ".etcd"
expectedPodName := getPodName(podName, podNamespace)
expectedUid := "9b01b80f-8fb4-11e4-95ab-4200af06647"
expectedContainerName := "baz"
expectedCommand := "ls -a"
@ -955,7 +957,7 @@ func TestServePortForward(t *testing.T) {
podNamespace := "other"
podName := "foo"
expectedPodName := podName + "." + podNamespace + ".etcd"
expectedPodName := getPodName(podName, podNamespace)
expectedUid := "9b01b80f-8fb4-11e4-95ab-4200af06647"
for i, test := range tests {

View File

@ -50,6 +50,8 @@ const (
ApiserverSource = "api"
// Updates from all sources
AllSource = "*"
NamespaceDefault = api.NamespaceDefault
)
// PodUpdate defines an operation sent on the channel. You can add or remove single services by
@ -69,5 +71,12 @@ type PodUpdate struct {
// GetPodFullName returns a name that uniquely identifies a pod across all config sources.
func GetPodFullName(pod *api.BoundPod) string {
return fmt.Sprintf("%s.%s.%s", pod.Name, pod.Namespace, pod.Annotations[ConfigSourceAnnotationKey])
// Use underscore as the delimiter because it is not allowed in pod name
// (DNS subdomain format), while allowed in the container name format.
return fmt.Sprintf("%s_%s", pod.Name, pod.Namespace)
}
// Build the pod full name from pod name and namespace.
func BuildPodFullName(name, namespace string) string {
return name + "_" + namespace
}