Question:
During implementation of KEP 3393 (PodReplacementPolicy for Jobs) we found that the unit tests of do not follow common patterns established in k/k. 1) The tests are not written using table driven design (). 2) The tests use rather than . This probably should be done as two separate PRs but wanted to highlight some areas that could use some cleanup. Not using means that we don't see diffs in the unit tests that makes this difficult. And not using table driven tests makes it difficult to add new test cases as it usually is brought up during review that we should use a table-driven test but the entire file does not obey this format.
This issue is currently awaiting triage. If a SIG or subproject determines this is a relevant issue, they will accept it by applying the label and provide further guidance. The label can be by org members by writing in a comment. <detailsInstructions for interacting with me using PR comments are available . If you have questions or suggestions related to my behavior, please file an issue against the repository. </details
/sig apps /kind cleanup /help /good-first-issue
This request has been marked as suitable for new contributors. Please ensure that the issue body includes answers to the following questions: Why are we solving this issue? To address this issue, are there any code changes? If there are code changes, what needs to be done in the code and what places can the assignee treat as reference points? Does this issue have zero to low barrier of entry? How can the assignee reach out to you for help? For more details on the requirements of such an issue, please see and ensure that they are met. If this request no longer meets these requirements, the label can be removed by commenting with the command. <detailsIn response to : /sig apps /kind cleanup /help /good-first-issue Instructions for interacting with me using PR comments are available . If you have questions or suggestions related to my behavior, please file an issue against the repository. </details
I'd like to work on it /assign
I'd also like to make some contributions. /assign
Looks like this need two PRs. tests are not written using table driven design (). tests use Differences rather than Cmp.Diff. I think I can work on the 2nd one and leave the 1st one to you. Sounds good?
By looking through the , I found the main function to comapre the results have already used cmp.Diff. Can you elaborate more on which part you expect to use cmp.Diff? func verifyDeletedAndPatchedPods(t testing.T, client fake.Clientset, wantDeletedPodNames, wantPatchedPodNames sets.String) { t.Helper() deletedPodNames := getDeletedPodNames(client) if diff := cmp.Diff(wantDeletedPodNames, deletedPodNames); diff != "" { t.Errorf("Deleted pod names (-want,+got):n%s", diff) } patchedPodNames := getPatchedPodNames(client) if diff := cmp.Diff(wantPatchedPodNames, patchedPodNames); diff != "" { t.Errorf("Patched pod names (-want,+got):n%s", diff) } }
I am really sorry about this. Too much multitasking!! I meant not
Hey ! Sorry, I didn't see this before. No problem at all, but consider that one change depends on the other, and since my task implies a big refactor, there might be conflicts when merging your PR... That's why I see two possible scenarios happening: Your PR gets merged before I raise mine: Then fine, I'll rebase your changes and adapt my code Mine is ready before yours is merged: In this case, I propose you commit your changes to my PR. Both of us will appear as coauthors of the change Getting a PR merged in the Kubernetes project takes quite some time (trust me, I talk by experience and can confirm ) WDYT?
Let's see how it goes. We can always rebase the code change to adapt new.
btw, did you already begin to work on task 1? If not, I may just go ahead and work on it right away since I have already dig into it.
yes, I already started And If you ask me, better to keep it this way so we both have an opportunity to have a contribution
cool. Sounds good.
/reopen
Reopened this issue. <detailsIn response to : /reopen Instructions for interacting with me using PR comments are available . If you have questions or suggestions related to my behavior, please file an issue against the repository. </details
Hi if this issue needs to be worked on any further, please assign me for the same.
has a PR up that will solve the second part of this issue.

} } <del> func newReplicaSet(name string, replicas int) *apps.ReplicaSet { </del> <ins> func newReplicaSet(name string, replicas int, rsUuid types.UID) *apps.ReplicaSet { </ins> return &apps.ReplicaSet{ TypeMeta: metav1.TypeMeta{APIVersion: "v1"}, ObjectMeta: metav1.ObjectMeta{ <del> UID:             uuid.NewUUID(), </del> <ins> UID:             rsUuid, </ins> Name:            name, Namespace:       metav1.NamespaceDefault, ResourceVersion: "18",


Question:
During implementation of KEP 3393 (PodReplacementPolicy for Jobs) we found that the unit tests of do not follow common patterns established in k/k. 1) The tests are not written using table driven design (). 2) The tests use rather than . This probably should be done as two separate PRs but wanted to highlight some areas that could use some cleanup. Not using means that we don't see diffs in the unit tests that makes this difficult. And not using table driven tests makes it difficult to add new test cases as it usually is brought up during review that we should use a table-driven test but the entire file does not obey this format.
This issue is currently awaiting triage. If a SIG or subproject determines this is a relevant issue, they will accept it by applying the label and provide further guidance. The label can be by org members by writing in a comment. <detailsInstructions for interacting with me using PR comments are available . If you have questions or suggestions related to my behavior, please file an issue against the repository. </details
/sig apps /kind cleanup /help /good-first-issue
This request has been marked as suitable for new contributors. Please ensure that the issue body includes answers to the following questions: Why are we solving this issue? To address this issue, are there any code changes? If there are code changes, what needs to be done in the code and what places can the assignee treat as reference points? Does this issue have zero to low barrier of entry? How can the assignee reach out to you for help? For more details on the requirements of such an issue, please see and ensure that they are met. If this request no longer meets these requirements, the label can be removed by commenting with the command. <detailsIn response to : /sig apps /kind cleanup /help /good-first-issue Instructions for interacting with me using PR comments are available . If you have questions or suggestions related to my behavior, please file an issue against the repository. </details
I'd like to work on it /assign
I'd also like to make some contributions. /assign
Looks like this need two PRs. tests are not written using table driven design (). tests use Differences rather than Cmp.Diff. I think I can work on the 2nd one and leave the 1st one to you. Sounds good?
By looking through the , I found the main function to comapre the results have already used cmp.Diff. Can you elaborate more on which part you expect to use cmp.Diff? func verifyDeletedAndPatchedPods(t testing.T, client fake.Clientset, wantDeletedPodNames, wantPatchedPodNames sets.String) { t.Helper() deletedPodNames := getDeletedPodNames(client) if diff := cmp.Diff(wantDeletedPodNames, deletedPodNames); diff != "" { t.Errorf("Deleted pod names (-want,+got):n%s", diff) } patchedPodNames := getPatchedPodNames(client) if diff := cmp.Diff(wantPatchedPodNames, patchedPodNames); diff != "" { t.Errorf("Patched pod names (-want,+got):n%s", diff) } }
I am really sorry about this. Too much multitasking!! I meant not
Hey ! Sorry, I didn't see this before. No problem at all, but consider that one change depends on the other, and since my task implies a big refactor, there might be conflicts when merging your PR... That's why I see two possible scenarios happening: Your PR gets merged before I raise mine: Then fine, I'll rebase your changes and adapt my code Mine is ready before yours is merged: In this case, I propose you commit your changes to my PR. Both of us will appear as coauthors of the change Getting a PR merged in the Kubernetes project takes quite some time (trust me, I talk by experience and can confirm ) WDYT?
Let's see how it goes. We can always rebase the code change to adapt new.
btw, did you already begin to work on task 1? If not, I may just go ahead and work on it right away since I have already dig into it.
yes, I already started And If you ask me, better to keep it this way so we both have an opportunity to have a contribution
cool. Sounds good.
/reopen
Reopened this issue. <detailsIn response to : /reopen Instructions for interacting with me using PR comments are available . If you have questions or suggestions related to my behavior, please file an issue against the repository. </details
Hi if this issue needs to be worked on any further, please assign me for the same.
has a PR up that will solve the second part of this issue.

} 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) {


Question:
During implementation of KEP 3393 (PodReplacementPolicy for Jobs) we found that the unit tests of do not follow common patterns established in k/k. 1) The tests are not written using table driven design (). 2) The tests use rather than . This probably should be done as two separate PRs but wanted to highlight some areas that could use some cleanup. Not using means that we don't see diffs in the unit tests that makes this difficult. And not using table driven tests makes it difficult to add new test cases as it usually is brought up during review that we should use a table-driven test but the entire file does not obey this format.
This issue is currently awaiting triage. If a SIG or subproject determines this is a relevant issue, they will accept it by applying the label and provide further guidance. The label can be by org members by writing in a comment. <detailsInstructions for interacting with me using PR comments are available . If you have questions or suggestions related to my behavior, please file an issue against the repository. </details
/sig apps /kind cleanup /help /good-first-issue
This request has been marked as suitable for new contributors. Please ensure that the issue body includes answers to the following questions: Why are we solving this issue? To address this issue, are there any code changes? If there are code changes, what needs to be done in the code and what places can the assignee treat as reference points? Does this issue have zero to low barrier of entry? How can the assignee reach out to you for help? For more details on the requirements of such an issue, please see and ensure that they are met. If this request no longer meets these requirements, the label can be removed by commenting with the command. <detailsIn response to : /sig apps /kind cleanup /help /good-first-issue Instructions for interacting with me using PR comments are available . If you have questions or suggestions related to my behavior, please file an issue against the repository. </details
I'd like to work on it /assign
I'd also like to make some contributions. /assign
Looks like this need two PRs. tests are not written using table driven design (). tests use Differences rather than Cmp.Diff. I think I can work on the 2nd one and leave the 1st one to you. Sounds good?
By looking through the , I found the main function to comapre the results have already used cmp.Diff. Can you elaborate more on which part you expect to use cmp.Diff? func verifyDeletedAndPatchedPods(t testing.T, client fake.Clientset, wantDeletedPodNames, wantPatchedPodNames sets.String) { t.Helper() deletedPodNames := getDeletedPodNames(client) if diff := cmp.Diff(wantDeletedPodNames, deletedPodNames); diff != "" { t.Errorf("Deleted pod names (-want,+got):n%s", diff) } patchedPodNames := getPatchedPodNames(client) if diff := cmp.Diff(wantPatchedPodNames, patchedPodNames); diff != "" { t.Errorf("Patched pod names (-want,+got):n%s", diff) } }
I am really sorry about this. Too much multitasking!! I meant not
Hey ! Sorry, I didn't see this before. No problem at all, but consider that one change depends on the other, and since my task implies a big refactor, there might be conflicts when merging your PR... That's why I see two possible scenarios happening: Your PR gets merged before I raise mine: Then fine, I'll rebase your changes and adapt my code Mine is ready before yours is merged: In this case, I propose you commit your changes to my PR. Both of us will appear as coauthors of the change Getting a PR merged in the Kubernetes project takes quite some time (trust me, I talk by experience and can confirm ) WDYT?
Let's see how it goes. We can always rebase the code change to adapt new.
btw, did you already begin to work on task 1? If not, I may just go ahead and work on it right away since I have already dig into it.
yes, I already started And If you ask me, better to keep it this way so we both have an opportunity to have a contribution
cool. Sounds good.
/reopen
Reopened this issue. <detailsIn response to : /reopen Instructions for interacting with me using PR comments are available . If you have questions or suggestions related to my behavior, please file an issue against the repository. </details
Hi if this issue needs to be worked on any further, please assign me for the same.
has a PR up that will solve the second part of this issue.

