Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 14 additions & 4 deletions pkg/deployer/deployer.go
Original file line number Diff line number Diff line change
Expand Up @@ -303,9 +303,19 @@ func (d *Deployer) SetNamespaceAndOwnerWithGVK(owner client.Object, ownerGVK sch
return objs
}

// getControllerNameForGatewayClass returns the appropriate controller name based on the gateway class name
func (d *Deployer) getControllerNameForGatewayClass(gatewayClassName string) string {
if gatewayClassName == d.agwGatewayClassName {
// getControllerNameForGatewayClass looks up the GatewayClass and returns the controller name
// from its spec, falling back to class name comparison if the lookup fails.
func (d *Deployer) getControllerNameForGatewayClass(ctx context.Context, gatewayClassName string) string {
gwc, err := d.client.GatewayAPI().GatewayV1().GatewayClasses().Get(ctx, gatewayClassName, metav1.GetOptions{})
if err != nil {
logger.Debug("failed to look up GatewayClass, falling back to class name comparison",
"gateway_class_name", gatewayClassName, "error", err)
if gatewayClassName == d.agwGatewayClassName {
return d.agwControllerName
}
return d.controllerName
}
if string(gwc.Spec.ControllerName) == d.agwControllerName {
return d.agwControllerName
}
return d.controllerName
Expand All @@ -320,7 +330,7 @@ func (d *Deployer) DeployObjsWithSource(ctx context.Context, objs []client.Objec
controllerName := d.controllerName
if sourceObj != nil {
if gw, ok := sourceObj.(*gwv1.Gateway); ok {
controllerName = d.getControllerNameForGatewayClass(string(gw.Spec.GatewayClassName))
controllerName = d.getControllerNameForGatewayClass(ctx, string(gw.Spec.GatewayClassName))
}
// For InferencePool objects, use the agwControllerName if this deployer was configured
// with the agent gateway controller name as the primary controller
Expand Down
55 changes: 55 additions & 0 deletions pkg/deployer/deployer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2799,4 +2799,59 @@ var _ = Describe("DeployObjs", func() {
Expect(err).ToNot(HaveOccurred())
Expect(patched).To(BeTrue())
})

It("uses GatewayClass controllerName (not class name) as SSA field manager", func() {
customClassName := "custom-agw-class"
gwc := &gwv1.GatewayClass{
ObjectMeta: metav1.ObjectMeta{Name: customClassName},
Spec: gwv1.GatewayClassSpec{ControllerName: wellknown.DefaultAgwControllerName},
}
gw := &gwv1.Gateway{
ObjectMeta: metav1.ObjectMeta{Name: "test-gw", Namespace: ns, UID: "12345"},
Spec: gwv1.GatewaySpec{GatewayClassName: gwv1.ObjectName(customClassName)},
}
gw.SetGroupVersionKind(wellknown.GatewayGVK)
cm := &corev1.ConfigMap{
TypeMeta: metav1.TypeMeta{Kind: gvk.ConfigMap.Kind, APIVersion: gvk.ConfigMap.GroupVersion()},
ObjectMeta: metav1.ObjectMeta{Name: name, Namespace: ns},
Data: map[string]string{"foo": "bar"},
}

fc := fake.NewClient(GinkgoT(), gwc)
var usedFieldManager string
d := getDeployer(fc, func(client apiclient.Client, fieldManager string, gvr schema.GroupVersionResource, name string, namespace string, data []byte, subresources ...string) error {
usedFieldManager = fieldManager
return nil
})
fc.RunAndWait(context.Background().Done())

err := d.DeployObjsWithSource(ctx, []client.Object{cm}, gw)
Expect(err).ToNot(HaveOccurred())
Expect(usedFieldManager).To(Equal(wellknown.DefaultAgwControllerName))
})

It("falls back to class name comparison when GatewayClass lookup fails", func() {
gw := &gwv1.Gateway{
ObjectMeta: metav1.ObjectMeta{Name: "test-gw", Namespace: ns, UID: "12345"},
Spec: gwv1.GatewaySpec{GatewayClassName: wellknown.DefaultAgwClassName},
}
gw.SetGroupVersionKind(wellknown.GatewayGVK)
cm := &corev1.ConfigMap{
TypeMeta: metav1.TypeMeta{Kind: gvk.ConfigMap.Kind, APIVersion: gvk.ConfigMap.GroupVersion()},
ObjectMeta: metav1.ObjectMeta{Name: name, Namespace: ns},
Data: map[string]string{"foo": "bar"},
}

fc := fake.NewClient(GinkgoT()) // no GatewayClass created
var usedFieldManager string
d := getDeployer(fc, func(client apiclient.Client, fieldManager string, gvr schema.GroupVersionResource, name string, namespace string, data []byte, subresources ...string) error {
usedFieldManager = fieldManager
return nil
})
fc.RunAndWait(context.Background().Done())

err := d.DeployObjsWithSource(ctx, []client.Object{cm}, gw)
Expect(err).ToNot(HaveOccurred())
Expect(usedFieldManager).To(Equal(wellknown.DefaultAgwControllerName))
})
})
37 changes: 18 additions & 19 deletions pkg/kgateway/controller/controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,20 +170,22 @@ func (s *ControllerSuite) TestGatewayStatus() {
s.T().Run(tc.name, func(t *testing.T) {
r := require.New(t)
ctx := t.Context()
var gw gwv1.Gateway
gwName := "test-" + tc.gatewayClass
gwNamespace := "default"

t.Cleanup(func() {
err := s.client.Delete(context.Background(), &gw)
gw := &gwv1.Gateway{ObjectMeta: metav1.ObjectMeta{Name: gwName, Namespace: gwNamespace}}
err := s.client.Delete(context.Background(), gw)
if err != nil && k8serrors.IsNotFound(err) {
return
}
r.NoError(err, "error deleting Gateway")
})

gw = gwv1.Gateway{
gw := gwv1.Gateway{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Namespace: "default",
Name: gwName,
Namespace: gwNamespace,
},
Spec: gwv1.GatewaySpec{
Addresses: []gwv1.GatewaySpecAddress{{
Expand All @@ -207,21 +209,17 @@ func (s *ControllerSuite) TestGatewayStatus() {
r.NoError(err, "error creating Gateway")

if tc.gatewayClass != selfManagedGatewayClassName {
// Update the status of the service for the controller to pick up
// We use an Eventually to ensure the Status updates succeeds on a retry if there is a conflict
// with the Object written by the controller
// Update the status of the service for the controller to pick up.
// We use EventuallyWithT to ensure the status update succeeds on retry if there
// is a conflict with the object written by the controller.
r.EventuallyWithT(func(c *assert.CollectT) {
cur := &corev1.Service{}
err := s.client.Get(ctx, types.NamespacedName{Name: gw.Name, Namespace: gw.Namespace}, cur)
err := s.client.Get(ctx, types.NamespacedName{Name: gwName, Namespace: gwNamespace}, cur)
require.NoError(c, err, "error getting Gateway Service")

cur.Status = corev1.ServiceStatus{
LoadBalancer: corev1.LoadBalancerStatus{
Ingress: []corev1.LoadBalancerIngress{
{
IP: localhost,
},
},
Ingress: []corev1.LoadBalancerIngress{{IP: localhost}},
},
}

Expand All @@ -230,13 +228,14 @@ func (s *ControllerSuite) TestGatewayStatus() {
}, defaultPollTimeout, 500*time.Millisecond, "timed out waiting for Gateway Service to be created")
}
r.EventuallyWithT(func(c *assert.CollectT) {
err := s.client.Get(ctx, types.NamespacedName{Name: gw.Name, Namespace: gw.Namespace}, &gw)
var gotGw gwv1.Gateway
err := s.client.Get(ctx, types.NamespacedName{Name: gwName, Namespace: gwNamespace}, &gotGw)
require.NoError(c, err, "error getting Gateway")
require.NotEmpty(c, gw.Status.Addresses, "expected Gateway to have status addresses")
require.NotEmpty(c, gotGw.Status.Addresses, "expected Gateway to have status addresses")

require.Len(c, gw.Status.Addresses, 1)
require.Equal(c, gwv1.IPAddressType, *gw.Status.Addresses[0].Type)
require.Equal(c, localhost, gw.Status.Addresses[0].Value)
require.Len(c, gotGw.Status.Addresses, 1)
require.Equal(c, gwv1.IPAddressType, *gotGw.Status.Addresses[0].Type)
require.Equal(c, localhost, gotGw.Status.Addresses[0].Value)
}, defaultPollTimeout, 500*time.Millisecond)
})
}
Expand Down