|
9 | 9 | "testing" |
10 | 10 | "time" |
11 | 11 |
|
| 12 | + core "k8s.io/client-go/testing" |
| 13 | + |
12 | 14 | log "github.com/sirupsen/logrus" |
13 | 15 | corev1 "k8s.io/api/core/v1" |
14 | 16 | "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" |
@@ -186,6 +188,65 @@ func TestProgressDeadlineAbortWithTrafficRoutingError(t *testing.T) { |
186 | 188 | f.verifyPatchedRolloutAborted(patchIndex, rs2.Name) |
187 | 189 | } |
188 | 190 |
|
| 191 | +// TestProgressDeadlineSyncStatusErrorWithTrafficRoutingError verifies that when both |
| 192 | +// reconcileTrafficRouting() and syncRolloutStatusCanary() return errors, the sync error is |
| 193 | +// surfaced (not silently dropped), so the controller requeues the reconcile. |
| 194 | +func TestProgressDeadlineSyncStatusErrorWithTrafficRoutingError(t *testing.T) { |
| 195 | + f := newFixture(t) |
| 196 | + defer f.Close() |
| 197 | + |
| 198 | + steps := []v1alpha1.CanaryStep{ |
| 199 | + {SetWeight: ptr.To[int32](50)}, |
| 200 | + } |
| 201 | + r1 := newCanaryRollout("foo", 10, nil, steps, ptr.To[int32](0), intstr.FromInt(1), intstr.FromInt(0)) |
| 202 | + progressDeadlineSeconds := int32(1) |
| 203 | + r1.Spec.ProgressDeadlineSeconds = &progressDeadlineSeconds |
| 204 | + r1.Spec.ProgressDeadlineAbort = true |
| 205 | + r2 := bumpVersion(r1) |
| 206 | + r2.Spec.Strategy.Canary.TrafficRouting = &v1alpha1.RolloutTrafficRouting{} |
| 207 | + r2.Spec.Strategy.Canary.CanaryService = "canary" |
| 208 | + r2.Spec.Strategy.Canary.StableService = "stable" |
| 209 | + |
| 210 | + rs1 := newReplicaSetWithStatus(r1, 10, 10) |
| 211 | + rs2 := newReplicaSetWithStatus(r2, 3, 3) |
| 212 | + |
| 213 | + rs1PodHash := rs1.Labels[v1alpha1.DefaultRolloutUniqueLabelKey] |
| 214 | + rs2PodHash := rs2.Labels[v1alpha1.DefaultRolloutUniqueLabelKey] |
| 215 | + canarySelector := map[string]string{v1alpha1.DefaultRolloutUniqueLabelKey: rs2PodHash} |
| 216 | + stableSelector := map[string]string{v1alpha1.DefaultRolloutUniqueLabelKey: rs1PodHash} |
| 217 | + canarySvc := newService("canary", 80, canarySelector, r2) |
| 218 | + stableSvc := newService("stable", 80, stableSelector, r2) |
| 219 | + |
| 220 | + f.kubeobjects = append(f.kubeobjects, rs1, rs2, canarySvc, stableSvc) |
| 221 | + f.replicaSetLister = append(f.replicaSetLister, rs1, rs2) |
| 222 | + |
| 223 | + r2 = updateCanaryRolloutStatus(r2, rs1PodHash, 13, 3, 13, false) |
| 224 | + r2.Status.CurrentPodHash = rs2PodHash |
| 225 | + |
| 226 | + msg := fmt.Sprintf("ReplicaSet %q has timed out progressing.", rs2.Name) |
| 227 | + timedOutCond := conditions.NewRolloutCondition(v1alpha1.RolloutProgressing, corev1.ConditionFalse, conditions.TimedOutReason, msg) |
| 228 | + conditions.SetRolloutCondition(&r2.Status, *timedOutCond) |
| 229 | + |
| 230 | + f.rolloutLister = append(f.rolloutLister, r2) |
| 231 | + f.objects = append(f.objects, r2) |
| 232 | + |
| 233 | + f.fakeTrafficRouting = newUnmockedFakeTrafficRoutingReconciler() |
| 234 | + f.fakeTrafficRouting.On("UpdateHash", mock.Anything, mock.Anything, mock.Anything).Return( |
| 235 | + fmt.Errorf("delaying destination rule switch: ReplicaSet %s not fully available", rs2.Name), |
| 236 | + ) |
| 237 | + |
| 238 | + // Initialize the controller first (creates f.client), then inject a reactor that makes |
| 239 | + // the rollout status patch fail. This causes syncRolloutStatusCanary() to return an error, |
| 240 | + // exercising the double-error branch: trafficErr != nil AND syncErr != nil → return syncErr. |
| 241 | + c, i, k8sI := f.newController(noResyncPeriodFunc) |
| 242 | + f.client.PrependReactor("patch", "rollouts", func(action core.Action) (bool, runtime.Object, error) { |
| 243 | + return true, nil, fmt.Errorf("injected patch failure") |
| 244 | + }) |
| 245 | + |
| 246 | + f.expectPatchRolloutAction(r2) |
| 247 | + f.runController(getKey(r2, t), true, true, c, i, k8sI) |
| 248 | +} |
| 249 | + |
189 | 250 | // verify error is not returned when VerifyWeight returns error (so that we can continue reconciling) |
190 | 251 | func TestReconcileTrafficRoutingVerifyWeightErr(t *testing.T) { |
191 | 252 | f, ro := newTrafficWeightFixture(t) |
|
0 commit comments