Skip to content

Commit 0a5f061

Browse files
committed
fix: align ingress and gateway watches with HTTPRoute
1 parent 73bada5 commit 0a5f061

File tree

2 files changed

+63
-7
lines changed

2 files changed

+63
-7
lines changed

internal/controller/codercontrolplane_controller.go

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"k8s.io/apimachinery/pkg/api/meta"
2525
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2626
"k8s.io/apimachinery/pkg/runtime"
27+
"k8s.io/apimachinery/pkg/runtime/schema"
2728
"k8s.io/apimachinery/pkg/types"
2829
"k8s.io/apimachinery/pkg/util/intstr"
2930
"k8s.io/client-go/util/retry"
@@ -1269,9 +1270,9 @@ func (r *CoderControlPlaneReconciler) reconcileIngress(ctx context.Context, code
12691270
}
12701271

12711272
wildcardHost := strings.TrimSpace(ingressExpose.WildcardHost)
1272-
servicePort := coderControlPlane.Spec.Service.Port
1273-
if servicePort == 0 {
1274-
servicePort = defaultControlPlanePort
1273+
backendServicePort, backendPortErr := httpRouteBackendServicePort(coderControlPlane)
1274+
if backendPortErr != nil {
1275+
return backendPortErr
12751276
}
12761277

12771278
ingress := &networkingv1.Ingress{ObjectMeta: metav1.ObjectMeta{Name: coderControlPlane.Name, Namespace: coderControlPlane.Namespace}}
@@ -1293,7 +1294,7 @@ func (r *CoderControlPlaneReconciler) reconcileIngress(ctx context.Context, code
12931294
Backend: networkingv1.IngressBackend{
12941295
Service: &networkingv1.IngressServiceBackend{
12951296
Name: coderControlPlane.Name,
1296-
Port: networkingv1.ServiceBackendPort{Number: servicePort},
1297+
Port: networkingv1.ServiceBackendPort{Number: backendServicePort},
12971298
},
12981299
},
12991300
},
@@ -1314,7 +1315,7 @@ func (r *CoderControlPlaneReconciler) reconcileIngress(ctx context.Context, code
13141315
Backend: networkingv1.IngressBackend{
13151316
Service: &networkingv1.IngressServiceBackend{
13161317
Name: coderControlPlane.Name,
1317-
Port: networkingv1.ServiceBackendPort{Number: servicePort},
1318+
Port: networkingv1.ServiceBackendPort{Number: backendServicePort},
13181319
},
13191320
},
13201321
},
@@ -2925,7 +2926,7 @@ func (r *CoderControlPlaneReconciler) SetupWithManager(mgr ctrl.Manager) error {
29252926
return fmt.Errorf("index coder control planes by envFrom Secret name: %w", err)
29262927
}
29272928

2928-
return ctrl.NewControllerManagedBy(mgr).
2929+
builder := ctrl.NewControllerManagedBy(mgr).
29292930
For(&coderv1alpha1.CoderControlPlane{}).
29302931
Owns(&appsv1.Deployment{}).
29312932
Owns(&corev1.Service{}).
@@ -2941,7 +2942,17 @@ func (r *CoderControlPlaneReconciler) SetupWithManager(mgr ctrl.Manager) error {
29412942
Watches(
29422943
&corev1.ConfigMap{},
29432944
handler.EnqueueRequestsFromMapFunc(r.reconcileRequestsForEnvFromConfigMap),
2944-
).
2945+
)
2946+
2947+
// Gateway API is optional; only watch HTTPRoutes when the CRD is installed.
2948+
httpRouteGVK := schema.GroupVersionKind{Group: gatewayv1.GroupVersion.Group, Version: gatewayv1.GroupVersion.Version, Kind: "HTTPRoute"}
2949+
if _, err := mgr.GetRESTMapper().RESTMapping(httpRouteGVK.GroupKind(), httpRouteGVK.Version); err == nil {
2950+
builder = builder.Owns(&gatewayv1.HTTPRoute{})
2951+
} else if !meta.IsNoMatchError(err) {
2952+
return fmt.Errorf("check HTTPRoute REST mapping: %w", err)
2953+
}
2954+
2955+
return builder.
29452956
Named("codercontrolplane").
29462957
Complete(r)
29472958
}

internal/controller/codercontrolplane_controller_test.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3994,6 +3994,51 @@ func TestReconcile_IngressExposure(t *testing.T) {
39943994
}
39953995
})
39963996

3997+
t.Run("IngressTLSServicePort443UsesHTTPBackend", func(t *testing.T) {
3998+
cp := &coderv1alpha1.CoderControlPlane{
3999+
ObjectMeta: metav1.ObjectMeta{Name: "test-ingress-tls-service-port-443-backend", Namespace: "default"},
4000+
Spec: coderv1alpha1.CoderControlPlaneSpec{
4001+
Image: "test-ingress:latest",
4002+
Service: coderv1alpha1.ServiceSpec{Port: 443},
4003+
TLS: coderv1alpha1.TLSSpec{SecretNames: []string{"ingress-backend-tls"}},
4004+
Expose: &coderv1alpha1.ExposeSpec{
4005+
Ingress: &coderv1alpha1.IngressExposeSpec{
4006+
Host: "tls-443.ingress.example.test",
4007+
WildcardHost: "*.tls-443.ingress.example.test",
4008+
},
4009+
},
4010+
},
4011+
}
4012+
if err := k8sClient.Create(ctx, cp); err != nil {
4013+
t.Fatalf("create control plane: %v", err)
4014+
}
4015+
t.Cleanup(func() {
4016+
_ = k8sClient.Delete(ctx, cp)
4017+
})
4018+
4019+
r := &controller.CoderControlPlaneReconciler{Client: k8sClient, Scheme: scheme}
4020+
if _, err := r.Reconcile(ctx, ctrl.Request{NamespacedName: types.NamespacedName{Name: cp.Name, Namespace: cp.Namespace}}); err != nil {
4021+
t.Fatalf("reconcile control plane: %v", err)
4022+
}
4023+
4024+
ingress := &networkingv1.Ingress{}
4025+
if err := k8sClient.Get(ctx, types.NamespacedName{Name: cp.Name, Namespace: cp.Namespace}, ingress); err != nil {
4026+
t.Fatalf("get ingress: %v", err)
4027+
}
4028+
for _, rule := range ingress.Spec.Rules {
4029+
if rule.HTTP == nil || len(rule.HTTP.Paths) != 1 {
4030+
t.Fatalf("expected one ingress HTTP path for host %q, got %#v", rule.Host, rule.HTTP)
4031+
}
4032+
path := rule.HTTP.Paths[0]
4033+
if path.Backend.Service == nil {
4034+
t.Fatalf("expected ingress backend service for host %q", rule.Host)
4035+
}
4036+
if got := path.Backend.Service.Port.Number; got != 80 {
4037+
t.Fatalf("expected ingress backend service port 80 for host %q, got %d", rule.Host, got)
4038+
}
4039+
}
4040+
})
4041+
39974042
t.Run("IngressTLSAndWildcardHost", func(t *testing.T) {
39984043
cp := &coderv1alpha1.CoderControlPlane{
39994044
ObjectMeta: metav1.ObjectMeta{Name: "test-ingress-tls-wildcard", Namespace: "default"},

0 commit comments

Comments
 (0)