Skip to content

Commit b5ba757

Browse files
committed
🤖 fix: retry control-plane status updates on conflicts
Retry CoderControlPlane status updates with `retry.RetryOnConflict` and a fresh read of the latest object before update. This ensures transient resourceVersion conflicts do not drop status updates after a successful license upload, which could otherwise trigger duplicate non-idempotent license posts. --- _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 6f550f4 commit b5ba757

1 file changed

Lines changed: 32 additions & 2 deletions

File tree

‎internal/controller/codercontrolplane_controller.go‎

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"k8s.io/apimachinery/pkg/runtime"
2525
"k8s.io/apimachinery/pkg/types"
2626
"k8s.io/apimachinery/pkg/util/intstr"
27+
"k8s.io/client-go/util/retry"
2728
ctrl "sigs.k8s.io/controller-runtime"
2829
"sigs.k8s.io/controller-runtime/pkg/client"
2930
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
@@ -985,12 +986,41 @@ func (r *CoderControlPlaneReconciler) reconcileStatus(
985986
coderControlPlane *coderv1alpha1.CoderControlPlane,
986987
nextStatus coderv1alpha1.CoderControlPlaneStatus,
987988
) error {
989+
if coderControlPlane == nil {
990+
return fmt.Errorf("assertion failed: coder control plane must not be nil")
991+
}
992+
988993
if equality.Semantic.DeepEqual(coderControlPlane.Status, nextStatus) {
989994
return nil
990995
}
991996

992-
coderControlPlane.Status = nextStatus
993-
if err := r.Status().Update(ctx, coderControlPlane); err != nil {
997+
namespacedName := types.NamespacedName{Name: coderControlPlane.Name, Namespace: coderControlPlane.Namespace}
998+
if strings.TrimSpace(namespacedName.Name) == "" || strings.TrimSpace(namespacedName.Namespace) == "" {
999+
return fmt.Errorf("assertion failed: coder control plane namespaced name must not be empty")
1000+
}
1001+
1002+
if err := retry.RetryOnConflict(retry.DefaultRetry, func() error {
1003+
latest := &coderv1alpha1.CoderControlPlane{}
1004+
if err := r.Get(ctx, namespacedName, latest); err != nil {
1005+
return err
1006+
}
1007+
if latest.Name != namespacedName.Name || latest.Namespace != namespacedName.Namespace {
1008+
return fmt.Errorf("assertion failed: fetched object %s/%s does not match expected %s/%s",
1009+
latest.Namespace, latest.Name, namespacedName.Namespace, namespacedName.Name)
1010+
}
1011+
if equality.Semantic.DeepEqual(latest.Status, nextStatus) {
1012+
coderControlPlane.Status = latest.Status
1013+
return nil
1014+
}
1015+
1016+
latest.Status = nextStatus
1017+
if err := r.Status().Update(ctx, latest); err != nil {
1018+
return err
1019+
}
1020+
1021+
coderControlPlane.Status = nextStatus
1022+
return nil
1023+
}); err != nil {
9941024
return fmt.Errorf("update control plane status: %w", err)
9951025
}
9961026

0 commit comments

Comments
 (0)