Skip to content

Commit d084244

Browse files
committed
Report proper conditions when GatewayClass is invalid or doesn't exist
If GatewayClass is invalid or doesn't exist: - For Gateway Listeners: NKG will make every listener invalid and report Accepted condition with status False and reason NoValidGatewayClass in every listener status. - For HTTPRoutes: An HTTPRoute will not be able to attach to any listener, because they will be invalid. This is already handled: NKG will report Accepted condition with status False and reason InvalidListener. Fixes #307
1 parent 5f9da63 commit d084244

File tree

7 files changed

+218
-286
lines changed

7 files changed

+218
-286
lines changed

internal/state/change_processor_test.go

+28-26
Original file line numberDiff line numberDiff line change
@@ -316,18 +316,20 @@ var _ = Describe("ChangeProcessor", func() {
316316
ObservedGeneration: gw1.Generation,
317317
ListenerStatuses: map[string]state.ListenerStatus{
318318
"listener-80-1": {
319-
AttachedRoutes: 1,
320-
Conditions: append(
321-
conditions.NewDefaultListenerConditions(),
322-
conditions.NewTODO("GatewayClass is invalid or doesn't exist"),
323-
),
319+
AttachedRoutes: 0,
320+
Conditions: []conditions.Condition{
321+
conditions.NewListenerResolvedRefs(),
322+
conditions.NewListenerNoConflicts(),
323+
conditions.NewListenerNoValidGatewayClass("GatewayClass doesn't exist"),
324+
},
324325
},
325326
"listener-443-1": {
326-
AttachedRoutes: 1,
327-
Conditions: append(
328-
conditions.NewDefaultListenerConditions(),
329-
conditions.NewTODO("GatewayClass is invalid or doesn't exist"),
330-
),
327+
AttachedRoutes: 0,
328+
Conditions: []conditions.Condition{
329+
conditions.NewListenerResolvedRefs(),
330+
conditions.NewListenerNoConflicts(),
331+
conditions.NewListenerNoValidGatewayClass("GatewayClass doesn't exist"),
332+
},
331333
},
332334
},
333335
},
@@ -339,18 +341,16 @@ var _ = Describe("ChangeProcessor", func() {
339341
{
340342
GatewayNsName: client.ObjectKeyFromObject(gw1),
341343
SectionName: helpers.GetPointer[v1beta1.SectionName]("listener-80-1"),
342-
Conditions: append(
343-
conditions.NewDefaultRouteConditions(),
344-
conditions.NewTODO("GatewayClass is invalid or doesn't exist"),
345-
),
344+
Conditions: []conditions.Condition{
345+
conditions.NewRouteInvalidListener(),
346+
},
346347
},
347348
{
348349
GatewayNsName: client.ObjectKeyFromObject(gw1),
349350
SectionName: helpers.GetPointer[v1beta1.SectionName]("listener-443-1"),
350-
Conditions: append(
351-
conditions.NewDefaultRouteConditions(),
352-
conditions.NewTODO("GatewayClass is invalid or doesn't exist"),
353-
),
351+
Conditions: []conditions.Condition{
352+
conditions.NewRouteInvalidListener(),
353+
},
354354
},
355355
},
356356
},
@@ -1219,17 +1219,19 @@ var _ = Describe("ChangeProcessor", func() {
12191219
ListenerStatuses: map[string]state.ListenerStatus{
12201220
"listener-80-1": {
12211221
AttachedRoutes: 0,
1222-
Conditions: append(
1223-
conditions.NewDefaultListenerConditions(),
1224-
conditions.NewTODO("GatewayClass is invalid or doesn't exist"),
1225-
),
1222+
Conditions: []conditions.Condition{
1223+
conditions.NewListenerResolvedRefs(),
1224+
conditions.NewListenerNoConflicts(),
1225+
conditions.NewListenerNoValidGatewayClass("GatewayClass doesn't exist"),
1226+
},
12261227
},
12271228
"listener-443-1": {
12281229
AttachedRoutes: 0,
1229-
Conditions: append(
1230-
conditions.NewDefaultListenerConditions(),
1231-
conditions.NewTODO("GatewayClass is invalid or doesn't exist"),
1232-
),
1230+
Conditions: []conditions.Condition{
1231+
conditions.NewListenerResolvedRefs(),
1232+
conditions.NewListenerNoConflicts(),
1233+
conditions.NewListenerNoValidGatewayClass("GatewayClass doesn't exist"),
1234+
},
12331235
},
12341236
},
12351237
},

internal/state/conditions/conditions.go

+48-18
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ const (
1515
// is invalid or not supported.
1616
ListenerReasonUnsupportedValue v1beta1.ListenerConditionReason = "UnsupportedValue"
1717

18+
// ListenerReasonNoValidGatewayClass is used with the "Accepted" condition when there is no valid GatewayClass
19+
// in the cluster.
20+
ListenerReasonNoValidGatewayClass v1beta1.ListenerConditionReason = "NoValidGatewayClass"
21+
1822
// RouteReasonBackendRefUnsupportedValue is used with the "ResolvedRefs" condition when one of the
1923
// Route rules has a backendRef with an unsupported value.
2024
RouteReasonBackendRefUnsupportedValue = "UnsupportedValue"
@@ -129,27 +133,42 @@ func NewListenerPortUnavailable(msg string) Condition {
129133
}
130134
}
131135

136+
// NewListenerAccepted returns a Condition that indicates that the Listener is accepted.
137+
func NewListenerAccepted() Condition {
138+
return Condition{
139+
Type: string(v1beta1.ListenerConditionAccepted),
140+
Status: metav1.ConditionTrue,
141+
Reason: string(v1beta1.ListenerReasonAccepted),
142+
Message: "Listener is accepted",
143+
}
144+
}
145+
146+
// NewListenerResolvedRefs returns a Condition that indicates that all references in a Listener are resolved.
147+
func NewListenerResolvedRefs() Condition {
148+
return Condition{
149+
Type: string(v1beta1.ListenerConditionResolvedRefs),
150+
Status: metav1.ConditionTrue,
151+
Reason: string(v1beta1.ListenerReasonResolvedRefs),
152+
Message: "All references are resolved",
153+
}
154+
}
155+
156+
// NewListenerNoConflicts returns a Condition that indicates that there are no conflicts in a Listener.
157+
func NewListenerNoConflicts() Condition {
158+
return Condition{
159+
Type: string(v1beta1.ListenerConditionConflicted),
160+
Status: metav1.ConditionFalse,
161+
Reason: string(v1beta1.ListenerReasonNoConflicts),
162+
Message: "No conflicts",
163+
}
164+
}
165+
132166
// NewDefaultListenerConditions returns the default Conditions that must be present in the status of a Listener.
133167
func NewDefaultListenerConditions() []Condition {
134168
return []Condition{
135-
{
136-
Type: string(v1beta1.ListenerConditionAccepted),
137-
Status: metav1.ConditionTrue,
138-
Reason: string(v1beta1.ListenerReasonAccepted),
139-
Message: "Listener is accepted",
140-
},
141-
{
142-
Type: string(v1beta1.ListenerReasonResolvedRefs),
143-
Status: metav1.ConditionTrue,
144-
Reason: string(v1beta1.ListenerReasonResolvedRefs),
145-
Message: "All references are resolved",
146-
},
147-
{
148-
Type: string(v1beta1.ListenerConditionConflicted),
149-
Status: metav1.ConditionFalse,
150-
Reason: string(v1beta1.ListenerReasonNoConflicts),
151-
Message: "No conflicts",
152-
},
169+
NewListenerAccepted(),
170+
NewListenerResolvedRefs(),
171+
NewListenerNoConflicts(),
153172
}
154173
}
155174

@@ -220,6 +239,17 @@ func NewListenerUnsupportedProtocol(msg string) Condition {
220239
}
221240
}
222241

242+
// NewListenerNoValidGatewayClass returns a Condition that indicates that the Listener is not accepted because
243+
// there is no valid GatewayClass.
244+
func NewListenerNoValidGatewayClass(msg string) Condition {
245+
return Condition{
246+
Type: string(v1beta1.ListenerConditionAccepted),
247+
Status: metav1.ConditionFalse,
248+
Reason: string(ListenerReasonNoValidGatewayClass),
249+
Message: msg,
250+
}
251+
}
252+
223253
// NewRouteBackendRefInvalidKind returns a Condition that indicates that the Route has a backendRef with an
224254
// invalid kind.
225255
func NewRouteBackendRefInvalidKind(msg string) Condition {

internal/state/graph/gateway.go

+21-3
Original file line numberDiff line numberDiff line change
@@ -107,24 +107,25 @@ func processGateways(
107107
}
108108
}
109109

110-
func buildGateway(gw *v1beta1.Gateway, secretMemoryMgr secrets.SecretDiskMemoryManager) *Gateway {
110+
func buildGateway(gw *v1beta1.Gateway, secretMemoryMgr secrets.SecretDiskMemoryManager, gc *GatewayClass) *Gateway {
111111
if gw == nil {
112112
return nil
113113
}
114114

115115
return &Gateway{
116116
Source: gw,
117-
Listeners: buildListeners(gw, secretMemoryMgr),
117+
Listeners: buildListeners(gw, secretMemoryMgr, gc),
118118
}
119119
}
120120

121121
func buildListeners(
122122
gw *v1beta1.Gateway,
123123
secretMemoryMgr secrets.SecretDiskMemoryManager,
124+
gc *GatewayClass,
124125
) map[string]*Listener {
125126
listeners := make(map[string]*Listener)
126127

127-
listenerFactory := newListenerConfiguratorFactory(gw, secretMemoryMgr)
128+
listenerFactory := newListenerConfiguratorFactory(gw, secretMemoryMgr, gc)
128129

129130
for _, gl := range gw.Spec.Listeners {
130131
configurator := listenerFactory.getConfiguratorForListener(gl)
@@ -152,6 +153,7 @@ func (f *listenerConfiguratorFactory) getConfiguratorForListener(l v1beta1.Liste
152153
func newListenerConfiguratorFactory(
153154
gw *v1beta1.Gateway,
154155
secretMemoryMgr secrets.SecretDiskMemoryManager,
156+
gc *GatewayClass,
155157
) *listenerConfiguratorFactory {
156158
return &listenerConfiguratorFactory{
157159
unsupportedProtocol: &listenerConfigurator{
@@ -170,6 +172,7 @@ func newListenerConfiguratorFactory(
170172
validators: []listenerValidator{
171173
validateListenerHostname,
172174
createAddressesValidator(gw),
175+
createNoValidGatewayClassValidator(gc),
173176
validateHTTPListener,
174177
},
175178
conflictResolvers: []listenerConflictResolver{
@@ -180,6 +183,7 @@ func newListenerConfiguratorFactory(
180183
validators: []listenerValidator{
181184
validateListenerHostname,
182185
createAddressesValidator(gw),
186+
createNoValidGatewayClassValidator(gc),
183187
createHTTPSListenerValidator(gw.Namespace),
184188
},
185189
conflictResolvers: []listenerConflictResolver{
@@ -286,6 +290,20 @@ func createAddressesValidator(gw *v1beta1.Gateway) listenerValidator {
286290
}
287291
}
288292

293+
func createNoValidGatewayClassValidator(gc *GatewayClass) listenerValidator {
294+
return func(listener v1beta1.Listener) []conditions.Condition {
295+
if gc == nil {
296+
return []conditions.Condition{conditions.NewListenerNoValidGatewayClass("GatewayClass doesn't exist")}
297+
}
298+
299+
if !gc.Valid {
300+
return []conditions.Condition{conditions.NewListenerNoValidGatewayClass("GatewayClass is invalid")}
301+
}
302+
303+
return nil
304+
}
305+
}
306+
289307
func validateHTTPListener(listener v1beta1.Listener) []conditions.Condition {
290308
if listener.Port != 80 {
291309
path := field.NewPath("port")

0 commit comments

Comments
 (0)