func TestUpdatePods(t *testing.T) { fakeWatch := watch.NewFake() client := &testclient.Fake{} client.AddWatchReactor("*", testclient.DefaultWatchReactor(fakeWatch, nil)) manager := NewReplicationManager(client, controller.NoResyncPeriodFunc, BurstReplicas) manager.podStoreSynced = alwaysReady received := make(chan string) manager.syncHandler = func(key string) error { obj, exists, err := manager.rcStore.Store.GetByKey(key) if !exists || err != nil { t.Errorf("Expected to find controller under key %v", key) } received <- obj.(*api.ReplicationController).Name return nil } stopCh := make(chan struct{}) defer close(stopCh) go util.Until(manager.worker, 10*time.Millisecond, stopCh) // Put 2 rcs and one pod into the controller's stores testControllerSpec1 := newReplicationController(1) manager.rcStore.Store.Add(testControllerSpec1) testControllerSpec2 := *testControllerSpec1 testControllerSpec2.Spec.Selector = map[string]string{"bar": "foo"} testControllerSpec2.Name = "barfoo" manager.rcStore.Store.Add(&testControllerSpec2) // Put one pod in the podStore pod1 := newPodList(manager.podStore.Store, 1, api.PodRunning, testControllerSpec1).Items[0] pod2 := pod1 pod2.Labels = testControllerSpec2.Spec.Selector // Send an update of the same pod with modified labels, and confirm we get a sync request for // both controllers manager.updatePod(&pod1, &pod2) expected := sets.NewString(testControllerSpec1.Name, testControllerSpec2.Name) for _, name := range expected.List() { t.Logf("Expecting update for %+v", name) select { case got := <-received: if !expected.Has(got) { t.Errorf("Expected keys %#v got %v", expected, got) } case <-time.After(util.ForeverTestTimeout): t.Errorf("Expected update notifications for controllers within 100ms each") } } }
func TestWatchPods(t *testing.T) { fakeWatch := watch.NewFake() client := &testclient.Fake{} client.AddWatchReactor("*", testclient.DefaultWatchReactor(fakeWatch, nil)) manager := NewJobController(client, controller.NoResyncPeriodFunc) manager.podStoreSynced = alwaysReady // Put one job and one pod into the store testJob := newJob(2, 2) manager.jobStore.Store.Add(testJob) received := make(chan string) // The pod update sent through the fakeWatcher should figure out the managing job and // send it into the syncHandler. manager.syncHandler = func(key string) error { obj, exists, err := manager.jobStore.Store.GetByKey(key) if !exists || err != nil { t.Errorf("Expected to find job under key %v", key) } job := obj.(*extensions.Job) if !api.Semantic.DeepDerivative(job, testJob) { t.Errorf("\nExpected %#v,\nbut got %#v", testJob, job) } close(received) return nil } // Start only the pod watcher and the workqueue, send a watch event, // and make sure it hits the sync method for the right job. stopCh := make(chan struct{}) defer close(stopCh) go manager.podController.Run(stopCh) go util.Until(manager.worker, 10*time.Millisecond, stopCh) pods := newPodList(1, api.PodRunning, testJob) testPod := pods[0] testPod.Status.Phase = api.PodFailed fakeWatch.Add(&testPod) select { case <-received: case <-time.After(controllerTimeout): t.Errorf("Expected 1 call but got 0") } }
func TestWatchControllers(t *testing.T) { fakeWatch := watch.NewFake() client := &testclient.Fake{} client.AddWatchReactor("*", testclient.DefaultWatchReactor(fakeWatch, nil)) manager := NewReplicationManager(client, controller.NoResyncPeriodFunc, BurstReplicas) manager.podStoreSynced = alwaysReady var testControllerSpec api.ReplicationController received := make(chan string) // The update sent through the fakeWatcher should make its way into the workqueue, // and eventually into the syncHandler. The handler validates the received controller // and closes the received channel to indicate that the test can finish. manager.syncHandler = func(key string) error { obj, exists, err := manager.rcStore.Store.GetByKey(key) if !exists || err != nil { t.Errorf("Expected to find controller under key %v", key) } controllerSpec := *obj.(*api.ReplicationController) if !api.Semantic.DeepDerivative(controllerSpec, testControllerSpec) { t.Errorf("Expected %#v, but got %#v", testControllerSpec, controllerSpec) } close(received) return nil } // Start only the rc watcher and the workqueue, send a watch event, // and make sure it hits the sync method. stopCh := make(chan struct{}) defer close(stopCh) go manager.rcController.Run(stopCh) go util.Until(manager.worker, 10*time.Millisecond, stopCh) testControllerSpec.Name = "foo" fakeWatch.Add(&testControllerSpec) select { case <-received: case <-time.After(util.ForeverTestTimeout): t.Errorf("Expected 1 call but got 0") } }
// TestAdmission func TestAdmission(t *testing.T) { namespaceObj := &api.Namespace{ ObjectMeta: api.ObjectMeta{ Name: "test", Namespace: "", }, Status: api.NamespaceStatus{ Phase: api.NamespaceActive, }, } var namespaceLock sync.RWMutex store := cache.NewStore(cache.MetaNamespaceKeyFunc) store.Add(namespaceObj) fakeWatch := watch.NewFake() mockClient := &testclient.Fake{} mockClient.AddWatchReactor("*", testclient.DefaultWatchReactor(fakeWatch, nil)) mockClient.AddReactor("get", "namespaces", func(action testclient.Action) (bool, runtime.Object, error) { namespaceLock.RLock() defer namespaceLock.RUnlock() if getAction, ok := action.(testclient.GetAction); ok && getAction.GetName() == namespaceObj.Name { return true, namespaceObj, nil } return true, nil, fmt.Errorf("No result for action %v", action) }) mockClient.AddReactor("list", "namespaces", func(action testclient.Action) (bool, runtime.Object, error) { namespaceLock.RLock() defer namespaceLock.RUnlock() return true, &api.NamespaceList{Items: []api.Namespace{*namespaceObj}}, nil }) lfhandler := NewLifecycle(mockClient).(*lifecycle) lfhandler.store = store handler := admission.NewChainHandler(lfhandler) pod := api.Pod{ ObjectMeta: api.ObjectMeta{Name: "123", Namespace: namespaceObj.Name}, Spec: api.PodSpec{ Volumes: []api.Volume{{Name: "vol"}}, Containers: []api.Container{{Name: "ctr", Image: "image"}}, }, } badPod := api.Pod{ ObjectMeta: api.ObjectMeta{Name: "456", Namespace: "doesnotexist"}, Spec: api.PodSpec{ Volumes: []api.Volume{{Name: "vol"}}, Containers: []api.Container{{Name: "ctr", Image: "image"}}, }, } err := handler.Admit(admission.NewAttributesRecord(&pod, "Pod", pod.Namespace, pod.Name, "pods", "", admission.Create, nil)) if err != nil { t.Errorf("Unexpected error returned from admission handler: %v", err) } // change namespace state to terminating namespaceLock.Lock() namespaceObj.Status.Phase = api.NamespaceTerminating namespaceLock.Unlock() store.Add(namespaceObj) // verify create operations in the namespace cause an error err = handler.Admit(admission.NewAttributesRecord(&pod, "Pod", pod.Namespace, pod.Name, "pods", "", admission.Create, nil)) if err == nil { t.Errorf("Expected error rejecting creates in a namespace when it is terminating") } // verify update operations in the namespace can proceed err = handler.Admit(admission.NewAttributesRecord(&pod, "Pod", pod.Namespace, pod.Name, "pods", "", admission.Update, nil)) if err != nil { t.Errorf("Unexpected error returned from admission handler: %v", err) } // verify delete operations in the namespace can proceed err = handler.Admit(admission.NewAttributesRecord(nil, "Pod", pod.Namespace, pod.Name, "pods", "", admission.Delete, nil)) if err != nil { t.Errorf("Unexpected error returned from admission handler: %v", err) } // verify delete of namespace default can never proceed err = handler.Admit(admission.NewAttributesRecord(nil, "Namespace", "", api.NamespaceDefault, "namespaces", "", admission.Delete, nil)) if err == nil { t.Errorf("Expected an error that this namespace can never be deleted") } // verify delete of namespace other than default can proceed err = handler.Admit(admission.NewAttributesRecord(nil, "Namespace", "", "other", "namespaces", "", admission.Delete, nil)) if err != nil { t.Errorf("Did not expect an error %v", err) } // verify create/update/delete of object in non-existant namespace throws error err = handler.Admit(admission.NewAttributesRecord(&badPod, "Pod", badPod.Namespace, badPod.Name, "pods", "", admission.Create, nil)) if err == nil { t.Errorf("Expected an aerror that objects cannot be created in non-existant namespaces", err) } err = handler.Admit(admission.NewAttributesRecord(&badPod, "Pod", badPod.Namespace, badPod.Name, "pods", "", admission.Update, nil)) if err == nil { t.Errorf("Expected an aerror that objects cannot be updated in non-existant namespaces", err) } err = handler.Admit(admission.NewAttributesRecord(&badPod, "Pod", badPod.Namespace, badPod.Name, "pods", "", admission.Delete, nil)) if err == nil { t.Errorf("Expected an aerror that objects cannot be deleted in non-existant namespaces", err) } }
func TestWatchJobs(t *testing.T) { fakeWatch := watch.NewFake() client := &testclient.Fake{} client.AddWatchReactor("*", testclient.DefaultWatchReactor(fakeWatch, nil)) manager := NewJobController(client, controller.NoResyncPeriodFunc) manager.podStoreSynced = alwaysReady var testJob extensions.Job received := make(chan string) // The update sent through the fakeWatcher should make its way into the workqueue, // and eventually into the syncHandler. manager.syncHandler = func(key string) error { obj, exists, err := manager.jobStore.Store.GetByKey(key) if !exists || err != nil { t.Errorf("Expected to find job under key %v", key) } job := *obj.(*extensions.Job) if !api.Semantic.DeepDerivative(job, testJob) { t.Errorf("Expected %#v, but got %#v", testJob, job) } received <- key return nil } // Start only the job watcher and the workqueue, send a watch event, // and make sure it hits the sync method. stopCh := make(chan struct{}) defer close(stopCh) go manager.jobController.Run(stopCh) go util.Until(manager.worker, 10*time.Millisecond, stopCh) // We're sending new job to see if it reaches syncHandler. testJob.Name = "foo" fakeWatch.Add(&testJob) select { case <-received: case <-time.After(controllerTimeout): t.Errorf("Expected 1 call but got 0") } // We're sending fake finished job, to see if it reaches syncHandler - it should not, // since we're filtering out finished jobs. testJobv2 := extensions.Job{ ObjectMeta: api.ObjectMeta{Name: "foo"}, Status: extensions.JobStatus{ Conditions: []extensions.JobCondition{{ Type: extensions.JobComplete, Status: api.ConditionTrue, LastProbeTime: unversioned.Now(), LastTransitionTime: unversioned.Now(), }}, }, } fakeWatch.Modify(&testJobv2) select { case <-received: t.Errorf("Expected 0 call but got 1") case <-time.After(controllerTimeout): } }