Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Programmed status for listener #786

Merged
merged 1 commit into from
Jun 23, 2023
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
2 changes: 2 additions & 0 deletions docs/gateway-api-compatibility.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ Fields:
* `Accepted/False/ProtocolConflict`
* `Accepted/False/UnsupportedValue`: Custom reason for when a value of a field in a Listener is invalid or not supported.
* `Accepted/False/GatewayConflict`: Custom reason for when the Gateway is ignored due to a conflicting Gateway. NKG only supports a single Gateway.
* `Programmed/True/Programmed`
* `Programmed/False/Invalid`
* `ResolvedRefs/True/ResolvedRefs`
* `ResolvedRefs/False/InvalidCertificateRef`
* `Conflicted/True/ProtocolConflict`
Expand Down
69 changes: 52 additions & 17 deletions internal/state/conditions/conditions.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ const (
// is invalid or not supported.
ListenerReasonUnsupportedValue v1beta1.ListenerConditionReason = "UnsupportedValue"

// ListenerMessageFailedNginxReload is a message used with ListenerConditionProgrammed (false)
// when nginx fails to reload.
ListenerMessageFailedNginxReload = "The Listener is not programmed due to a failure to " +
"reload nginx with the configuration"

// RouteReasonBackendRefUnsupportedValue is used with the "ResolvedRefs" condition when one of the
// Route rules has a backendRef with an unsupported value.
RouteReasonBackendRefUnsupportedValue = "UnsupportedValue"
Expand Down Expand Up @@ -253,6 +258,7 @@ func NewRouteGatewayNotProgrammed(msg string) Condition {
func NewDefaultListenerConditions() []Condition {
return []Condition{
NewListenerAccepted(),
NewListenerProgrammed(),
NewListenerResolvedRefs(),
NewListenerNoConflicts(),
}
Expand All @@ -268,6 +274,16 @@ func NewListenerAccepted() Condition {
}
}

// NewListenerProgrammed returns a Condition that indicates the Listener is programmed.
func NewListenerProgrammed() Condition {
return Condition{
Type: string(v1beta1.ListenerConditionProgrammed),
Status: metav1.ConditionTrue,
Reason: string(v1beta1.ListenerReasonProgrammed),
Message: "Listener is programmed",
}
}

// NewListenerResolvedRefs returns a Condition that indicates that all references in a Listener are resolved.
func NewListenerResolvedRefs() Condition {
return Condition{
Expand All @@ -288,17 +304,31 @@ func NewListenerNoConflicts() Condition {
}
}

// NewListenerUnsupportedValue returns a Condition that indicates that a field of a Listener has an unsupported value.
// Unsupported means that the value is not supported by the implementation or invalid.
func NewListenerUnsupportedValue(msg string) Condition {
// NewListenerNotProgrammedInvalid returns a Condition that indicates the Listener is not programmed because it is
// semantically or syntactically invalid. The provided message contains the details of why the Listener is invalid.
func NewListenerNotProgrammedInvalid(msg string) Condition {
return Condition{
Type: string(v1beta1.ListenerConditionAccepted),
Type: string(v1beta1.ListenerConditionProgrammed),
Status: metav1.ConditionFalse,
Reason: string(ListenerReasonUnsupportedValue),
Reason: string(v1beta1.ListenerReasonInvalid),
Message: msg,
}
}

// NewListenerUnsupportedValue returns Conditions that indicate that a field of a Listener has an unsupported value.
// Unsupported means that the value is not supported by the implementation or invalid.
func NewListenerUnsupportedValue(msg string) []Condition {
return []Condition{
{
Type: string(v1beta1.ListenerConditionAccepted),
Status: metav1.ConditionFalse,
Reason: string(ListenerReasonUnsupportedValue),
Message: msg,
},
NewListenerNotProgrammedInvalid(msg),
}
}

// NewListenerInvalidCertificateRef returns Conditions that indicate that a CertificateRef of a Listener is invalid.
func NewListenerInvalidCertificateRef(msg string) []Condition {
return []Condition{
Expand All @@ -314,6 +344,7 @@ func NewListenerInvalidCertificateRef(msg string) []Condition {
Reason: string(v1beta1.ListenerReasonInvalidCertificateRef),
Message: msg,
},
NewListenerNotProgrammedInvalid(msg),
}
}

Expand All @@ -333,16 +364,20 @@ func NewListenerProtocolConflict(msg string) []Condition {
Reason: string(v1beta1.ListenerReasonProtocolConflict),
Message: msg,
},
NewListenerNotProgrammedInvalid(msg),
}
}

// NewListenerUnsupportedProtocol returns a Condition that indicates that the protocol of a Listener is unsupported.
func NewListenerUnsupportedProtocol(msg string) Condition {
return Condition{
Type: string(v1beta1.ListenerConditionAccepted),
Status: metav1.ConditionFalse,
Reason: string(v1beta1.ListenerReasonUnsupportedProtocol),
Message: msg,
// NewListenerUnsupportedProtocol returns Conditions that indicate that the protocol of a Listener is unsupported.
func NewListenerUnsupportedProtocol(msg string) []Condition {
return []Condition{
{
Type: string(v1beta1.ListenerConditionAccepted),
Status: metav1.ConditionFalse,
Reason: string(v1beta1.ListenerReasonUnsupportedProtocol),
Message: msg,
},
NewListenerNotProgrammedInvalid(msg),
}
}

Expand All @@ -368,7 +403,7 @@ func NewGatewayClassInvalidParameters(msg string) Condition {
}
}

// NewDefaultGatewayConditions returns the default Condition that must be present in the status of a Gateway.
// NewDefaultGatewayConditions returns the default Conditions that must be present in the status of a Gateway.
func NewDefaultGatewayConditions() []Condition {
return []Condition{
NewGatewayAccepted(),
Expand All @@ -386,7 +421,7 @@ func NewGatewayAccepted() Condition {
}
}

// NewGatewayConflict returns a Condition that indicates the Gateway has a conflict with another Gateway.
// NewGatewayConflict returns Conditions that indicate the Gateway has a conflict with another Gateway.
func NewGatewayConflict() []Condition {
return []Condition{
{
Expand All @@ -410,7 +445,7 @@ func NewGatewayAcceptedListenersNotValid() Condition {
}
}

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

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

// NewGatewayUnsupportedValue returns a Condition that indicates that a field of the Gateway has an unsupported value.
// NewGatewayUnsupportedValue returns Conditions that indicate that a field of the Gateway has an unsupported value.
// Unsupported means that the value is not supported by the implementation or invalid.
func NewGatewayUnsupportedValue(msg string) []Condition {
return []Condition{
Expand Down
20 changes: 10 additions & 10 deletions internal/state/graph/gateway_listener.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ func newListenerConfiguratorFactory(
listener.Protocol,
[]string{string(v1beta1.HTTPProtocolType), string(v1beta1.HTTPSProtocolType)},
)
return []conditions.Condition{conditions.NewListenerUnsupportedProtocol(valErr.Error())}
return conditions.NewListenerUnsupportedProtocol(valErr.Error())
},
},
},
Expand Down Expand Up @@ -152,7 +152,7 @@ func (c *listenerConfigurator) configure(listener v1beta1.Listener) *Listener {
allowedRouteSelector, err = metav1.LabelSelectorAsSelector(selector)
if err != nil {
msg := fmt.Sprintf("invalid label selector: %s", err.Error())
conds = append(conds, conditions.NewListenerUnsupportedValue(msg))
conds = append(conds, conditions.NewListenerUnsupportedValue(msg)...)
}
}

Expand Down Expand Up @@ -199,7 +199,7 @@ func validateListenerHostname(listener v1beta1.Listener) []conditions.Condition
if err != nil {
path := field.NewPath("hostname")
valErr := field.Invalid(path, listener.Hostname, err.Error())
return []conditions.Condition{conditions.NewListenerUnsupportedValue(valErr.Error())}
return conditions.NewListenerUnsupportedValue(valErr.Error())
}
return nil
}
Expand All @@ -221,7 +221,7 @@ func validateListenerAllowedRouteKind(listener v1beta1.Listener) []conditions.Co
for _, kind := range listener.AllowedRoutes.Kinds {
if !validHTTPRouteKind(kind) {
msg := fmt.Sprintf("Unsupported route kind \"%s/%s\"", *kind.Group, kind.Kind)
return []conditions.Condition{conditions.NewListenerUnsupportedValue(msg)}
return conditions.NewListenerUnsupportedValue(msg)
}
}
}
Expand All @@ -237,7 +237,7 @@ func validateListenerLabelSelector(listener v1beta1.Listener) []conditions.Condi
*listener.AllowedRoutes.Namespaces.From == v1beta1.NamespacesFromSelector &&
listener.AllowedRoutes.Namespaces.Selector == nil {
msg := "Listener's AllowedRoutes Selector must be set when From is set to type Selector"
return []conditions.Condition{conditions.NewListenerUnsupportedValue(msg)}
return conditions.NewListenerUnsupportedValue(msg)
}

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

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

if listener.TLS == nil {
Expand All @@ -287,13 +287,13 @@ func createHTTPSListenerValidator(gwNsName string) listenerValidator {
*listener.TLS.Mode,
[]string{string(v1beta1.TLSModeTerminate)},
)
conds = append(conds, conditions.NewListenerUnsupportedValue(valErr.Error()))
conds = append(conds, conditions.NewListenerUnsupportedValue(valErr.Error())...)
}

if len(listener.TLS.Options) > 0 {
path := tlsPath.Child("options")
valErr := field.Forbidden(path, "options are not supported")
conds = append(conds, conditions.NewListenerUnsupportedValue(valErr.Error()))
conds = append(conds, conditions.NewListenerUnsupportedValue(valErr.Error())...)
}

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

return conds
Expand Down
32 changes: 11 additions & 21 deletions internal/state/graph/gateway_listener_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,8 @@ func TestValidateHTTPListener(t *testing.T) {
l: v1beta1.Listener{
Port: 0,
},
expected: []conditions.Condition{
conditions.NewListenerUnsupportedValue(`port: Invalid value: 0: port must be between 1-65535`),
},
name: "invalid port",
expected: conditions.NewListenerUnsupportedValue(`port: Invalid value: 0: port must be between 1-65535`),
name: "invalid port",
},
}

Expand Down Expand Up @@ -98,10 +96,8 @@ func TestValidateHTTPSListener(t *testing.T) {
CertificateRefs: []v1beta1.SecretObjectReference{validSecretRef},
},
},
expected: []conditions.Condition{
conditions.NewListenerUnsupportedValue(`port: Invalid value: 0: port must be between 1-65535`),
},
name: "invalid port",
expected: conditions.NewListenerUnsupportedValue(`port: Invalid value: 0: port must be between 1-65535`),
name: "invalid port",
},
{
l: v1beta1.Listener{
Expand All @@ -112,10 +108,8 @@ func TestValidateHTTPSListener(t *testing.T) {
Options: map[v1beta1.AnnotationKey]v1beta1.AnnotationValue{"key": "val"},
},
},
expected: []conditions.Condition{
conditions.NewListenerUnsupportedValue("tls.options: Forbidden: options are not supported"),
},
name: "invalid options",
expected: conditions.NewListenerUnsupportedValue("tls.options: Forbidden: options are not supported"),
name: "invalid options",
},
{
l: v1beta1.Listener{
Expand All @@ -125,11 +119,9 @@ func TestValidateHTTPSListener(t *testing.T) {
CertificateRefs: []v1beta1.SecretObjectReference{validSecretRef},
},
},
expected: []conditions.Condition{
conditions.NewListenerUnsupportedValue(
`tls.mode: Unsupported value: "Passthrough": supported values: "Terminate"`,
),
},
expected: conditions.NewListenerUnsupportedValue(
`tls.mode: Unsupported value: "Passthrough": supported values: "Terminate"`,
),
name: "invalid tls mode",
},
{
Expand Down Expand Up @@ -180,10 +172,8 @@ func TestValidateHTTPSListener(t *testing.T) {
CertificateRefs: []v1beta1.SecretObjectReference{validSecretRef, validSecretRef},
},
},
expected: []conditions.Condition{
conditions.NewListenerUnsupportedValue("tls.certificateRefs: Too many: 2: must have at most 1 items"),
},
name: "too many cert refs",
expected: conditions.NewListenerUnsupportedValue("tls.certificateRefs: Too many: 2: must have at most 1 items"),
name: "too many cert refs",
},
}

Expand Down
Loading