Skip to content

Commit 3ebee55

Browse files
committed
fix: requeue gateway exposure to repair httproute drift
1 parent 624ccbe commit 3ebee55

2 files changed

Lines changed: 35 additions & 23 deletions

File tree

internal/controller/codercontrolplane_controller.go

Lines changed: 30 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ const (
6767
licenseConditionReasonNotSupported = "NotSupported"
6868
licenseConditionReasonError = "Error"
6969

70+
gatewayExposureRequeueInterval = 2 * time.Minute
7071
licenseUploadRequestTimeout = 30 * time.Second
7172
entitlementsStatusRefreshInterval = 2 * time.Minute
7273
)
@@ -246,7 +247,8 @@ func (r *CoderControlPlaneReconciler) Reconcile(ctx context.Context, req ctrl.Re
246247
if err != nil {
247248
return ctrl.Result{}, err
248249
}
249-
if err := r.reconcileExposure(ctx, coderControlPlane); err != nil {
250+
gatewayExposureNeedsRequeue, err := r.reconcileExposure(ctx, coderControlPlane)
251+
if err != nil {
250252
return ctrl.Result{}, err
251253
}
252254

@@ -272,7 +274,12 @@ func (r *CoderControlPlaneReconciler) Reconcile(ctx context.Context, req ctrl.Re
272274
return ctrl.Result{}, err
273275
}
274276

275-
return mergeResults(operatorResult, licenseResult, entitlementsResult), nil
277+
result := mergeResults(operatorResult, licenseResult, entitlementsResult)
278+
if gatewayExposureNeedsRequeue {
279+
result = mergeResults(result, ctrl.Result{RequeueAfter: gatewayExposureRequeueInterval})
280+
}
281+
282+
return result, nil
276283
}
277284

278285
func resolveServiceAccountName(cp *coderv1alpha1.CoderControlPlane) string {
@@ -834,44 +841,45 @@ func (r *CoderControlPlaneReconciler) reconcileService(ctx context.Context, code
834841
return service, nil
835842
}
836843

837-
func (r *CoderControlPlaneReconciler) reconcileExposure(ctx context.Context, coderControlPlane *coderv1alpha1.CoderControlPlane) error {
844+
func (r *CoderControlPlaneReconciler) reconcileExposure(ctx context.Context, coderControlPlane *coderv1alpha1.CoderControlPlane) (bool, error) {
838845
if coderControlPlane == nil {
839-
return fmt.Errorf("assertion failed: coder control plane must not be nil")
846+
return false, fmt.Errorf("assertion failed: coder control plane must not be nil")
840847
}
841848

842849
exposeSpec := coderControlPlane.Spec.Expose
843850
if exposeSpec == nil || (exposeSpec.Ingress == nil && exposeSpec.Gateway == nil) {
844851
if err := r.cleanupOwnedIngress(ctx, coderControlPlane); err != nil {
845-
return fmt.Errorf("cleanup managed ingress: %w", err)
852+
return false, fmt.Errorf("cleanup managed ingress: %w", err)
846853
}
847854
if err := r.cleanupOwnedHTTPRoute(ctx, coderControlPlane); err != nil {
848-
return fmt.Errorf("cleanup managed httproute: %w", err)
855+
return false, fmt.Errorf("cleanup managed httproute: %w", err)
849856
}
850-
return nil
857+
return false, nil
851858
}
852859

853860
if exposeSpec.Ingress != nil && exposeSpec.Gateway != nil {
854-
return fmt.Errorf("assertion failed: only one of ingress or gateway exposure may be configured")
861+
return false, fmt.Errorf("assertion failed: only one of ingress or gateway exposure may be configured")
855862
}
856863

857864
if exposeSpec.Ingress != nil {
858865
if err := r.reconcileIngress(ctx, coderControlPlane); err != nil {
859-
return err
866+
return false, err
860867
}
861868
if err := r.cleanupOwnedHTTPRoute(ctx, coderControlPlane); err != nil {
862-
return fmt.Errorf("cleanup managed httproute: %w", err)
869+
return false, fmt.Errorf("cleanup managed httproute: %w", err)
863870
}
864-
return nil
871+
return false, nil
865872
}
866873

867-
if err := r.reconcileHTTPRoute(ctx, coderControlPlane); err != nil {
868-
return err
874+
httpRouteReconciled, err := r.reconcileHTTPRoute(ctx, coderControlPlane)
875+
if err != nil {
876+
return false, err
869877
}
870878
if err := r.cleanupOwnedIngress(ctx, coderControlPlane); err != nil {
871-
return fmt.Errorf("cleanup managed ingress: %w", err)
879+
return false, fmt.Errorf("cleanup managed ingress: %w", err)
872880
}
873881

874-
return nil
882+
return httpRouteReconciled, nil
875883
}
876884

877885
func (r *CoderControlPlaneReconciler) reconcileIngress(ctx context.Context, coderControlPlane *coderv1alpha1.CoderControlPlane) error {
@@ -985,18 +993,18 @@ func (r *CoderControlPlaneReconciler) reconcileIngress(ctx context.Context, code
985993
return nil
986994
}
987995

988-
func (r *CoderControlPlaneReconciler) reconcileHTTPRoute(ctx context.Context, coderControlPlane *coderv1alpha1.CoderControlPlane) error {
996+
func (r *CoderControlPlaneReconciler) reconcileHTTPRoute(ctx context.Context, coderControlPlane *coderv1alpha1.CoderControlPlane) (bool, error) {
989997
if coderControlPlane == nil {
990-
return fmt.Errorf("assertion failed: coder control plane must not be nil")
998+
return false, fmt.Errorf("assertion failed: coder control plane must not be nil")
991999
}
9921000
if coderControlPlane.Spec.Expose == nil || coderControlPlane.Spec.Expose.Gateway == nil {
993-
return fmt.Errorf("assertion failed: gateway exposure spec must not be nil")
1001+
return false, fmt.Errorf("assertion failed: gateway exposure spec must not be nil")
9941002
}
9951003

9961004
gatewayExpose := coderControlPlane.Spec.Expose.Gateway
9971005
primaryHost := strings.TrimSpace(gatewayExpose.Host)
9981006
if primaryHost == "" {
999-
return fmt.Errorf("assertion failed: gateway host must not be empty")
1007+
return false, fmt.Errorf("assertion failed: gateway host must not be empty")
10001008
}
10011009

10021010
httpRoute := &gatewayv1.HTTPRoute{ObjectMeta: metav1.ObjectMeta{Name: coderControlPlane.Name, Namespace: coderControlPlane.Namespace}}
@@ -1089,12 +1097,12 @@ func (r *CoderControlPlaneReconciler) reconcileHTTPRoute(ctx context.Context, co
10891097
ctrl.LoggerFrom(ctx).WithName("controller").WithName("codercontrolplane").Info(
10901098
"Gateway API CRDs not available, skipping HTTPRoute reconciliation",
10911099
)
1092-
return nil
1100+
return false, nil
10931101
}
1094-
return fmt.Errorf("reconcile control plane httproute: %w", err)
1102+
return false, fmt.Errorf("reconcile control plane httproute: %w", err)
10951103
}
10961104

1097-
return nil
1105+
return true, nil
10981106
}
10991107

11001108
func (r *CoderControlPlaneReconciler) cleanupOwnedIngress(ctx context.Context, coderControlPlane *coderv1alpha1.CoderControlPlane) error {

internal/controller/codercontrolplane_controller_test.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3100,9 +3100,13 @@ func TestReconcile_HTTPRouteExposure(t *testing.T) {
31003100

31013101
r := &controller.CoderControlPlaneReconciler{Client: k8sClient, Scheme: scheme}
31023102
namespacedName := types.NamespacedName{Name: cp.Name, Namespace: cp.Namespace}
3103-
if _, err := r.Reconcile(ctx, ctrl.Request{NamespacedName: namespacedName}); err != nil {
3103+
result, err := r.Reconcile(ctx, ctrl.Request{NamespacedName: namespacedName})
3104+
if err != nil {
31043105
t.Fatalf("reconcile control plane: %v", err)
31053106
}
3107+
if result.RequeueAfter <= 0 {
3108+
t.Fatalf("expected gateway exposure to request periodic drift requeue, got %+v", result)
3109+
}
31063110

31073111
httpRoute := &gatewayv1.HTTPRoute{}
31083112
if err := k8sClient.Get(ctx, namespacedName, httpRoute); err != nil {

0 commit comments

Comments
 (0)