func TestActivePodFiltering(t *testing.T) { logger, _ := ktesting.NewTestContext(t) <del> // This rc is not needed by the test, only the newPodList to give the pods labels/a namespace. rc := newReplicationController(0) podList := newPodList(nil, 5, v1.PodRunning, rc) podList.Items[0].Status.Phase = v1.PodSucceeded podList.Items[1].Status.Phase = v1.PodFailed expectedNames := sets.NewString() for _, pod := range podList.Items[2:] { expectedNames.Insert(pod.Name) </del> <ins> type podData struct { podName  string podPhase v1.PodPhase </ins> } <del> var podPointers []*v1.Pod for i := range podList.Items { podPointers = append(podPointers, &podList.Items[i]) </del> <ins> type test struct { name         string pods         []podData wantPodNames []string </ins> } <del> got := FilterActivePods(logger, podPointers) gotNames := sets.NewString() for _, pod := range got { gotNames.Insert(pod.Name) </del> <ins> tests := []test{ { name: "Filters active pods", pods: []podData{ {podName: "pod-1", podPhase: v1.PodSucceeded}, {podName: "pod-2", podPhase: v1.PodFailed}, {podName: "pod-3"}, {podName: "pod-4"}, {podName: "pod-5"}, }, wantPodNames: []string{"pod-3", "pod-4", "pod-5"}, }, </ins> } <del> if diff := cmp.Diff(expectedNames.List(), gotNames.List()); diff != "" { t.Errorf("Active pod names (-want,+got):n%s", diff) </del> <ins> for _, test := range tests { t.Run(test.name, func(t *testing.T) { // This rc is not needed by the test, only the newPodList to give the pods labels/a namespace. rc := newReplicationController(0) podList := newPodList(nil, 5, v1.PodRunning, rc) for idx, testPod := range test.pods { podList.Items[idx].Name = testPod.podName podList.Items[idx].Status.Phase = testPod.podPhase } var podPointers []*v1.Pod for i := range podList.Items { podPointers = append(podPointers, &podList.Items[i]) } got := FilterActivePods(logger, podPointers) gotNames := sets.NewString() for _, pod := range got { gotNames.Insert(pod.Name) } if diff := cmp.Diff(test.wantPodNames, gotNames.List()); diff != "" { t.Errorf("Active pod names (-want,+got):n%s", diff) } }) </ins> } } func TestSortingActivePods(t *testing.T) { <del> numPods := 9 // This rc is not needed by the test, only the newPodList to give the pods labels/a namespace. rc := newReplicationController(0) podList := newPodList(nil, numPods, v1.PodRunning, rc) pods := make([]*v1.Pod, len(podList.Items)) for i := range podList.Items { pods[i] = &podList.Items[i] } // pods[0] is not scheduled yet. pods[0].Spec.NodeName = "" pods[0].Status.Phase = v1.PodPending // pods[1] is scheduled but pending. pods[1].Spec.NodeName = "bar" pods[1].Status.Phase = v1.PodPending // pods[2] is unknown. pods[2].Spec.NodeName = "foo" pods[2].Status.Phase = v1.PodUnknown // pods[3] is running but not ready. pods[3].Spec.NodeName = "foo" pods[3].Status.Phase = v1.PodRunning // pods[4] is running and ready but without LastTransitionTime. </del> now := metav1.Now() <del> pods[4].Spec.NodeName = "foo" pods[4].Status.Phase = v1.PodRunning pods[4].Status.Conditions = []v1.PodCondition{{Type: v1.PodReady, Status: v1.ConditionTrue}} pods[4].Status.ContainerStatuses = []v1.ContainerStatus{{RestartCount: 3}, {RestartCount: 0}} // pods[5] is running and ready and with LastTransitionTime. pods[5].Spec.NodeName = "foo" pods[5].Status.Phase = v1.PodRunning pods[5].Status.Conditions = []v1.PodCondition{{Type: v1.PodReady, Status: v1.ConditionTrue, LastTransitionTime: now}} pods[5].Status.ContainerStatuses = []v1.ContainerStatus{{RestartCount: 3}, {RestartCount: 0}} // pods[6] is running ready for a longer time than pods[5]. </del> then := metav1.Time{Time: now.AddDate(0, -1, 0)} <del> pods[6].Spec.NodeName = "foo" pods[6].Status.Phase = v1.PodRunning pods[6].Status.Conditions = []v1.PodCondition{{Type: v1.PodReady, Status: v1.ConditionTrue, LastTransitionTime: then}} pods[6].Status.ContainerStatuses = []v1.ContainerStatus{{RestartCount: 3}, {RestartCount: 0}} // pods[7] has lower container restart count than pods[6]. pods[7].Spec.NodeName = "foo" pods[7].Status.Phase = v1.PodRunning pods[7].Status.Conditions = []v1.PodCondition{{Type: v1.PodReady, Status: v1.ConditionTrue, LastTransitionTime: then}} pods[7].Status.ContainerStatuses = []v1.ContainerStatus{{RestartCount: 2}, {RestartCount: 1}} pods[7].CreationTimestamp = now // pods[8] is older than pods[7]. pods[8].Spec.NodeName = "foo" pods[8].Status.Phase = v1.PodRunning pods[8].Status.Conditions = []v1.PodCondition{{Type: v1.PodReady, Status: v1.ConditionTrue, LastTransitionTime: then}} pods[8].Status.ContainerStatuses = []v1.ContainerStatus{{RestartCount: 2}, {RestartCount: 1}} pods[8].CreationTimestamp = then getOrder := func(pods []*v1.Pod) []string { names := make([]string, len(pods)) for i := range pods { names[i] = pods[i].Name } return names </del> <ins> tests := []struct { name      string pods      []v1.Pod wantOrder []string }{ { name: "Sorts by active pod", pods: []v1.Pod{ { ObjectMeta: metav1.ObjectMeta{Name: "unscheduled"}, Spec:       v1.PodSpec{NodeName: ""}, Status:     v1.PodStatus{Phase: v1.PodPending}, }, { ObjectMeta: metav1.ObjectMeta{Name: "scheduledButPending"}, Spec:       v1.PodSpec{NodeName: "bar"}, Status:     v1.PodStatus{Phase: v1.PodPending}, }, { ObjectMeta: metav1.ObjectMeta{Name: "unknownPhase"}, Spec:       v1.PodSpec{NodeName: "foo"}, Status:     v1.PodStatus{Phase: v1.PodUnknown}, }, { ObjectMeta: metav1.ObjectMeta{Name: "runningButNotReady"}, Spec:       v1.PodSpec{NodeName: "foo"}, Status:     v1.PodStatus{Phase: v1.PodRunning}, }, { ObjectMeta: metav1.ObjectMeta{Name: "runningNoLastTransitionTime"}, Spec:       v1.PodSpec{NodeName: "foo"}, Status: v1.PodStatus{ Phase:             v1.PodRunning, Conditions:        []v1.PodCondition{{Type: v1.PodReady, Status: v1.ConditionTrue}}, ContainerStatuses: []v1.ContainerStatus{{RestartCount: 3}, {RestartCount: 0}}, }, }, { ObjectMeta: metav1.ObjectMeta{Name: "runningWithLastTransitionTime"}, Spec:       v1.PodSpec{NodeName: "foo"}, Status: v1.PodStatus{ Phase:             v1.PodRunning, Conditions:        []v1.PodCondition{{Type: v1.PodReady, Status: v1.ConditionTrue, LastTransitionTime: now}}, ContainerStatuses: []v1.ContainerStatus{{RestartCount: 3}, {RestartCount: 0}}, }, }, { ObjectMeta: metav1.ObjectMeta{Name: "runningLongerTime"}, Spec:       v1.PodSpec{NodeName: "foo"}, Status: v1.PodStatus{ Phase:             v1.PodRunning, Conditions:        []v1.PodCondition{{Type: v1.PodReady, Status: v1.ConditionTrue, LastTransitionTime: then}}, ContainerStatuses: []v1.ContainerStatus{{RestartCount: 3}, {RestartCount: 0}}, }, }, { ObjectMeta: metav1.ObjectMeta{Name: "lowerContainerRestartCount", CreationTimestamp: now}, Spec:       v1.PodSpec{NodeName: "foo"}, Status: v1.PodStatus{ Phase:             v1.PodRunning, Conditions:        []v1.PodCondition{{Type: v1.PodReady, Status: v1.ConditionTrue, LastTransitionTime: then}}, ContainerStatuses: []v1.ContainerStatus{{RestartCount: 2}, {RestartCount: 1}}, }, }, { ObjectMeta: metav1.ObjectMeta{Name: "oldest", CreationTimestamp: then}, Spec:       v1.PodSpec{NodeName: "foo"}, Status: v1.PodStatus{ Phase:             v1.PodRunning, Conditions:        []v1.PodCondition{{Type: v1.PodReady, Status: v1.ConditionTrue, LastTransitionTime: then}}, ContainerStatuses: []v1.ContainerStatus{{RestartCount: 2}, {RestartCount: 1}}, }, }, }, wantOrder: []string{ "unscheduled", "scheduledButPending", "unknownPhase", "runningButNotReady", "runningNoLastTransitionTime", "runningWithLastTransitionTime", "runningLongerTime", "lowerContainerRestartCount", "oldest", }, }, </ins> } <del> expected := getOrder(pods) </del> <ins> for _, test := range tests { t.Run(test.name, func(t *testing.T) { numPods := len(test.pods) </ins> <del> for i := 0; i < 20; i++ { idx := rand.Perm(numPods) randomizedPods := make([]*v1.Pod, numPods) for j := 0; j < numPods; j++ { randomizedPods[j] = pods[idx[j]] } sort.Sort(ActivePods(randomizedPods)) actual := getOrder(randomizedPods) </del> <ins> for i := 0; i < 20; i++ { idx := rand.Perm(numPods) randomizedPods := make([]*v1.Pod, numPods) for j := 0; j < numPods; j++ { randomizedPods[j] = &test.pods[idx[j]] } </ins> <del> assert.EqualValues(t, expected, actual, "expected %v, got %v", expected, actual) </del> <ins> sort.Sort(ActivePods(randomizedPods)) gotOrder := make([]string, len(randomizedPods)) for i := range randomizedPods { gotOrder[i] = randomizedPods[i].Name } if diff := cmp.Diff(test.wantOrder, gotOrder); diff != "" { t.Errorf("Sorted active pod names (-want,+got):n%s", diff) } } }) </ins> } }


Question:
During implementation of KEP 3393 (PodReplacementPolicy for Jobs) we found that the unit tests of do not follow common patterns established in k/k. 1) The tests are not written using table driven design (). 2) The tests use rather than . This probably should be done as two separate PRs but wanted to highlight some areas that could use some cleanup. Not using means that we don't see diffs in the unit tests that makes this difficult. And not using table driven tests makes it difficult to add new test cases as it usually is brought up during review that we should use a table-driven test but the entire file does not obey this format.
This issue is currently awaiting triage. If a SIG or subproject determines this is a relevant issue, they will accept it by applying the label and provide further guidance. The label can be by org members by writing in a comment. <detailsInstructions for interacting with me using PR comments are available . If you have questions or suggestions related to my behavior, please file an issue against the repository. </details
/sig apps /kind cleanup /help /good-first-issue
This request has been marked as suitable for new contributors. Please ensure that the issue body includes answers to the following questions: Why are we solving this issue? To address this issue, are there any code changes? If there are code changes, what needs to be done in the code and what places can the assignee treat as reference points? Does this issue have zero to low barrier of entry? How can the assignee reach out to you for help? For more details on the requirements of such an issue, please see and ensure that they are met. If this request no longer meets these requirements, the label can be removed by commenting with the command. <detailsIn response to : /sig apps /kind cleanup /help /good-first-issue Instructions for interacting with me using PR comments are available . If you have questions or suggestions related to my behavior, please file an issue against the repository. </details
I'd like to work on it /assign
I'd also like to make some contributions. /assign
Looks like this need two PRs. tests are not written using table driven design (). tests use Differences rather than Cmp.Diff. I think I can work on the 2nd one and leave the 1st one to you. Sounds good?
By looking through the , I found the main function to comapre the results have already used cmp.Diff. Can you elaborate more on which part you expect to use cmp.Diff? func verifyDeletedAndPatchedPods(t testing.T, client fake.Clientset, wantDeletedPodNames, wantPatchedPodNames sets.String) { t.Helper() deletedPodNames := getDeletedPodNames(client) if diff := cmp.Diff(wantDeletedPodNames, deletedPodNames); diff != "" { t.Errorf("Deleted pod names (-want,+got):n%s", diff) } patchedPodNames := getPatchedPodNames(client) if diff := cmp.Diff(wantPatchedPodNames, patchedPodNames); diff != "" { t.Errorf("Patched pod names (-want,+got):n%s", diff) } }
I am really sorry about this. Too much multitasking!! I meant not
Hey ! Sorry, I didn't see this before. No problem at all, but consider that one change depends on the other, and since my task implies a big refactor, there might be conflicts when merging your PR... That's why I see two possible scenarios happening: Your PR gets merged before I raise mine: Then fine, I'll rebase your changes and adapt my code Mine is ready before yours is merged: In this case, I propose you commit your changes to my PR. Both of us will appear as coauthors of the change Getting a PR merged in the Kubernetes project takes quite some time (trust me, I talk by experience and can confirm ) WDYT?
Let's see how it goes. We can always rebase the code change to adapt new.
btw, did you already begin to work on task 1? If not, I may just go ahead and work on it right away since I have already dig into it.
yes, I already started And If you ask me, better to keep it this way so we both have an opportunity to have a contribution
cool. Sounds good.
/reopen
Reopened this issue. <detailsIn response to : /reopen Instructions for interacting with me using PR comments are available . If you have questions or suggestions related to my behavior, please file an issue against the repository. </details
Hi if this issue needs to be worked on any further, please assign me for the same.
has a PR up that will solve the second part of this issue.

