mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-21 02:41:25 +00:00
Merge pull request #112737 from gjkim42/cleanup-defer-from-sts
StatefulSet: Cleanup the complex defer function updating the status
This commit is contained in:
commit
3451501c2e
@ -105,8 +105,28 @@ func (ssc *defaultStatefulSetControl) performUpdate(
|
|||||||
|
|
||||||
// perform the main update function and get the status
|
// perform the main update function and get the status
|
||||||
currentStatus, err = ssc.updateStatefulSet(ctx, set, currentRevision, updateRevision, collisionCount, pods)
|
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
|
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),
|
klog.V(4).InfoS("StatefulSet revisions", "statefulSet", klog.KObj(set),
|
||||||
@ -263,7 +283,7 @@ func (ssc *defaultStatefulSetControl) updateStatefulSet(
|
|||||||
currentRevision *apps.ControllerRevision,
|
currentRevision *apps.ControllerRevision,
|
||||||
updateRevision *apps.ControllerRevision,
|
updateRevision *apps.ControllerRevision,
|
||||||
collisionCount int32,
|
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.
|
// get the current and update revisions of the set.
|
||||||
currentSet, err := ApplyRevision(set, currentRevision)
|
currentSet, err := ApplyRevision(set, currentRevision)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -325,23 +345,6 @@ func (ssc *defaultStatefulSetControl) updateStatefulSet(
|
|||||||
// If the ordinal could not be parsed (ord < 0), ignore the Pod.
|
// 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 any empty indices in the sequence [0,set.Spec.Replicas) create a new Pod at the correct revision
|
||||||
for ord := 0; ord < replicaCount; ord++ {
|
for ord := 0; ord < replicaCount; ord++ {
|
||||||
if replicas[ord] == nil {
|
if replicas[ord] == nil {
|
||||||
@ -647,7 +650,7 @@ func updateStatefulSetAfterInvariantEstablished(
|
|||||||
replicas[target].Name)
|
replicas[target].Name)
|
||||||
if err := ssc.podControl.DeleteStatefulPod(set, replicas[target]); err != nil {
|
if err := ssc.podControl.DeleteStatefulPod(set, replicas[target]); err != nil {
|
||||||
if !errors.IsNotFound(err) {
|
if !errors.IsNotFound(err) {
|
||||||
return nil, err
|
return &status, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
deletedPods++
|
deletedPods++
|
||||||
|
@ -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 {
|
type requestTracker struct {
|
||||||
requests int
|
requests int
|
||||||
err error
|
err error
|
||||||
|
Loading…
Reference in New Issue
Block a user