} wg.Wait() <del> // Expectations have been surpassed podExp, exists, err := e.GetExpectations(rcKey) assert.NoError(t, err, "Could not get expectations for rc, exists %v and err %v", exists, err) assert.True(t, exists, "Could not get expectations for rc, exists %v and err %v", exists, err) add, del := podExp.GetExpectations() assert.Equal(t, int64(-1), add, "Unexpected pod expectations %#v", podExp) assert.Equal(t, int64(-1), del, "Unexpected pod expectations %#v", podExp) assert.True(t, e.SatisfiedExpectations(logger, rcKey), "Expectations are met but the rc will not sync") // Next round of rc sync, old expectations are cleared e.SetExpectations(logger, rcKey, 1, 2) podExp, exists, err = e.GetExpectations(rcKey) assert.NoError(t, err, "Could not get expectations for rc, exists %v and err %v", exists, err) assert.True(t, exists, "Could not get expectations for rc, exists %v and err %v", exists, err) add, del = podExp.GetExpectations() assert.Equal(t, int64(1), add, "Unexpected pod expectations %#v", podExp) assert.Equal(t, int64(2), del, "Unexpected pod expectations %#v", podExp) // Expectations have expired because of ttl fakeClock.Step(ttl + 1) assert.True(t, e.SatisfiedExpectations(logger, rcKey), "Expectations should have expired but didn't") </del> <ins> tests := []struct { name                      string expectationsToSet         []int expireExpectations        bool wantPodExpectations       []int64 wantExpectationsSatisfied bool }{ { name:                      "Expectations have been surpassed", expireExpectations:        false, wantPodExpectations:       []int64{int64(-1), int64(-1)}, wantExpectationsSatisfied: true, }, { name:                      "Old expectations are cleared because of ttl", expectationsToSet:         []int{1, 2}, expireExpectations:        true, wantPodExpectations:       []int64{int64(1), int64(2)}, wantExpectationsSatisfied: false, }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { if len(test.expectationsToSet) > 0 { e.SetExpectations(logger, rcKey, test.expectationsToSet[0], test.expectationsToSet[1]) } podExp, exists, err := e.GetExpectations(rcKey) assert.NoError(t, err, "Could not get expectations for rc, exists %v and err %v", exists, err) assert.True(t, exists, "Could not get expectations for rc, exists %v and err %v", exists, err) add, del := podExp.GetExpectations() assert.Equal(t, test.wantPodExpectations[0], add, "Unexpected pod expectations %#v", podExp) assert.Equal(t, test.wantPodExpectations[1], del, "Unexpected pod expectations %#v", podExp) assert.Equal(t, test.wantExpectationsSatisfied, e.SatisfiedExpectations(logger, rcKey), "Expectations are met but the rc will not sync") if test.expireExpectations { fakeClock.Step(ttl + 1) assert.True(t, e.SatisfiedExpectations(logger, rcKey), "Expectations should have expired but didn't") } }) } </ins> } func TestUIDExpectations(t *testing.T) { logger, _ := ktesting.NewTestContext(t) uidExp := NewUIDTrackingControllerExpectations(NewControllerExpectations()) <del> rcList := []*v1.ReplicationController{ newReplicationController(2), newReplicationController(1), newReplicationController(0), newReplicationController(5), </del> <ins> type test struct { name        string numReplicas int } shuffleTests := func(tests []test) { for i := range tests { j := rand.Intn(i + 1) tests[i], tests[j] = tests[j], tests[i] } </ins> } <del> rcToPods := map[string][]string{} rcKeys := []string{} for i := range rcList { rc := rcList[i] rcName := fmt.Sprintf("rc-%v", i) </del> <ins> getRcDataFrom := func(test test) (string, []string) { rc := newReplicationController(test.numReplicas) rcName := fmt.Sprintf("rc-%v", test.numReplicas) </ins> rc.Name = rcName rc.Spec.Selector[rcName] = rcName podList := newPodList(nil, 5, v1.PodRunning, rc) rcKey, err := KeyFunc(rc) if err != nil { t.Fatalf("Couldn't get key for object %#v: %v", rc, err) } <del> rcKeys = append(rcKeys, rcKey) </del> rcPodNames := []string{} for i := range podList.Items { p := &podList.Items[i] p.Name = fmt.Sprintf("%v-%v", p.Name, rc.Name) rcPodNames = append(rcPodNames, PodKey(p)) } <del> rcToPods[rcKey] = rcPodNames </del> uidExp.ExpectDeletions(logger, rcKey, rcPodNames) <ins> return rcKey, rcPodNames </ins> } <del> for i := range rcKeys { j := rand.Intn(i + 1) rcKeys[i], rcKeys[j] = rcKeys[j], rcKeys[i] </del> <ins> tests := []test{ {name: "Replication controller with 2 replicas", numReplicas: 2}, {name: "Replication controller with 1 replica", numReplicas: 1}, {name: "Replication controller with no replicas", numReplicas: 0}, {name: "Replication controller with 5 replicas", numReplicas: 5}, </ins> } <del> for _, rcKey := range rcKeys { assert.False(t, uidExp.SatisfiedExpectations(logger, rcKey), "Controller %v satisfied expectations before deletion", rcKey) for _, p := range rcToPods[rcKey] { uidExp.DeletionObserved(logger, rcKey, p) } </del> <ins> shuffleTests(tests) for _, test := range tests { t.Run(test.name, func(t *testing.T) { </ins> <del> assert.True(t, uidExp.SatisfiedExpectations(logger, rcKey), "Controller %v didn't satisfy expectations after deletion", rcKey) </del> <ins> rcKey, rcPodNames := getRcDataFrom(test) assert.False(t, uidExp.SatisfiedExpectations(logger, rcKey), "Controller %v satisfied expectations before deletion", rcKey) </ins> <del> uidExp.DeleteExpectations(logger, rcKey) </del> <ins> for _, p := range rcPodNames { uidExp.DeletionObserved(logger, rcKey, p) } </ins> <del> assert.Nil(t, uidExp.GetUIDs(rcKey), "Failed to delete uid expectations for %v", rcKey) } } </del> <ins> assert.True(t, uidExp.SatisfiedExpectations(logger, rcKey), "Controller %v didn't satisfy expectations after deletion", rcKey) </ins> <del> func TestCreatePods(t *testing.T) { ns := metav1.NamespaceDefault body := runtime.EncodeOrDie(clientscheme.Codecs.LegacyCodec(v1.SchemeGroupVersion), &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "empty_pod"}}) fakeHandler := utiltesting.FakeHandler{ StatusCode:   200, ResponseBody: string(body), } testServer := httptest.NewServer(&fakeHandler) defer testServer.Close() clientset := clientset.NewForConfigOrDie(&restclient.Config{Host: testServer.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) </del> <ins> uidExp.DeleteExpectations(logger, rcKey) </ins> <del> podControl := RealPodControl{ KubeClient: clientset, Recorder:   &record.FakeRecorder{}, </del> <ins> assert.Nil(t, uidExp.GetUIDs(rcKey), "Failed to delete uid expectations for %v", rcKey) }) </ins> } <ins> } func TestCreatePodsWithGenerateName(t *testing.T) { ns := metav1.NamespaceDefault generateName := "hello-" </ins> controllerSpec := newReplicationController(1) controllerRef := metav1.NewControllerRef(controllerSpec, v1.SchemeGroupVersion.WithKind("ReplicationController")) <del> // Make sure createReplica sends a POST to the apiserver with a pod from the controllers pod template err := podControl.CreatePods(context.TODO(), ns, controllerSpec.Spec.Template, controllerSpec, controllerRef) assert.NoError(t, err, "unexpected error: %v", err) expectedPod := v1.Pod{ ObjectMeta: metav1.ObjectMeta{ Labels:       controllerSpec.Spec.Template.Labels, GenerateName: fmt.Sprintf("%s-", controllerSpec.Name), }, Spec: controllerSpec.Spec.Template.Spec, </del> <ins> type test struct { name            string podCreationFunc func(podControl RealPodControl) error wantPod         *v1.Pod </ins> } <del> fakeHandler.ValidateRequest(t, "/api/v1/namespaces/default/pods", "POST", nil) var actualPod = &v1.Pod{} err = json.Unmarshal([]byte(fakeHandler.RequestBody), actualPod) assert.NoError(t, err, "unexpected error: %v", err) assert.True(t, apiequality.Semantic.DeepDerivative(&expectedPod, actualPod), "Body: %s", fakeHandler.RequestBody) } func TestCreatePodsWithGenerateName(t *testing.T) { ns := metav1.NamespaceDefault body := runtime.EncodeOrDie(clientscheme.Codecs.LegacyCodec(v1.SchemeGroupVersion), &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "empty_pod"}}) fakeHandler := utiltesting.FakeHandler{ StatusCode:   200, ResponseBody: string(body), </del> <ins> var tests = []test{ { name: "Create pod", podCreationFunc: func(podControl RealPodControl) error { return podControl.CreatePods(context.TODO(), ns, controllerSpec.Spec.Template, controllerSpec, controllerRef) }, wantPod: &v1.Pod{ ObjectMeta: metav1.ObjectMeta{ Labels:       controllerSpec.Spec.Template.Labels, GenerateName: fmt.Sprintf("%s-", controllerSpec.Name), }, Spec: controllerSpec.Spec.Template.Spec, }, }, { name: "Create pod with generate name", podCreationFunc: func(podControl RealPodControl) error { // Make sure createReplica sends a POST to the apiserver with a pod from the controllers pod template return podControl.CreatePodsWithGenerateName(context.TODO(), ns, controllerSpec.Spec.Template, controllerSpec, controllerRef, generateName) }, wantPod: &v1.Pod{ ObjectMeta: metav1.ObjectMeta{ Labels:          controllerSpec.Spec.Template.Labels, GenerateName:    generateName, OwnerReferences: []metav1.OwnerReference{*controllerRef}, }, Spec: controllerSpec.Spec.Template.Spec, }, }, </ins> } <del> testServer := httptest.NewServer(&fakeHandler) defer testServer.Close() clientset := clientset.NewForConfigOrDie(&restclient.Config{Host: testServer.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) podControl := RealPodControl{ KubeClient: clientset, Recorder:   &record.FakeRecorder{}, } </del> <ins> for _, test := range tests { t.Run(test.name, func(t *testing.T) { body := runtime.EncodeOrDie(clientscheme.Codecs.LegacyCodec(v1.SchemeGroupVersion), &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "empty_pod"}}) fakeHandler := utiltesting.FakeHandler{ StatusCode:   200, ResponseBody: string(body), } testServer := httptest.NewServer(&fakeHandler) defer testServer.Close() clientset := clientset.NewForConfigOrDie(&restclient.Config{Host: testServer.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}) </ins> <del> controllerSpec := newReplicationController(1) controllerRef := metav1.NewControllerRef(controllerSpec, v1.SchemeGroupVersion.WithKind("ReplicationController")) </del> <ins> podControl := RealPodControl{ KubeClient: clientset, Recorder:   &record.FakeRecorder{}, } </ins> <del> // Make sure createReplica sends a POST to the apiserver with a pod from the controllers pod template generateName := "hello-" err := podControl.CreatePodsWithGenerateName(context.TODO(), ns, controllerSpec.Spec.Template, controllerSpec, controllerRef, generateName) assert.NoError(t, err, "unexpected error: %v", err) </del> <ins> err := test.podCreationFunc(podControl) assert.NoError(t, err, "unexpected error: %v", err) </ins> <del> expectedPod := v1.Pod{ ObjectMeta: metav1.ObjectMeta{ Labels:          controllerSpec.Spec.Template.Labels, GenerateName:    generateName, OwnerReferences: []metav1.OwnerReference{*controllerRef}, }, Spec: controllerSpec.Spec.Template.Spec, </del> <ins> fakeHandler.ValidateRequest(t, "/api/v1/namespaces/default/pods", "POST", nil) var actualPod = &v1.Pod{} err = json.Unmarshal([]byte(fakeHandler.RequestBody), actualPod) assert.NoError(t, err, "unexpected error: %v", err) assert.True(t, apiequality.Semantic.DeepDerivative(test.wantPod, actualPod), "Body: %s", fakeHandler.RequestBody) }) </ins> } <del> fakeHandler.ValidateRequest(t, "/api/v1/namespaces/default/pods", "POST", nil) var actualPod = &v1.Pod{} err = json.Unmarshal([]byte(fakeHandler.RequestBody), actualPod) assert.NoError(t, err, "unexpected error: %v", err) assert.True(t, apiequality.Semantic.DeepDerivative(&expectedPod, actualPod), "Body: %s", fakeHandler.RequestBody) </del> } func TestDeletePodsAllowsMissing(t *testing.T) {