{p1: unscheduled5Hours, p2: unscheduled8Hours}, {p1: ready5Hours, p2: ready10Hours}, } <del> for _, tc := range equalityTests { defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.LogarithmicScaleDown, !tc.disableLogarithmicScaleDown)() if tc.p2 == nil { tc.p2 = tc.p1 } podsWithRanks := ActivePodsWithRanks{ Pods: []*v1.Pod{tc.p1, tc.p2}, Rank: []int{1, 1}, Now:  now, } if podsWithRanks.Less(0, 1) || podsWithRanks.Less(1, 0) { t.Errorf("expected pod %q to be equivalent to %q", tc.p1.Name, tc.p2.Name) } </del> <ins> for i, test := range equalityTests { t.Run(fmt.Sprintf("Equality tests %d", i), func(t *testing.T) { defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.LogarithmicScaleDown, !test.disableLogarithmicScaleDown)() if test.p2 == nil { test.p2 = test.p1 } podsWithRanks := ActivePodsWithRanks{ Pods: []*v1.Pod{test.p1, test.p2}, Rank: []int{1, 1}, Now:  now, } if podsWithRanks.Less(0, 1) || podsWithRanks.Less(1, 0) { t.Errorf("expected pod %q to be equivalent to %q", test.p1.Name, test.p2.Name) } }) </ins> } type podWithRank struct { pod  *v1.Pod rank int


Question:
During implementation of KEP 3393 (PodReplacementPolicy for Jobs) we found that the unit tests of do not follow common patterns established in k/k. 1) The tests are not written using table driven design (). 2) The tests use rather than . This probably should be done as two separate PRs but wanted to highlight some areas that could use some cleanup. Not using means that we don't see diffs in the unit tests that makes this difficult. And not using table driven tests makes it difficult to add new test cases as it usually is brought up during review that we should use a table-driven test but the entire file does not obey this format.
This issue is currently awaiting triage. If a SIG or subproject determines this is a relevant issue, they will accept it by applying the label and provide further guidance. The label can be by org members by writing in a comment. <detailsInstructions for interacting with me using PR comments are available . If you have questions or suggestions related to my behavior, please file an issue against the repository. </details
/sig apps /kind cleanup /help /good-first-issue
This request has been marked as suitable for new contributors. Please ensure that the issue body includes answers to the following questions: Why are we solving this issue? To address this issue, are there any code changes? If there are code changes, what needs to be done in the code and what places can the assignee treat as reference points? Does this issue have zero to low barrier of entry? How can the assignee reach out to you for help? For more details on the requirements of such an issue, please see and ensure that they are met. If this request no longer meets these requirements, the label can be removed by commenting with the command. <detailsIn response to : /sig apps /kind cleanup /help /good-first-issue Instructions for interacting with me using PR comments are available . If you have questions or suggestions related to my behavior, please file an issue against the repository. </details
I'd like to work on it /assign
I'd also like to make some contributions. /assign
Looks like this need two PRs. tests are not written using table driven design (). tests use Differences rather than Cmp.Diff. I think I can work on the 2nd one and leave the 1st one to you. Sounds good?
By looking through the , I found the main function to comapre the results have already used cmp.Diff. Can you elaborate more on which part you expect to use cmp.Diff? func verifyDeletedAndPatchedPods(t testing.T, client fake.Clientset, wantDeletedPodNames, wantPatchedPodNames sets.String) { t.Helper() deletedPodNames := getDeletedPodNames(client) if diff := cmp.Diff(wantDeletedPodNames, deletedPodNames); diff != "" { t.Errorf("Deleted pod names (-want,+got):n%s", diff) } patchedPodNames := getPatchedPodNames(client) if diff := cmp.Diff(wantPatchedPodNames, patchedPodNames); diff != "" { t.Errorf("Patched pod names (-want,+got):n%s", diff) } }
I am really sorry about this. Too much multitasking!! I meant not
Hey ! Sorry, I didn't see this before. No problem at all, but consider that one change depends on the other, and since my task implies a big refactor, there might be conflicts when merging your PR... That's why I see two possible scenarios happening: Your PR gets merged before I raise mine: Then fine, I'll rebase your changes and adapt my code Mine is ready before yours is merged: In this case, I propose you commit your changes to my PR. Both of us will appear as coauthors of the change Getting a PR merged in the Kubernetes project takes quite some time (trust me, I talk by experience and can confirm ) WDYT?
Let's see how it goes. We can always rebase the code change to adapt new.
btw, did you already begin to work on task 1? If not, I may just go ahead and work on it right away since I have already dig into it.
yes, I already started And If you ask me, better to keep it this way so we both have an opportunity to have a contribution
cool. Sounds good.
/reopen
Reopened this issue. <detailsIn response to : /reopen Instructions for interacting with me using PR comments are available . If you have questions or suggestions related to my behavior, please file an issue against the repository. </details
Hi if this issue needs to be worked on any further, please assign me for the same.
has a PR up that will solve the second part of this issue.

