Skip to content

Commit 08e54e0

Browse files
authored
Add Programmed status for listener (#786)
Problem: programmed status was set for gateway but not for listeners Solution: programmed status now set for listeners. Is set to false when the listener is invalid or nginx fails to reload.
1 parent 7fa6dff commit 08e54e0

File tree

7 files changed

+119
-102
lines changed

7 files changed

+119
-102
lines changed

docs/gateway-api-compatibility.md

+2
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ Fields:
8989
* `Accepted/False/ProtocolConflict`
9090
* `Accepted/False/UnsupportedValue`: Custom reason for when a value of a field in a Listener is invalid or not supported.
9191
* `Accepted/False/GatewayConflict`: Custom reason for when the Gateway is ignored due to a conflicting Gateway. NKG only supports a single Gateway.
92+
* `Programmed/True/Programmed`
93+
* `Programmed/False/Invalid`
9294
* `ResolvedRefs/True/ResolvedRefs`
9395
* `ResolvedRefs/False/InvalidCertificateRef`
9496
* `Conflicted/True/ProtocolConflict`

internal/state/conditions/conditions.go

+52-17
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@ const (
1212
// is invalid or not supported.
1313
ListenerReasonUnsupportedValue v1beta1.ListenerConditionReason = "UnsupportedValue"
1414

15+
// ListenerMessageFailedNginxReload is a message used with ListenerConditionProgrammed (false)
16+
// when nginx fails to reload.
17+
ListenerMessageFailedNginxReload = "The Listener is not programmed due to a failure to " +
18+
"reload nginx with the configuration"
19+
1520
// RouteReasonBackendRefUnsupportedValue is used with the "ResolvedRefs" condition when one of the
1621
// Route rules has a backendRef with an unsupported value.
1722
RouteReasonBackendRefUnsupportedValue = "UnsupportedValue"
@@ -253,6 +258,7 @@ func NewRouteGatewayNotProgrammed(msg string) Condition {
253258
func NewDefaultListenerConditions() []Condition {
254259
return []Condition{
255260
NewListenerAccepted(),
261+
NewListenerProgrammed(),
256262
NewListenerResolvedRefs(),
257263
NewListenerNoConflicts(),
258264
}
@@ -268,6 +274,16 @@ func NewListenerAccepted() Condition {
268274
}
269275
}
270276

277+
// NewListenerProgrammed returns a Condition that indicates the Listener is programmed.
278+
func NewListenerProgrammed() Condition {
279+
return Condition{
280+
Type: string(v1beta1.ListenerConditionProgrammed),
281+
Status: metav1.ConditionTrue,
282+
Reason: string(v1beta1.ListenerReasonProgrammed),
283+
Message: "Listener is programmed",
284+
}
285+
}
286+
271287
// NewListenerResolvedRefs returns a Condition that indicates that all references in a Listener are resolved.
272288
func NewListenerResolvedRefs() Condition {
273289
return Condition{
@@ -288,17 +304,31 @@ func NewListenerNoConflicts() Condition {
288304
}
289305
}
290306

291-
// NewListenerUnsupportedValue returns a Condition that indicates that a field of a Listener has an unsupported value.
292-
// Unsupported means that the value is not supported by the implementation or invalid.
293-
func NewListenerUnsupportedValue(msg string) Condition {
307+
// NewListenerNotProgrammedInvalid returns a Condition that indicates the Listener is not programmed because it is
308+
// semantically or syntactically invalid. The provided message contains the details of why the Listener is invalid.
309+
func NewListenerNotProgrammedInvalid(msg string) Condition {
294310
return Condition{
295-
Type: string(v1beta1.ListenerConditionAccepted),
311+
Type: string(v1beta1.ListenerConditionProgrammed),
296312
Status: metav1.ConditionFalse,
297-
Reason: string(ListenerReasonUnsupportedValue),
313+
Reason: string(v1beta1.ListenerReasonInvalid),
298314
Message: msg,
299315
}
300316
}
301317

318+
// NewListenerUnsupportedValue returns Conditions that indicate that a field of a Listener has an unsupported value.
319+
// Unsupported means that the value is not supported by the implementation or invalid.
320+
func NewListenerUnsupportedValue(msg string) []Condition {
321+
return []Condition{
322+
{
323+
Type: string(v1beta1.ListenerConditionAccepted),
324+
Status: metav1.ConditionFalse,
325+
Reason: string(ListenerReasonUnsupportedValue),
326+
Message: msg,
327+
},
328+
NewListenerNotProgrammedInvalid(msg),
329+
}
330+
}
331+
302332
// NewListenerInvalidCertificateRef returns Conditions that indicate that a CertificateRef of a Listener is invalid.
303333
func NewListenerInvalidCertificateRef(msg string) []Condition {
304334
return []Condition{
@@ -314,6 +344,7 @@ func NewListenerInvalidCertificateRef(msg string) []Condition {
314344
Reason: string(v1beta1.ListenerReasonInvalidCertificateRef),
315345
Message: msg,
316346
},
347+
NewListenerNotProgrammedInvalid(msg),
317348
}
318349
}
319350

@@ -333,16 +364,20 @@ func NewListenerProtocolConflict(msg string) []Condition {
333364
Reason: string(v1beta1.ListenerReasonProtocolConflict),
334365
Message: msg,
335366
},
367+
NewListenerNotProgrammedInvalid(msg),
336368
}
337369
}
338370

339-
// NewListenerUnsupportedProtocol returns a Condition that indicates that the protocol of a Listener is unsupported.
340-
func NewListenerUnsupportedProtocol(msg string) Condition {
341-
return Condition{
342-
Type: string(v1beta1.ListenerConditionAccepted),
343-
Status: metav1.ConditionFalse,
344-
Reason: string(v1beta1.ListenerReasonUnsupportedProtocol),
345-
Message: msg,
371+
// NewListenerUnsupportedProtocol returns Conditions that indicate that the protocol of a Listener is unsupported.
372+
func NewListenerUnsupportedProtocol(msg string) []Condition {
373+
return []Condition{
374+
{
375+
Type: string(v1beta1.ListenerConditionAccepted),
376+
Status: metav1.ConditionFalse,
377+
Reason: string(v1beta1.ListenerReasonUnsupportedProtocol),
378+
Message: msg,
379+
},
380+
NewListenerNotProgrammedInvalid(msg),
346381
}
347382
}
348383

@@ -368,7 +403,7 @@ func NewGatewayClassInvalidParameters(msg string) Condition {
368403
}
369404
}
370405

371-
// NewDefaultGatewayConditions returns the default Condition that must be present in the status of a Gateway.
406+
// NewDefaultGatewayConditions returns the default Conditions that must be present in the status of a Gateway.
372407
func NewDefaultGatewayConditions() []Condition {
373408
return []Condition{
374409
NewGatewayAccepted(),
@@ -386,7 +421,7 @@ func NewGatewayAccepted() Condition {
386421
}
387422
}
388423

389-
// NewGatewayConflict returns a Condition that indicates the Gateway has a conflict with another Gateway.
424+
// NewGatewayConflict returns Conditions that indicate the Gateway has a conflict with another Gateway.
390425
func NewGatewayConflict() []Condition {
391426
return []Condition{
392427
{
@@ -410,7 +445,7 @@ func NewGatewayAcceptedListenersNotValid() Condition {
410445
}
411446
}
412447

413-
// NewGatewayNotAcceptedListenersNotValid returns a Condition that indicates the Gateway is not accepted,
448+
// NewGatewayNotAcceptedListenersNotValid returns Conditions that indicate the Gateway is not accepted,
414449
// because all listeners are invalid.
415450
func NewGatewayNotAcceptedListenersNotValid() []Condition {
416451
msg := "Gateway has no valid listeners"
@@ -425,7 +460,7 @@ func NewGatewayNotAcceptedListenersNotValid() []Condition {
425460
}
426461
}
427462

428-
// NewGatewayInvalid returns a Condition that indicates the Gateway is not accepted and programmed because it is
463+
// NewGatewayInvalid returns Conditions that indicate the Gateway is not accepted and programmed because it is
429464
// semantically or syntactically invalid. The provided message contains the details of why the Gateway is invalid.
430465
func NewGatewayInvalid(msg string) []Condition {
431466
return []Condition{
@@ -439,7 +474,7 @@ func NewGatewayInvalid(msg string) []Condition {
439474
}
440475
}
441476

442-
// NewGatewayUnsupportedValue returns a Condition that indicates that a field of the Gateway has an unsupported value.
477+
// NewGatewayUnsupportedValue returns Conditions that indicate that a field of the Gateway has an unsupported value.
443478
// Unsupported means that the value is not supported by the implementation or invalid.
444479
func NewGatewayUnsupportedValue(msg string) []Condition {
445480
return []Condition{

internal/state/graph/gateway_listener.go

+10-10
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ func newListenerConfiguratorFactory(
7979
listener.Protocol,
8080
[]string{string(v1beta1.HTTPProtocolType), string(v1beta1.HTTPSProtocolType)},
8181
)
82-
return []conditions.Condition{conditions.NewListenerUnsupportedProtocol(valErr.Error())}
82+
return conditions.NewListenerUnsupportedProtocol(valErr.Error())
8383
},
8484
},
8585
},
@@ -152,7 +152,7 @@ func (c *listenerConfigurator) configure(listener v1beta1.Listener) *Listener {
152152
allowedRouteSelector, err = metav1.LabelSelectorAsSelector(selector)
153153
if err != nil {
154154
msg := fmt.Sprintf("invalid label selector: %s", err.Error())
155-
conds = append(conds, conditions.NewListenerUnsupportedValue(msg))
155+
conds = append(conds, conditions.NewListenerUnsupportedValue(msg)...)
156156
}
157157
}
158158

@@ -199,7 +199,7 @@ func validateListenerHostname(listener v1beta1.Listener) []conditions.Condition
199199
if err != nil {
200200
path := field.NewPath("hostname")
201201
valErr := field.Invalid(path, listener.Hostname, err.Error())
202-
return []conditions.Condition{conditions.NewListenerUnsupportedValue(valErr.Error())}
202+
return conditions.NewListenerUnsupportedValue(valErr.Error())
203203
}
204204
return nil
205205
}
@@ -221,7 +221,7 @@ func validateListenerAllowedRouteKind(listener v1beta1.Listener) []conditions.Co
221221
for _, kind := range listener.AllowedRoutes.Kinds {
222222
if !validHTTPRouteKind(kind) {
223223
msg := fmt.Sprintf("Unsupported route kind \"%s/%s\"", *kind.Group, kind.Kind)
224-
return []conditions.Condition{conditions.NewListenerUnsupportedValue(msg)}
224+
return conditions.NewListenerUnsupportedValue(msg)
225225
}
226226
}
227227
}
@@ -237,7 +237,7 @@ func validateListenerLabelSelector(listener v1beta1.Listener) []conditions.Condi
237237
*listener.AllowedRoutes.Namespaces.From == v1beta1.NamespacesFromSelector &&
238238
listener.AllowedRoutes.Namespaces.Selector == nil {
239239
msg := "Listener's AllowedRoutes Selector must be set when From is set to type Selector"
240-
return []conditions.Condition{conditions.NewListenerUnsupportedValue(msg)}
240+
return conditions.NewListenerUnsupportedValue(msg)
241241
}
242242

243243
return nil
@@ -247,7 +247,7 @@ func validateHTTPListener(listener v1beta1.Listener) []conditions.Condition {
247247
if err := validateListenerPort(listener.Port); err != nil {
248248
path := field.NewPath("port")
249249
valErr := field.Invalid(path, listener.Port, err.Error())
250-
return []conditions.Condition{conditions.NewListenerUnsupportedValue(valErr.Error())}
250+
return conditions.NewListenerUnsupportedValue(valErr.Error())
251251
}
252252

253253
if listener.TLS != nil {
@@ -272,7 +272,7 @@ func createHTTPSListenerValidator(gwNsName string) listenerValidator {
272272
if err := validateListenerPort(listener.Port); err != nil {
273273
path := field.NewPath("port")
274274
valErr := field.Invalid(path, listener.Port, err.Error())
275-
conds = append(conds, conditions.NewListenerUnsupportedValue(valErr.Error()))
275+
conds = append(conds, conditions.NewListenerUnsupportedValue(valErr.Error())...)
276276
}
277277

278278
if listener.TLS == nil {
@@ -287,13 +287,13 @@ func createHTTPSListenerValidator(gwNsName string) listenerValidator {
287287
*listener.TLS.Mode,
288288
[]string{string(v1beta1.TLSModeTerminate)},
289289
)
290-
conds = append(conds, conditions.NewListenerUnsupportedValue(valErr.Error()))
290+
conds = append(conds, conditions.NewListenerUnsupportedValue(valErr.Error())...)
291291
}
292292

293293
if len(listener.TLS.Options) > 0 {
294294
path := tlsPath.Child("options")
295295
valErr := field.Forbidden(path, "options are not supported")
296-
conds = append(conds, conditions.NewListenerUnsupportedValue(valErr.Error()))
296+
conds = append(conds, conditions.NewListenerUnsupportedValue(valErr.Error())...)
297297
}
298298

299299
if len(listener.TLS.CertificateRefs) == 0 {
@@ -328,7 +328,7 @@ func createHTTPSListenerValidator(gwNsName string) listenerValidator {
328328
if l := len(listener.TLS.CertificateRefs); l > 1 {
329329
path := tlsPath.Child("certificateRefs")
330330
valErr := field.TooMany(path, l, 1)
331-
conds = append(conds, conditions.NewListenerUnsupportedValue(valErr.Error()))
331+
conds = append(conds, conditions.NewListenerUnsupportedValue(valErr.Error())...)
332332
}
333333

334334
return conds

internal/state/graph/gateway_listener_test.go

+11-21
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,8 @@ func TestValidateHTTPListener(t *testing.T) {
2929
l: v1beta1.Listener{
3030
Port: 0,
3131
},
32-
expected: []conditions.Condition{
33-
conditions.NewListenerUnsupportedValue(`port: Invalid value: 0: port must be between 1-65535`),
34-
},
35-
name: "invalid port",
32+
expected: conditions.NewListenerUnsupportedValue(`port: Invalid value: 0: port must be between 1-65535`),
33+
name: "invalid port",
3634
},
3735
}
3836

@@ -98,10 +96,8 @@ func TestValidateHTTPSListener(t *testing.T) {
9896
CertificateRefs: []v1beta1.SecretObjectReference{validSecretRef},
9997
},
10098
},
101-
expected: []conditions.Condition{
102-
conditions.NewListenerUnsupportedValue(`port: Invalid value: 0: port must be between 1-65535`),
103-
},
104-
name: "invalid port",
99+
expected: conditions.NewListenerUnsupportedValue(`port: Invalid value: 0: port must be between 1-65535`),
100+
name: "invalid port",
105101
},
106102
{
107103
l: v1beta1.Listener{
@@ -112,10 +108,8 @@ func TestValidateHTTPSListener(t *testing.T) {
112108
Options: map[v1beta1.AnnotationKey]v1beta1.AnnotationValue{"key": "val"},
113109
},
114110
},
115-
expected: []conditions.Condition{
116-
conditions.NewListenerUnsupportedValue("tls.options: Forbidden: options are not supported"),
117-
},
118-
name: "invalid options",
111+
expected: conditions.NewListenerUnsupportedValue("tls.options: Forbidden: options are not supported"),
112+
name: "invalid options",
119113
},
120114
{
121115
l: v1beta1.Listener{
@@ -125,11 +119,9 @@ func TestValidateHTTPSListener(t *testing.T) {
125119
CertificateRefs: []v1beta1.SecretObjectReference{validSecretRef},
126120
},
127121
},
128-
expected: []conditions.Condition{
129-
conditions.NewListenerUnsupportedValue(
130-
`tls.mode: Unsupported value: "Passthrough": supported values: "Terminate"`,
131-
),
132-
},
122+
expected: conditions.NewListenerUnsupportedValue(
123+
`tls.mode: Unsupported value: "Passthrough": supported values: "Terminate"`,
124+
),
133125
name: "invalid tls mode",
134126
},
135127
{
@@ -180,10 +172,8 @@ func TestValidateHTTPSListener(t *testing.T) {
180172
CertificateRefs: []v1beta1.SecretObjectReference{validSecretRef, validSecretRef},
181173
},
182174
},
183-
expected: []conditions.Condition{
184-
conditions.NewListenerUnsupportedValue("tls.certificateRefs: Too many: 2: must have at most 1 items"),
185-
},
186-
name: "too many cert refs",
175+
expected: conditions.NewListenerUnsupportedValue("tls.certificateRefs: Too many: 2: must have at most 1 items"),
176+
name: "too many cert refs",
187177
},
188178
}
189179

0 commit comments

Comments
 (0)