func TestExtractFromDir(t *testing.T) { manifest, expectedPod := ExampleManifestAndPod("1") manifest2, expectedPod2 := ExampleManifestAndPod("2") manifests := []api.ContainerManifest{manifest, manifest2} pods := []api.BoundPod{expectedPod, expectedPod2} files := make([]*os.File, len(manifests)) dirName, err := ioutil.TempDir("", "foo") if err != nil { t.Fatalf("Unexpected error: %v", err) } for i, manifest := range manifests { data, err := json.Marshal(manifest) if err != nil { t.Errorf("Unexpected error: %v", err) continue } file, err := ioutil.TempFile(dirName, manifest.ID) if err != nil { t.Errorf("Unexpected error: %v", err) continue } name := file.Name() if err := file.Close(); err != nil { t.Errorf("Unexpected error: %v", err) continue } ioutil.WriteFile(name, data, 0755) files[i] = file } ch := make(chan interface{}, 1) c := sourceFile{dirName, ch} err = c.extractFromPath() if err != nil { t.Fatalf("Unexpected error: %v", err) } 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...) for i := range expected.Pods { expected.Pods[i].Namespace = "foobar" } sort.Sort(sortedPods(update.Pods)) sort.Sort(sortedPods(expected.Pods)) if !api.Semantic.DeepEqual(expected, update) { t.Fatalf("Expected %#v, Got %#v", expected, update) } 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) } } }
func filterInvalidPods(pods []api.BoundPod, source string) (filtered []*api.BoundPod) { names := util.StringSet{} for i := range pods { pod := &pods[i] var errlist []error if errs := validation.ValidateBoundPod(pod); len(errs) != 0 { errlist = append(errlist, errs...) // If validation fails, don't trust it any further - // even Name could be bad. } else { name := podUniqueName(pod) if names.Has(name) { errlist = append(errlist, apierrs.NewFieldDuplicate("name", pod.Name)) } else { names.Insert(name) } } if len(errlist) > 0 { name := bestPodIdentString(pod) err := utilerrors.NewAggregate(errlist) glog.Warningf("Pod[%d] (%s) from %s failed validation, ignoring: %v", i+1, name, source, err) record.Eventf(pod, "failedValidation", "Error validating pod %s from %s, ignoring: %v", name, source, err) continue } filtered = append(filtered, pod) } return }
func filterInvalidPods(pods []api.BoundPod, source string) (filtered []*api.BoundPod) { names := util.StringSet{} for i := range pods { var errors []error name := podUniqueName(&pods[i]) if names.Has(name) { errors = append(errors, apierrs.NewFieldDuplicate("name", pods[i].Name)) } else { names.Insert(name) } if errs := validation.ValidateBoundPod(&pods[i]); len(errs) != 0 { errors = append(errors, errs...) } if len(errors) > 0 { glog.Warningf("Pod %d (%s) from %s failed validation, ignoring: %v", i+1, pods[i].Name, source, errors) continue } filtered = append(filtered, &pods[i]) } return }
func TestExtractFromHTTP(t *testing.T) { var testCases = []struct { desc string manifests interface{} expected kubelet.PodUpdate }{ { desc: "Single manifest", manifests: api.ContainerManifest{Version: "v1beta1", ID: "foo"}, expected: CreatePodUpdate(kubelet.SET, api.BoundPod{ ObjectMeta: api.ObjectMeta{ Name: "foo", Namespace: "default", }, Spec: api.PodSpec{ RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}}, }, }), }, { desc: "Multiple manifests", manifests: []api.ContainerManifest{ {Version: "v1beta1", ID: "", Containers: []api.Container{{Name: "1", Image: "foo"}}}, {Version: "v1beta1", ID: "bar", Containers: []api.Container{{Name: "1", Image: "foo"}}}, }, expected: CreatePodUpdate(kubelet.SET, api.BoundPod{ ObjectMeta: api.ObjectMeta{ Name: "1", Namespace: "default", }, Spec: api.PodSpec{ Containers: []api.Container{{ Name: "1", Image: "foo", TerminationMessagePath: "/dev/termination-log"}}, }, }, api.BoundPod{ ObjectMeta: api.ObjectMeta{ Name: "bar", Namespace: "default", }, Spec: api.PodSpec{ Containers: []api.Container{{ Name: "1", Image: "foo", TerminationMessagePath: "/dev/termination-log"}}, }, }), }, { desc: "Empty Array", manifests: []api.ContainerManifest{}, expected: CreatePodUpdate(kubelet.SET), }, } for _, testCase := range testCases { data, err := json.Marshal(testCase.manifests) if err != nil { t.Fatalf("%s: Some weird json problem: %v", testCase.desc, err) } fakeHandler := util.FakeHandler{ StatusCode: 200, ResponseBody: string(data), } testServer := httptest.NewServer(&fakeHandler) defer testServer.Close() ch := make(chan interface{}, 1) c := sourceURL{testServer.URL, ch, nil} if err := c.extractFromURL(); err != nil { t.Errorf("%s: Unexpected error: %v", testCase.desc, err) continue } update := (<-ch).(kubelet.PodUpdate) if !reflect.DeepEqual(testCase.expected, update) { t.Errorf("%s: Expected: %#v, Got: %#v", testCase.desc, testCase.expected, update) } for i := range update.Pods { 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) } } } }
func TestExtractFromHTTP(t *testing.T) { var testCases = []struct { desc string manifests interface{} expected kubelet.PodUpdate }{ { desc: "Single manifest", manifests: v1beta1.ContainerManifest{Version: "v1beta1", ID: "foo", UUID: "111", Containers: []v1beta1.Container{{Name: "1", Image: "foo", ImagePullPolicy: v1beta1.PullAlways}}}, expected: CreatePodUpdate(kubelet.SET, kubelet.HTTPSource, api.BoundPod{ ObjectMeta: api.ObjectMeta{ UID: "111", Name: "foo", Namespace: "foobar", }, Spec: api.PodSpec{ RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}}, DNSPolicy: api.DNSClusterFirst, Containers: []api.Container{{ Name: "1", Image: "foo", TerminationMessagePath: "/dev/termination-log", ImagePullPolicy: "Always"}}, }, }), }, { desc: "Single manifest without ID", manifests: api.ContainerManifest{Version: "v1beta1", UUID: "111"}, expected: CreatePodUpdate(kubelet.SET, kubelet.HTTPSource, api.BoundPod{ ObjectMeta: api.ObjectMeta{ UID: "111", Name: "111", Namespace: "foobar", }, Spec: api.PodSpec{ RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}}, DNSPolicy: api.DNSClusterFirst, }, }), }, { desc: "Single manifest with v1beta2", manifests: v1beta1.ContainerManifest{Version: "v1beta2", ID: "foo", UUID: "111", Containers: []v1beta1.Container{{Name: "1", Image: "foo", ImagePullPolicy: v1beta1.PullAlways}}}, expected: CreatePodUpdate(kubelet.SET, kubelet.HTTPSource, api.BoundPod{ ObjectMeta: api.ObjectMeta{ UID: "111", Name: "foo", Namespace: "foobar", }, Spec: api.PodSpec{ RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}}, DNSPolicy: api.DNSClusterFirst, Containers: []api.Container{{ Name: "1", Image: "foo", TerminationMessagePath: "/dev/termination-log", ImagePullPolicy: "Always"}}, }, }), }, { desc: "Multiple manifests", manifests: []v1beta1.ContainerManifest{ {Version: "v1beta1", ID: "foo", UUID: "111", Containers: []v1beta1.Container{{Name: "1", Image: "foo", ImagePullPolicy: v1beta1.PullAlways}}}, {Version: "v1beta1", ID: "bar", UUID: "222", Containers: []v1beta1.Container{{Name: "1", Image: "foo", ImagePullPolicy: ""}}}, }, expected: CreatePodUpdate(kubelet.SET, kubelet.HTTPSource, api.BoundPod{ ObjectMeta: api.ObjectMeta{ UID: "111", Name: "foo", Namespace: "foobar", }, Spec: api.PodSpec{ RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}}, DNSPolicy: api.DNSClusterFirst, Containers: []api.Container{{ Name: "1", Image: "foo", TerminationMessagePath: "/dev/termination-log", ImagePullPolicy: "Always"}}, }, }, api.BoundPod{ ObjectMeta: api.ObjectMeta{ UID: "222", Name: "bar", Namespace: "foobar", }, Spec: api.PodSpec{ RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}}, DNSPolicy: api.DNSClusterFirst, Containers: []api.Container{{ Name: "1", Image: "foo", TerminationMessagePath: "/dev/termination-log", ImagePullPolicy: "PullIfNotPresent"}}, }, }), }, { desc: "Empty Array", manifests: []v1beta1.ContainerManifest{}, expected: CreatePodUpdate(kubelet.SET, kubelet.HTTPSource), }, } for _, testCase := range testCases { data, err := json.Marshal(testCase.manifests) if err != nil { t.Fatalf("%s: Some weird json problem: %v", testCase.desc, err) } fakeHandler := util.FakeHandler{ StatusCode: 200, ResponseBody: string(data), } testServer := httptest.NewServer(&fakeHandler) defer testServer.Close() ch := make(chan interface{}, 1) c := sourceURL{testServer.URL, ch, nil} if err := c.extractFromURL(); err != nil { t.Errorf("%s: Unexpected error: %v", testCase.desc, err) continue } 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) { t.Errorf("%s: Expected: %#v, Got: %#v", testCase.desc, testCase.expected, update) } for i := range update.Pods { 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], errors.NewAggregate(errs)) } } } }