{lesser: podWithRank{highPodDeletionCost, 2}, greater: podWithRank{lowPodDeletionCost, 1}, disablePodDeletioncost: true}, {lesser: podWithRank{ready2Hours, 1}, greater: podWithRank{ready5Hours, 1}}, } for i, test := range inequalityTests { <del> t.Run(fmt.Sprintf("test%d", i), func(t *testing.T) { </del> <ins> t.Run(fmt.Sprintf("Inequality tests %d", i), func(t *testing.T) { </ins> defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.PodDeletionCost, !test.disablePodDeletioncost)() defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.LogarithmicScaleDown, !test.disableLogarithmicScaleDown)()


Question:
During implementation of KEP 3393 (PodReplacementPolicy for Jobs) we found that the unit tests of do not follow common patterns established in k/k. 1) The tests are not written using table driven design (). 2) The tests use rather than . This probably should be done as two separate PRs but wanted to highlight some areas that could use some cleanup. Not using means that we don't see diffs in the unit tests that makes this difficult. And not using table driven tests makes it difficult to add new test cases as it usually is brought up during review that we should use a table-driven test but the entire file does not obey this format.
This issue is currently awaiting triage. If a SIG or subproject determines this is a relevant issue, they will accept it by applying the label and provide further guidance. The label can be by org members by writing in a comment. <detailsInstructions for interacting with me using PR comments are available . If you have questions or suggestions related to my behavior, please file an issue against the repository. </details
/sig apps /kind cleanup /help /good-first-issue
This request has been marked as suitable for new contributors. Please ensure that the issue body includes answers to the following questions: Why are we solving this issue? To address this issue, are there any code changes? If there are code changes, what needs to be done in the code and what places can the assignee treat as reference points? Does this issue have zero to low barrier of entry? How can the assignee reach out to you for help? For more details on the requirements of such an issue, please see and ensure that they are met. If this request no longer meets these requirements, the label can be removed by commenting with the command. <detailsIn response to : /sig apps /kind cleanup /help /good-first-issue Instructions for interacting with me using PR comments are available . If you have questions or suggestions related to my behavior, please file an issue against the repository. </details
I'd like to work on it /assign
I'd also like to make some contributions. /assign
Looks like this need two PRs. tests are not written using table driven design (). tests use Differences rather than Cmp.Diff. I think I can work on the 2nd one and leave the 1st one to you. Sounds good?
By looking through the , I found the main function to comapre the results have already used cmp.Diff. Can you elaborate more on which part you expect to use cmp.Diff? func verifyDeletedAndPatchedPods(t testing.T, client fake.Clientset, wantDeletedPodNames, wantPatchedPodNames sets.String) { t.Helper() deletedPodNames := getDeletedPodNames(client) if diff := cmp.Diff(wantDeletedPodNames, deletedPodNames); diff != "" { t.Errorf("Deleted pod names (-want,+got):n%s", diff) } patchedPodNames := getPatchedPodNames(client) if diff := cmp.Diff(wantPatchedPodNames, patchedPodNames); diff != "" { t.Errorf("Patched pod names (-want,+got):n%s", diff) } }
I am really sorry about this. Too much multitasking!! I meant not
Hey ! Sorry, I didn't see this before. No problem at all, but consider that one change depends on the other, and since my task implies a big refactor, there might be conflicts when merging your PR... That's why I see two possible scenarios happening: Your PR gets merged before I raise mine: Then fine, I'll rebase your changes and adapt my code Mine is ready before yours is merged: In this case, I propose you commit your changes to my PR. Both of us will appear as coauthors of the change Getting a PR merged in the Kubernetes project takes quite some time (trust me, I talk by experience and can confirm ) WDYT?
Let's see how it goes. We can always rebase the code change to adapt new.
btw, did you already begin to work on task 1? If not, I may just go ahead and work on it right away since I have already dig into it.
yes, I already started And If you ask me, better to keep it this way so we both have an opportunity to have a contribution
cool. Sounds good.
/reopen
Reopened this issue. <detailsIn response to : /reopen Instructions for interacting with me using PR comments are available . If you have questions or suggestions related to my behavior, please file an issue against the repository. </details
Hi if this issue needs to be worked on any further, please assign me for the same.
has a PR up that will solve the second part of this issue.

} func TestActiveReplicaSetsFiltering(t *testing.T) { <del> var replicaSets []*apps.ReplicaSet replicaSets = append(replicaSets, newReplicaSet("zero", 0)) replicaSets = append(replicaSets, nil) replicaSets = append(replicaSets, newReplicaSet("foo", 1)) replicaSets = append(replicaSets, newReplicaSet("bar", 2)) expectedNames := sets.NewString() for _, rs := range replicaSets[2:] { expectedNames.Insert(rs.Name) } got := FilterActiveReplicaSets(replicaSets) gotNames := sets.NewString() for _, rs := range got { gotNames.Insert(rs.Name) </del> <ins> rsUuid := uuid.NewUUID() tests := []struct { name            string replicaSets     []*apps.ReplicaSet wantReplicaSets []*apps.ReplicaSet }{ { name: "Filters active replica sets", replicaSets: []*apps.ReplicaSet{ newReplicaSet("zero", 0, rsUuid), nil, newReplicaSet("foo", 1, rsUuid), newReplicaSet("bar", 2, rsUuid), }, wantReplicaSets: []*apps.ReplicaSet{ newReplicaSet("foo", 1, rsUuid), newReplicaSet("bar", 2, rsUuid), }, }, </ins> } <del> if diff := cmp.Diff(expectedNames.List(), gotNames.List()); diff != "" { t.Errorf("Active replica set names (-want,+got):n%s", diff) </del> <ins> for _, test := range tests { t.Run(test.name, func(t *testing.T) { gotReplicaSets := FilterActiveReplicaSets(test.replicaSets) if diff := cmp.Diff(test.wantReplicaSets, gotReplicaSets); diff != "" { t.Errorf("Active replica set names (-want,+got):n%s", diff) } }) </ins> } }


Question:
When I put a Pod yaml file without in , started the kubelet and hoped it would create the corresponding staticPod for me, I got the following error, which also caused the staticPod to not be created. I then read the kubelet code and quickly found the problem. When kubelet tries to decode the pod yaml file, it will apply default values and validate the pod. The function to apply the defaults is in . In this function, the is set. This causes an error when is not set, because it causes the '-' character to be at the front. I think kubelet should circumvent this error, because is optional, It is possible for this field not to be set. When Pod's is not set, the '-' character at the start should be avoided, as it will cause an error. Prepare a Pod yaml file without and set it into . If the maintainers think this circumvention change is necessary, I'm happy to contribute code to the kubelet! <details</details<details</details<detailsconsole $ cat /etc/os-release NAME="Alibaba Cloud Linux" VERSION="3 (Soaring Falcon)" ID="alinux" IDLIKE="rhel fedora centos anolis" VERSIONID="3" PLATFORMID="platform:al8" PRETTYNAME="Alibaba Cloud Linux 3 (Soaring Falcon)" ANSICOLOR="0;31" HOMEURL="" $ uname -a Linux cloud 5.10.134-14.al8.x8664 SMP Thu Apr 27 16:46:29 CST 2023 x8664 x8664 x8664 GNU/Linux </details<detailsusing kubeadm </details<details</details<details</details
/sig node
I would like to open a PR to fix this issue, can I be assigned?
If the maintainer thinks this should be fixed, I want it fixed by myself:)
OK
I do not know if a pod without name should be considered valid Please discuss with sig-node before doing anything to understand what is a valid solution for this problem /cc
names are needed for the Pod. I think the correct fix for this issue will be to add validation for static Pods to have a name. This validation is OK to add since Pods without names are not working anyways because of this bug.
Okay, I will submit a PR to add validation for static Pods to have a name.
Hey, I found out that kubelet will apply default value first and then validate the pod. Do you mean to let me add a single validation for static Pods to have a name before applying default value?
hi and If modified according to this logic, it seems that the current code is fine. Current logic: it will use the old pod.Name to generate the new pod.Name , in ValidatePodCreate, it will validate pod name. The pod.Name is already to new pod.Name this case, the original pod does not have a name and will also be recognized. It's just that it's identified with a validation prefixed with "-". The logic of the current validation will recognize the pod without a name. In this way, is it necessary to improve the error information?
/triage accepted
/priority backlog

return false, pod, fmt.Errorf("invalid pod: %#v", obj) } <ins> if newPod.Name == "" { return true, pod, fmt.Errorf("invalid pod: name is needed for the pod") } </ins> // Apply default values and validate the pod. if err = defaultFn(newPod); err != nil { return true, pod, err


Question:
When I put a Pod yaml file without in , started the kubelet and hoped it would create the corresponding staticPod for me, I got the following error, which also caused the staticPod to not be created. I then read the kubelet code and quickly found the problem. When kubelet tries to decode the pod yaml file, it will apply default values and validate the pod. The function to apply the defaults is in . In this function, the is set. This causes an error when is not set, because it causes the '-' character to be at the front. I think kubelet should circumvent this error, because is optional, It is possible for this field not to be set. When Pod's is not set, the '-' character at the start should be avoided, as it will cause an error. Prepare a Pod yaml file without and set it into . If the maintainers think this circumvention change is necessary, I'm happy to contribute code to the kubelet! <details</details<details</details<detailsconsole $ cat /etc/os-release NAME="Alibaba Cloud Linux" VERSION="3 (Soaring Falcon)" ID="alinux" IDLIKE="rhel fedora centos anolis" VERSIONID="3" PLATFORMID="platform:al8" PRETTYNAME="Alibaba Cloud Linux 3 (Soaring Falcon)" ANSICOLOR="0;31" HOMEURL="" $ uname -a Linux cloud 5.10.134-14.al8.x8664 SMP Thu Apr 27 16:46:29 CST 2023 x8664 x8664 x8664 GNU/Linux </details<detailsusing kubeadm </details<details</details<details</details
/sig node
I would like to open a PR to fix this issue, can I be assigned?
If the maintainer thinks this should be fixed, I want it fixed by myself:)
OK
I do not know if a pod without name should be considered valid Please discuss with sig-node before doing anything to understand what is a valid solution for this problem /cc
names are needed for the Pod. I think the correct fix for this issue will be to add validation for static Pods to have a name. This validation is OK to add since Pods without names are not working anyways because of this bug.
Okay, I will submit a PR to add validation for static Pods to have a name.
Hey, I found out that kubelet will apply default value first and then validate the pod. Do you mean to let me add a single validation for static Pods to have a name before applying default value?
hi and If modified according to this logic, it seems that the current code is fine. Current logic: it will use the old pod.Name to generate the new pod.Name , in ValidatePodCreate, it will validate pod name. The pod.Name is already to new pod.Name this case, the original pod does not have a name and will also be recognized. It's just that it's identified with a validation prefixed with "-". The logic of the current validation will recognize the pod without a name. In this way, is it necessary to improve the error information?
/triage accepted
/priority backlog

