diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/status/status_manager_test.go b/vendor/k8s.io/kubernetes/pkg/kubelet/status/status_manager_test.go index 03f79b2a1bb5..7ca1ee13aecd 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/status/status_manager_test.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/status/status_manager_test.go @@ -96,6 +96,7 @@ func getRandomPodStatus() v1.PodStatus { } func verifyActions(t *testing.T, manager *manager, expectedActions []core.Action) { + t.Helper() manager.consumeUpdates() actions := manager.kubeClient.(*fake.Clientset).Actions() defer manager.kubeClient.(*fake.Clientset).ClearActions() @@ -401,17 +402,17 @@ func TestStaleUpdates(t *testing.T) { t.Logf("Nothing left in the channel to sync") verifyActions(t, m, []core.Action{}) - t.Log("Unchanged status should not send an update.") + t.Log("Unchanged status should not send an update") m.SetPodStatus(pod, status) verifyUpdates(t, m, 0) - t.Log("... unless it's stale.") + t.Log("... even if it's stale as long as nothing changes") mirrorPodUID := kubetypes.MirrorPodUID(pod.UID) m.apiStatusVersions[mirrorPodUID] = m.apiStatusVersions[mirrorPodUID] - 1 m.SetPodStatus(pod, status) m.syncBatch() - verifyActions(t, m, []core.Action{getAction(), patchAction()}) + verifyActions(t, m, []core.Action{getAction()}) t.Logf("Nothing stuck in the pipe.") verifyUpdates(t, m, 0) @@ -737,8 +738,9 @@ func TestReconcilePodStatus(t *testing.T) { t.Logf("If the pod status is the same, a reconciliation is not needed and syncBatch should do nothing") syncer.podManager.UpdatePod(testPod) if syncer.needsReconcile(testPod.UID, podStatus) { - t.Errorf("Pod status is the same, a reconciliation is not needed") + t.Fatalf("Pod status is the same, a reconciliation is not needed") } + syncer.SetPodStatus(testPod, podStatus) syncer.syncBatch() verifyActions(t, syncer, []core.Action{}) @@ -751,17 +753,19 @@ func TestReconcilePodStatus(t *testing.T) { testPod.Status.StartTime = &normalizedStartTime syncer.podManager.UpdatePod(testPod) if syncer.needsReconcile(testPod.UID, podStatus) { - t.Errorf("Pod status only differs for timestamp format, a reconciliation is not needed") + t.Fatalf("Pod status only differs for timestamp format, a reconciliation is not needed") } + syncer.SetPodStatus(testPod, podStatus) syncer.syncBatch() verifyActions(t, syncer, []core.Action{}) t.Logf("If the pod status is different, a reconciliation is needed, syncBatch should trigger an update") - testPod.Status = getRandomPodStatus() + changedPodStatus := getRandomPodStatus() syncer.podManager.UpdatePod(testPod) - if !syncer.needsReconcile(testPod.UID, podStatus) { - t.Errorf("Pod status is different, a reconciliation is needed") + if !syncer.needsReconcile(testPod.UID, changedPodStatus) { + t.Fatalf("Pod status is different, a reconciliation is needed") } + syncer.SetPodStatus(testPod, changedPodStatus) syncer.syncBatch() verifyActions(t, syncer, []core.Action{getAction(), patchAction()}) } diff --git a/vendor/k8s.io/kubernetes/pkg/util/pod/pod.go b/vendor/k8s.io/kubernetes/pkg/util/pod/pod.go index 73b1a3834343..c9bb4e385306 100644 --- a/vendor/k8s.io/kubernetes/pkg/util/pod/pod.go +++ b/vendor/k8s.io/kubernetes/pkg/util/pod/pod.go @@ -17,6 +17,7 @@ limitations under the License. package pod import ( + "bytes" "encoding/json" "fmt" @@ -28,25 +29,28 @@ import ( ) // PatchPodStatus patches pod status. -func PatchPodStatus(c clientset.Interface, namespace, name string, uid types.UID, oldPodStatus, newPodStatus v1.PodStatus) (*v1.Pod, []byte, error) { - patchBytes, err := preparePatchBytesforPodStatus(namespace, name, uid, oldPodStatus, newPodStatus) +func PatchPodStatus(c clientset.Interface, namespace, name string, uid types.UID, oldPodStatus, newPodStatus v1.PodStatus) (*v1.Pod, []byte, bool, error) { + patchBytes, unchanged, err := preparePatchBytesforPodStatus(namespace, name, uid, oldPodStatus, newPodStatus) if err != nil { - return nil, nil, err + return nil, nil, false, err + } + if unchanged { + return nil, patchBytes, true, nil } updatedPod, err := c.CoreV1().Pods(namespace).Patch(name, types.StrategicMergePatchType, patchBytes, "status") if err != nil { - return nil, nil, fmt.Errorf("failed to patch status %q for pod %q/%q: %v", patchBytes, namespace, name, err) + return nil, nil, false, fmt.Errorf("failed to patch status %q for pod %q/%q: %v", patchBytes, namespace, name, err) } - return updatedPod, patchBytes, nil + return updatedPod, patchBytes, false, nil } -func preparePatchBytesforPodStatus(namespace, name string, uid types.UID, oldPodStatus, newPodStatus v1.PodStatus) ([]byte, error) { +func preparePatchBytesforPodStatus(namespace, name string, uid types.UID, oldPodStatus, newPodStatus v1.PodStatus) ([]byte, bool, error) { oldData, err := json.Marshal(v1.Pod{ Status: oldPodStatus, }) if err != nil { - return nil, fmt.Errorf("failed to Marshal oldData for pod %q/%q: %v", namespace, name, err) + return nil, false, fmt.Errorf("failed to Marshal oldData for pod %q/%q: %v", namespace, name, err) } newData, err := json.Marshal(v1.Pod{ @@ -54,12 +58,12 @@ func preparePatchBytesforPodStatus(namespace, name string, uid types.UID, oldPod Status: newPodStatus, }) if err != nil { - return nil, fmt.Errorf("failed to Marshal newData for pod %q/%q: %v", namespace, name, err) + return nil, false, fmt.Errorf("failed to Marshal newData for pod %q/%q: %v", namespace, name, err) } patchBytes, err := strategicpatch.CreateTwoWayMergePatch(oldData, newData, v1.Pod{}) if err != nil { - return nil, fmt.Errorf("failed to CreateTwoWayMergePatch for pod %q/%q: %v", namespace, name, err) + return nil, false, fmt.Errorf("failed to CreateTwoWayMergePatch for pod %q/%q: %v", namespace, name, err) } - return patchBytes, nil + return patchBytes, bytes.Equal(patchBytes, []byte(fmt.Sprintf(`{"metadata":{"uid":%q}}`, uid))), nil } diff --git a/vendor/k8s.io/kubernetes/pkg/util/pod/pod_test.go b/vendor/k8s.io/kubernetes/pkg/util/pod/pod_test.go index 9c2b7e4f11af..b438f0a7493c 100644 --- a/vendor/k8s.io/kubernetes/pkg/util/pod/pod_test.go +++ b/vendor/k8s.io/kubernetes/pkg/util/pod/pod_test.go @@ -43,11 +43,13 @@ func TestPatchPodStatus(t *testing.T) { testCases := []struct { description string mutate func(input v1.PodStatus) v1.PodStatus + expectUnchanged bool expectedPatchBytes []byte }{ { "no change", func(input v1.PodStatus) v1.PodStatus { return input }, + true, []byte(fmt.Sprintf(`{"metadata":{"uid":"myuid"}}`)), }, { @@ -56,6 +58,7 @@ func TestPatchPodStatus(t *testing.T) { input.Message = "random message" return input }, + false, []byte(fmt.Sprintf(`{"metadata":{"uid":"myuid"},"status":{"message":"random message"}}`)), }, { @@ -64,6 +67,7 @@ func TestPatchPodStatus(t *testing.T) { input.Conditions[0].Status = v1.ConditionFalse return input }, + false, []byte(fmt.Sprintf(`{"metadata":{"uid":"myuid"},"status":{"$setElementOrder/conditions":[{"type":"Ready"},{"type":"PodScheduled"}],"conditions":[{"status":"False","type":"Ready"}]}}`)), }, { @@ -77,17 +81,23 @@ func TestPatchPodStatus(t *testing.T) { } return input }, + false, []byte(fmt.Sprintf(`{"metadata":{"uid":"myuid"},"status":{"initContainerStatuses":[{"image":"","imageID":"","lastState":{},"name":"init-container","ready":true,"restartCount":0,"state":{}}]}}`)), }, } for _, tc := range testCases { - _, patchBytes, err := PatchPodStatus(client, ns, name, uid, getPodStatus(), tc.mutate(getPodStatus())) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if !reflect.DeepEqual(patchBytes, tc.expectedPatchBytes) { - t.Errorf("for test case %q, expect patchBytes: %q, got: %q\n", tc.description, tc.expectedPatchBytes, patchBytes) - } + t.Run(tc.description, func(t *testing.T) { + _, patchBytes, unchanged, err := PatchPodStatus(client, ns, name, uid, getPodStatus(), tc.mutate(getPodStatus())) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + if unchanged != tc.expectUnchanged { + t.Errorf("unexpected change: %t", unchanged) + } + if !reflect.DeepEqual(patchBytes, tc.expectedPatchBytes) { + t.Errorf("expect patchBytes: %q, got: %q\n", tc.expectedPatchBytes, patchBytes) + } + }) } }