From b1926b87989079400bfff3b450ae112626abe256 Mon Sep 17 00:00:00 2001 From: Steve Kriss Date: Fri, 1 Jul 2022 19:04:29 +0000 Subject: [PATCH 1/3] internal/dag: set Listener condition for invalid namespace selector Moves the logic for parsing/validating a Listener namespace label selector into computeListener, and sets Listener conditions appropriately when the selector is invalid. Signed-off-by: Steve Kriss --- internal/dag/gatewayapi_processor.go | 122 +++++++++------- internal/dag/gatewayapi_processor_test.go | 65 ++------- internal/dag/status_test.go | 163 ++++++++++++++++++++++ 3 files changed, 245 insertions(+), 105 deletions(-) diff --git a/internal/dag/gatewayapi_processor.go b/internal/dag/gatewayapi_processor.go index 8e87dae5763..bd3e72f581b 100644 --- a/internal/dag/gatewayapi_processor.go +++ b/internal/dag/gatewayapi_processor.go @@ -117,12 +117,12 @@ func (p *GatewayAPIProcessor) Run(dag *DAG, source *KubernetesCache) { ) } - // Compute listeners and save a list of the ready ones. + // Compute listeners and save a list of the valid/ready ones. var readyListeners []*listenerInfo for _, listener := range p.source.gateway.Spec.Listeners { - if info := p.computeListener(listener, gwAccessor, validateListenersResult); info != nil && gwAccessor.IsListenerReady(string(listener.Name)) { - readyListeners = append(readyListeners, info) + if ready, listenerInfo := p.computeListener(listener, gwAccessor, validateListenersResult); ready { + readyListeners = append(readyListeners, listenerInfo) } } @@ -331,14 +331,7 @@ func (p *GatewayAPIProcessor) getListenersForRouteParentRef( } // Check if the route is in a namespace that the listener allows. - // TODO move validation of the NS label selector (if it exists) into - // computeListener, so we can set an appropriate condition on the listener, - // and avoid having to deal with an error here. - namespaceAllowed, err := p.namespaceMatches(selectedListener.listener.AllowedRoutes.Namespaces, routeNamespace) - if err != nil { - p.Errorf("error validating namespaces against Listener.Routes.Namespaces: %s", err) - } - if !namespaceAllowed { + if !p.namespaceMatches(selectedListener.listener.AllowedRoutes.Namespaces, selectedListener.namespaceSelector, routeNamespace) { continue } @@ -359,9 +352,10 @@ func (p *GatewayAPIProcessor) getListenersForRouteParentRef( } type listenerInfo struct { - listener gatewayapi_v1beta1.Listener - allowedKinds []gatewayapi_v1beta1.Kind - tlsSecret *Secret + listener gatewayapi_v1beta1.Listener + allowedKinds []gatewayapi_v1beta1.Kind + namespaceSelector labels.Selector + tlsSecret *Secret } func (l *listenerInfo) AllowsKind(kind gatewayapi_v1beta1.Kind) bool { @@ -416,7 +410,7 @@ func (p *GatewayAPIProcessor) computeListener( listener gatewayapi_v1beta1.Listener, gwAccessor *status.GatewayStatusUpdate, validateListenersResult gatewayapi.ValidateListenersResult, -) *listenerInfo { +) (bool, *listenerInfo) { // set the listener's "Ready" condition based on whether we've // added any other conditions for the listener. The assumption // here is that if another condition is set, the listener is @@ -460,13 +454,54 @@ func (p *GatewayAPIProcessor) computeListener( // If the listener had an invalid protocol/port/hostname, we don't need to go // any further. if _, ok := validateListenersResult.InvalidListenerConditions[listener.Name]; ok { - return nil + return false, nil } // Get a list of the route kinds that the listener accepts. listenerRouteKinds := p.getListenerRouteKinds(listener, gwAccessor) gwAccessor.SetListenerSupportedKinds(string(listener.Name), listenerRouteKinds) + var selector labels.Selector + + if listener.AllowedRoutes != nil && listener.AllowedRoutes.Namespaces != nil && + listener.AllowedRoutes.Namespaces.From != nil && *listener.AllowedRoutes.Namespaces.From == gatewayapi_v1beta1.NamespacesFromSelector { + + if listener.AllowedRoutes.Namespaces.Selector == nil { + gwAccessor.AddListenerCondition( + string(listener.Name), + gatewayapi_v1beta1.ListenerConditionReady, + metav1.ConditionFalse, + gatewayapi_v1beta1.ListenerReasonInvalid, + "Listener.AllowedRoutes.Namespaces.Selector is required when Listener.AllowedRoutes.Namespaces.From is set to \"Selector\".", + ) + return false, nil + } + + if len(listener.AllowedRoutes.Namespaces.Selector.MatchExpressions)+len(listener.AllowedRoutes.Namespaces.Selector.MatchLabels) == 0 { + gwAccessor.AddListenerCondition( + string(listener.Name), + gatewayapi_v1beta1.ListenerConditionReady, + metav1.ConditionFalse, + gatewayapi_v1beta1.ListenerReasonInvalid, + "Listener.AllowedRoutes.Namespaces.Selector must specify at least one MatchLabel or MatchExpression.", + ) + return false, nil + } + + var err error + selector, err = metav1.LabelSelectorAsSelector(listener.AllowedRoutes.Namespaces.Selector) + if err != nil { + gwAccessor.AddListenerCondition( + string(listener.Name), + gatewayapi_v1beta1.ListenerConditionReady, + metav1.ConditionFalse, + gatewayapi_v1beta1.ListenerReasonInvalid, + fmt.Sprintf("Error parsing Listener.AllowedRoutes.Namespaces.Selector: %v.", err), + ) + return false, nil + } + } + var listenerSecret *Secret // Validate TLS details for HTTPS/TLS protocol listeners. @@ -481,14 +516,14 @@ func (p *GatewayAPIProcessor) computeListener( gatewayapi_v1beta1.ListenerReasonInvalid, fmt.Sprintf("Listener.TLS is required when protocol is %q.", listener.Protocol), ) - return nil + return false, nil } // Check for valid TLS configuration on the Gateway. if listenerSecret = p.validGatewayTLS(*listener.TLS, string(listener.Name), gwAccessor); listenerSecret == nil { // If TLS was configured on the Listener, but it's invalid, don't allow any // routes to be bound to this listener since it can't serve TLS traffic. - return nil + return false, nil } case gatewayapi_v1beta1.TLSProtocolType: // TLS is required for the type TLS. @@ -500,7 +535,7 @@ func (p *GatewayAPIProcessor) computeListener( gatewayapi_v1beta1.ListenerReasonInvalid, fmt.Sprintf("Listener.TLS is required when protocol is %q.", listener.Protocol), ) - return nil + return false, nil } if listener.TLS.Mode != nil { @@ -510,7 +545,7 @@ func (p *GatewayAPIProcessor) computeListener( if listenerSecret = p.validGatewayTLS(*listener.TLS, string(listener.Name), gwAccessor); listenerSecret == nil { // If TLS was configured on the Listener, but it's invalid, don't allow any // routes to be bound to this listener since it can't serve TLS traffic. - return nil + return false, nil } case gatewayapi_v1beta1.TLSModePassthrough: if len(listener.TLS.CertificateRefs) > 0 { @@ -521,16 +556,17 @@ func (p *GatewayAPIProcessor) computeListener( gatewayapi_v1beta1.ListenerReasonInvalid, fmt.Sprintf("Listener.TLS.CertificateRefs cannot be defined when TLS Mode is %q.", *listener.TLS.Mode), ) - return nil + return false, nil } } } } - return &listenerInfo{ - listener: listener, - allowedKinds: listenerRouteKinds, - tlsSecret: listenerSecret, + return true, &listenerInfo{ + listener: listener, + allowedKinds: listenerRouteKinds, + tlsSecret: listenerSecret, + namespaceSelector: selector, } } @@ -839,9 +875,9 @@ func hostnameMatchesWildcardHostname(hostname, wildcardHostname string) bool { return len(wildcardMatch) > 0 } -// namespaceMatches returns true if the namespaces selector matches -// the route that is being processed. -func (p *GatewayAPIProcessor) namespaceMatches(namespaces *gatewayapi_v1beta1.RouteNamespaces, routeNamespace string) (bool, error) { +// namespaceMatches returns true if namespaces allows +// the provided route namespace. +func (p *GatewayAPIProcessor) namespaceMatches(namespaces *gatewayapi_v1beta1.RouteNamespaces, namespaceSelector labels.Selector, routeNamespace string) bool { // From indicates where Routes will be selected for this Gateway. // Possible values are: // * All: Routes in all namespaces may be used by this Gateway. @@ -849,40 +885,26 @@ func (p *GatewayAPIProcessor) namespaceMatches(namespaces *gatewayapi_v1beta1.Ro // this Gateway. // * Same: Only Routes in the same namespace may be used by this Gateway. - if namespaces == nil { - return true, nil - } - - if namespaces.From == nil { - return true, nil + if namespaces == nil || namespaces.From == nil { + return true } switch *namespaces.From { case gatewayapi_v1beta1.NamespacesFromAll: - return true, nil + return true case gatewayapi_v1beta1.NamespacesFromSame: - return p.source.gateway.Namespace == routeNamespace, nil + return p.source.gateway.Namespace == routeNamespace case gatewayapi_v1beta1.NamespacesFromSelector: - if namespaces.Selector == nil || - (len(namespaces.Selector.MatchLabels) == 0 && len(namespaces.Selector.MatchExpressions) == 0) { - return false, fmt.Errorf("RouteNamespaces selector must be specified when `RouteSelectType=Selector`") - } - // Look up the route's namespace in the list of cached namespaces. if ns := p.source.namespaces[routeNamespace]; ns != nil { // Check that the route's namespace is included in the Gateway's - // namespace selector/expression. - l, err := metav1.LabelSelectorAsSelector(namespaces.Selector) - if err != nil { - return false, err - } - - // Look for matching labels on Selector. - return l.Matches(labels.Set(ns.Labels)), nil + // namespace selector. + return namespaceSelector.Matches(labels.Set(ns.Labels)) } } - return true, nil + + return true } func (p *GatewayAPIProcessor) computeGatewayConditions(gwAccessor *status.GatewayStatusUpdate, gatewayNotReadyCondition *metav1.Condition) { diff --git a/internal/dag/gatewayapi_processor_test.go b/internal/dag/gatewayapi_processor_test.go index c05038921e3..99648f0dd85 100644 --- a/internal/dag/gatewayapi_processor_test.go +++ b/internal/dag/gatewayapi_processor_test.go @@ -21,8 +21,10 @@ import ( "github.com/projectcontour/contour/internal/gatewayapi" "github.com/projectcontour/contour/internal/status" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/util/sets" gatewayapi_v1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1" ) @@ -245,13 +247,11 @@ func TestNamespaceMatches(t *testing.T) { namespaces *gatewayapi_v1beta1.RouteNamespaces namespace string valid bool - wantError bool }{ "nil matches all": { namespaces: nil, namespace: "projectcontour", valid: true, - wantError: false, }, "nil From matches all": { namespaces: &gatewayapi_v1beta1.RouteNamespaces{ @@ -259,7 +259,6 @@ func TestNamespaceMatches(t *testing.T) { }, namespace: "projectcontour", valid: true, - wantError: false, }, "From.NamespacesFromAll matches all": { namespaces: &gatewayapi_v1beta1.RouteNamespaces{ @@ -267,7 +266,6 @@ func TestNamespaceMatches(t *testing.T) { }, namespace: "projectcontour", valid: true, - wantError: false, }, "From.NamespacesFromSame matches": { namespaces: &gatewayapi_v1beta1.RouteNamespaces{ @@ -275,7 +273,6 @@ func TestNamespaceMatches(t *testing.T) { }, namespace: "projectcontour", valid: true, - wantError: false, }, "From.NamespacesFromSame doesn't match": { namespaces: &gatewayapi_v1beta1.RouteNamespaces{ @@ -283,7 +280,6 @@ func TestNamespaceMatches(t *testing.T) { }, namespace: "custom", valid: false, - wantError: false, }, "From.NamespacesFromSelector matches labels, same ns as gateway": { namespaces: &gatewayapi_v1beta1.RouteNamespaces{ @@ -296,7 +292,6 @@ func TestNamespaceMatches(t *testing.T) { }, namespace: "projectcontour", valid: true, - wantError: false, }, "From.NamespacesFromSelector matches labels, different ns as gateway": { namespaces: &gatewayapi_v1beta1.RouteNamespaces{ @@ -309,7 +304,6 @@ func TestNamespaceMatches(t *testing.T) { }, namespace: "custom", valid: true, - wantError: false, }, "From.NamespacesFromSelector doesn't matches labels, different ns as gateway": { namespaces: &gatewayapi_v1beta1.RouteNamespaces{ @@ -322,7 +316,6 @@ func TestNamespaceMatches(t *testing.T) { }, namespace: "projectcontour", valid: false, - wantError: false, }, "From.NamespacesFromSelector matches expression 'In', different ns as gateway": { namespaces: &gatewayapi_v1beta1.RouteNamespaces{ @@ -337,7 +330,6 @@ func TestNamespaceMatches(t *testing.T) { }, namespace: "custom", valid: true, - wantError: false, }, "From.NamespacesFromSelector matches expression 'DoesNotExist', different ns as gateway": { namespaces: &gatewayapi_v1beta1.RouteNamespaces{ @@ -351,7 +343,6 @@ func TestNamespaceMatches(t *testing.T) { }, namespace: "custom", valid: true, - wantError: false, }, "From.NamespacesFromSelector doesn't match expression 'DoesNotExist', different ns as gateway": { namespaces: &gatewayapi_v1beta1.RouteNamespaces{ @@ -365,7 +356,6 @@ func TestNamespaceMatches(t *testing.T) { }, namespace: "custom", valid: false, - wantError: false, }, "From.NamespacesFromSelector matches expression 'Exists', different ns as gateway": { namespaces: &gatewayapi_v1beta1.RouteNamespaces{ @@ -379,7 +369,6 @@ func TestNamespaceMatches(t *testing.T) { }, namespace: "custom", valid: false, - wantError: false, }, "From.NamespacesFromSelector doesn't match expression 'Exists', different ns as gateway": { namespaces: &gatewayapi_v1beta1.RouteNamespaces{ @@ -393,46 +382,6 @@ func TestNamespaceMatches(t *testing.T) { }, namespace: "custom", valid: true, - wantError: false, - }, - "From.NamespacesFromSelector match expression 'Exists', cannot specify values": { - namespaces: &gatewayapi_v1beta1.RouteNamespaces{ - From: gatewayapi.FromNamespacesPtr(gatewayapi_v1beta1.NamespacesFromSelector), - Selector: &metav1.LabelSelector{ - MatchExpressions: []metav1.LabelSelectorRequirement{{ - Key: "something", - Operator: metav1.LabelSelectorOpExists, - Values: []string{"error"}, - }}, - }, - }, - namespace: "custom", - valid: false, - wantError: true, - }, - "From.NamespacesFromSelector match expression 'NotExists', cannot specify values": { - namespaces: &gatewayapi_v1beta1.RouteNamespaces{ - From: gatewayapi.FromNamespacesPtr(gatewayapi_v1beta1.NamespacesFromSelector), - Selector: &metav1.LabelSelector{ - MatchExpressions: []metav1.LabelSelectorRequirement{{ - Key: "something", - Operator: metav1.LabelSelectorOpDoesNotExist, - Values: []string{"error"}, - }}, - }, - }, - namespace: "custom", - valid: false, - wantError: true, - }, - "From.NamespacesFromSelector must define matchLabels or matchExpression": { - namespaces: &gatewayapi_v1beta1.RouteNamespaces{ - From: gatewayapi.FromNamespacesPtr(gatewayapi_v1beta1.NamespacesFromSelector), - Selector: &metav1.LabelSelector{}, - }, - namespace: "custom", - valid: false, - wantError: true, }, } @@ -479,9 +428,15 @@ func TestNamespaceMatches(t *testing.T) { }, } - got, gotError := processor.namespaceMatches(tc.namespaces, tc.namespace) + var selector labels.Selector + var err error + if tc.namespaces != nil && tc.namespaces.Selector != nil { + selector, err = metav1.LabelSelectorAsSelector(tc.namespaces.Selector) + require.NoError(t, err) + } + + got := processor.namespaceMatches(tc.namespaces, selector, tc.namespace) assert.Equal(t, tc.valid, got) - assert.Equal(t, tc.wantError, gotError != nil) }) } } diff --git a/internal/dag/status_test.go b/internal/dag/status_test.go index d30166c607a..6e8cfca2df2 100644 --- a/internal/dag/status_test.go +++ b/internal/dag/status_test.go @@ -5961,6 +5961,169 @@ func TestGatewayAPIHTTPRouteDAGStatus(t *testing.T) { }, }}, }) + + run(t, "Listener with FromNamespaces=Selector, no selector specified", testcase{ + objs: []interface{}{}, + gateway: &gatewayapi_v1beta1.Gateway{ + ObjectMeta: metav1.ObjectMeta{ + Name: "contour", + Namespace: "projectcontour", + }, + Spec: gatewayapi_v1beta1.GatewaySpec{ + Listeners: []gatewayapi_v1beta1.Listener{ + { + Name: "http", + Port: 80, + Protocol: gatewayapi_v1beta1.HTTPProtocolType, + AllowedRoutes: &gatewayapi_v1beta1.AllowedRoutes{ + Namespaces: &gatewayapi_v1beta1.RouteNamespaces{ + From: gatewayapi.FromNamespacesPtr(gatewayapi_v1beta1.NamespacesFromSelector), + Selector: nil, + }, + }, + }}, + }, + }, + wantGatewayStatusUpdate: []*status.GatewayStatusUpdate{{ + FullName: types.NamespacedName{Namespace: "projectcontour", Name: "contour"}, + Conditions: map[gatewayapi_v1beta1.GatewayConditionType]metav1.Condition{ + gatewayapi_v1beta1.GatewayConditionScheduled: gatewayScheduledCondition(), + gatewayapi_v1beta1.GatewayConditionReady: { + Type: string(gatewayapi_v1beta1.GatewayConditionReady), + Status: contour_api_v1.ConditionFalse, + Reason: string(gatewayapi_v1beta1.GatewayReasonListenersNotValid), + Message: "Listeners are not valid", + }, + }, + ListenerStatus: map[string]*gatewayapi_v1beta1.ListenerStatus{ + "http": { + Name: "http", + SupportedKinds: []gatewayapi_v1beta1.RouteGroupKind{ + {Group: gatewayapi.GroupPtr(gatewayapi_v1alpha2.GroupName), Kind: "HTTPRoute"}, + }, + Conditions: []metav1.Condition{ + { + Type: "Ready", + Status: metav1.ConditionFalse, + Reason: "Invalid", + Message: "Listener.AllowedRoutes.Namespaces.Selector is required when Listener.AllowedRoutes.Namespaces.From is set to \"Selector\".", + }, + }, + }, + }, + }}, + }) + + run(t, "Listener with FromNamespaces=Selector, invalid selector (can't specify values with Exists operator)", testcase{ + objs: []interface{}{}, + gateway: &gatewayapi_v1beta1.Gateway{ + ObjectMeta: metav1.ObjectMeta{ + Name: "contour", + Namespace: "projectcontour", + }, + Spec: gatewayapi_v1beta1.GatewaySpec{ + Listeners: []gatewayapi_v1beta1.Listener{ + { + Name: "http", + Port: 80, + Protocol: gatewayapi_v1beta1.HTTPProtocolType, + AllowedRoutes: &gatewayapi_v1beta1.AllowedRoutes{ + Namespaces: &gatewayapi_v1beta1.RouteNamespaces{ + From: gatewayapi.FromNamespacesPtr(gatewayapi_v1beta1.NamespacesFromSelector), + Selector: &metav1.LabelSelector{ + MatchExpressions: []metav1.LabelSelectorRequirement{{ + Key: "something", + Operator: metav1.LabelSelectorOpExists, + Values: []string{"error"}, + }}, + }, + }, + }, + }}, + }, + }, + wantGatewayStatusUpdate: []*status.GatewayStatusUpdate{{ + FullName: types.NamespacedName{Namespace: "projectcontour", Name: "contour"}, + Conditions: map[gatewayapi_v1beta1.GatewayConditionType]metav1.Condition{ + gatewayapi_v1beta1.GatewayConditionScheduled: gatewayScheduledCondition(), + gatewayapi_v1beta1.GatewayConditionReady: { + Type: string(gatewayapi_v1beta1.GatewayConditionReady), + Status: contour_api_v1.ConditionFalse, + Reason: string(gatewayapi_v1beta1.GatewayReasonListenersNotValid), + Message: "Listeners are not valid", + }, + }, + ListenerStatus: map[string]*gatewayapi_v1beta1.ListenerStatus{ + "http": { + Name: "http", + SupportedKinds: []gatewayapi_v1beta1.RouteGroupKind{ + {Group: gatewayapi.GroupPtr(gatewayapi_v1alpha2.GroupName), Kind: "HTTPRoute"}, + }, + Conditions: []metav1.Condition{ + { + Type: "Ready", + Status: metav1.ConditionFalse, + Reason: "Invalid", + Message: "Error parsing Listener.AllowedRoutes.Namespaces.Selector: values: Invalid value: []string{\"error\"}: values set must be empty for exists and does not exist.", + }, + }, + }, + }, + }}, + }) + + run(t, "Listener with FromNamespaces=Selector, invalid selector (must specify MatchLabels and/or MatchExpressions)", testcase{ + objs: []interface{}{}, + gateway: &gatewayapi_v1beta1.Gateway{ + ObjectMeta: metav1.ObjectMeta{ + Name: "contour", + Namespace: "projectcontour", + }, + Spec: gatewayapi_v1beta1.GatewaySpec{ + Listeners: []gatewayapi_v1beta1.Listener{ + { + Name: "http", + Port: 80, + Protocol: gatewayapi_v1beta1.HTTPProtocolType, + AllowedRoutes: &gatewayapi_v1beta1.AllowedRoutes{ + Namespaces: &gatewayapi_v1beta1.RouteNamespaces{ + From: gatewayapi.FromNamespacesPtr(gatewayapi_v1beta1.NamespacesFromSelector), + Selector: &metav1.LabelSelector{}, + }, + }, + }}, + }, + }, + wantGatewayStatusUpdate: []*status.GatewayStatusUpdate{{ + FullName: types.NamespacedName{Namespace: "projectcontour", Name: "contour"}, + Conditions: map[gatewayapi_v1beta1.GatewayConditionType]metav1.Condition{ + gatewayapi_v1beta1.GatewayConditionScheduled: gatewayScheduledCondition(), + gatewayapi_v1beta1.GatewayConditionReady: { + Type: string(gatewayapi_v1beta1.GatewayConditionReady), + Status: contour_api_v1.ConditionFalse, + Reason: string(gatewayapi_v1beta1.GatewayReasonListenersNotValid), + Message: "Listeners are not valid", + }, + }, + ListenerStatus: map[string]*gatewayapi_v1beta1.ListenerStatus{ + "http": { + Name: "http", + SupportedKinds: []gatewayapi_v1beta1.RouteGroupKind{ + {Group: gatewayapi.GroupPtr(gatewayapi_v1alpha2.GroupName), Kind: "HTTPRoute"}, + }, + Conditions: []metav1.Condition{ + { + Type: "Ready", + Status: metav1.ConditionFalse, + Reason: "Invalid", + Message: "Listener.AllowedRoutes.Namespaces.Selector must specify at least one MatchLabel or MatchExpression.", + }, + }, + }, + }, + }}, + }) + } func TestGatewayAPITLSRouteDAGStatus(t *testing.T) { From 977d0e105924e3cba5534d0f06ecf11fb76d764b Mon Sep 17 00:00:00 2001 From: Steve Kriss Date: Tue, 12 Jul 2022 21:18:51 +0000 Subject: [PATCH 2/3] changelog Signed-off-by: Steve Kriss --- changelogs/unreleased/4615-skriss-small.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelogs/unreleased/4615-skriss-small.md diff --git a/changelogs/unreleased/4615-skriss-small.md b/changelogs/unreleased/4615-skriss-small.md new file mode 100644 index 00000000000..168432e6386 --- /dev/null +++ b/changelogs/unreleased/4615-skriss-small.md @@ -0,0 +1 @@ +Gateway API: set a Listener condition of `Ready: false` with reason `Invalid` when a Listener allows routes from a namespace selector but the selector is invalid. From b053e8c21cdf337275493e6d1f2252301f868e8d Mon Sep 17 00:00:00 2001 From: Steve Kriss Date: Tue, 12 Jul 2022 21:23:20 +0000 Subject: [PATCH 3/3] fix lint issue Signed-off-by: Steve Kriss --- internal/dag/status_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/dag/status_test.go b/internal/dag/status_test.go index 6e8cfca2df2..218edd7ca07 100644 --- a/internal/dag/status_test.go +++ b/internal/dag/status_test.go @@ -6087,7 +6087,7 @@ func TestGatewayAPIHTTPRouteDAGStatus(t *testing.T) { Protocol: gatewayapi_v1beta1.HTTPProtocolType, AllowedRoutes: &gatewayapi_v1beta1.AllowedRoutes{ Namespaces: &gatewayapi_v1beta1.RouteNamespaces{ - From: gatewayapi.FromNamespacesPtr(gatewayapi_v1beta1.NamespacesFromSelector), + From: gatewayapi.FromNamespacesPtr(gatewayapi_v1beta1.NamespacesFromSelector), Selector: &metav1.LabelSelector{}, }, },