// Apply default values and validate pods. for i := range newPods.Items { newPod := &newPods.Items[i] <ins> if newPod.Name == "" { return true, pods, fmt.Errorf("invalid pod: name is needed for the pod") } </ins> if err = defaultFn(newPod); err != nil { return true, pods, err }


Question:
What happened: Shortly after was merged, the "multiple nodes reallocation works" E2E DRA test started to fail randomly. Please provide links to example occurrences, if any: /sig node /kind bug needs to stay green. No response master n/a No response No response No response No response
This issue is currently awaiting triage. If a SIG or subproject determines this is a relevant issue, they will accept it by applying the label and provide further guidance. The label can be by org members by writing in a comment. <detailsInstructions for interacting with me using PR comments are available . If you have questions or suggestions related to my behavior, please file an issue against the repository. </details

driver := NewDriver(f, nodes, func() app.Resources { return app.Resources{ NodeLocal:      true, <del> MaxAllocations: 2, </del> <ins> MaxAllocations: 1, </ins> Nodes:          nodes.NodeNames, } }) driver2 := NewDriver(f, nodes, func() app.Resources { return app.Resources{ NodeLocal:      true, <del> MaxAllocations: 2, </del> <ins> MaxAllocations: 1, </ins> Nodes:          nodes.NodeNames, AllocateWrapper: func(


Question:
What happened: Shortly after was merged, the "multiple nodes reallocation works" E2E DRA test started to fail randomly. Please provide links to example occurrences, if any: /sig node /kind bug needs to stay green. No response master n/a No response No response No response No response
This issue is currently awaiting triage. If a SIG or subproject determines this is a relevant issue, they will accept it by applying the label and provide further guidance. The label can be by org members by writing in a comment. <detailsInstructions for interacting with me using PR comments are available . If you have questions or suggestions related to my behavior, please file an issue against the repository. </details

parameters1 := b.parameters() parameters2 := b2.parameters() <del> pod1 := b.podExternal() pod2 := b2.podExternal() </del> <ins> // Order is relevant here: each pod must be matched with its own claim. </ins> pod1claim1 := b.externalClaim(resourcev1alpha2.AllocationModeWaitForFirstConsumer) <ins> pod1 := b.podExternal() </ins> pod2claim1 := b2.externalClaim(resourcev1alpha2.AllocationModeWaitForFirstConsumer) <del> pod1claim2 := b2.externalClaim(resourcev1alpha2.AllocationModeWaitForFirstConsumer) pod1claim3 := b2.externalClaim(resourcev1alpha2.AllocationModeWaitForFirstConsumer) </del> <ins> pod2 := b2.podExternal() // Add another claim to pod1. pod1claim2 := b2.externalClaim(resourcev1alpha2.AllocationModeWaitForFirstConsumer) </ins> pod1.Spec.ResourceClaims = append(pod1.Spec.ResourceClaims, v1.PodResourceClaim{ <del> Name: "claim-other1", </del> <ins> Name: "claim-other", </ins> Source: v1.ClaimSource{ ResourceClaimName: &pod1claim2.Name, }, }, <del> v1.PodResourceClaim{ Name: "claim-other2", Source: v1.ClaimSource{ ResourceClaimName: &pod1claim3.Name, }, }, </del> ) <del> // Block on the second, third external claim from driver2 that is to be allocated. </del> <ins> // Allocating the second claim in pod1 has to wait until pod2 has // consumed the available resources on the node. </ins> blockClaim, cancelBlockClaim := context.WithCancel(ctx) defer cancelBlockClaim() <del> b2.create(ctx, parameters2, pod1claim2, pod1claim3) b.create(ctx, parameters1, pod1claim1, pod1) </del> allocateWrapper2 = func(ctx context.Context, claimAllocations []*controller.ClaimAllocation, selectedNode string,


Question:
What happened: Shortly after was merged, the "multiple nodes reallocation works" E2E DRA test started to fail randomly. Please provide links to example occurrences, if any: /sig node /kind bug needs to stay green. No response master n/a No response No response No response No response
This issue is currently awaiting triage. If a SIG or subproject determines this is a relevant issue, they will accept it by applying the label and provide further guidance. The label can be by org members by writing in a comment. <detailsInstructions for interacting with me using PR comments are available . If you have questions or suggestions related to my behavior, please file an issue against the repository. </details

claimAllocations []*controller.ClaimAllocation, selectedNode string), ) { <del> // pod1 will have only external-claim[2-3], it has to wait // for pod2 to consume resources from driver2 if claimAllocations[0].Claim.Name != "external-claim-other" { </del> <ins> if claimAllocations[0].Claim.Name == pod1claim2.Name { </ins> <-blockClaim.Done() } handler(ctx, claimAllocations, selectedNode) return } <ins> b.create(ctx, parameters1, parameters2, pod1claim1, pod1claim2, pod1) </ins> ginkgo.By("waiting for one claim from driver1 to be allocated") var nodeSelector *v1.NodeSelector gomega.Eventually(ctx, func(ctx context.Context) (int, error) {


Question:
What happened: Shortly after was merged, the "multiple nodes reallocation works" E2E DRA test started to fail randomly. Please provide links to example occurrences, if any: /sig node /kind bug needs to stay green. No response master n/a No response No response No response No response
This issue is currently awaiting triage. If a SIG or subproject determines this is a relevant issue, they will accept it by applying the label and provide further guidance. The label can be by org members by writing in a comment. <detailsInstructions for interacting with me using PR comments are available . If you have questions or suggestions related to my behavior, please file an issue against the repository. </details

b2.create(ctx, pod2claim1, pod2) framework.ExpectNoError(e2epod.WaitForPodRunningInNamespace(ctx, f.ClientSet, pod2), "start pod 2") <del> // Allow allocation of pod1 claim2, claim3 to proceed. It should fail now </del> <ins> // Allow allocation of second claim in pod1 to proceed. It should fail now </ins> // and the other node must be used instead, after deallocating // the first claim. ginkgo.By("move first pod to other node")


Question:
Kubernetes does not respect the of a probe. I found this while fixing the e2e tests. Test result: /kind regression /kind bug /sig node /priority important-soon The of a container's probe should override the pod's . a pod with long pod-level terminationGracePeriodSeconds and short probe-level terminationGracePeriodSeconds. for the container not respecting the probe-level terminationGracePeriodSeconds No response <details</details<details</details<details</details<details</details<details</details<details</details
This issue is currently awaiting triage. If a SIG or subproject determines this is a relevant issue, they will accept it by applying the label and provide further guidance. The label can be by org members by writing in a comment. <detailsInstructions for interacting with me using PR comments are available . If you have questions or suggestions related to my behavior, please file an issue against the repository. </details
I guess the probe's terminationGracePeriodSeconds field is dropped for some reason.
/assign

} } <del> if !probeGracePeriodInUse(oldPodSpec) { // Set pod-level terminationGracePeriodSeconds to nil if the feature is disabled and it is not used VisitContainers(podSpec, AllContainers, func(c *api.Container, containerType ContainerType) bool { if c.LivenessProbe != nil { c.LivenessProbe.TerminationGracePeriodSeconds = nil } if c.StartupProbe != nil { c.StartupProbe.TerminationGracePeriodSeconds = nil } // cannot be set for readiness probes return true }) } </del> // If the feature is disabled and not in use, drop the hostUsers field. if !utilfeature.DefaultFeatureGate.Enabled(features.UserNamespacesSupport) && !hostUsersInUse(oldPodSpec) { // Drop the field in podSpec only if SecurityContext is not nil.


Question:
Kubernetes does not respect the of a probe. I found this while fixing the e2e tests. Test result: /kind regression /kind bug /sig node /priority important-soon The of a container's probe should override the pod's . a pod with long pod-level terminationGracePeriodSeconds and short probe-level terminationGracePeriodSeconds. for the container not respecting the probe-level terminationGracePeriodSeconds No response <details</details<details</details<details</details<details</details<details</details<details</details
This issue is currently awaiting triage. If a SIG or subproject determines this is a relevant issue, they will accept it by applying the label and provide further guidance. The label can be by org members by writing in a comment. <detailsInstructions for interacting with me using PR comments are available . If you have questions or suggestions related to my behavior, please file an issue against the repository. </details
I guess the probe's terminationGracePeriodSeconds field is dropped for some reason.
/assign

return false } <del> // probeGracePeriodInUse returns true if the pod spec is non-nil and has a probe that makes use // of the probe-level terminationGracePeriodSeconds feature func probeGracePeriodInUse(podSpec *api.PodSpec) bool { if podSpec == nil { return false } var inUse bool VisitContainers(podSpec, AllContainers, func(c *api.Container, containerType ContainerType) bool { // cannot be set for readiness probes if (c.LivenessProbe != nil && c.LivenessProbe.TerminationGracePeriodSeconds != nil) || (c.StartupProbe != nil && c.StartupProbe.TerminationGracePeriodSeconds != nil) { inUse = true return false } return true }) return inUse } </del> // schedulingGatesInUse returns true if the pod spec is non-nil and it has SchedulingGates field set. func schedulingGatesInUse(podSpec *api.PodSpec) bool { if podSpec == nil {


Question:
A client is allowed to add custom finalizers to Custom Resources with a finalizer name that's not fully qualified (e.g. or ). However they're prevented from doing the same on builtin resource types, returning the following error: Invalid value: "": name is neither a standard finalizer name nor is it fully qualified Per , custom finalizer names are expected to be in format "consist of a domain name, a forward slash and the name of the finalizer" (e.g. ). Therefore, I expected the enforcement to be the same for CRs and builtin types. a custom resource on the cluster it to add the edit does not fail the same on a builtin resource (e.g. Namespace or Pod), observe it fails No response Reproducible at least starting from 1.21 and still on latest versions. <details</details<detailsN/A kind cluster </details<detailsN/A - kind cluster accessed via macOS </details<details</details<details</details<details</details
/area api /cc /sig api-machinery
/assign /triage accepted
There is no validation of finalizer in and . Please unassign me if you guys have started to work on it. /assign
it is called from here on custom resources:
lacks validation for finalizer name. I have raised a pr for this. PTAL.

"k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" <ins> "k8s.io/apimachinery/pkg/util/sets" </ins> "k8s.io/apimachinery/pkg/util/validation/field" celconfig "k8s.io/apiserver/pkg/apis/cel" "k8s.io/apiserver/pkg/features"


Question:
A client is allowed to add custom finalizers to Custom Resources with a finalizer name that's not fully qualified (e.g. or ). However they're prevented from doing the same on builtin resource types, returning the following error: Invalid value: "": name is neither a standard finalizer name nor is it fully qualified Per , custom finalizer names are expected to be in format "consist of a domain name, a forward slash and the name of the finalizer" (e.g. ). Therefore, I expected the enforcement to be the same for CRs and builtin types. a custom resource on the cluster it to add the edit does not fail the same on a builtin resource (e.g. Namespace or Pod), observe it fails No response Reproducible at least starting from 1.21 and still on latest versions. <details</details<detailsN/A kind cluster </details<detailsN/A - kind cluster accessed via macOS </details<details</details<details</details<details</details
/area api /cc /sig api-machinery
/assign /triage accepted
There is no validation of finalizer in and . Please unassign me if you guys have started to work on it. /assign
it is called from here on custom resources:
lacks validation for finalizer name. I have raised a pr for this. PTAL.

} // WarningsOnCreate returns warnings for the creation of the given object. <del> func (customResourceStrategy) WarningsOnCreate(ctx context.Context, obj runtime.Object) []string { return nil </del> <ins> func (a customResourceStrategy) WarningsOnCreate(ctx context.Context, obj runtime.Object) []string { return generateWarningsFromObj(obj, nil) } func generateWarningsFromObj(obj, old runtime.Object) []string { var allWarnings []string fldPath := field.NewPath("metadata", "finalizers") newObjAccessor, err := meta.Accessor(obj) if err != nil { return allWarnings } newAdded := sets.NewString(newObjAccessor.GetFinalizers()...) if old != nil { oldObjAccessor, err := meta.Accessor(old) if err != nil { return allWarnings } newAdded = newAdded.Difference(sets.NewString(oldObjAccessor.GetFinalizers()...)) } for _, finalizer := range newAdded.List() { allWarnings = append(allWarnings, validateKubeFinalizerName(finalizer, fldPath)...) } return allWarnings </ins> } // Canonicalize normalizes the object after validation.


