Merge pull request #112737 from gjkim42/cleanup-defer-from-sts

StatefulSet: Cleanup the complex defer function updating the status
This commit is contained in:
Kubernetes Prow Robot 2022-11-08 03:16:21 -08:00 committed by GitHub
commit 3451501c2e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 95 additions and 20 deletions

View File

@ -105,8 +105,28 @@ func (ssc *defaultStatefulSetControl) performUpdate(
// perform the main update function and get the status
currentStatus, err = ssc.updateStatefulSet(ctx, set, currentRevision, updateRevision, collisionCount, pods)
if err != nil {
if err != nil && currentStatus == nil {
return currentRevision, updateRevision, nil, err
}
// make sure to update the latest status even if there is an error with non-nil currentStatus
statusErr := ssc.updateStatefulSetStatus(ctx, set, currentStatus)
if statusErr == nil {
klog.V(4).InfoS("Updated status", "statefulSet", klog.KObj(set),
"replicas", currentStatus.Replicas,
"readyReplicas", currentStatus.ReadyReplicas,
"currentReplicas", currentStatus.CurrentReplicas,
"updatedReplicas", currentStatus.UpdatedReplicas)
}
switch {
case err != nil && statusErr != nil:
klog.ErrorS(statusErr, "Could not update status", "statefulSet", klog.KObj(set))
return currentRevision, updateRevision, currentStatus, err
case err != nil:
return currentRevision, updateRevision, currentStatus, err
case statusErr != nil:
return currentRevision, updateRevision, currentStatus, statusErr
}
klog.V(4).InfoS("StatefulSet revisions", "statefulSet", klog.KObj(set),
@ -263,7 +283,7 @@ func (ssc *defaultStatefulSetControl) updateStatefulSet(
currentRevision *apps.ControllerRevision,
updateRevision *apps.ControllerRevision,
collisionCount int32,
pods []*v1.Pod) (statefulSetStatus *apps.StatefulSetStatus, updateErr error) {
pods []*v1.Pod) (*apps.StatefulSetStatus, error) {
// get the current and update revisions of the set.
currentSet, err := ApplyRevision(set, currentRevision)
if err != nil {
@ -325,23 +345,6 @@ func (ssc *defaultStatefulSetControl) updateStatefulSet(
// If the ordinal could not be parsed (ord < 0), ignore the Pod.
}
// make sure to update the latest status even if there is an error later
defer func() {
// update the set's status
statusErr := ssc.updateStatefulSetStatus(ctx, set, &status)
if statusErr == nil {
klog.V(4).InfoS("Updated status", "statefulSet", klog.KObj(set),
"replicas", status.Replicas,
"readyReplicas", status.ReadyReplicas,
"currentReplicas", status.CurrentReplicas,
"updatedReplicas", status.UpdatedReplicas)
} else if updateErr == nil {
updateErr = statusErr
} else {
klog.V(4).InfoS("Could not update status", "statefulSet", klog.KObj(set), "err", statusErr)
}
}()
// for any empty indices in the sequence [0,set.Spec.Replicas) create a new Pod at the correct revision
for ord := 0; ord < replicaCount; ord++ {
if replicas[ord] == nil {
@ -647,7 +650,7 @@ func updateStatefulSetAfterInvariantEstablished(
replicas[target].Name)
if err := ssc.podControl.DeleteStatefulPod(set, replicas[target]); err != nil {
if !errors.IsNotFound(err) {
return nil, err
return &status, err
}
}
deletedPods++

View File

@ -2106,6 +2106,78 @@ func TestStatefulSetAvailability(t *testing.T) {
}
}
func TestStatefulSetStatusUpdate(t *testing.T) {
var (
syncErr = fmt.Errorf("sync error")
statusErr = fmt.Errorf("status error")
)
testCases := []struct {
desc string
hasSyncErr bool
hasStatusErr bool
expectedErr error
}{
{
desc: "no error",
hasSyncErr: false,
hasStatusErr: false,
expectedErr: nil,
},
{
desc: "sync error",
hasSyncErr: true,
hasStatusErr: false,
expectedErr: syncErr,
},
{
desc: "status error",
hasSyncErr: false,
hasStatusErr: true,
expectedErr: statusErr,
},
{
desc: "sync and status error",
hasSyncErr: true,
hasStatusErr: true,
expectedErr: syncErr,
},
}
for _, tc := range testCases {
t.Run(tc.desc, func(t *testing.T) {
set := newStatefulSet(3)
client := fake.NewSimpleClientset(set)
om, ssu, ssc := setupController(client)
if tc.hasSyncErr {
om.SetCreateStatefulPodError(syncErr, 0)
}
if tc.hasStatusErr {
ssu.SetUpdateStatefulSetStatusError(statusErr, 0)
}
selector, err := metav1.LabelSelectorAsSelector(set.Spec.Selector)
if err != nil {
t.Error(err)
}
pods, err := om.podsLister.Pods(set.Namespace).List(selector)
if err != nil {
t.Error(err)
}
_, err = ssc.UpdateStatefulSet(context.TODO(), set, pods)
if ssu.updateStatusTracker.requests != 1 {
t.Errorf("Did not update status")
}
if !errors.Is(err, tc.expectedErr) {
t.Errorf("Expected error: %v, got: %v", tc.expectedErr, err)
}
})
}
}
type requestTracker struct {
requests int
err error