Preserve old observedGen if incoming attempts to clear it

This commit is contained in:
Natasha Sarkar 2025-03-06 20:14:46 +00:00
parent 12d34624ba
commit bb3ba9d073
2 changed files with 184 additions and 0 deletions

View File

@ -227,9 +227,38 @@ func (podStatusStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.
newPod.Status.QOSClass = oldPod.Status.QOSClass
}
preserveOldObservedGeneration(newPod, oldPod)
podutil.DropDisabledPodFields(newPod, oldPod)
}
// If a client request tries to clear `observedGeneration`, in the pod status or
// conditions, we preserve the original value.
func preserveOldObservedGeneration(newPod, oldPod *api.Pod) {
if newPod.Status.ObservedGeneration == 0 {
newPod.Status.ObservedGeneration = oldPod.Status.ObservedGeneration
}
// Remember observedGeneration values from old status conditions.
// This is a list per type because validation permits multiple conditions with the same type.
oldConditionGenerations := map[api.PodConditionType][]int64{}
for _, oldCondition := range oldPod.Status.Conditions {
oldConditionGenerations[oldCondition.Type] = append(oldConditionGenerations[oldCondition.Type], oldCondition.ObservedGeneration)
}
// For any conditions in the new status without observedGeneration set, preserve the old value.
for i, newCondition := range newPod.Status.Conditions {
oldGeneration := int64(0)
if oldGenerations, ok := oldConditionGenerations[newCondition.Type]; ok && len(oldGenerations) > 0 {
oldGeneration = oldGenerations[0]
oldConditionGenerations[newCondition.Type] = oldGenerations[1:]
}
if newCondition.ObservedGeneration == 0 {
newPod.Status.Conditions[i].ObservedGeneration = oldGeneration
}
}
}
func (podStatusStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList {
pod := obj.(*api.Pod)
oldPod := old.(*api.Pod)

View File

@ -3396,6 +3396,161 @@ func TestStatusPrepareForUpdate(t *testing.T) {
},
},
},
{
description: "preserve old status.observedGeneration if empty",
oldPod: &api.Pod{
ObjectMeta: metav1.ObjectMeta{Name: "pod"},
Status: api.PodStatus{
ObservedGeneration: 20,
},
},
newPod: &api.Pod{
ObjectMeta: metav1.ObjectMeta{Name: "pod"},
},
expected: &api.Pod{
ObjectMeta: metav1.ObjectMeta{Name: "pod"},
Status: api.PodStatus{
ObservedGeneration: 20,
},
},
},
{
description: "preserve old conditions.observedGeneration if empty",
oldPod: &api.Pod{
ObjectMeta: metav1.ObjectMeta{Name: "pod"},
Status: api.PodStatus{
Conditions: []api.PodCondition{
{
Type: "old=without,new=without",
Status: api.ConditionTrue,
},
{
Type: "old=with,new=without",
Status: api.ConditionTrue,
ObservedGeneration: 20,
},
{
Type: "old=without,new=with",
Status: api.ConditionTrue,
},
{
Type: "old=with,new=with",
Status: api.ConditionTrue,
ObservedGeneration: 20,
},
{
Type: "removed-condition",
Status: api.ConditionTrue,
ObservedGeneration: 1,
},
{
Type: "duplicate type",
Status: api.ConditionTrue,
},
{
Type: "duplicate type",
Status: api.ConditionTrue,
ObservedGeneration: 1,
},
{
Type: "duplicate type",
Status: api.ConditionTrue,
ObservedGeneration: 2,
},
},
},
},
newPod: &api.Pod{
ObjectMeta: metav1.ObjectMeta{Name: "pod"},
Status: api.PodStatus{
Conditions: []api.PodCondition{
{
Type: "old=without,new=without",
Status: api.ConditionTrue,
},
{
Type: "old=with,new=without",
Status: api.ConditionTrue,
},
{
Type: "old=without,new=with",
Status: api.ConditionTrue,
ObservedGeneration: 20,
},
{
Type: "old=with,new=with",
Status: api.ConditionTrue,
ObservedGeneration: 20,
},
{
Type: "new-condition",
Status: api.ConditionTrue,
ObservedGeneration: 1,
},
{
Type: "duplicate type",
Status: api.ConditionTrue,
ObservedGeneration: 1,
},
{
Type: "duplicate type",
Status: api.ConditionTrue,
},
{
Type: "duplicate type",
Status: api.ConditionTrue,
ObservedGeneration: 2,
},
},
},
},
expected: &api.Pod{
ObjectMeta: metav1.ObjectMeta{Name: "pod"},
Status: api.PodStatus{
Conditions: []api.PodCondition{
{
Type: "old=without,new=without",
Status: api.ConditionTrue,
},
{
Type: "old=with,new=without",
Status: api.ConditionTrue,
ObservedGeneration: 20,
},
{
Type: "old=without,new=with",
Status: api.ConditionTrue,
ObservedGeneration: 20,
},
{
Type: "old=with,new=with",
Status: api.ConditionTrue,
ObservedGeneration: 20,
},
{
Type: "new-condition",
Status: api.ConditionTrue,
ObservedGeneration: 1,
},
{
Type: "duplicate type",
Status: api.ConditionTrue,
ObservedGeneration: 1,
},
{
Type: "duplicate type",
Status: api.ConditionTrue,
ObservedGeneration: 1,
},
{
Type: "duplicate type",
Status: api.ConditionTrue,
ObservedGeneration: 2,
},
},
},
},
},
}
for _, tc := range testCases {