Question:
A client is allowed to add custom finalizers to Custom Resources with a finalizer name that's not fully qualified (e.g. or ). However they're prevented from doing the same on builtin resource types, returning the following error: Invalid value: "": name is neither a standard finalizer name nor is it fully qualified Per , custom finalizer names are expected to be in format "consist of a domain name, a forward slash and the name of the finalizer" (e.g. ). Therefore, I expected the enforcement to be the same for CRs and builtin types. a custom resource on the cluster it to add the edit does not fail the same on a builtin resource (e.g. Namespace or Pod), observe it fails No response Reproducible at least starting from 1.21 and still on latest versions. <details</details<detailsN/A kind cluster </details<detailsN/A - kind cluster accessed via macOS </details<details</details<details</details<details</details
/area api /cc /sig api-machinery
/assign /triage accepted
There is no validation of finalizer in and . Please unassign me if you guys have started to work on it. /assign
it is called from here on custom resources:
lacks validation for finalizer name. I have raised a pr for this. PTAL.

} // WarningsOnUpdate returns warnings for the given update. <del> func (customResourceStrategy) WarningsOnUpdate(ctx context.Context, obj, old runtime.Object) []string { return nil </del> <ins> func (a customResourceStrategy) WarningsOnUpdate(ctx context.Context, obj, old runtime.Object) []string { return generateWarningsFromObj(obj, old) </ins> } // GetAttrs returns labels and fields of a given object for filtering purposes.


Question:
A client is allowed to add custom finalizers to Custom Resources with a finalizer name that's not fully qualified (e.g. or ). However they're prevented from doing the same on builtin resource types, returning the following error: Invalid value: "": name is neither a standard finalizer name nor is it fully qualified Per , custom finalizer names are expected to be in format "consist of a domain name, a forward slash and the name of the finalizer" (e.g. ). Therefore, I expected the enforcement to be the same for CRs and builtin types. a custom resource on the cluster it to add the edit does not fail the same on a builtin resource (e.g. Namespace or Pod), observe it fails No response Reproducible at least starting from 1.21 and still on latest versions. <details</details<detailsN/A kind cluster </details<detailsN/A - kind cluster accessed via macOS </details<details</details<details</details<details</details
/area api /cc /sig api-machinery
/assign /triage accepted
There is no validation of finalizer in and . Please unassign me if you guys have started to work on it. /assign
it is called from here on custom resources:
lacks validation for finalizer name. I have raised a pr for this. PTAL.

"math" "strings" <ins> corev1 "k8s.io/api/core/v1" </ins> "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/api/validation" <ins> metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" </ins> "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" <ins> "k8s.io/apimachinery/pkg/util/sets" apimachineryvalidation "k8s.io/apimachinery/pkg/util/validation" </ins> "k8s.io/apimachinery/pkg/util/validation/field" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"


Question:
A client is allowed to add custom finalizers to Custom Resources with a finalizer name that's not fully qualified (e.g. or ). However they're prevented from doing the same on builtin resource types, returning the following error: Invalid value: "": name is neither a standard finalizer name nor is it fully qualified Per , custom finalizer names are expected to be in format "consist of a domain name, a forward slash and the name of the finalizer" (e.g. ). Therefore, I expected the enforcement to be the same for CRs and builtin types. a custom resource on the cluster it to add the edit does not fail the same on a builtin resource (e.g. Namespace or Pod), observe it fails No response Reproducible at least starting from 1.21 and still on latest versions. <details</details<detailsN/A kind cluster </details<detailsN/A - kind cluster accessed via macOS </details<details</details<details</details<details</details
/area api /cc /sig api-machinery
/assign /triage accepted
There is no validation of finalizer in and . Please unassign me if you guys have started to work on it. /assign
it is called from here on custom resources:
lacks validation for finalizer name. I have raised a pr for this. PTAL.

return allErrs } <del> // WarningsOnUpdate returns warnings for the given update. func (customResourceValidator) WarningsOnUpdate(ctx context.Context, obj, old runtime.Object) []string { return nil </del> <ins> var standardFinalizers = sets.NewString( metav1.FinalizerOrphanDependents, metav1.FinalizerDeleteDependents, string(corev1.FinalizerKubernetes), ) func validateKubeFinalizerName(stringValue string, fldPath *field.Path) []string { var allWarnings []string for _, msg := range apimachineryvalidation.IsQualifiedName(stringValue) { allWarnings = append(allWarnings, fmt.Sprintf("%s: %q: %s", fldPath.String(), stringValue, msg)) } if len(strings.Split(stringValue, "/")) == 1 { if !standardFinalizers.Has(stringValue) { allWarnings = append(allWarnings, fmt.Sprintf("%s: %q: prefer a domain-qualified finalizer name to avoid accidental conflicts with other finalizer writers", fldPath.String(), stringValue)) } } return allWarnings </ins> } func (a customResourceValidator) ValidateStatusUpdate(ctx context.Context, obj, old runtime.Object, scale *apiextensions.CustomResourceSubresourceScale) field.ErrorList {


Question:
A client is allowed to add custom finalizers to Custom Resources with a finalizer name that's not fully qualified (e.g. or ). However they're prevented from doing the same on builtin resource types, returning the following error: Invalid value: "": name is neither a standard finalizer name nor is it fully qualified Per , custom finalizer names are expected to be in format "consist of a domain name, a forward slash and the name of the finalizer" (e.g. ). Therefore, I expected the enforcement to be the same for CRs and builtin types. a custom resource on the cluster it to add the edit does not fail the same on a builtin resource (e.g. Namespace or Pod), observe it fails No response Reproducible at least starting from 1.21 and still on latest versions. <details</details<detailsN/A kind cluster </details<detailsN/A - kind cluster accessed via macOS </details<details</details<details</details<details</details
/area api /cc /sig api-machinery
/assign /triage accepted
There is no validation of finalizer in and . Please unassign me if you guys have started to work on it. /assign
it is called from here on custom resources:
lacks validation for finalizer name. I have raised a pr for this. PTAL.

} }` <ins> crdApplyFinalizerBody = ` { "apiVersion": "%s", "kind": "%s", "metadata": { "name": "%s", "finalizers": %s }, "spec": { "knownField1": "val1", "ports": [{ "name": "portName", "containerPort": 8080, "protocol": "TCP", "hostPort": 8082 }], "embeddedObj": { "apiVersion": "v1", "kind": "ConfigMap", "metadata": { "name": "my-cm", "namespace": "my-ns" } } } }` </ins> patchYAMLBody = ` apiVersion: %s kind: %s metadata: name: %s finalizers: <del> - test-finalizer </del> <ins> - test/finalizer </ins> spec: cronSpec: "* * * * */5" ports:


Question:
A client is allowed to add custom finalizers to Custom Resources with a finalizer name that's not fully qualified (e.g. or ). However they're prevented from doing the same on builtin resource types, returning the following error: Invalid value: "": name is neither a standard finalizer name nor is it fully qualified Per , custom finalizer names are expected to be in format "consist of a domain name, a forward slash and the name of the finalizer" (e.g. ). Therefore, I expected the enforcement to be the same for CRs and builtin types. a custom resource on the cluster it to add the edit does not fail the same on a builtin resource (e.g. Namespace or Pod), observe it fails No response Reproducible at least starting from 1.21 and still on latest versions. <details</details<detailsN/A kind cluster </details<detailsN/A - kind cluster accessed via macOS </details<details</details<details</details<details</details
/area api /cc /sig api-machinery
/assign /triage accepted
There is no validation of finalizer in and . Please unassign me if you guys have started to work on it. /assign
it is called from here on custom resources:
lacks validation for finalizer name. I have raised a pr for this. PTAL.

