mirror of https://github.com/k3s-io/k3s
Merge pull request #3382 from thockin/uid_ns_required
UID and Namespace are required fields in Kubeletpull/6/head
commit
823ab24068
|
@ -622,7 +622,7 @@ func main() {
|
||||||
createdPods.Insert(p[:n-8])
|
createdPods.Insert(p[:n-8])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// We expect 5: 2 net containers + 2 pods from the replication controller +
|
// We expect 9: 2 net containers + 2 pods from the replication controller +
|
||||||
// 1 net container + 2 pods from the URL +
|
// 1 net container + 2 pods from the URL +
|
||||||
// 1 net container + 1 pod from the service test.
|
// 1 net container + 1 pod from the service test.
|
||||||
if len(createdPods) != 9 {
|
if len(createdPods) != 9 {
|
||||||
|
|
|
@ -559,7 +559,7 @@ func ValidateBoundPod(pod *api.BoundPod) errs.ValidationErrorList {
|
||||||
} else if !util.IsDNSSubdomain(pod.Name) {
|
} else if !util.IsDNSSubdomain(pod.Name) {
|
||||||
allErrs = append(allErrs, errs.NewFieldInvalid("name", pod.Name, ""))
|
allErrs = append(allErrs, errs.NewFieldInvalid("name", pod.Name, ""))
|
||||||
}
|
}
|
||||||
if len(pod.Name) == 0 {
|
if len(pod.Namespace) == 0 {
|
||||||
allErrs = append(allErrs, errs.NewFieldRequired("namespace", pod.Namespace))
|
allErrs = append(allErrs, errs.NewFieldRequired("namespace", pod.Namespace))
|
||||||
} else if !util.IsDNSSubdomain(pod.Namespace) {
|
} else if !util.IsDNSSubdomain(pod.Namespace) {
|
||||||
allErrs = append(allErrs, errs.NewFieldInvalid("namespace", pod.Namespace, ""))
|
allErrs = append(allErrs, errs.NewFieldInvalid("namespace", pod.Namespace, ""))
|
||||||
|
|
|
@ -24,9 +24,11 @@ import (
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||||
apierrs "github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
|
apierrs "github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/validation"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/validation"
|
||||||
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/client/record"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/util/config"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/util/config"
|
||||||
|
utilerrors "github.com/GoogleCloudPlatform/kubernetes/pkg/util/errors"
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -293,21 +295,28 @@ func (s *podStorage) seenSources(sources ...string) bool {
|
||||||
func filterInvalidPods(pods []api.BoundPod, source string) (filtered []*api.BoundPod) {
|
func filterInvalidPods(pods []api.BoundPod, source string) (filtered []*api.BoundPod) {
|
||||||
names := util.StringSet{}
|
names := util.StringSet{}
|
||||||
for i := range pods {
|
for i := range pods {
|
||||||
var errors []error
|
pod := &pods[i]
|
||||||
name := podUniqueName(&pods[i])
|
var errlist []error
|
||||||
if names.Has(name) {
|
if errs := validation.ValidateBoundPod(pod); len(errs) != 0 {
|
||||||
errors = append(errors, apierrs.NewFieldDuplicate("name", pods[i].Name))
|
errlist = append(errlist, errs...)
|
||||||
|
// If validation fails, don't trust it any further -
|
||||||
|
// even Name could be bad.
|
||||||
} else {
|
} else {
|
||||||
names.Insert(name)
|
name := podUniqueName(pod)
|
||||||
|
if names.Has(name) {
|
||||||
|
errlist = append(errlist, apierrs.NewFieldDuplicate("name", pod.Name))
|
||||||
|
} else {
|
||||||
|
names.Insert(name)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if errs := validation.ValidateBoundPod(&pods[i]); len(errs) != 0 {
|
if len(errlist) > 0 {
|
||||||
errors = append(errors, errs...)
|
name := bestPodIdentString(pod)
|
||||||
}
|
err := utilerrors.NewAggregate(errlist)
|
||||||
if len(errors) > 0 {
|
glog.Warningf("Pod[%d] (%s) from %s failed validation, ignoring: %v", i+1, name, source, err)
|
||||||
glog.Warningf("Pod %d (%s) from %s failed validation, ignoring: %v", i+1, pods[i].Name, source, errors)
|
record.Eventf(pod, "", "failedValidation", "Error validating pod %s from %s, ignoring: %v", name, source, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
filtered = append(filtered, &pods[i])
|
filtered = append(filtered, pod)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -337,11 +346,19 @@ func (s *podStorage) MergedState() interface{} {
|
||||||
}
|
}
|
||||||
|
|
||||||
// podUniqueName returns a value for a given pod that is unique across a source,
|
// podUniqueName returns a value for a given pod that is unique across a source,
|
||||||
// which is the combination of namespace and ID.
|
// which is the combination of namespace and name.
|
||||||
func podUniqueName(pod *api.BoundPod) string {
|
func podUniqueName(pod *api.BoundPod) string {
|
||||||
namespace := pod.Namespace
|
return fmt.Sprintf("%s.%s", pod.Name, pod.Namespace)
|
||||||
if len(namespace) == 0 {
|
}
|
||||||
namespace = api.NamespaceDefault
|
|
||||||
}
|
func bestPodIdentString(pod *api.BoundPod) string {
|
||||||
return fmt.Sprintf("%s.%s", pod.Name, namespace)
|
namespace := pod.Namespace
|
||||||
|
if namespace == "" {
|
||||||
|
namespace = "<empty-namespace>"
|
||||||
|
}
|
||||||
|
name := pod.Name
|
||||||
|
if name == "" {
|
||||||
|
name = "<empty-name>"
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%s.%s", name, namespace)
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,6 +52,7 @@ func (s sortedPods) Less(i, j int) bool {
|
||||||
func CreateValidPod(name, namespace, source string) api.BoundPod {
|
func CreateValidPod(name, namespace, source string) api.BoundPod {
|
||||||
return api.BoundPod{
|
return api.BoundPod{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
UID: name, // for the purpose of testing, this is unique enough
|
||||||
Name: name,
|
Name: name,
|
||||||
Namespace: namespace,
|
Namespace: namespace,
|
||||||
Annotations: map[string]string{kubelet.ConfigSourceAnnotationKey: source},
|
Annotations: map[string]string{kubelet.ConfigSourceAnnotationKey: source},
|
||||||
|
|
|
@ -20,7 +20,6 @@ package config
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"path"
|
"path"
|
||||||
"strconv"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||||
|
@ -105,11 +104,8 @@ func eventToPods(ev watch.Event) ([]api.BoundPod, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, pod := range boundPods.Items {
|
for _, pod := range boundPods.Items {
|
||||||
// TODO: generate random UID if not present
|
|
||||||
if pod.UID == "" && !pod.CreationTimestamp.IsZero() {
|
|
||||||
pod.UID = strconv.FormatInt(pod.CreationTimestamp.Unix(), 10)
|
|
||||||
}
|
|
||||||
// Backwards compatibility with old api servers
|
// Backwards compatibility with old api servers
|
||||||
|
// TODO: Remove this after 1.0 release.
|
||||||
if len(pod.Namespace) == 0 {
|
if len(pod.Namespace) == 0 {
|
||||||
pod.Namespace = api.NamespaceDefault
|
pod.Namespace = api.NamespaceDefault
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,14 +44,14 @@ func TestEventToPods(t *testing.T) {
|
||||||
input: watch.Event{
|
input: watch.Event{
|
||||||
Object: &api.BoundPods{
|
Object: &api.BoundPods{
|
||||||
Items: []api.BoundPod{
|
Items: []api.BoundPod{
|
||||||
{ObjectMeta: api.ObjectMeta{Name: "foo"}},
|
{ObjectMeta: api.ObjectMeta{UID: "111", Name: "foo", Namespace: "foo"}},
|
||||||
{ObjectMeta: api.ObjectMeta{Name: "bar"}},
|
{ObjectMeta: api.ObjectMeta{UID: "222", Name: "bar", Namespace: "bar"}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
pods: []api.BoundPod{
|
pods: []api.BoundPod{
|
||||||
{ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: "default"}, Spec: api.PodSpec{}},
|
{ObjectMeta: api.ObjectMeta{UID: "111", Name: "foo", Namespace: "foo"}, Spec: api.PodSpec{}},
|
||||||
{ObjectMeta: api.ObjectMeta{Name: "bar", Namespace: "default"}, Spec: api.PodSpec{}},
|
{ObjectMeta: api.ObjectMeta{UID: "222", Name: "bar", Namespace: "bar"}, Spec: api.PodSpec{}},
|
||||||
},
|
},
|
||||||
fail: false,
|
fail: false,
|
||||||
},
|
},
|
||||||
|
@ -59,14 +59,12 @@ func TestEventToPods(t *testing.T) {
|
||||||
input: watch.Event{
|
input: watch.Event{
|
||||||
Object: &api.BoundPods{
|
Object: &api.BoundPods{
|
||||||
Items: []api.BoundPod{
|
Items: []api.BoundPod{
|
||||||
{ObjectMeta: api.ObjectMeta{Name: "1"}},
|
{ObjectMeta: api.ObjectMeta{UID: "111", Name: "foo"}},
|
||||||
{ObjectMeta: api.ObjectMeta{Name: "2", Namespace: "foo"}},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
pods: []api.BoundPod{
|
pods: []api.BoundPod{
|
||||||
{ObjectMeta: api.ObjectMeta{Name: "1", Namespace: "default"}, Spec: api.PodSpec{}},
|
{ObjectMeta: api.ObjectMeta{UID: "111", Name: "foo", Namespace: "default"}, Spec: api.PodSpec{}},
|
||||||
{ObjectMeta: api.ObjectMeta{Name: "2", Namespace: "foo"}, Spec: api.PodSpec{}},
|
|
||||||
},
|
},
|
||||||
fail: false,
|
fail: false,
|
||||||
},
|
},
|
||||||
|
|
|
@ -18,15 +18,14 @@ limitations under the License.
|
||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/sha1"
|
"crypto/md5"
|
||||||
"encoding/base32"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"hash/adler32"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||||
|
@ -155,11 +154,27 @@ func extractFromFile(filename string) (api.BoundPod, error) {
|
||||||
return pod, fmt.Errorf("can't convert pod from file %q: %v", filename, err)
|
return pod, fmt.Errorf("can't convert pod from file %q: %v", filename, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hostname, err := os.Hostname() //TODO: kubelet name would be better
|
||||||
|
if err != nil {
|
||||||
|
return pod, err
|
||||||
|
}
|
||||||
|
|
||||||
if len(pod.UID) == 0 {
|
if len(pod.UID) == 0 {
|
||||||
pod.UID = simpleSubdomainSafeHash(filename)
|
hasher := md5.New()
|
||||||
|
fmt.Fprintf(hasher, "host:%s", hostname)
|
||||||
|
fmt.Fprintf(hasher, "file:%s", filename)
|
||||||
|
util.DeepHashObject(hasher, pod)
|
||||||
|
pod.UID = hex.EncodeToString(hasher.Sum(nil)[0:])
|
||||||
|
glog.V(5).Infof("Generated UID %q for pod %q from file %s", pod.UID, pod.Name, filename)
|
||||||
}
|
}
|
||||||
if len(pod.Namespace) == 0 {
|
if len(pod.Namespace) == 0 {
|
||||||
pod.Namespace = api.NamespaceDefault
|
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)
|
||||||
}
|
}
|
||||||
// TODO(dchen1107): BoundPod is not type of runtime.Object. Once we allow kubelet talks
|
// 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
|
// about Pod directly, we can use SelfLinker defined in package: latest
|
||||||
|
@ -174,17 +189,3 @@ func extractFromFile(filename string) (api.BoundPod, error) {
|
||||||
}
|
}
|
||||||
return pod, nil
|
return pod, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var simpleSubdomainSafeEncoding = base32.NewEncoding("0123456789abcdefghijklmnopqrstuv")
|
|
||||||
var unsafeDNSLabelReplacement = regexp.MustCompile("[^a-z0-9]+")
|
|
||||||
|
|
||||||
// simpleSubdomainSafeHash generates a pod name for the given path that is
|
|
||||||
// suitable as a subdomain label.
|
|
||||||
func simpleSubdomainSafeHash(path string) string {
|
|
||||||
name := strings.ToLower(filepath.Base(path))
|
|
||||||
name = unsafeDNSLabelReplacement.ReplaceAllString(name, "")
|
|
||||||
hasher := sha1.New()
|
|
||||||
hasher.Write([]byte(path))
|
|
||||||
sha := simpleSubdomainSafeEncoding.EncodeToString(hasher.Sum(nil))
|
|
||||||
return fmt.Sprintf("%.15s%.30s", name, sha)
|
|
||||||
}
|
|
||||||
|
|
|
@ -21,20 +21,19 @@ import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"sort"
|
"sort"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/validation"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/validation"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet"
|
||||||
|
|
||||||
"github.com/ghodss/yaml"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func ExampleManifestAndPod(id string) (api.ContainerManifest, api.BoundPod) {
|
func ExampleManifestAndPod(id string) (api.ContainerManifest, api.BoundPod) {
|
||||||
manifest := api.ContainerManifest{
|
manifest := api.ContainerManifest{
|
||||||
ID: id,
|
ID: id,
|
||||||
UUID: "uid",
|
UUID: id,
|
||||||
Containers: []api.Container{
|
Containers: []api.Container{
|
||||||
{
|
{
|
||||||
Name: "c" + id,
|
Name: "c" + id,
|
||||||
|
@ -53,9 +52,8 @@ func ExampleManifestAndPod(id string) (api.ContainerManifest, api.BoundPod) {
|
||||||
}
|
}
|
||||||
expectedPod := api.BoundPod{
|
expectedPod := api.BoundPod{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
Name: id,
|
Name: id,
|
||||||
UID: "uid",
|
UID: id,
|
||||||
Namespace: "default",
|
|
||||||
},
|
},
|
||||||
Spec: api.PodSpec{
|
Spec: api.PodSpec{
|
||||||
Containers: []api.Container{
|
Containers: []api.Container{
|
||||||
|
@ -116,7 +114,13 @@ func writeTestFile(t *testing.T, dir, name string, contents string) *os.File {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestReadFromFile(t *testing.T) {
|
func TestReadFromFile(t *testing.T) {
|
||||||
file := writeTestFile(t, os.TempDir(), "test_pod_config", "version: v1beta1\nid: test\ncontainers:\n- image: test/image")
|
file := writeTestFile(t, os.TempDir(), "test_pod_config",
|
||||||
|
`{
|
||||||
|
"version": "v1beta1",
|
||||||
|
"uuid": "12345",
|
||||||
|
"id": "test",
|
||||||
|
"containers": [{ "image": "test/image" }]
|
||||||
|
}`)
|
||||||
defer os.Remove(file.Name())
|
defer os.Remove(file.Name())
|
||||||
|
|
||||||
ch := make(chan interface{})
|
ch := make(chan interface{})
|
||||||
|
@ -127,14 +131,28 @@ func TestReadFromFile(t *testing.T) {
|
||||||
expected := CreatePodUpdate(kubelet.SET, kubelet.FileSource, api.BoundPod{
|
expected := CreatePodUpdate(kubelet.SET, kubelet.FileSource, api.BoundPod{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
Name: "test",
|
Name: "test",
|
||||||
UID: simpleSubdomainSafeHash(file.Name()),
|
UID: "12345",
|
||||||
Namespace: "default",
|
Namespace: "",
|
||||||
SelfLink: "/api/v1beta2/pods/test?namespace=default",
|
SelfLink: "",
|
||||||
},
|
},
|
||||||
Spec: api.PodSpec{
|
Spec: api.PodSpec{
|
||||||
Containers: []api.Container{{Image: "test/image", TerminationMessagePath: "/dev/termination-log"}},
|
Containers: []api.Container{{Image: "test/image", TerminationMessagePath: "/dev/termination-log"}},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
}
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
update.Pods[0].ObjectMeta.SelfLink = ""
|
||||||
|
|
||||||
if !api.Semantic.DeepEqual(expected, update) {
|
if !api.Semantic.DeepEqual(expected, update) {
|
||||||
t.Fatalf("Expected %#v, Got %#v", expected, update)
|
t.Fatalf("Expected %#v, Got %#v", expected, update)
|
||||||
}
|
}
|
||||||
|
@ -144,6 +162,29 @@ func TestReadFromFile(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestReadFromFileWithDefaults(t *testing.T) {
|
||||||
|
file := writeTestFile(t, os.TempDir(), "test_pod_config",
|
||||||
|
`{
|
||||||
|
"version": "v1beta1",
|
||||||
|
"id": "test",
|
||||||
|
"containers": [{ "image": "test/image" }]
|
||||||
|
}`)
|
||||||
|
defer os.Remove(file.Name())
|
||||||
|
|
||||||
|
ch := make(chan interface{})
|
||||||
|
NewSourceFile(file.Name(), time.Millisecond, ch)
|
||||||
|
select {
|
||||||
|
case got := <-ch:
|
||||||
|
update := got.(kubelet.PodUpdate)
|
||||||
|
if update.Pods[0].ObjectMeta.UID == "" {
|
||||||
|
t.Errorf("Unexpected UID: %s", update.Pods[0].ObjectMeta.UID)
|
||||||
|
}
|
||||||
|
|
||||||
|
case <-time.After(2 * time.Millisecond):
|
||||||
|
t.Errorf("Expected update, timeout instead")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestExtractFromBadDataFile(t *testing.T) {
|
func TestExtractFromBadDataFile(t *testing.T) {
|
||||||
file := writeTestFile(t, os.TempDir(), "test_pod_config", string([]byte{1, 2, 3}))
|
file := writeTestFile(t, os.TempDir(), "test_pod_config", string([]byte{1, 2, 3}))
|
||||||
defer os.Remove(file.Name())
|
defer os.Remove(file.Name())
|
||||||
|
@ -157,30 +198,6 @@ func TestExtractFromBadDataFile(t *testing.T) {
|
||||||
expectEmptyChannel(t, ch)
|
expectEmptyChannel(t, ch)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExtractFromValidDataFile(t *testing.T) {
|
|
||||||
manifest, expectedPod := ExampleManifestAndPod("id")
|
|
||||||
|
|
||||||
text, err := json.Marshal(manifest)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Unexpected error: %v", err)
|
|
||||||
}
|
|
||||||
file := writeTestFile(t, os.TempDir(), "test_pod_config", string(text))
|
|
||||||
defer os.Remove(file.Name())
|
|
||||||
|
|
||||||
expectedPod.ObjectMeta.SelfLink = "/api/v1beta2/pods/" + expectedPod.Name + "?namespace=default"
|
|
||||||
ch := make(chan interface{}, 1)
|
|
||||||
c := sourceFile{file.Name(), ch}
|
|
||||||
err = c.extractFromPath()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Unexpected error: %v", err)
|
|
||||||
}
|
|
||||||
update := (<-ch).(kubelet.PodUpdate)
|
|
||||||
expected := CreatePodUpdate(kubelet.SET, kubelet.FileSource, expectedPod)
|
|
||||||
if !api.Semantic.DeepEqual(expected, update) {
|
|
||||||
t.Errorf("Expected %#v, Got %#v", expected, update)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestExtractFromEmptyDir(t *testing.T) {
|
func TestExtractFromEmptyDir(t *testing.T) {
|
||||||
dirName, err := ioutil.TempDir("", "foo")
|
dirName, err := ioutil.TempDir("", "foo")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -233,7 +250,6 @@ func TestExtractFromDir(t *testing.T) {
|
||||||
}
|
}
|
||||||
ioutil.WriteFile(name, data, 0755)
|
ioutil.WriteFile(name, data, 0755)
|
||||||
files[i] = file
|
files[i] = file
|
||||||
pods[i].ObjectMeta.SelfLink = "/api/v1beta2/pods/" + pods[i].Name + "?namespace=default"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ch := make(chan interface{}, 1)
|
ch := make(chan interface{}, 1)
|
||||||
|
@ -244,7 +260,14 @@ func TestExtractFromDir(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
update := (<-ch).(kubelet.PodUpdate)
|
update := (<-ch).(kubelet.PodUpdate)
|
||||||
|
for i := range update.Pods {
|
||||||
|
update.Pods[i].Namespace = "foobar"
|
||||||
|
update.Pods[i].SelfLink = ""
|
||||||
|
}
|
||||||
expected := CreatePodUpdate(kubelet.SET, kubelet.FileSource, pods...)
|
expected := CreatePodUpdate(kubelet.SET, kubelet.FileSource, pods...)
|
||||||
|
for i := range expected.Pods {
|
||||||
|
expected.Pods[i].Namespace = "foobar"
|
||||||
|
}
|
||||||
sort.Sort(sortedPods(update.Pods))
|
sort.Sort(sortedPods(update.Pods))
|
||||||
sort.Sort(sortedPods(expected.Pods))
|
sort.Sort(sortedPods(expected.Pods))
|
||||||
if !api.Semantic.DeepEqual(expected, update) {
|
if !api.Semantic.DeepEqual(expected, update) {
|
||||||
|
@ -256,60 +279,3 @@ func TestExtractFromDir(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSubdomainSafeName(t *testing.T) {
|
|
||||||
type Case struct {
|
|
||||||
Input string
|
|
||||||
Expected string
|
|
||||||
}
|
|
||||||
testCases := []Case{
|
|
||||||
{"/some/path/invalidUPPERCASE", "invaliduppercasa6hlenc0vpqbbdtt26ghneqsq3pvud"},
|
|
||||||
{"/some/path/_-!%$#&@^&*(){}", "nvhc03p016m60huaiv3avts372rl2p"},
|
|
||||||
}
|
|
||||||
for _, testCase := range testCases {
|
|
||||||
value := simpleSubdomainSafeHash(testCase.Input)
|
|
||||||
if value != testCase.Expected {
|
|
||||||
t.Errorf("Expected %s, Got %s", testCase.Expected, value)
|
|
||||||
}
|
|
||||||
value2 := simpleSubdomainSafeHash(testCase.Input)
|
|
||||||
if value != value2 {
|
|
||||||
t.Errorf("Value for %s was not stable across runs: %s %s", testCase.Input, value, value2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// These are used for testing extract json (below)
|
|
||||||
type TestData struct {
|
|
||||||
Value string
|
|
||||||
Number int
|
|
||||||
}
|
|
||||||
|
|
||||||
type TestObject struct {
|
|
||||||
Name string
|
|
||||||
Data TestData
|
|
||||||
}
|
|
||||||
|
|
||||||
func verifyStringEquals(t *testing.T, actual, expected string) {
|
|
||||||
if actual != expected {
|
|
||||||
t.Errorf("Verification failed. Expected: %s, Found %s", expected, actual)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func verifyIntEquals(t *testing.T, actual, expected int) {
|
|
||||||
if actual != expected {
|
|
||||||
t.Errorf("Verification failed. Expected: %d, Found %d", expected, actual)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestExtractJSON(t *testing.T) {
|
|
||||||
obj := TestObject{}
|
|
||||||
data := `{ "name": "foo", "data": { "value": "bar", "number": 10 } }`
|
|
||||||
|
|
||||||
if err := yaml.Unmarshal([]byte(data), &obj); err != nil {
|
|
||||||
t.Fatalf("Could not unmarshal JSON: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
verifyStringEquals(t, obj.Name, "foo")
|
|
||||||
verifyStringEquals(t, obj.Data.Value, "bar")
|
|
||||||
verifyIntEquals(t, obj.Data.Number, 10)
|
|
||||||
}
|
|
||||||
|
|
|
@ -19,7 +19,10 @@ package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"crypto/md5"
|
||||||
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"hash/adler32"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
@ -93,9 +96,7 @@ func (s *sourceURL) extractFromURL() error {
|
||||||
if err := api.Scheme.Convert(&manifest, &pod); err != nil {
|
if err := api.Scheme.Convert(&manifest, &pod); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if len(pod.Namespace) == 0 {
|
applyDefaults(&pod, s.url)
|
||||||
pod.Namespace = api.NamespaceDefault
|
|
||||||
}
|
|
||||||
s.updates <- kubelet.PodUpdate{[]api.BoundPod{pod}, kubelet.SET, kubelet.HTTPSource}
|
s.updates <- kubelet.PodUpdate{[]api.BoundPod{pod}, kubelet.SET, kubelet.HTTPSource}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -130,12 +131,7 @@ func (s *sourceURL) extractFromURL() error {
|
||||||
}
|
}
|
||||||
for i := range boundPods.Items {
|
for i := range boundPods.Items {
|
||||||
pod := &boundPods.Items[i]
|
pod := &boundPods.Items[i]
|
||||||
if len(pod.Name) == 0 {
|
applyDefaults(pod, s.url)
|
||||||
pod.Name = fmt.Sprintf("%d", i+1)
|
|
||||||
}
|
|
||||||
if len(pod.Namespace) == 0 {
|
|
||||||
pod.Namespace = api.NamespaceDefault
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
s.updates <- kubelet.PodUpdate{boundPods.Items, kubelet.SET, kubelet.HTTPSource}
|
s.updates <- kubelet.PodUpdate{boundPods.Items, kubelet.SET, kubelet.HTTPSource}
|
||||||
return nil
|
return nil
|
||||||
|
@ -145,3 +141,19 @@ func (s *sourceURL) extractFromURL() error {
|
||||||
"single manifest (%v: %+v) or as multiple manifests (%v: %+v).\n",
|
"single manifest (%v: %+v) or as multiple manifests (%v: %+v).\n",
|
||||||
s.url, string(data), singleErr, manifest, multiErr, manifests)
|
s.url, string(data), singleErr, manifest, multiErr, manifests)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func applyDefaults(pod *api.BoundPod, url string) {
|
||||||
|
if len(pod.UID) == 0 {
|
||||||
|
hasher := md5.New()
|
||||||
|
fmt.Fprintf(hasher, "url:%s", url)
|
||||||
|
util.DeepHashObject(hasher, pod)
|
||||||
|
pod.UID = hex.EncodeToString(hasher.Sum(nil)[0:])
|
||||||
|
glog.V(5).Infof("Generated UID %q for pod %q from URL %s", pod.UID, pod.Name, 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ package config
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -26,6 +27,7 @@ import (
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/validation"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/validation"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
|
||||||
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/util/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestURLErrorNotExistNoUpdate(t *testing.T) {
|
func TestURLErrorNotExistNoUpdate(t *testing.T) {
|
||||||
|
@ -121,13 +123,14 @@ func TestExtractFromHTTP(t *testing.T) {
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
desc: "Single manifest",
|
desc: "Single manifest",
|
||||||
manifests: api.ContainerManifest{Version: "v1beta1", ID: "foo"},
|
manifests: api.ContainerManifest{Version: "v1beta1", ID: "foo", UUID: "111"},
|
||||||
expected: CreatePodUpdate(kubelet.SET,
|
expected: CreatePodUpdate(kubelet.SET,
|
||||||
kubelet.HTTPSource,
|
kubelet.HTTPSource,
|
||||||
api.BoundPod{
|
api.BoundPod{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
UID: "111",
|
||||||
Name: "foo",
|
Name: "foo",
|
||||||
Namespace: "default",
|
Namespace: "foobar",
|
||||||
},
|
},
|
||||||
Spec: api.PodSpec{
|
Spec: api.PodSpec{
|
||||||
RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}},
|
RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}},
|
||||||
|
@ -138,15 +141,16 @@ func TestExtractFromHTTP(t *testing.T) {
|
||||||
{
|
{
|
||||||
desc: "Multiple manifests",
|
desc: "Multiple manifests",
|
||||||
manifests: []api.ContainerManifest{
|
manifests: []api.ContainerManifest{
|
||||||
{Version: "v1beta1", ID: "", Containers: []api.Container{{Name: "1", Image: "foo"}}},
|
{Version: "v1beta1", ID: "foo", UUID: "111", Containers: []api.Container{{Name: "1", Image: "foo"}}},
|
||||||
{Version: "v1beta1", ID: "bar", Containers: []api.Container{{Name: "1", Image: "foo"}}},
|
{Version: "v1beta1", ID: "bar", UUID: "222", Containers: []api.Container{{Name: "1", Image: "foo"}}},
|
||||||
},
|
},
|
||||||
expected: CreatePodUpdate(kubelet.SET,
|
expected: CreatePodUpdate(kubelet.SET,
|
||||||
kubelet.HTTPSource,
|
kubelet.HTTPSource,
|
||||||
api.BoundPod{
|
api.BoundPod{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
Name: "1",
|
UID: "111",
|
||||||
Namespace: "default",
|
Name: "foo",
|
||||||
|
Namespace: "foobar",
|
||||||
},
|
},
|
||||||
Spec: api.PodSpec{
|
Spec: api.PodSpec{
|
||||||
Containers: []api.Container{{
|
Containers: []api.Container{{
|
||||||
|
@ -157,8 +161,9 @@ func TestExtractFromHTTP(t *testing.T) {
|
||||||
},
|
},
|
||||||
api.BoundPod{
|
api.BoundPod{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
UID: "222",
|
||||||
Name: "bar",
|
Name: "bar",
|
||||||
Namespace: "default",
|
Namespace: "foobar",
|
||||||
},
|
},
|
||||||
Spec: api.PodSpec{
|
Spec: api.PodSpec{
|
||||||
Containers: []api.Container{{
|
Containers: []api.Container{{
|
||||||
|
@ -192,12 +197,21 @@ func TestExtractFromHTTP(t *testing.T) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
update := (<-ch).(kubelet.PodUpdate)
|
update := (<-ch).(kubelet.PodUpdate)
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
update.Pods[i].ObjectMeta.Namespace = "foobar"
|
||||||
|
}
|
||||||
if !api.Semantic.DeepEqual(testCase.expected, update) {
|
if !api.Semantic.DeepEqual(testCase.expected, update) {
|
||||||
t.Errorf("%s: Expected: %#v, Got: %#v", testCase.desc, testCase.expected, update)
|
t.Errorf("%s: Expected: %#v, Got: %#v", testCase.desc, testCase.expected, update)
|
||||||
}
|
}
|
||||||
for i := range update.Pods {
|
for i := range update.Pods {
|
||||||
if errs := validation.ValidateBoundPod(&update.Pods[i]); len(errs) != 0 {
|
if errs := validation.ValidateBoundPod(&update.Pods[i]); len(errs) != 0 {
|
||||||
t.Errorf("%s: Expected no validation errors on %#v, Got %#v", testCase.desc, update.Pods[i], errs)
|
t.Errorf("%s: Expected no validation errors on %#v, Got %v", testCase.desc, update.Pods[i], errors.NewAggregate(errs))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -545,28 +545,19 @@ func HashContainer(container *api.Container) uint64 {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates a name which can be reversed to identify both full pod name and container name.
|
// Creates a name which can be reversed to identify both full pod name and container name.
|
||||||
func BuildDockerName(manifestUUID, podFullName string, container *api.Container) string {
|
func BuildDockerName(podUID, podFullName string, container *api.Container) string {
|
||||||
containerName := container.Name + "." + strconv.FormatUint(HashContainer(container), 16)
|
containerName := container.Name + "." + strconv.FormatUint(HashContainer(container), 16)
|
||||||
// Note, manifest.ID could be blank.
|
return fmt.Sprintf("%s_%s_%s_%s_%08x",
|
||||||
if len(manifestUUID) == 0 {
|
containerNamePrefix,
|
||||||
return fmt.Sprintf("%s_%s_%s_%08x",
|
containerName,
|
||||||
containerNamePrefix,
|
podFullName,
|
||||||
containerName,
|
podUID,
|
||||||
podFullName,
|
rand.Uint32())
|
||||||
rand.Uint32())
|
|
||||||
} else {
|
|
||||||
return fmt.Sprintf("%s_%s_%s_%s_%08x",
|
|
||||||
containerNamePrefix,
|
|
||||||
containerName,
|
|
||||||
podFullName,
|
|
||||||
manifestUUID,
|
|
||||||
rand.Uint32())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unpacks a container name, returning the pod full name and container name we would have used to
|
// Unpacks a container name, returning the pod full name and container name we would have used to
|
||||||
// construct the docker name. If the docker name isn't the one we created, we may return empty strings.
|
// construct the docker name. If the docker name isn't the one we created, we may return empty strings.
|
||||||
func ParseDockerName(name string) (podFullName, uuid, containerName string, hash uint64) {
|
func ParseDockerName(name string) (podFullName, podUID, containerName string, hash uint64) {
|
||||||
// For some reason docker appears to be appending '/' to names.
|
// For some reason docker appears to be appending '/' to names.
|
||||||
// If it's there, strip it.
|
// If it's there, strip it.
|
||||||
if name[0] == '/' {
|
if name[0] == '/' {
|
||||||
|
@ -576,23 +567,31 @@ func ParseDockerName(name string) (podFullName, uuid, containerName string, hash
|
||||||
if len(parts) == 0 || parts[0] != containerNamePrefix {
|
if len(parts) == 0 || parts[0] != containerNamePrefix {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if len(parts) > 1 {
|
if len(parts) < 5 {
|
||||||
pieces := strings.Split(parts[1], ".")
|
// We have at least 5 fields. We may have more in the future.
|
||||||
containerName = pieces[0]
|
// Anything with less fields than this is not something we can
|
||||||
if len(pieces) > 1 {
|
// manage.
|
||||||
var err error
|
glog.Warningf("found a container with the %q prefix, but too few fields (%d): ", containerNamePrefix, len(parts), name)
|
||||||
hash, err = strconv.ParseUint(pieces[1], 16, 32)
|
return
|
||||||
if err != nil {
|
}
|
||||||
glog.Warningf("invalid container hash: %s", pieces[1])
|
|
||||||
}
|
// Container name.
|
||||||
|
nameParts := strings.Split(parts[1], ".")
|
||||||
|
containerName = nameParts[0]
|
||||||
|
if len(nameParts) > 1 {
|
||||||
|
var err error
|
||||||
|
hash, err = strconv.ParseUint(nameParts[1], 16, 32)
|
||||||
|
if err != nil {
|
||||||
|
glog.Warningf("invalid container hash: %s", nameParts[1])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(parts) > 2 {
|
|
||||||
podFullName = parts[2]
|
// Pod fullname.
|
||||||
}
|
podFullName = parts[2]
|
||||||
if len(parts) > 4 {
|
|
||||||
uuid = parts[3]
|
// Pod UID.
|
||||||
}
|
podUID = parts[3]
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -53,11 +53,11 @@ func TestGetContainerID(t *testing.T) {
|
||||||
fakeDocker.ContainerList = []docker.APIContainers{
|
fakeDocker.ContainerList = []docker.APIContainers{
|
||||||
{
|
{
|
||||||
ID: "foobar",
|
ID: "foobar",
|
||||||
Names: []string{"/k8s_foo_qux_1234"},
|
Names: []string{"/k8s_foo_qux_1234_42"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ID: "barbar",
|
ID: "barbar",
|
||||||
Names: []string{"/k8s_bar_qux_2565"},
|
Names: []string{"/k8s_bar_qux_2565_42"},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
fakeDocker.Container = &docker.Container{
|
fakeDocker.Container = &docker.Container{
|
||||||
|
@ -85,41 +85,37 @@ func TestGetContainerID(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func verifyPackUnpack(t *testing.T, podNamespace, manifestUUID, podName, containerName string) {
|
func verifyPackUnpack(t *testing.T, podNamespace, podUID, podName, containerName string) {
|
||||||
container := &api.Container{Name: containerName}
|
container := &api.Container{Name: containerName}
|
||||||
hasher := adler32.New()
|
hasher := adler32.New()
|
||||||
util.DeepHashObject(hasher, *container)
|
util.DeepHashObject(hasher, *container)
|
||||||
computedHash := uint64(hasher.Sum32())
|
computedHash := uint64(hasher.Sum32())
|
||||||
podFullName := fmt.Sprintf("%s.%s", podName, podNamespace)
|
podFullName := fmt.Sprintf("%s.%s", podName, podNamespace)
|
||||||
name := BuildDockerName(manifestUUID, podFullName, container)
|
name := BuildDockerName(podUID, podFullName, container)
|
||||||
returnedPodFullName, returnedUUID, returnedContainerName, hash := ParseDockerName(name)
|
returnedPodFullName, returnedUID, returnedContainerName, hash := ParseDockerName(name)
|
||||||
if podFullName != returnedPodFullName || manifestUUID != returnedUUID || containerName != returnedContainerName || computedHash != hash {
|
if podFullName != returnedPodFullName || podUID != returnedUID || containerName != returnedContainerName || computedHash != hash {
|
||||||
t.Errorf("For (%s, %s, %s, %d), unpacked (%s, %s, %s, %d)", podFullName, manifestUUID, containerName, computedHash, returnedPodFullName, returnedUUID, returnedContainerName, hash)
|
t.Errorf("For (%s, %s, %s, %d), unpacked (%s, %s, %s, %d)", podFullName, podUID, containerName, computedHash, returnedPodFullName, returnedUID, returnedContainerName, hash)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestContainerManifestNaming(t *testing.T) {
|
func TestContainerManifestNaming(t *testing.T) {
|
||||||
manifestUUID := "d1b925c9-444a-11e4-a576-42010af0a203"
|
podUID := "12345678"
|
||||||
verifyPackUnpack(t, "file", manifestUUID, "manifest1234", "container5678")
|
verifyPackUnpack(t, "file", podUID, "name", "container")
|
||||||
verifyPackUnpack(t, "file", manifestUUID, "mani-fest-1234", "container5678")
|
verifyPackUnpack(t, "file", podUID, "name-with-dashes", "container")
|
||||||
// UUID is same as pod name
|
// UID is same as pod name
|
||||||
verifyPackUnpack(t, "file", manifestUUID, manifestUUID, "container123")
|
verifyPackUnpack(t, "file", podUID, podUID, "container")
|
||||||
// empty namespace
|
|
||||||
verifyPackUnpack(t, "", manifestUUID, manifestUUID, "container123")
|
|
||||||
// No UUID
|
|
||||||
verifyPackUnpack(t, "other", "", manifestUUID, "container456")
|
|
||||||
// No Container name
|
// No Container name
|
||||||
verifyPackUnpack(t, "other", "", manifestUUID, "")
|
verifyPackUnpack(t, "other", podUID, "name", "")
|
||||||
|
|
||||||
container := &api.Container{Name: "container"}
|
container := &api.Container{Name: "container"}
|
||||||
podName := "foo"
|
podName := "foo"
|
||||||
podNamespace := "test"
|
podNamespace := "test"
|
||||||
name := fmt.Sprintf("k8s_%s_%s.%s_12345", container.Name, podName, podNamespace)
|
name := fmt.Sprintf("k8s_%s_%s.%s_%s_42", container.Name, podName, podNamespace, podUID)
|
||||||
|
|
||||||
podFullName := fmt.Sprintf("%s.%s", podName, podNamespace)
|
podFullName := fmt.Sprintf("%s.%s", podName, podNamespace)
|
||||||
returnedPodFullName, _, returnedContainerName, hash := ParseDockerName(name)
|
|
||||||
if returnedPodFullName != podFullName || returnedContainerName != container.Name || hash != 0 {
|
returnedPodFullName, returnedPodUID, returnedContainerName, hash := ParseDockerName(name)
|
||||||
t.Errorf("unexpected parse: %s %s %d", returnedPodFullName, returnedContainerName, hash)
|
if returnedPodFullName != podFullName || returnedPodUID != podUID || returnedContainerName != container.Name || hash != 0 {
|
||||||
|
t.Errorf("unexpected parse: %s %s %s %d", returnedPodFullName, returnedPodUID, returnedContainerName, hash)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1056,8 +1056,7 @@ func (kl *Kubelet) SyncPods(pods []api.BoundPod) error {
|
||||||
|
|
||||||
// Run the sync in an async manifest worker.
|
// Run the sync in an async manifest worker.
|
||||||
kl.podWorkers.Run(podFullName, func() {
|
kl.podWorkers.Run(podFullName, func() {
|
||||||
err := kl.syncPod(pod, dockerContainers)
|
if err := kl.syncPod(pod, dockerContainers); err != nil {
|
||||||
if err != nil {
|
|
||||||
glog.Errorf("Error syncing pod, skipping: %v", err)
|
glog.Errorf("Error syncing pod, skipping: %v", err)
|
||||||
record.Eventf(pod, "", "failedSync", "Error syncing pod, skipping: %v", err)
|
record.Eventf(pod, "", "failedSync", "Error syncing pod, skipping: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -220,11 +220,11 @@ func TestKillContainerWithError(t *testing.T) {
|
||||||
ContainerList: []docker.APIContainers{
|
ContainerList: []docker.APIContainers{
|
||||||
{
|
{
|
||||||
ID: "1234",
|
ID: "1234",
|
||||||
Names: []string{"/k8s_foo_qux_1234"},
|
Names: []string{"/k8s_foo_qux_1234_42"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ID: "5678",
|
ID: "5678",
|
||||||
Names: []string{"/k8s_bar_qux_5678"},
|
Names: []string{"/k8s_bar_qux_5678_42"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -242,11 +242,11 @@ func TestKillContainer(t *testing.T) {
|
||||||
fakeDocker.ContainerList = []docker.APIContainers{
|
fakeDocker.ContainerList = []docker.APIContainers{
|
||||||
{
|
{
|
||||||
ID: "1234",
|
ID: "1234",
|
||||||
Names: []string{"/k8s_foo_qux_1234"},
|
Names: []string{"/k8s_foo_qux_1234_42"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ID: "5678",
|
ID: "5678",
|
||||||
Names: []string{"/k8s_bar_qux_5678"},
|
Names: []string{"/k8s_bar_qux_5678_42"},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
fakeDocker.Container = &docker.Container{
|
fakeDocker.Container = &docker.Container{
|
||||||
|
@ -291,19 +291,20 @@ func TestSyncPodsDoesNothing(t *testing.T) {
|
||||||
container := api.Container{Name: "bar"}
|
container := api.Container{Name: "bar"}
|
||||||
fakeDocker.ContainerList = []docker.APIContainers{
|
fakeDocker.ContainerList = []docker.APIContainers{
|
||||||
{
|
{
|
||||||
// format is k8s_<container-id>_<pod-fullname>
|
// format is // k8s_<container-id>_<pod-fullname>_<pod-uid>_<random>
|
||||||
Names: []string{"/k8s_bar." + strconv.FormatUint(dockertools.HashContainer(&container), 16) + "_foo.new.test"},
|
Names: []string{"/k8s_bar." + strconv.FormatUint(dockertools.HashContainer(&container), 16) + "_foo.new.test_12345678_0"},
|
||||||
ID: "1234",
|
ID: "1234",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// network container
|
// network container
|
||||||
Names: []string{"/k8s_net_foo.new.test_"},
|
Names: []string{"/k8s_net_foo.new.test_12345678_0"},
|
||||||
ID: "9876",
|
ID: "9876",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
err := kubelet.SyncPods([]api.BoundPod{
|
err := kubelet.SyncPods([]api.BoundPod{
|
||||||
{
|
{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
UID: "12345678",
|
||||||
Name: "foo",
|
Name: "foo",
|
||||||
Namespace: "new",
|
Namespace: "new",
|
||||||
Annotations: map[string]string{ConfigSourceAnnotationKey: "test"},
|
Annotations: map[string]string{ConfigSourceAnnotationKey: "test"},
|
||||||
|
@ -332,7 +333,7 @@ func TestSyncPodsWithTerminationLog(t *testing.T) {
|
||||||
err := kubelet.SyncPods([]api.BoundPod{
|
err := kubelet.SyncPods([]api.BoundPod{
|
||||||
{
|
{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
UID: "0123-45-67-89ab-cdef",
|
UID: "12345678",
|
||||||
Name: "foo",
|
Name: "foo",
|
||||||
Namespace: "new",
|
Namespace: "new",
|
||||||
Annotations: map[string]string{ConfigSourceAnnotationKey: "test"},
|
Annotations: map[string]string{ConfigSourceAnnotationKey: "test"},
|
||||||
|
@ -353,7 +354,7 @@ func TestSyncPodsWithTerminationLog(t *testing.T) {
|
||||||
|
|
||||||
fakeDocker.Lock()
|
fakeDocker.Lock()
|
||||||
parts := strings.Split(fakeDocker.Container.HostConfig.Binds[0], ":")
|
parts := strings.Split(fakeDocker.Container.HostConfig.Binds[0], ":")
|
||||||
if !matchString(t, kubelet.GetPodContainerDir("0123-45-67-89ab-cdef", "bar")+"/k8s_bar\\.[a-f0-9]", parts[0]) {
|
if !matchString(t, kubelet.GetPodContainerDir("12345678", "bar")+"/k8s_bar\\.[a-f0-9]", parts[0]) {
|
||||||
t.Errorf("Unexpected host path: %s", parts[0])
|
t.Errorf("Unexpected host path: %s", parts[0])
|
||||||
}
|
}
|
||||||
if parts[1] != "/dev/somepath" {
|
if parts[1] != "/dev/somepath" {
|
||||||
|
@ -390,6 +391,7 @@ func TestSyncPodsCreatesNetAndContainer(t *testing.T) {
|
||||||
err := kubelet.SyncPods([]api.BoundPod{
|
err := kubelet.SyncPods([]api.BoundPod{
|
||||||
{
|
{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
UID: "12345678",
|
||||||
Name: "foo",
|
Name: "foo",
|
||||||
Namespace: "new",
|
Namespace: "new",
|
||||||
Annotations: map[string]string{ConfigSourceAnnotationKey: "test"},
|
Annotations: map[string]string{ConfigSourceAnnotationKey: "test"},
|
||||||
|
@ -438,6 +440,7 @@ func TestSyncPodsCreatesNetAndContainerPullsImage(t *testing.T) {
|
||||||
err := kubelet.SyncPods([]api.BoundPod{
|
err := kubelet.SyncPods([]api.BoundPod{
|
||||||
{
|
{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
UID: "12345678",
|
||||||
Name: "foo",
|
Name: "foo",
|
||||||
Namespace: "new",
|
Namespace: "new",
|
||||||
Annotations: map[string]string{ConfigSourceAnnotationKey: "test"},
|
Annotations: map[string]string{ConfigSourceAnnotationKey: "test"},
|
||||||
|
@ -476,13 +479,14 @@ func TestSyncPodsWithNetCreatesContainer(t *testing.T) {
|
||||||
fakeDocker.ContainerList = []docker.APIContainers{
|
fakeDocker.ContainerList = []docker.APIContainers{
|
||||||
{
|
{
|
||||||
// network container
|
// network container
|
||||||
Names: []string{"/k8s_net_foo.new.test_"},
|
Names: []string{"/k8s_net_foo.new.test_12345678_0"},
|
||||||
ID: "9876",
|
ID: "9876",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
err := kubelet.SyncPods([]api.BoundPod{
|
err := kubelet.SyncPods([]api.BoundPod{
|
||||||
{
|
{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
UID: "12345678",
|
||||||
Name: "foo",
|
Name: "foo",
|
||||||
Namespace: "new",
|
Namespace: "new",
|
||||||
Annotations: map[string]string{ConfigSourceAnnotationKey: "test"},
|
Annotations: map[string]string{ConfigSourceAnnotationKey: "test"},
|
||||||
|
@ -517,13 +521,14 @@ func TestSyncPodsWithNetCreatesContainerCallsHandler(t *testing.T) {
|
||||||
fakeDocker.ContainerList = []docker.APIContainers{
|
fakeDocker.ContainerList = []docker.APIContainers{
|
||||||
{
|
{
|
||||||
// network container
|
// network container
|
||||||
Names: []string{"/k8s_net_foo.new.test_"},
|
Names: []string{"/k8s_net_foo.new.test_12345678_0"},
|
||||||
ID: "9876",
|
ID: "9876",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
err := kubelet.SyncPods([]api.BoundPod{
|
err := kubelet.SyncPods([]api.BoundPod{
|
||||||
{
|
{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
UID: "12345678",
|
||||||
Name: "foo",
|
Name: "foo",
|
||||||
Namespace: "new",
|
Namespace: "new",
|
||||||
Annotations: map[string]string{ConfigSourceAnnotationKey: "test"},
|
Annotations: map[string]string{ConfigSourceAnnotationKey: "test"},
|
||||||
|
@ -569,14 +574,15 @@ func TestSyncPodsDeletesWithNoNetContainer(t *testing.T) {
|
||||||
kubelet, _, fakeDocker := newTestKubelet(t)
|
kubelet, _, fakeDocker := newTestKubelet(t)
|
||||||
fakeDocker.ContainerList = []docker.APIContainers{
|
fakeDocker.ContainerList = []docker.APIContainers{
|
||||||
{
|
{
|
||||||
// format is k8s_<container-id>_<pod-fullname>
|
// format is // k8s_<container-id>_<pod-fullname>_<pod-uid>
|
||||||
Names: []string{"/k8s_bar_foo.new.test"},
|
Names: []string{"/k8s_bar_foo.new.test_12345678_0"},
|
||||||
ID: "1234",
|
ID: "1234",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
err := kubelet.SyncPods([]api.BoundPod{
|
err := kubelet.SyncPods([]api.BoundPod{
|
||||||
{
|
{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
UID: "12345678",
|
||||||
Name: "foo",
|
Name: "foo",
|
||||||
Namespace: "new",
|
Namespace: "new",
|
||||||
Annotations: map[string]string{ConfigSourceAnnotationKey: "test"},
|
Annotations: map[string]string{ConfigSourceAnnotationKey: "test"},
|
||||||
|
@ -616,12 +622,12 @@ func TestSyncPodsDeletesWhenSourcesAreReady(t *testing.T) {
|
||||||
fakeDocker.ContainerList = []docker.APIContainers{
|
fakeDocker.ContainerList = []docker.APIContainers{
|
||||||
{
|
{
|
||||||
// the k8s prefix is required for the kubelet to manage the container
|
// the k8s prefix is required for the kubelet to manage the container
|
||||||
Names: []string{"/k8s_foo_bar.new.test"},
|
Names: []string{"/k8s_foo_bar.new.test_12345678_42"},
|
||||||
ID: "1234",
|
ID: "1234",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// network container
|
// network container
|
||||||
Names: []string{"/k8s_net_foo.new.test_"},
|
Names: []string{"/k8s_net_foo.new.test_12345678_42"},
|
||||||
ID: "9876",
|
ID: "9876",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -656,12 +662,12 @@ func TestSyncPodsDeletes(t *testing.T) {
|
||||||
fakeDocker.ContainerList = []docker.APIContainers{
|
fakeDocker.ContainerList = []docker.APIContainers{
|
||||||
{
|
{
|
||||||
// the k8s prefix is required for the kubelet to manage the container
|
// the k8s prefix is required for the kubelet to manage the container
|
||||||
Names: []string{"/k8s_foo_bar.new.test"},
|
Names: []string{"/k8s_foo_bar.new.test_12345678_42"},
|
||||||
ID: "1234",
|
ID: "1234",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// network container
|
// network container
|
||||||
Names: []string{"/k8s_net_foo.new.test_"},
|
Names: []string{"/k8s_net_foo.new.test_12345678_42"},
|
||||||
ID: "9876",
|
ID: "9876",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -694,27 +700,28 @@ func TestSyncPodDeletesDuplicate(t *testing.T) {
|
||||||
dockerContainers := dockertools.DockerContainers{
|
dockerContainers := dockertools.DockerContainers{
|
||||||
"1234": &docker.APIContainers{
|
"1234": &docker.APIContainers{
|
||||||
// the k8s prefix is required for the kubelet to manage the container
|
// the k8s prefix is required for the kubelet to manage the container
|
||||||
Names: []string{"/k8s_foo_bar.new.test_1"},
|
Names: []string{"/k8s_foo_bar.new.test_12345678_1111"},
|
||||||
ID: "1234",
|
ID: "1234",
|
||||||
},
|
},
|
||||||
"9876": &docker.APIContainers{
|
"9876": &docker.APIContainers{
|
||||||
// network container
|
// network container
|
||||||
Names: []string{"/k8s_net_bar.new.test_"},
|
Names: []string{"/k8s_net_bar.new.test_12345678_2222"},
|
||||||
ID: "9876",
|
ID: "9876",
|
||||||
},
|
},
|
||||||
"4567": &docker.APIContainers{
|
"4567": &docker.APIContainers{
|
||||||
// Duplicate for the same container.
|
// Duplicate for the same container.
|
||||||
Names: []string{"/k8s_foo_bar.new.test_2"},
|
Names: []string{"/k8s_foo_bar.new.test_12345678_3333"},
|
||||||
ID: "4567",
|
ID: "4567",
|
||||||
},
|
},
|
||||||
"2304": &docker.APIContainers{
|
"2304": &docker.APIContainers{
|
||||||
// Container for another pod, untouched.
|
// Container for another pod, untouched.
|
||||||
Names: []string{"/k8s_baz_fiz.new.test_6"},
|
Names: []string{"/k8s_baz_fiz.new.test_6_42"},
|
||||||
ID: "2304",
|
ID: "2304",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
err := kubelet.syncPod(&api.BoundPod{
|
err := kubelet.syncPod(&api.BoundPod{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
UID: "12345678",
|
||||||
Name: "bar",
|
Name: "bar",
|
||||||
Namespace: "new",
|
Namespace: "new",
|
||||||
Annotations: map[string]string{ConfigSourceAnnotationKey: "test"},
|
Annotations: map[string]string{ConfigSourceAnnotationKey: "test"},
|
||||||
|
@ -732,7 +739,7 @@ func TestSyncPodDeletesDuplicate(t *testing.T) {
|
||||||
verifyCalls(t, fakeDocker, []string{"list", "stop"})
|
verifyCalls(t, fakeDocker, []string{"list", "stop"})
|
||||||
|
|
||||||
// Expect one of the duplicates to be killed.
|
// Expect one of the duplicates to be killed.
|
||||||
if len(fakeDocker.Stopped) != 1 || (len(fakeDocker.Stopped) != 0 && fakeDocker.Stopped[0] != "1234" && fakeDocker.Stopped[0] != "4567") {
|
if len(fakeDocker.Stopped) != 1 || (fakeDocker.Stopped[0] != "1234" && fakeDocker.Stopped[0] != "4567") {
|
||||||
t.Errorf("Wrong containers were stopped: %v", fakeDocker.Stopped)
|
t.Errorf("Wrong containers were stopped: %v", fakeDocker.Stopped)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -753,17 +760,18 @@ func TestSyncPodBadHash(t *testing.T) {
|
||||||
dockerContainers := dockertools.DockerContainers{
|
dockerContainers := dockertools.DockerContainers{
|
||||||
"1234": &docker.APIContainers{
|
"1234": &docker.APIContainers{
|
||||||
// the k8s prefix is required for the kubelet to manage the container
|
// the k8s prefix is required for the kubelet to manage the container
|
||||||
Names: []string{"/k8s_bar.1234_foo.new.test"},
|
Names: []string{"/k8s_bar.1234_foo.new.test_12345678_42"},
|
||||||
ID: "1234",
|
ID: "1234",
|
||||||
},
|
},
|
||||||
"9876": &docker.APIContainers{
|
"9876": &docker.APIContainers{
|
||||||
// network container
|
// network container
|
||||||
Names: []string{"/k8s_net_foo.new.test_"},
|
Names: []string{"/k8s_net_foo.new.test_12345678_42"},
|
||||||
ID: "9876",
|
ID: "9876",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
err := kubelet.syncPod(&api.BoundPod{
|
err := kubelet.syncPod(&api.BoundPod{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
UID: "12345678",
|
||||||
Name: "foo",
|
Name: "foo",
|
||||||
Namespace: "new",
|
Namespace: "new",
|
||||||
Annotations: map[string]string{ConfigSourceAnnotationKey: "test"},
|
Annotations: map[string]string{ConfigSourceAnnotationKey: "test"},
|
||||||
|
@ -799,17 +807,18 @@ func TestSyncPodUnhealthy(t *testing.T) {
|
||||||
dockerContainers := dockertools.DockerContainers{
|
dockerContainers := dockertools.DockerContainers{
|
||||||
"1234": &docker.APIContainers{
|
"1234": &docker.APIContainers{
|
||||||
// the k8s prefix is required for the kubelet to manage the container
|
// the k8s prefix is required for the kubelet to manage the container
|
||||||
Names: []string{"/k8s_bar_foo.new.test"},
|
Names: []string{"/k8s_bar_foo.new.test_12345678_42"},
|
||||||
ID: "1234",
|
ID: "1234",
|
||||||
},
|
},
|
||||||
"9876": &docker.APIContainers{
|
"9876": &docker.APIContainers{
|
||||||
// network container
|
// network container
|
||||||
Names: []string{"/k8s_net_foo.new.test_"},
|
Names: []string{"/k8s_net_foo.new.test_12345678_42"},
|
||||||
ID: "9876",
|
ID: "9876",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
err := kubelet.syncPod(&api.BoundPod{
|
err := kubelet.syncPod(&api.BoundPod{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
UID: "12345678",
|
||||||
Name: "foo",
|
Name: "foo",
|
||||||
Namespace: "new",
|
Namespace: "new",
|
||||||
Annotations: map[string]string{ConfigSourceAnnotationKey: "test"},
|
Annotations: map[string]string{ConfigSourceAnnotationKey: "test"},
|
||||||
|
@ -872,6 +881,7 @@ func TestMountExternalVolumes(t *testing.T) {
|
||||||
kubelet, _, _ := newTestKubelet(t)
|
kubelet, _, _ := newTestKubelet(t)
|
||||||
pod := api.BoundPod{
|
pod := api.BoundPod{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
UID: "12345678",
|
||||||
Name: "foo",
|
Name: "foo",
|
||||||
Namespace: "test",
|
Namespace: "test",
|
||||||
},
|
},
|
||||||
|
@ -927,6 +937,7 @@ func TestMakeVolumesAndBinds(t *testing.T) {
|
||||||
|
|
||||||
pod := api.BoundPod{
|
pod := api.BoundPod{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
UID: "12345678",
|
||||||
Name: "pod",
|
Name: "pod",
|
||||||
Namespace: "test",
|
Namespace: "test",
|
||||||
},
|
},
|
||||||
|
@ -1124,7 +1135,7 @@ func TestGetContainerInfo(t *testing.T) {
|
||||||
ID: containerID,
|
ID: containerID,
|
||||||
// pod id: qux
|
// pod id: qux
|
||||||
// container id: foo
|
// container id: foo
|
||||||
Names: []string{"/k8s_foo_qux_1234"},
|
Names: []string{"/k8s_foo_qux_1234_42"},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1279,7 +1290,7 @@ func TestRunInContainer(t *testing.T) {
|
||||||
fakeDocker.ContainerList = []docker.APIContainers{
|
fakeDocker.ContainerList = []docker.APIContainers{
|
||||||
{
|
{
|
||||||
ID: containerID,
|
ID: containerID,
|
||||||
Names: []string{"/k8s_" + containerName + "_" + podName + "." + podNamespace + ".test_1234"},
|
Names: []string{"/k8s_" + containerName + "_" + podName + "." + podNamespace + ".test_12345678_42"},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1287,6 +1298,7 @@ func TestRunInContainer(t *testing.T) {
|
||||||
_, err := kubelet.RunInContainer(
|
_, err := kubelet.RunInContainer(
|
||||||
GetPodFullName(&api.BoundPod{
|
GetPodFullName(&api.BoundPod{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
UID: "12345678",
|
||||||
Name: podName,
|
Name: podName,
|
||||||
Namespace: podNamespace,
|
Namespace: podNamespace,
|
||||||
Annotations: map[string]string{ConfigSourceAnnotationKey: "test"},
|
Annotations: map[string]string{ConfigSourceAnnotationKey: "test"},
|
||||||
|
@ -1319,7 +1331,7 @@ func TestRunHandlerExec(t *testing.T) {
|
||||||
fakeDocker.ContainerList = []docker.APIContainers{
|
fakeDocker.ContainerList = []docker.APIContainers{
|
||||||
{
|
{
|
||||||
ID: containerID,
|
ID: containerID,
|
||||||
Names: []string{"/k8s_" + containerName + "_" + podName + "." + podNamespace + "_1234"},
|
Names: []string{"/k8s_" + containerName + "_" + podName + "." + podNamespace + "_12345678_42"},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1423,12 +1435,13 @@ func TestSyncPodEventHandlerFails(t *testing.T) {
|
||||||
dockerContainers := dockertools.DockerContainers{
|
dockerContainers := dockertools.DockerContainers{
|
||||||
"9876": &docker.APIContainers{
|
"9876": &docker.APIContainers{
|
||||||
// network container
|
// network container
|
||||||
Names: []string{"/k8s_net_foo.new.test_"},
|
Names: []string{"/k8s_net_foo.new.test_12345678_42"},
|
||||||
ID: "9876",
|
ID: "9876",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
err := kubelet.syncPod(&api.BoundPod{
|
err := kubelet.syncPod(&api.BoundPod{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
UID: "12345678",
|
||||||
Name: "foo",
|
Name: "foo",
|
||||||
Namespace: "new",
|
Namespace: "new",
|
||||||
Annotations: map[string]string{ConfigSourceAnnotationKey: "test"},
|
Annotations: map[string]string{ConfigSourceAnnotationKey: "test"},
|
||||||
|
@ -1470,32 +1483,32 @@ func TestKubeletGarbageCollection(t *testing.T) {
|
||||||
containers: []docker.APIContainers{
|
containers: []docker.APIContainers{
|
||||||
{
|
{
|
||||||
// network container
|
// network container
|
||||||
Names: []string{"/k8s_net_foo.new.test_.deadbeef"},
|
Names: []string{"/k8s_net_foo.new.test_.deadbeef_42"},
|
||||||
ID: "1876",
|
ID: "1876",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// network container
|
// network container
|
||||||
Names: []string{"/k8s_net_foo.new.test_.deadbeef"},
|
Names: []string{"/k8s_net_foo.new.test_.deadbeef_42"},
|
||||||
ID: "2876",
|
ID: "2876",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// network container
|
// network container
|
||||||
Names: []string{"/k8s_net_foo.new.test_.deadbeef"},
|
Names: []string{"/k8s_net_foo.new.test_.deadbeef_42"},
|
||||||
ID: "3876",
|
ID: "3876",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// network container
|
// network container
|
||||||
Names: []string{"/k8s_net_foo.new.test_.deadbeef"},
|
Names: []string{"/k8s_net_foo.new.test_.deadbeef_42"},
|
||||||
ID: "4876",
|
ID: "4876",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// network container
|
// network container
|
||||||
Names: []string{"/k8s_net_foo.new.test_.deadbeef"},
|
Names: []string{"/k8s_net_foo.new.test_.deadbeef_42"},
|
||||||
ID: "5876",
|
ID: "5876",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// network container
|
// network container
|
||||||
Names: []string{"/k8s_net_foo.new.test_.deadbeef"},
|
Names: []string{"/k8s_net_foo.new.test_.deadbeef_42"},
|
||||||
ID: "6876",
|
ID: "6876",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -1514,37 +1527,37 @@ func TestKubeletGarbageCollection(t *testing.T) {
|
||||||
containers: []docker.APIContainers{
|
containers: []docker.APIContainers{
|
||||||
{
|
{
|
||||||
// network container
|
// network container
|
||||||
Names: []string{"/k8s_net_foo.new.test_.deadbeef"},
|
Names: []string{"/k8s_net_foo.new.test_.deadbeef_42"},
|
||||||
ID: "1876",
|
ID: "1876",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// network container
|
// network container
|
||||||
Names: []string{"/k8s_net_foo.new.test_.deadbeef"},
|
Names: []string{"/k8s_net_foo.new.test_.deadbeef_42"},
|
||||||
ID: "2876",
|
ID: "2876",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// network container
|
// network container
|
||||||
Names: []string{"/k8s_net_foo.new.test_.deadbeef"},
|
Names: []string{"/k8s_net_foo.new.test_.deadbeef_42"},
|
||||||
ID: "3876",
|
ID: "3876",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// network container
|
// network container
|
||||||
Names: []string{"/k8s_net_foo.new.test_.deadbeef"},
|
Names: []string{"/k8s_net_foo.new.test_.deadbeef_42"},
|
||||||
ID: "4876",
|
ID: "4876",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// network container
|
// network container
|
||||||
Names: []string{"/k8s_net_foo.new.test_.deadbeef"},
|
Names: []string{"/k8s_net_foo.new.test_.deadbeef_42"},
|
||||||
ID: "5876",
|
ID: "5876",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// network container
|
// network container
|
||||||
Names: []string{"/k8s_net_foo.new.test_.deadbeef"},
|
Names: []string{"/k8s_net_foo.new.test_.deadbeef_42"},
|
||||||
ID: "6876",
|
ID: "6876",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// network container
|
// network container
|
||||||
Names: []string{"/k8s_net_foo.new.test_.deadbeef"},
|
Names: []string{"/k8s_net_foo.new.test_.deadbeef_42"},
|
||||||
ID: "7876",
|
ID: "7876",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -1570,7 +1583,7 @@ func TestKubeletGarbageCollection(t *testing.T) {
|
||||||
containers: []docker.APIContainers{
|
containers: []docker.APIContainers{
|
||||||
{
|
{
|
||||||
// network container
|
// network container
|
||||||
Names: []string{"/k8s_net_foo.new.test_.deadbeef"},
|
Names: []string{"/k8s_net_foo.new.test_.deadbeef_42"},
|
||||||
ID: "1876",
|
ID: "1876",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -1763,6 +1776,7 @@ func TestSyncPodsWithPullPolicy(t *testing.T) {
|
||||||
err := kubelet.SyncPods([]api.BoundPod{
|
err := kubelet.SyncPods([]api.BoundPod{
|
||||||
{
|
{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
UID: "12345678",
|
||||||
Name: "foo",
|
Name: "foo",
|
||||||
Namespace: "new",
|
Namespace: "new",
|
||||||
Annotations: map[string]string{ConfigSourceAnnotationKey: "test"},
|
Annotations: map[string]string{ConfigSourceAnnotationKey: "test"},
|
||||||
|
|
|
@ -69,12 +69,12 @@ func TestRunOnce(t *testing.T) {
|
||||||
kb := &Kubelet{}
|
kb := &Kubelet{}
|
||||||
podContainers := []docker.APIContainers{
|
podContainers := []docker.APIContainers{
|
||||||
{
|
{
|
||||||
Names: []string{"/k8s_bar." + strconv.FormatUint(dockertools.HashContainer(&api.Container{Name: "bar"}), 16) + "_foo.new.test"},
|
Names: []string{"/k8s_bar." + strconv.FormatUint(dockertools.HashContainer(&api.Container{Name: "bar"}), 16) + "_foo.new.test_12345678_42"},
|
||||||
ID: "1234",
|
ID: "1234",
|
||||||
Status: "running",
|
Status: "running",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Names: []string{"/k8s_net_foo.new.test_"},
|
Names: []string{"/k8s_net_foo.new.test_abcdefgh_42"},
|
||||||
ID: "9876",
|
ID: "9876",
|
||||||
Status: "running",
|
Status: "running",
|
||||||
},
|
},
|
||||||
|
@ -109,6 +109,7 @@ func TestRunOnce(t *testing.T) {
|
||||||
results, err := kb.runOnce([]api.BoundPod{
|
results, err := kb.runOnce([]api.BoundPod{
|
||||||
{
|
{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
UID: "12345678",
|
||||||
Name: "foo",
|
Name: "foo",
|
||||||
Namespace: "new",
|
Namespace: "new",
|
||||||
Annotations: map[string]string{ConfigSourceAnnotationKey: "test"},
|
Annotations: map[string]string{ConfigSourceAnnotationKey: "test"},
|
||||||
|
|
|
@ -22,7 +22,7 @@ import (
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
const ConfigSourceAnnotationKey = "kubernetes/config.source"
|
const ConfigSourceAnnotationKey = "kubernetes.io/config.source"
|
||||||
|
|
||||||
// PodOperation defines what changes will be made on a pod configuration.
|
// PodOperation defines what changes will be made on a pod configuration.
|
||||||
type PodOperation int
|
type PodOperation int
|
||||||
|
|
Loading…
Reference in New Issue