Skip to content

Commit b09da13

Browse files
committed
🤖 fix: merge status deltas to avoid same-gen stale overwrites
Use the reconcile-start status snapshot as a delta base and only apply fields that this reconcile actually changed when retrying status writes on conflicts. This prevents same-generation stale reconciles from clearing fresher license status updates written by newer reconciles. --- _Generated with `mux` • Model: `openai:gpt-5.3-codex` • Thinking: `xhigh` • Cost: `$1.21`_ <!-- mux-attribution: model=openai:gpt-5.3-codex thinking=xhigh costs=1.21 -->
1 parent 9184ed3 commit b09da13

1 file changed

Lines changed: 64 additions & 5 deletions

File tree

‎internal/controller/codercontrolplane_controller.go‎

Lines changed: 64 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,7 @@ func (r *CoderControlPlaneReconciler) Reconcile(ctx context.Context, req ctrl.Re
191191
return ctrl.Result{}, err
192192
}
193193

194+
originalStatus := *coderControlPlane.Status.DeepCopy()
194195
nextStatus := r.desiredStatus(coderControlPlane, deployment, service)
195196

196197
operatorResult, err := r.reconcileOperatorAccess(ctx, coderControlPlane, &nextStatus)
@@ -203,7 +204,7 @@ func (r *CoderControlPlaneReconciler) Reconcile(ctx context.Context, req ctrl.Re
203204
return ctrl.Result{}, err
204205
}
205206

206-
if err := r.reconcileStatus(ctx, coderControlPlane, nextStatus); err != nil {
207+
if err := r.reconcileStatus(ctx, coderControlPlane, originalStatus, nextStatus); err != nil {
207208
return ctrl.Result{}, err
208209
}
209210

@@ -1052,16 +1053,72 @@ func (r *CoderControlPlaneReconciler) reconcileRequestsForLicenseSecret(
10521053
return requests
10531054
}
10541055

1056+
func mergeControlPlaneStatusDelta(
1057+
baseStatus coderv1alpha1.CoderControlPlaneStatus,
1058+
nextStatus coderv1alpha1.CoderControlPlaneStatus,
1059+
latestStatus coderv1alpha1.CoderControlPlaneStatus,
1060+
) coderv1alpha1.CoderControlPlaneStatus {
1061+
mergedStatus := latestStatus
1062+
1063+
if baseStatus.ObservedGeneration != nextStatus.ObservedGeneration {
1064+
mergedStatus.ObservedGeneration = nextStatus.ObservedGeneration
1065+
}
1066+
if baseStatus.ReadyReplicas != nextStatus.ReadyReplicas {
1067+
mergedStatus.ReadyReplicas = nextStatus.ReadyReplicas
1068+
}
1069+
if baseStatus.URL != nextStatus.URL {
1070+
mergedStatus.URL = nextStatus.URL
1071+
}
1072+
if !equality.Semantic.DeepEqual(baseStatus.OperatorTokenSecretRef, nextStatus.OperatorTokenSecretRef) {
1073+
mergedStatus.OperatorTokenSecretRef = cloneSecretKeySelector(nextStatus.OperatorTokenSecretRef)
1074+
}
1075+
if baseStatus.OperatorAccessReady != nextStatus.OperatorAccessReady {
1076+
mergedStatus.OperatorAccessReady = nextStatus.OperatorAccessReady
1077+
}
1078+
if !equality.Semantic.DeepEqual(baseStatus.LicenseLastApplied, nextStatus.LicenseLastApplied) {
1079+
mergedStatus.LicenseLastApplied = cloneMetav1Time(nextStatus.LicenseLastApplied)
1080+
}
1081+
if baseStatus.LicenseLastAppliedHash != nextStatus.LicenseLastAppliedHash {
1082+
mergedStatus.LicenseLastAppliedHash = nextStatus.LicenseLastAppliedHash
1083+
}
1084+
if baseStatus.Phase != nextStatus.Phase {
1085+
mergedStatus.Phase = nextStatus.Phase
1086+
}
1087+
if !equality.Semantic.DeepEqual(baseStatus.Conditions, nextStatus.Conditions) {
1088+
mergedStatus.Conditions = append([]metav1.Condition(nil), nextStatus.Conditions...)
1089+
}
1090+
1091+
return mergedStatus
1092+
}
1093+
1094+
func cloneSecretKeySelector(selector *coderv1alpha1.SecretKeySelector) *coderv1alpha1.SecretKeySelector {
1095+
if selector == nil {
1096+
return nil
1097+
}
1098+
1099+
copied := *selector
1100+
return &copied
1101+
}
1102+
1103+
func cloneMetav1Time(timestamp *metav1.Time) *metav1.Time {
1104+
if timestamp == nil {
1105+
return nil
1106+
}
1107+
1108+
return timestamp.DeepCopy()
1109+
}
1110+
10551111
func (r *CoderControlPlaneReconciler) reconcileStatus(
10561112
ctx context.Context,
10571113
coderControlPlane *coderv1alpha1.CoderControlPlane,
1114+
baseStatus coderv1alpha1.CoderControlPlaneStatus,
10581115
nextStatus coderv1alpha1.CoderControlPlaneStatus,
10591116
) error {
10601117
if coderControlPlane == nil {
10611118
return fmt.Errorf("assertion failed: coder control plane must not be nil")
10621119
}
10631120

1064-
if equality.Semantic.DeepEqual(coderControlPlane.Status, nextStatus) {
1121+
if equality.Semantic.DeepEqual(baseStatus, nextStatus) {
10651122
return nil
10661123
}
10671124

@@ -1093,17 +1150,19 @@ func (r *CoderControlPlaneReconciler) reconcileStatus(
10931150
coderControlPlane.Status = latest.Status
10941151
return nil
10951152
}
1096-
if equality.Semantic.DeepEqual(latest.Status, nextStatus) {
1153+
1154+
mergedStatus := mergeControlPlaneStatusDelta(baseStatus, nextStatus, latest.Status)
1155+
if equality.Semantic.DeepEqual(latest.Status, mergedStatus) {
10971156
coderControlPlane.Status = latest.Status
10981157
return nil
10991158
}
11001159

1101-
latest.Status = nextStatus
1160+
latest.Status = mergedStatus
11021161
if err := r.Status().Update(ctx, latest); err != nil {
11031162
return err
11041163
}
11051164

1106-
coderControlPlane.Status = nextStatus
1165+
coderControlPlane.Status = mergedStatus
11071166
return nil
11081167
}); err != nil {
11091168
return fmt.Errorf("update control plane status: %w", err)

0 commit comments

Comments
 (0)