t.Run("PatchCRDSchemaless", func(t *testing.T) { testFieldValidationPatchCRDSchemaless(t, rest, schemalessGVK, schemalessGVR) }) t.Run("ApplyCreateCRDSchemaless", func(t *testing.T) { testFieldValidationApplyCreateCRDSchemaless(t, rest, schemalessGVK, schemalessGVR) }) t.Run("ApplyUpdateCRDSchemaless", func(t *testing.T) { testFieldValidationApplyUpdateCRDSchemaless(t, rest, schemalessGVK, schemalessGVR) }) <ins> t.Run("testFinalizerValidationApplyCreateCRD", func(t *testing.T) { testFinalizerValidationApplyCreateAndUpdateCRD(t, rest, schemalessGVK, schemalessGVR) }) </ins> } // testFieldValidationPost tests POST requests containing unknown fields with


Question:
A client is allowed to add custom finalizers to Custom Resources with a finalizer name that's not fully qualified (e.g. or ). However they're prevented from doing the same on builtin resource types, returning the following error: Invalid value: "": name is neither a standard finalizer name nor is it fully qualified Per , custom finalizer names are expected to be in format "consist of a domain name, a forward slash and the name of the finalizer" (e.g. ). Therefore, I expected the enforcement to be the same for CRs and builtin types. a custom resource on the cluster it to add the edit does not fail the same on a builtin resource (e.g. Namespace or Pod), observe it fails No response Reproducible at least starting from 1.21 and still on latest versions. <details</details<detailsN/A kind cluster </details<detailsN/A - kind cluster accessed via macOS </details<details</details<details</details<details</details
/area api /cc /sig api-machinery
/assign /triage accepted
There is no validation of finalizer in and . Please unassign me if you guys have started to work on it. /assign
it is called from here on custom resources:
lacks validation for finalizer name. I have raised a pr for this. PTAL.

} } <ins> func testFinalizerValidationApplyCreateAndUpdateCRD(t *testing.T, rest rest.Interface, gvk schema.GroupVersionKind, gvr schema.GroupVersionResource) { var testcases = []struct { name                 string finalizer            []string updatedFinalizer     []string opts                 metav1.PatchOptions expectUpdateWarnings []string expectCreateWarnings []string }{ { name:      "create-crd-with-invalid-finalizer", finalizer: []string{"invalid-finalizer"}, expectCreateWarnings: []string{ `metadata.finalizers: "invalid-finalizer": prefer a domain-qualified finalizer name to avoid accidental conflicts with other finalizer writers`, }, }, { name:      "create-crd-with-valid-finalizer", finalizer: []string{"kubernetes.io/valid-finalizer"}, }, { name:             "update-crd-with-invalid-finalizer", finalizer:        []string{"invalid-finalizer"}, updatedFinalizer: []string{"another-invalid-finalizer"}, expectCreateWarnings: []string{ `metadata.finalizers: "invalid-finalizer": prefer a domain-qualified finalizer name to avoid accidental conflicts with other finalizer writers`, }, expectUpdateWarnings: []string{ `metadata.finalizers: "another-invalid-finalizer": prefer a domain-qualified finalizer name to avoid accidental conflicts with other finalizer writers`, }, }, { name:             "update-crd-with-valid-finalizer", finalizer:        []string{"kubernetes.io/valid-finalizer"}, updatedFinalizer: []string{"kubernetes.io/another-valid-finalizer"}, }, { name:             "update-crd-with-valid-finalizer-leaving-an-existing-invalid-finalizer", finalizer:        []string{"invalid-finalizer"}, updatedFinalizer: []string{"kubernetes.io/another-valid-finalizer"}, expectCreateWarnings: []string{ `metadata.finalizers: "invalid-finalizer": prefer a domain-qualified finalizer name to avoid accidental conflicts with other finalizer writers`, }, }, } for _, tc := range testcases { t.Run(tc.name, func(t *testing.T) { kind := gvk.Kind apiVersion := gvk.Group + "/" + gvk.Version // create the CR as specified by the test case name := fmt.Sprintf("apply-create-crd-%s", tc.name) finalizerVal, _ := json.Marshal(tc.finalizer) applyCreateBody := []byte(fmt.Sprintf(crdApplyFinalizerBody, apiVersion, kind, name, finalizerVal)) req := rest.Patch(types.ApplyPatchType). AbsPath("/apis", gvr.Group, gvr.Version, gvr.Resource). Name(name). Param("fieldManager", "apply_test"). VersionedParams(&tc.opts, metav1.ParameterCodec) result := req.Body(applyCreateBody).Do(context.TODO()) if result.Error() != nil { t.Fatalf("unexpected error: %v", result.Error()) } if len(result.Warnings()) != len(tc.expectCreateWarnings) { for _, r := range result.Warnings() { t.Logf("received warning: %v", r) } t.Fatalf("unexpected number of warnings, expected: %d, got: %d", len(tc.expectCreateWarnings), len(result.Warnings())) } for i, expectedWarning := range tc.expectCreateWarnings { if expectedWarning != result.Warnings()[i].Text { t.Fatalf("expected warning: %s, got warning: %s", expectedWarning, result.Warnings()[i].Text) } } if len(tc.updatedFinalizer) != 0 { finalizerVal, _ := json.Marshal(tc.updatedFinalizer) applyUpdateBody := []byte(fmt.Sprintf(crdApplyFinalizerBody, apiVersion, kind, name, finalizerVal)) updateReq := rest.Patch(types.ApplyPatchType). AbsPath("/apis", gvr.Group, gvr.Version, gvr.Resource). Name(name). Param("fieldManager", "apply_test"). VersionedParams(&tc.opts, metav1.ParameterCodec) result = updateReq.Body(applyUpdateBody).Do(context.TODO()) if result.Error() != nil { t.Fatalf("unexpected error: %v", result.Error()) } if len(result.Warnings()) != len(tc.expectUpdateWarnings) { t.Fatalf("unexpected number of warnings, expected: %d, got: %d", len(tc.expectUpdateWarnings), len(result.Warnings())) } for i, expectedWarning := range tc.expectUpdateWarnings { if expectedWarning != result.Warnings()[i].Text { t.Fatalf("expected warning: %s, got warning: %s", expectedWarning, result.Warnings()[i].Text) } } } }) } } </ins> func setupCRD(t testing.TB, config *rest.Config, apiGroup string, schemaless bool) *apiextensionsv1.CustomResourceDefinition { apiExtensionClient, err := apiextensionsclient.NewForConfig(config) if err != nil {


Question:
A client is allowed to add custom finalizers to Custom Resources with a finalizer name that's not fully qualified (e.g. or ). However they're prevented from doing the same on builtin resource types, returning the following error: Invalid value: "": name is neither a standard finalizer name nor is it fully qualified Per , custom finalizer names are expected to be in format "consist of a domain name, a forward slash and the name of the finalizer" (e.g. ). Therefore, I expected the enforcement to be the same for CRs and builtin types. a custom resource on the cluster it to add the edit does not fail the same on a builtin resource (e.g. Namespace or Pod), observe it fails No response Reproducible at least starting from 1.21 and still on latest versions. <details</details<detailsN/A kind cluster </details<detailsN/A - kind cluster accessed via macOS </details<details</details<details</details<details</details
/area api /cc /sig api-machinery
/assign /triage accepted
There is no validation of finalizer in and . Please unassign me if you guys have started to work on it. /assign
it is called from here on custom resources:
lacks validation for finalizer name. I have raised a pr for this. PTAL.

metadata: name: %s finalizers: <del> - test-finalizer </del> <ins> - test/finalizer </ins> spec: cronSpec: "* * * * */5" ports:


Question:
/kind failing-test <!-- If this is a flake, please add: /kind flake --/sig network seems to be related.
This issue is currently awaiting triage. If a SIG or subproject determines this is a relevant issue, they will accept it by applying the label and provide further guidance. The label can be by org members by writing in a comment. <detailsInstructions for interacting with me using PR comments are available . If you have questions or suggestions related to my behavior, please file an issue against the repository. </details
/assign
/triage accepted

Labels: testSvcLabels, }, Spec: v1.ServiceSpec{ <del> Type: "ClusterIP", </del> <ins> Type: "LoadBalancer", </ins> Ports: []v1.ServicePort{{ Name:       "http", Protocol:   v1.ProtocolTCP, Port:       int32(80), TargetPort: intstr.FromInt(80), }}, <ins> LoadBalancerClass: utilpointer.String("example.com/internal-vip"), </ins> }, } _, err = cs.CoreV1().Services(ns).Create(ctx, &testService, metav1.CreateOptions{})


Question:
When PreFilter returns UnschedulableAndUnresolvable, we don't need to run the preemption, but currently we run. This unexpected preemption could cause errors from the preemption by trying to read non-exist PreFilter data. As pointed out (), actually we didn't run the preemption in such cases in the past versions, but introduced this bug. /kind bug /kind regression /sig scheduling /triage accepted /priority important-soon
/assign
will fix this.

// Error returns detailed information of why the pod failed to fit on each node. // A message format is "0/X nodes are available: <PreFilterMsg>. <FilterMsg>. <PostFilterMsg>." func (f *FitError) Error() string { <del> reasons := make(map[string]int) for _, status := range f.Diagnosis.NodeToStatusMap { for _, reason := range status.Reasons() { reasons[reason]++ } } </del> reasonMsg := fmt.Sprintf(NoNodeAvailableMsg+":", f.NumAllNodes) <del> // Add the messages from PreFilter plugins to reasonMsg. </del> preFilterMsg := f.Diagnosis.PreFilterMsg if preFilterMsg != "" { <ins> // PreFilter plugin returns unschedulable. // Add the messages from PreFilter plugins to reasonMsg. </ins> reasonMsg += fmt.Sprintf(SeparatorFormat, preFilterMsg) } <del> sortReasonsHistogram := func() []string { var reasonStrings []string for k, v := range reasons { reasonStrings = append(reasonStrings, fmt.Sprintf("%v %v", v, k)) </del> <ins> if preFilterMsg == "" { // the scheduling cycle went through PreFilter extension point successfully. // // When the prefilter plugin returns unschedulable, // the scheduling framework inserts the same unschedulable status to all nodes in NodeToStatusMap. // So, we shouldn't add the message from NodeToStatusMap when the PreFilter failed. // Otherwise, we will have duplicated reasons in the error message. reasons := make(map[string]int) for _, status := range f.Diagnosis.NodeToStatusMap { for _, reason := range status.Reasons() { reasons[reason]++ } } sortReasonsHistogram := func() []string { var reasonStrings []string for k, v := range reasons { reasonStrings = append(reasonStrings, fmt.Sprintf("%v %v", v, k)) } sort.Strings(reasonStrings) return reasonStrings } sortedFilterMsg := sortReasonsHistogram() if len(sortedFilterMsg) != 0 { reasonMsg += fmt.Sprintf(SeparatorFormat, strings.Join(sortedFilterMsg, ", ")) </ins> } <del> sort.Strings(reasonStrings) return reasonStrings } sortedFilterMsg := sortReasonsHistogram() if len(sortedFilterMsg) != 0 { reasonMsg += fmt.Sprintf(SeparatorFormat, strings.Join(sortedFilterMsg, ", ")) </del> } // Add the messages from PostFilter plugins to reasonMsg. <ins> // We can add this message regardless of whether the scheduling cycle fails at PreFilter or Filter // since we may run PostFilter (if enabled) in both cases. </ins> postFilterMsg := f.Diagnosis.PostFilterMsg if postFilterMsg != "" { reasonMsg += fmt.Sprintf(SeparatorFormat, postFilterMsg)


Question:
When PreFilter returns UnschedulableAndUnresolvable, we don't need to run the preemption, but currently we run. This unexpected preemption could cause errors from the preemption by trying to read non-exist PreFilter data. As pointed out (), actually we didn't run the preemption in such cases in the past versions, but introduced this bug. /kind bug /kind regression /sig scheduling /triage accepted /priority important-soon
/assign
will fix this.

numAllNodes: 3, diagnosis: Diagnosis{ PreFilterMsg: "Node(s) failed PreFilter plugin FalsePreFilter", <ins> NodeToStatusMap: NodeToStatusMap{ // They're inserted by the framework. // We don't include them in the reason message because they'd be just duplicates. "node1": NewStatus(Unschedulable, "Node(s) failed PreFilter plugin FalsePreFilter"), "node2": NewStatus(Unschedulable, "Node(s) failed PreFilter plugin FalsePreFilter"), "node3": NewStatus(Unschedulable, "Node(s) failed PreFilter plugin FalsePreFilter"), }, </ins> }, wantReasonMsg: "0/3 nodes are available: Node(s) failed PreFilter plugin FalsePreFilter.", }, { <ins> name:        "nodes failed Prefilter plugin and the preemption also failed", numAllNodes: 3, diagnosis: Diagnosis{ PreFilterMsg: "Node(s) failed PreFilter plugin FalsePreFilter", NodeToStatusMap: NodeToStatusMap{ // They're inserted by the framework. // We don't include them in the reason message because they'd be just duplicates. "node1": NewStatus(Unschedulable, "Node(s) failed PreFilter plugin FalsePreFilter"), "node2": NewStatus(Unschedulable, "Node(s) failed PreFilter plugin FalsePreFilter"), "node3": NewStatus(Unschedulable, "Node(s) failed PreFilter plugin FalsePreFilter"), }, // PostFilterMsg will be included. PostFilterMsg: "Error running PostFilter plugin FailedPostFilter", }, wantReasonMsg: "0/3 nodes are available: Node(s) failed PreFilter plugin FalsePreFilter. Error running PostFilter plugin FailedPostFilter.", }, { </ins> name:        "nodes failed one Filter plugin with an empty PostFilterMsg", numAllNodes: 3, diagnosis: Diagnosis{


Question:
When PreFilter returns UnschedulableAndUnresolvable, we don't need to run the preemption, but currently we run. This unexpected preemption could cause errors from the preemption by trying to read non-exist PreFilter data. As pointed out (), actually we didn't run the preemption in such cases in the past versions, but introduced this bug. /kind bug /kind regression /sig scheduling /triage accepted /priority important-soon
/assign
will fix this.

if !s.IsUnschedulable() { return nil, diagnosis, s.AsError() } <ins> // All nodes in NodeToStatusMap will have the same status so that they can be handled in the preemption. // Some non trivial refactoring is needed to avoid this copy. for _, n := range allNodes { diagnosis.NodeToStatusMap[n.Node().Name] = s } </ins> // Record the messages from PreFilter in Diagnosis.PreFilterMsg. msg := s.Message() diagnosis.PreFilterMsg = msg


Question:
When PreFilter returns UnschedulableAndUnresolvable, we don't need to run the preemption, but currently we run. This unexpected preemption could cause errors from the preemption by trying to read non-exist PreFilter data. As pointed out (), actually we didn't run the preemption in such cases in the past versions, but introduced this bug. /kind bug /kind regression /sig scheduling /triage accepted /priority important-soon
/assign
will fix this.

Pod:         st.MakePod().Name("ignore").UID("ignore").PVC("unknownPVC").Obj(), NumAllNodes: 2, Diagnosis: framework.Diagnosis{ <del> NodeToStatusMap:      framework.NodeToStatusMap{}, </del> <ins> NodeToStatusMap: framework.NodeToStatusMap{ "node1": framework.NewStatus(framework.UnschedulableAndUnresolvable, `persistentvolumeclaim "unknownPVC" not found`).WithFailedPlugin("VolumeBinding"), "node2": framework.NewStatus(framework.UnschedulableAndUnresolvable, `persistentvolumeclaim "unknownPVC" not found`).WithFailedPlugin("VolumeBinding"), }, </ins> PreFilterMsg:         `persistentvolumeclaim "unknownPVC" not found`, UnschedulablePlugins: sets.New(volumebinding.Name), },


Question:
When PreFilter returns UnschedulableAndUnresolvable, we don't need to run the preemption, but currently we run. This unexpected preemption could cause errors from the preemption by trying to read non-exist PreFilter data. As pointed out (), actually we didn't run the preemption in such cases in the past versions, but introduced this bug. /kind bug /kind regression /sig scheduling /triage accepted /priority important-soon
/assign
will fix this.

Pod:         st.MakePod().Name("ignore").UID("ignore").Namespace(v1.NamespaceDefault).PVC("existingPVC").Obj(), NumAllNodes: 2, Diagnosis: framework.Diagnosis{ <del> NodeToStatusMap:      framework.NodeToStatusMap{}, </del> <ins> NodeToStatusMap: framework.NodeToStatusMap{ "node1": framework.NewStatus(framework.UnschedulableAndUnresolvable, `persistentvolumeclaim "existingPVC" is being deleted`).WithFailedPlugin("VolumeBinding"), "node2": framework.NewStatus(framework.UnschedulableAndUnresolvable, `persistentvolumeclaim "existingPVC" is being deleted`).WithFailedPlugin("VolumeBinding"), }, </ins> PreFilterMsg:         `persistentvolumeclaim "existingPVC" is being deleted`, UnschedulablePlugins: sets.New(volumebinding.Name), },


Question:
When PreFilter returns UnschedulableAndUnresolvable, we don't need to run the preemption, but currently we run. This unexpected preemption could cause errors from the preemption by trying to read non-exist PreFilter data. As pointed out (), actually we didn't run the preemption in such cases in the past versions, but introduced this bug. /kind bug /kind regression /sig scheduling /triage accepted /priority important-soon
/assign
will fix this.

Pod:         st.MakePod().Name("test-prefilter").UID("test-prefilter").Obj(), NumAllNodes: 2, Diagnosis: framework.Diagnosis{ <del> NodeToStatusMap:      framework.NodeToStatusMap{}, </del> <ins> NodeToStatusMap: framework.NodeToStatusMap{ "1": framework.NewStatus(framework.UnschedulableAndUnresolvable, "injected unschedulable status").WithFailedPlugin("FakePreFilter"), "2": framework.NewStatus(framework.UnschedulableAndUnresolvable, "injected unschedulable status").WithFailedPlugin("FakePreFilter"), }, </ins> PreFilterMsg:         "injected unschedulable status", UnschedulablePlugins: sets.New("FakePreFilter"), },


Question:
When PreFilter returns UnschedulableAndUnresolvable, we don't need to run the preemption, but currently we run. This unexpected preemption could cause errors from the preemption by trying to read non-exist PreFilter data. As pointed out (), actually we didn't run the preemption in such cases in the past versions, but introduced this bug. /kind bug /kind regression /sig scheduling /triage accepted /priority important-soon
/assign
will fix this.

Pod:         st.MakePod().Name("test-prefilter").UID("test-prefilter").Obj(), NumAllNodes: 3, Diagnosis: framework.Diagnosis{ <del> NodeToStatusMap:      framework.NodeToStatusMap{}, </del> <ins> NodeToStatusMap: framework.NodeToStatusMap{ "node1": framework.NewStatus(framework.Unschedulable, "node(s) didn't satisfy plugin(s) [FakePreFilter2 FakePreFilter3] simultaneously"), "node2": framework.NewStatus(framework.Unschedulable, "node(s) didn't satisfy plugin(s) [FakePreFilter2 FakePreFilter3] simultaneously"), "node3": framework.NewStatus(framework.Unschedulable, "node(s) didn't satisfy plugin(s) [FakePreFilter2 FakePreFilter3] simultaneously"), }, </ins> UnschedulablePlugins: sets.Set[string]{}, PreFilterMsg:         "node(s) didn't satisfy plugin(s) [FakePreFilter2 FakePreFilter3] simultaneously", },


Question:
When PreFilter returns UnschedulableAndUnresolvable, we don't need to run the preemption, but currently we run. This unexpected preemption could cause errors from the preemption by trying to read non-exist PreFilter data. As pointed out (), actually we didn't run the preemption in such cases in the past versions, but introduced this bug. /kind bug /kind regression /sig scheduling /triage accepted /priority important-soon
/assign
will fix this.

Pod:         st.MakePod().Name("test-prefilter").UID("test-prefilter").Obj(), NumAllNodes: 1, Diagnosis: framework.Diagnosis{ <del> NodeToStatusMap:      framework.NodeToStatusMap{}, </del> <ins> NodeToStatusMap: framework.NodeToStatusMap{ "node1": framework.NewStatus(framework.Unschedulable, "node(s) didn't satisfy plugin FakePreFilter2"), }, </ins> UnschedulablePlugins: sets.Set[string]{}, PreFilterMsg:         "node(s) didn't satisfy plugin FakePreFilter2", },