Documentation ¶
Index ¶
Constants ¶
This section is empty.
Variables ¶
View Source
var ConformanceTests []suite.ConformanceTest
View Source
var GatewayInvalidRouteKind = suite.ConformanceTest{ ShortName: "GatewayInvalidRouteKind", Description: "A Gateway in the gateway-conformance-infra namespace should fail to become ready an invalid Route kind is specified.", Manifests: []string{"tests/gateway-invalid-route-kind.yaml"}, Test: func(t *testing.T, s *suite.ConformanceTestSuite) { t.Run("Gateway listener should have a false ResolvedRefs condition with reason InvalidRouteKinds and no supportedKinds", func(t *testing.T) { gwNN := types.NamespacedName{Name: "gateway-only-invalid-route-kind", Namespace: "gateway-conformance-infra"} listeners := []v1beta1.ListenerStatus{{ Name: v1beta1.SectionName("http"), SupportedKinds: []v1beta1.RouteGroupKind{}, Conditions: []metav1.Condition{{ Type: string(v1beta1.ListenerConditionResolvedRefs), Status: metav1.ConditionFalse, Reason: string(v1beta1.ListenerReasonInvalidRouteKinds), }}, }} kubernetes.GatewayStatusMustHaveListeners(t, s.Client, s.TimeoutConfig, gwNN, listeners) }) t.Run("Gateway listener should have a false ResolvedRefs condition with reason InvalidRouteKinds and HTTPRoute must be put in the supportedKinds", func(t *testing.T) { gwNN := types.NamespacedName{Name: "gateway-supported-and-invalid-route-kind", Namespace: "gateway-conformance-infra"} listeners := []v1beta1.ListenerStatus{{ Name: v1beta1.SectionName("http"), SupportedKinds: []v1beta1.RouteGroupKind{{ Group: (*v1beta1.Group)(&v1beta1.GroupVersion.Group), Kind: v1beta1.Kind("HTTPRoute"), }}, Conditions: []metav1.Condition{{ Type: string(v1beta1.ListenerConditionResolvedRefs), Status: metav1.ConditionFalse, Reason: string(v1beta1.ListenerReasonInvalidRouteKinds), }}, }} kubernetes.GatewayStatusMustHaveListeners(t, s.Client, s.TimeoutConfig, gwNN, listeners) }) }, }
View Source
var GatewayInvalidTLSConfiguration = suite.ConformanceTest{ ShortName: "GatewayInvalidTLSConfiguration", Description: "A Gateway should fail to become ready if the Gateway has an invalid TLS configuration", Manifests: []string{"tests/gateway-invalid-tls-certificateref.yaml"}, Test: func(t *testing.T, s *suite.ConformanceTestSuite) { listeners := []v1beta1.ListenerStatus{{ Name: v1beta1.SectionName("https"), SupportedKinds: []v1beta1.RouteGroupKind{{ Group: (*v1beta1.Group)(&v1beta1.GroupVersion.Group), Kind: v1beta1.Kind("HTTPRoute"), }}, Conditions: []metav1.Condition{{ Type: string(v1beta1.ListenerConditionResolvedRefs), Status: metav1.ConditionFalse, Reason: string(v1beta1.ListenerReasonInvalidCertificateRef), }}, }} testCases := []struct { name string gatewayNamespacedName types.NamespacedName }{ { name: "Nonexistent secret referenced as CertificateRef in a Gateway listener", gatewayNamespacedName: types.NamespacedName{Name: "gateway-certificate-nonexistent-secret", Namespace: "gateway-conformance-infra"}, }, { name: "Unsupported group resource referenced as CertificateRef in a Gateway listener", gatewayNamespacedName: types.NamespacedName{Name: "gateway-certificate-unsupported-group", Namespace: "gateway-conformance-infra"}, }, { name: "Unsupported kind resource referenced as CertificateRef in a Gateway listener", gatewayNamespacedName: types.NamespacedName{Name: "gateway-certificate-unsupported-kind", Namespace: "gateway-conformance-infra"}, }, { name: "Malformed secret referenced as CertificateRef in a Gateway listener", gatewayNamespacedName: types.NamespacedName{Name: "gateway-certificate-malformed-secret", Namespace: "gateway-conformance-infra"}, }, } for _, tc := range testCases { tc := tc t.Run(tc.name, func(t *testing.T) { t.Parallel() kubernetes.GatewayStatusMustHaveListeners(t, s.Client, s.TimeoutConfig, tc.gatewayNamespacedName, listeners) }) } }, }
View Source
var GatewaySecretInvalidReferenceGrant = suite.ConformanceTest{ ShortName: "GatewaySecretInvalidReferenceGrant", Description: "A Gateway in the gateway-conformance-infra namespace should fail to become ready if the Gateway has a certificateRef for a Secret in the gateway-conformance-web-backend namespace and a ReferenceGrant exists but does not grant permission to that specific Secret", Features: []suite.SupportedFeature{suite.SupportReferenceGrant}, Manifests: []string{"tests/gateway-secret-invalid-reference-grant.yaml"}, Test: func(t *testing.T, s *suite.ConformanceTestSuite) { gwNN := types.NamespacedName{Name: "gateway-secret-invalid-reference-grant", Namespace: "gateway-conformance-infra"} t.Run("Gateway listener should have a false ResolvedRefs condition with reason RefNotPermitted", func(t *testing.T) { listeners := []v1beta1.ListenerStatus{{ Name: v1beta1.SectionName("https"), SupportedKinds: []v1beta1.RouteGroupKind{{ Group: (*v1beta1.Group)(&v1beta1.GroupVersion.Group), Kind: v1beta1.Kind("HTTPRoute"), }}, Conditions: []metav1.Condition{{ Type: string(v1beta1.ListenerConditionResolvedRefs), Status: metav1.ConditionFalse, Reason: string(v1beta1.ListenerReasonRefNotPermitted), }}, }} kubernetes.GatewayStatusMustHaveListeners(t, s.Client, s.TimeoutConfig, gwNN, listeners) }) }, }
View Source
var GatewaySecretMissingReferenceGrant = suite.ConformanceTest{ ShortName: "GatewaySecretMissingReferenceGrant", Description: "A Gateway in the gateway-conformance-infra namespace should fail to become programmed if the Gateway has a certificateRef for a Secret in the gateway-conformance-web-backend namespace and a ReferenceGrant granting permission to the Secret does not exist", Features: []suite.SupportedFeature{suite.SupportReferenceGrant}, Manifests: []string{"tests/gateway-secret-missing-reference-grant.yaml"}, Test: func(t *testing.T, s *suite.ConformanceTestSuite) { gwNN := types.NamespacedName{Name: "gateway-secret-missing-reference-grant", Namespace: "gateway-conformance-infra"} t.Run("Gateway listener should have a false ResolvedRefs condition with reason RefNotPermitted", func(t *testing.T) { listeners := []v1beta1.ListenerStatus{{ Name: v1beta1.SectionName("https"), SupportedKinds: []v1beta1.RouteGroupKind{{ Group: (*v1beta1.Group)(&v1beta1.GroupVersion.Group), Kind: v1beta1.Kind("HTTPRoute"), }}, Conditions: []metav1.Condition{{ Type: string(v1beta1.ListenerConditionResolvedRefs), Status: metav1.ConditionFalse, Reason: string(v1beta1.ListenerReasonRefNotPermitted), }}, }} kubernetes.GatewayStatusMustHaveListeners(t, s.Client, s.TimeoutConfig, gwNN, listeners) }) }, }
View Source
var GatewaySecretReferenceGrantAllInNamespace = suite.ConformanceTest{ ShortName: "GatewaySecretReferenceGrantAllInNamespace", Description: "A Gateway in the gateway-conformance-infra namespace should become programmed if the Gateway has a certificateRef for a Secret in the gateway-conformance-web-backend namespace and a ReferenceGrant granting permission to all Secrets in the namespace exists", Features: []suite.SupportedFeature{suite.SupportReferenceGrant}, Manifests: []string{"tests/gateway-secret-reference-grant-all-in-namespace.yaml"}, Test: func(t *testing.T, s *suite.ConformanceTestSuite) { gwNN := types.NamespacedName{Name: "gateway-secret-reference-grant", Namespace: "gateway-conformance-infra"} t.Run("Gateway listener should have a true ResolvedRefs condition and a true Programmed condition", func(t *testing.T) { listeners := []v1beta1.ListenerStatus{{ Name: v1beta1.SectionName("https"), SupportedKinds: []v1beta1.RouteGroupKind{{ Group: (*v1beta1.Group)(&v1beta1.GroupVersion.Group), Kind: v1beta1.Kind("HTTPRoute"), }}, Conditions: []metav1.Condition{ { Type: string(v1beta1.ListenerConditionProgrammed), Status: metav1.ConditionTrue, Reason: string(v1beta1.ListenerConditionProgrammed), }, }, }} kubernetes.GatewayStatusMustHaveListeners(t, s.Client, s.TimeoutConfig, gwNN, listeners) }) }, }
View Source
var GatewaySecretReferenceGrantSpecific = suite.ConformanceTest{ ShortName: "GatewaySecretReferenceGrantSpecific", Description: "A Gateway in the gateway-conformance-infra namespace should become programmed if the Gateway has a certificateRef for a Secret in the gateway-conformance-web-backend namespace and a ReferenceGrant granting permission to the specific Secret exists", Features: []suite.SupportedFeature{suite.SupportReferenceGrant}, Manifests: []string{"tests/gateway-secret-reference-grant-specific.yaml"}, Test: func(t *testing.T, s *suite.ConformanceTestSuite) { gwNN := types.NamespacedName{Name: "gateway-secret-reference-grant", Namespace: "gateway-conformance-infra"} t.Run("Gateway listener should have a true ResolvedRefs condition and a true Programmed condition", func(t *testing.T) { listeners := []v1beta1.ListenerStatus{{ Name: v1beta1.SectionName("https"), SupportedKinds: []v1beta1.RouteGroupKind{{ Group: (*v1beta1.Group)(&v1beta1.GroupVersion.Group), Kind: v1beta1.Kind("HTTPRoute"), }}, Conditions: []metav1.Condition{ { Type: string(v1beta1.ListenerConditionProgrammed), Status: metav1.ConditionTrue, Reason: string(v1beta1.ListenerReasonProgrammed), }, }, }} kubernetes.GatewayStatusMustHaveListeners(t, s.Client, s.TimeoutConfig, gwNN, listeners) }) }, }
View Source
var HTTPExactPathMatching = suite.ConformanceTest{ ShortName: "HTTPExactPathMatching", Description: "A single HTTPRoute with exact path matching for different backends", Manifests: []string{"tests/httproute-exact-path-matching.yaml"}, Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { ns := "gateway-conformance-infra" routeNN := types.NamespacedName{Name: "exact-matching", Namespace: ns} gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns} gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN) testCases := []http.ExpectedResponse{ { Request: http.Request{Path: "/one"}, Backend: "infra-backend-v1", Namespace: ns, }, { Request: http.Request{Path: "/two"}, Backend: "infra-backend-v2", Namespace: ns, }, { Request: http.Request{Path: "/"}, Response: http.Response{StatusCode: 404}, }, { Request: http.Request{Path: "/one/example"}, Response: http.Response{StatusCode: 404}, }, { Request: http.Request{Path: "/two/"}, Response: http.Response{StatusCode: 404}, }, } for i := range testCases { tc := testCases[i] t.Run(tc.GetTestCaseName(i), func(t *testing.T) { t.Parallel() http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, tc) }) } }, }
View Source
var HTTPRouteCrossNamespace = suite.ConformanceTest{ ShortName: "HTTPRouteCrossNamespace", Description: "A single HTTPRoute in the gateway-conformance-web-backend namespace should attach to Gateway in another namespace", Manifests: []string{"tests/httproute-cross-namespace.yaml"}, Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { routeNN := types.NamespacedName{Name: "cross-namespace", Namespace: "gateway-conformance-web-backend"} gwNN := types.NamespacedName{Name: "backend-namespaces", Namespace: "gateway-conformance-infra"} gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN) t.Run("Simple HTTP request should reach web-backend", func(t *testing.T) { http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, http.ExpectedResponse{ Request: http.Request{Path: "/"}, Response: http.Response{StatusCode: 200}, Backend: "web-backend", Namespace: "gateway-conformance-web-backend", }) }) }, }
View Source
var HTTPRouteDisallowedKind = suite.ConformanceTest{ ShortName: "HTTPRouteDisallowedKind", Description: "A single HTTPRoute in the gateway-conformance-infra namespace should fail to attach to a Listener that does not allow the HTTPRoute kind", Features: []suite.SupportedFeature{suite.SupportTLSRoute}, Manifests: []string{"tests/httproute-disallowed-kind.yaml"}, Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { kubernetes.NamespacesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, []string{"gateway-conformance-infra"}) routeName := types.NamespacedName{Name: "disallowed-kind", Namespace: "gateway-conformance-infra"} gwName := types.NamespacedName{Name: "tlsroutes-only", Namespace: "gateway-conformance-infra"} t.Run("Route should not have Parents set in status", func(t *testing.T) { kubernetes.HTTPRouteMustHaveNoAcceptedParents(t, suite.Client, suite.TimeoutConfig, routeName) }) t.Run("Gateway should have 0 Routes attached", func(t *testing.T) { kubernetes.GatewayMustHaveZeroRoutes(t, suite.Client, suite.TimeoutConfig, gwName) }) }, }
View Source
var HTTPRouteHeaderMatching = suite.ConformanceTest{ ShortName: "HTTPRouteHeaderMatching", Description: "A single HTTPRoute with header matching for different backends", Manifests: []string{"tests/httproute-header-matching.yaml"}, Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { ns := "gateway-conformance-infra" routeNN := types.NamespacedName{Name: "header-matching", Namespace: ns} gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns} gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN) testCases := []http.ExpectedResponse{{ Request: http.Request{Path: "/", Headers: map[string]string{"Version": "one"}}, Backend: "infra-backend-v1", Namespace: ns, }, { Request: http.Request{Path: "/", Headers: map[string]string{"Version": "two"}}, Backend: "infra-backend-v2", Namespace: ns, }, { Request: http.Request{Path: "/", Headers: map[string]string{"Version": "two", "Color": "orange"}}, Backend: "infra-backend-v1", Namespace: ns, }, { Request: http.Request{Path: "/", Headers: map[string]string{"Version": "two", "Color": "blue"}}, Backend: "infra-backend-v2", Namespace: ns, }, { Request: http.Request{Path: "/", Headers: map[string]string{"Color": "orange"}}, Response: http.Response{StatusCode: 404}, }, { Request: http.Request{Path: "/", Headers: map[string]string{"Some-Other-Header": "one"}}, Response: http.Response{StatusCode: 404}, }, { Request: http.Request{Path: "/", Headers: map[string]string{"Color": "blue"}}, Backend: "infra-backend-v1", Namespace: ns, }, { Request: http.Request{Path: "/", Headers: map[string]string{"Color": "green"}}, Backend: "infra-backend-v1", Namespace: ns, }, { Request: http.Request{Path: "/", Headers: map[string]string{"Color": "red"}}, Backend: "infra-backend-v2", Namespace: ns, }, { Request: http.Request{Path: "/", Headers: map[string]string{"Color": "yellow"}}, Backend: "infra-backend-v2", Namespace: ns, }, { Request: http.Request{Path: "/", Headers: map[string]string{"Color": "purple"}}, Response: http.Response{StatusCode: 404}, }} for i := range testCases { tc := testCases[i] t.Run(tc.GetTestCaseName(i), func(t *testing.T) { t.Parallel() http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, tc) }) } }, }
View Source
var HTTPRouteHostnameIntersection = suite.ConformanceTest{ ShortName: "HTTPRouteHostnameIntersection", Description: "HTTPRoutes should attach to listeners only if they have intersecting hostnames, and should accept requests only for the intersecting hostnames", Manifests: []string{"tests/httproute-hostname-intersection.yaml"}, Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { ns := "gateway-conformance-infra" gwNN := types.NamespacedName{Name: "httproute-hostname-intersection", Namespace: ns} kubernetes.NamespacesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, []string{ns}) t.Run("HTTPRoutes that do intersect with listener hostnames", func(t *testing.T) { routes := []types.NamespacedName{ {Namespace: ns, Name: "specific-host-matches-listener-specific-host"}, {Namespace: ns, Name: "specific-host-matches-listener-wildcard-host"}, {Namespace: ns, Name: "wildcard-host-matches-listener-specific-host"}, {Namespace: ns, Name: "wildcard-host-matches-listener-wildcard-host"}, } gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routes...) var testCases []http.ExpectedResponse testCases = append(testCases, http.ExpectedResponse{ Request: http.Request{Host: "very.specific.com", Path: "/s1"}, Backend: "infra-backend-v1", Namespace: ns, }, http.ExpectedResponse{ Request: http.Request{Host: "non.matching.com", Path: "/s1"}, Response: http.Response{StatusCode: 404}, }, http.ExpectedResponse{ Request: http.Request{Host: "foo.nonmatchingwildcard.io", Path: "/s1"}, Response: http.Response{StatusCode: 404}, }, http.ExpectedResponse{ Request: http.Request{Host: "foo.wildcard.io", Path: "/s1"}, Response: http.Response{StatusCode: 404}, }, http.ExpectedResponse{ Request: http.Request{Host: "very.specific.com", Path: "/non-matching-prefix"}, Response: http.Response{StatusCode: 404}, }, ) testCases = append(testCases, http.ExpectedResponse{ Request: http.Request{Host: "foo.wildcard.io", Path: "/s2"}, Backend: "infra-backend-v2", Namespace: ns, }, http.ExpectedResponse{ Request: http.Request{Host: "bar.wildcard.io", Path: "/s2"}, Backend: "infra-backend-v2", Namespace: ns, }, http.ExpectedResponse{ Request: http.Request{Host: "foo.bar.wildcard.io", Path: "/s2"}, Backend: "infra-backend-v2", Namespace: ns, }, http.ExpectedResponse{ Request: http.Request{Host: "non.matching.com", Path: "/s2"}, Response: http.Response{StatusCode: 404}, }, http.ExpectedResponse{ Request: http.Request{Host: "wildcard.io", Path: "/s2"}, Response: http.Response{StatusCode: 404}, }, http.ExpectedResponse{ Request: http.Request{Host: "very.specific.com", Path: "/s2"}, Response: http.Response{StatusCode: 404}, }, http.ExpectedResponse{ Request: http.Request{Host: "foo.wildcard.io", Path: "/non-matching-prefix"}, Response: http.Response{StatusCode: 404}, }, ) testCases = append(testCases, http.ExpectedResponse{ Request: http.Request{Host: "very.specific.com", Path: "/s3"}, Backend: "infra-backend-v3", Namespace: ns, }, http.ExpectedResponse{ Request: http.Request{Host: "non.matching.com", Path: "/s3"}, Response: http.Response{StatusCode: 404}, }, http.ExpectedResponse{ Request: http.Request{Host: "foo.specific.com", Path: "/s3"}, Response: http.Response{StatusCode: 404}, }, http.ExpectedResponse{ Request: http.Request{Host: "foo.wildcard.io", Path: "/s3"}, Response: http.Response{StatusCode: 404}, }, http.ExpectedResponse{ Request: http.Request{Host: "very.specific.com", Path: "/non-matching-prefix"}, Response: http.Response{StatusCode: 404}, }, ) testCases = append(testCases, http.ExpectedResponse{ Request: http.Request{Host: "foo.anotherwildcard.io", Path: "/s4"}, Backend: "infra-backend-v1", Namespace: ns, }, http.ExpectedResponse{ Request: http.Request{Host: "bar.anotherwildcard.io", Path: "/s4"}, Backend: "infra-backend-v1", Namespace: ns, }, http.ExpectedResponse{ Request: http.Request{Host: "foo.bar.anotherwildcard.io", Path: "/s4"}, Backend: "infra-backend-v1", Namespace: ns, }, http.ExpectedResponse{ Request: http.Request{Host: "anotherwildcard.io", Path: "/s4"}, Response: http.Response{StatusCode: 404}, }, http.ExpectedResponse{ Request: http.Request{Host: "foo.wildcard.io", Path: "/s4"}, Response: http.Response{StatusCode: 404}, }, http.ExpectedResponse{ Request: http.Request{Host: "very.specific.com", Path: "/s4"}, Response: http.Response{StatusCode: 404}, }, http.ExpectedResponse{ Request: http.Request{Host: "foo.anotherwildcard.io", Path: "/non-matching-prefix"}, Response: http.Response{StatusCode: 404}, }, ) for i := range testCases { tc := testCases[i] t.Run(tc.GetTestCaseName(i), func(t *testing.T) { t.Parallel() http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, tc) }) } }) t.Run("HTTPRoutes that do not intersect with listener hostnames", func(t *testing.T) { gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN)) routeName := types.NamespacedName{Namespace: ns, Name: "no-intersecting-hosts"} parents := []v1beta1.RouteParentStatus{{ ParentRef: parentRefTo(gwNN), ControllerName: v1beta1.GatewayController(suite.ControllerName), Conditions: []metav1.Condition{ { Type: string(v1beta1.RouteConditionAccepted), Status: metav1.ConditionFalse, Reason: string(v1beta1.RouteReasonNoMatchingListenerHostname), }, }, }} kubernetes.HTTPRouteMustHaveParents(t, suite.Client, suite.TimeoutConfig, routeName, parents, true) testCases := []http.ExpectedResponse{ { Request: http.Request{Host: "specific.but.wrong.com", Path: "/s5"}, Response: http.Response{StatusCode: 404}, }, { Request: http.Request{Host: "wildcard.io", Path: "/s5"}, Response: http.Response{StatusCode: 404}, }, } for i := range testCases { tc := testCases[i] t.Run(tc.GetTestCaseName(i), func(t *testing.T) { t.Parallel() http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, tc) }) } }) }, }
View Source
var HTTPRouteInvalidBackendRefUnknownKind = suite.ConformanceTest{ ShortName: "HTTPRouteInvalidBackendRefUnknownKind", Description: "A single HTTPRoute in the gateway-conformance-infra namespace should set a ResolvedRefs status False with reason InvalidKind when attempting to bind to a Gateway in the same namespace if the route has a BackendRef that points to an unknown Kind.", Manifests: []string{"tests/httproute-invalid-backendref-unknown-kind.yaml"}, Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { routeNN := types.NamespacedName{Name: "invalid-backend-ref-unknown-kind", Namespace: "gateway-conformance-infra"} gwNN := types.NamespacedName{Name: "same-namespace", Namespace: "gateway-conformance-infra"} gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN) t.Run("HTTPRoute with Invalid Kind has a ResolvedRefs Condition with status False and Reason InvalidKind", func(t *testing.T) { resolvedRefsCond := metav1.Condition{ Type: string(v1beta1.RouteConditionResolvedRefs), Status: metav1.ConditionFalse, Reason: string(v1beta1.RouteReasonInvalidKind), } kubernetes.HTTPRouteMustHaveCondition(t, suite.Client, suite.TimeoutConfig, routeNN, gwNN, resolvedRefsCond) }) t.Run("HTTP Request to invalid backend with invalid Kind receives a 500", func(t *testing.T) { http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, http.ExpectedResponse{ Request: http.Request{ Method: "GET", Path: "/v2", }, Response: http.Response{StatusCode: 500}, }) }) }, }
View Source
var HTTPRouteInvalidCrossNamespaceBackendRef = suite.ConformanceTest{ ShortName: "HTTPRouteInvalidCrossNamespaceBackendRef", Description: "A single HTTPRoute in the gateway-conformance-infra namespace should set a ResolvedRefs status False with reason RefNotPermitted when attempting to bind to a Gateway in the same namespace if the route has a BackendRef Service in the gateway-conformance-web-backend namespace and a ReferenceGrant granting permission to route to that Service does not exist", Features: []suite.SupportedFeature{suite.SupportReferenceGrant}, Manifests: []string{"tests/httproute-invalid-cross-namespace-backend-ref.yaml"}, Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { routeNN := types.NamespacedName{Name: "invalid-cross-namespace-backend-ref", Namespace: "gateway-conformance-infra"} gwNN := types.NamespacedName{Name: "same-namespace", Namespace: "gateway-conformance-infra"} gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN) t.Run("HTTPRoute with a cross-namespace BackendRef and no ReferenceGrant has a ResolvedRefs Condition with status False and Reason RefNotPermitted", func(t *testing.T) { resolvedRefsCond := metav1.Condition{ Type: string(v1beta1.RouteConditionResolvedRefs), Status: metav1.ConditionFalse, Reason: string(v1beta1.RouteReasonRefNotPermitted), } kubernetes.HTTPRouteMustHaveCondition(t, suite.Client, suite.TimeoutConfig, routeNN, gwNN, resolvedRefsCond) }) t.Run("HTTP Request to invalid cross-namespace backend must receive a 500", func(t *testing.T) { http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, http.ExpectedResponse{ Request: http.Request{ Method: "GET", Path: "/", }, Response: http.Response{StatusCode: 500}, }) }) }, }
View Source
var HTTPRouteInvalidCrossNamespaceParentRef = suite.ConformanceTest{ ShortName: "HTTPRouteInvalidCrossNamespaceParentRef", Description: "A single HTTPRoute in the gateway-conformance-web-backend namespace should fail to attach to a Gateway in another namespace that it is not allowed to", Manifests: []string{"tests/httproute-invalid-cross-namespace-parent-ref.yaml"}, Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { routeName := types.NamespacedName{Name: "invalid-cross-namespace-parent-ref", Namespace: "gateway-conformance-web-backend"} gwName := types.NamespacedName{Name: "same-namespace", Namespace: "gateway-conformance-infra"} t.Run("Route should not have Parents set in status", func(t *testing.T) { kubernetes.HTTPRouteMustHaveNoAcceptedParents(t, suite.Client, suite.TimeoutConfig, routeName) }) t.Run("Gateway should have 0 Routes attached", func(t *testing.T) { kubernetes.GatewayMustHaveZeroRoutes(t, suite.Client, suite.TimeoutConfig, gwName) }) }, }
View Source
var HTTPRouteInvalidNonExistentBackendRef = suite.ConformanceTest{ ShortName: "HTTPRouteInvalidNonExistentBackendRef", Description: "A single HTTPRoute in the gateway-conformance-infra namespace should set a ResolvedRefs status False with reason BackendNotFound and return 500 when binding to a Gateway in the same namespace if the route has a BackendRef Service that does not exist", Manifests: []string{"tests/httproute-invalid-backendref-nonexistent.yaml"}, Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { routeNN := types.NamespacedName{Name: "invalid-nonexistent-backend-ref", Namespace: "gateway-conformance-infra"} gwNN := types.NamespacedName{Name: "same-namespace", Namespace: "gateway-conformance-infra"} gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN) t.Run("HTTPRoute with only a nonexistent BackendRef has a ResolvedRefs Condition with status False and Reason BackendNotFound", func(t *testing.T) { resolvedRefsCond := metav1.Condition{ Type: string(v1beta1.RouteConditionResolvedRefs), Status: metav1.ConditionFalse, Reason: string(v1beta1.RouteReasonBackendNotFound), } kubernetes.HTTPRouteMustHaveCondition(t, suite.Client, suite.TimeoutConfig, routeNN, gwNN, resolvedRefsCond) }) t.Run("HTTP Request to invalid nonexistent backend receive a 500", func(t *testing.T) { http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, http.ExpectedResponse{ Request: http.Request{ Method: "GET", Path: "/", }, Response: http.Response{StatusCode: 500}, }) }) }, }
View Source
var HTTPRouteInvalidParentRefNotMatchingListenerPort = suite.ConformanceTest{ ShortName: "HTTPRouteInvalidParentRefNotMatchingListenerPort", Description: "A single HTTPRoute in the gateway-conformance-infra namespace should set the Accepted status to False with reason NoMatchingParent when attempting to bind to a Gateway that does not have a matching ListenerPort.", Features: []suite.SupportedFeature{suite.SupportRouteDestinationPortMatching}, Manifests: []string{"tests/httproute-invalid-parentref-not-matching-listener-port.yaml"}, Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { routeNN := types.NamespacedName{Name: "httproute-listener-not-matching-route-port", Namespace: "gateway-conformance-infra"} gwNN := types.NamespacedName{Name: "same-namespace", Namespace: "gateway-conformance-infra"} t.Run("HTTPRoute with no matching port in ParentRef has an Accepted Condition with status False and Reason NoMatchingParent", func(t *testing.T) { resolvedRefsCond := metav1.Condition{ Type: string(v1beta1.RouteConditionAccepted), Status: metav1.ConditionFalse, Reason: string(v1beta1.RouteReasonNoMatchingParent), } kubernetes.HTTPRouteMustHaveCondition(t, suite.Client, suite.TimeoutConfig, routeNN, gwNN, resolvedRefsCond) }) t.Run("Route should not have Parents accepted in status", func(t *testing.T) { kubernetes.HTTPRouteMustHaveNoAcceptedParents(t, suite.Client, suite.TimeoutConfig, routeNN) }) t.Run("Gateway should have 0 Routes attached", func(t *testing.T) { kubernetes.GatewayMustHaveZeroRoutes(t, suite.Client, suite.TimeoutConfig, gwNN) }) }, }
View Source
var HTTPRouteListenerHostnameMatching = suite.ConformanceTest{ ShortName: "HTTPRouteListenerHostnameMatching", Description: "Multiple HTTP listeners with the same port and different hostnames, each with a different HTTPRoute", Manifests: []string{"tests/httproute-listener-hostname-matching.yaml"}, Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { ns := "gateway-conformance-infra" kubernetes.NamespacesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, []string{ns}) gwNN := types.NamespacedName{Name: "httproute-listener-hostname-matching", Namespace: ns} _ = kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN, "listener-1"), types.NamespacedName{Namespace: ns, Name: "backend-v1"}, ) _ = kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN, "listener-2"), types.NamespacedName{Namespace: ns, Name: "backend-v2"}, ) gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN, "listener-3", "listener-4"), types.NamespacedName{Namespace: ns, Name: "backend-v3"}, ) testCases := []http.ExpectedResponse{{ Request: http.Request{Host: "bar.com", Path: "/"}, Backend: "infra-backend-v1", Namespace: ns, }, { Request: http.Request{Host: "foo.bar.com", Path: "/"}, Backend: "infra-backend-v2", Namespace: ns, }, { Request: http.Request{Host: "baz.bar.com", Path: "/"}, Backend: "infra-backend-v3", Namespace: ns, }, { Request: http.Request{Host: "boo.bar.com", Path: "/"}, Backend: "infra-backend-v3", Namespace: ns, }, { Request: http.Request{Host: "multiple.prefixes.bar.com", Path: "/"}, Backend: "infra-backend-v3", Namespace: ns, }, { Request: http.Request{Host: "multiple.prefixes.foo.com", Path: "/"}, Backend: "infra-backend-v3", Namespace: ns, }, { Request: http.Request{Host: "foo.com", Path: "/"}, Response: http.Response{StatusCode: 404}, }, { Request: http.Request{Host: "no.matching.host", Path: "/"}, Response: http.Response{StatusCode: 404}, }} for i := range testCases { tc := testCases[i] t.Run(tc.GetTestCaseName(i), func(t *testing.T) { t.Parallel() http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, tc) }) } }, }
View Source
var HTTPRouteMatching = suite.ConformanceTest{ ShortName: "HTTPRouteMatching", Description: "A single HTTPRoute with path and header matching for different backends", Manifests: []string{"tests/httproute-matching.yaml"}, Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { ns := "gateway-conformance-infra" routeNN := types.NamespacedName{Name: "matching", Namespace: ns} gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns} gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN) testCases := []http.ExpectedResponse{{ Request: http.Request{Path: "/"}, Backend: "infra-backend-v1", Namespace: ns, }, { Request: http.Request{Path: "/example"}, Backend: "infra-backend-v1", Namespace: ns, }, { Request: http.Request{Path: "/", Headers: map[string]string{"Version": "one"}}, Backend: "infra-backend-v1", Namespace: ns, }, { Request: http.Request{Path: "/v2"}, Backend: "infra-backend-v2", Namespace: ns, }, { Request: http.Request{Path: "/v2/example"}, Backend: "infra-backend-v2", Namespace: ns, }, { Request: http.Request{Path: "/", Headers: map[string]string{"Version": "two"}}, Backend: "infra-backend-v2", Namespace: ns, }} for i := range testCases { tc := testCases[i] t.Run(tc.GetTestCaseName(i), func(t *testing.T) { t.Parallel() http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, tc) }) } }, }
View Source
var HTTPRouteMatchingAcrossRoutes = suite.ConformanceTest{ ShortName: "HTTPRouteMatchingAcrossRoutes", Description: "Two HTTPRoutes with path matching for different backends", Manifests: []string{"tests/httproute-matching-across-routes.yaml"}, Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { ns := "gateway-conformance-infra" routeNN1 := types.NamespacedName{Name: "matching-part1", Namespace: ns} routeNN2 := types.NamespacedName{Name: "matching-part2", Namespace: ns} gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns} gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN1, routeNN2) testCases := []http.ExpectedResponse{{ Request: http.Request{ Host: "example.com", Path: "/", }, Backend: "infra-backend-v1", Namespace: ns, }, { Request: http.Request{ Host: "example.com", Path: "/example", }, Backend: "infra-backend-v1", Namespace: ns, }, { Request: http.Request{ Host: "example.net", Path: "/example", }, Backend: "infra-backend-v1", Namespace: ns, }, { Request: http.Request{ Host: "example.com", Path: "/example", Headers: map[string]string{"Version": "one"}, }, Backend: "infra-backend-v1", Namespace: ns, }, { Request: http.Request{ Host: "example.com", Path: "/v2", }, Backend: "infra-backend-v2", Namespace: ns, }, { Request: http.Request{ Host: "example.net", Path: "/v2", }, Backend: "infra-backend-v1", Namespace: ns, }, { Request: http.Request{ Host: "example.com", Path: "/v2/example", }, Backend: "infra-backend-v2", Namespace: ns, }, { Request: http.Request{ Host: "example.com", Path: "/", Headers: map[string]string{"Version": "two"}, }, Backend: "infra-backend-v2", Namespace: ns, }} for i := range testCases { tc := testCases[i] t.Run(tc.GetTestCaseName(i), func(t *testing.T) { t.Parallel() http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, tc) }) } }, }
View Source
var HTTPRouteMethodMatching = suite.ConformanceTest{ ShortName: "HTTPRouteMethodMatching", Description: "A single HTTPRoute with method matching for different backends", Manifests: []string{"tests/httproute-method-matching.yaml"}, Features: []suite.SupportedFeature{suite.SupportHTTPRouteMethodMatching}, Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { ns := "gateway-conformance-infra" routeNN := types.NamespacedName{Name: "method-matching", Namespace: ns} gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns} gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN) testCases := []http.ExpectedResponse{ { Request: http.Request{Method: "POST", Path: "/"}, Backend: "infra-backend-v1", Namespace: ns, }, { Request: http.Request{Method: "GET", Path: "/"}, Backend: "infra-backend-v2", Namespace: ns, }, { Request: http.Request{Method: "HEAD", Path: "/"}, Response: http.Response{StatusCode: 404}, }, } for i := range testCases { tc := testCases[i] t.Run(tc.GetTestCaseName(i), func(t *testing.T) { t.Parallel() http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, tc) }) } }, }
View Source
var HTTPRoutePartiallyInvalidViaInvalidReferenceGrant = suite.ConformanceTest{ ShortName: "HTTPRoutePartiallyInvalidViaInvalidReferenceGrant", Description: "A single HTTPRoute in the gateway-conformance-infra namespace should attach to a Gateway in the same namespace if the route has a backendRef Service in the gateway-conformance-app-backend namespace and a ReferenceGrant exists but does not grant permission to route to that specific Service", Features: []suite.SupportedFeature{suite.SupportReferenceGrant}, Manifests: []string{"tests/httproute-partially-invalid-via-reference-grant.yaml"}, Test: func(t *testing.T, s *suite.ConformanceTestSuite) { routeNN := types.NamespacedName{Name: "invalid-reference-grant", Namespace: "gateway-conformance-infra"} gwNN := types.NamespacedName{Name: "same-namespace", Namespace: "gateway-conformance-infra"} gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, s.Client, s.TimeoutConfig, s.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN) t.Run("HTTPRoute with BackendRef in another namespace and no ReferenceGrant covering the Service has a ResolvedRefs Condition with status False and Reason RefNotPermitted", func(t *testing.T) { resolvedRefsCond := metav1.Condition{ Type: string(v1beta1.RouteConditionResolvedRefs), Status: metav1.ConditionFalse, Reason: string(v1beta1.RouteReasonRefNotPermitted), } kubernetes.HTTPRouteMustHaveCondition(t, s.Client, s.TimeoutConfig, routeNN, gwNN, resolvedRefsCond) }) t.Run("HTTP Request to invalid backend with missing referenceGrant should receive a 500", func(t *testing.T) { http.MakeRequestAndExpectEventuallyConsistentResponse(t, s.RoundTripper, s.TimeoutConfig, gwAddr, http.ExpectedResponse{ Request: http.Request{ Method: "GET", Path: "/v2", }, Response: http.Response{StatusCode: 500}, }) }) t.Run("HTTP Request to valid sibling backend should succeed", func(t *testing.T) { http.MakeRequestAndExpectEventuallyConsistentResponse(t, s.RoundTripper, s.TimeoutConfig, gwAddr, http.ExpectedResponse{ Request: http.Request{ Method: "GET", Path: "/", }, Response: http.Response{StatusCode: 200}, Backend: "app-backend-v1", Namespace: "gateway-conformance-app-backend", }) }) }, }
View Source
var HTTPRouteQueryParamMatching = suite.ConformanceTest{ ShortName: "HTTPRouteQueryParamMatching", Description: "A single HTTPRoute with query param matching for different backends", Manifests: []string{"tests/httproute-query-param-matching.yaml"}, Features: []suite.SupportedFeature{suite.SupportHTTPRouteQueryParamMatching}, Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { var ( ns = "gateway-conformance-infra" routeNN = types.NamespacedName{Namespace: ns, Name: "query-param-matching"} gwNN = types.NamespacedName{Namespace: ns, Name: "same-namespace"} gwAddr = kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN) ) testCases := []http.ExpectedResponse{{ Request: http.Request{Path: "/?animal=whale"}, Backend: "infra-backend-v1", Namespace: ns, }, { Request: http.Request{Path: "/?animal=dolphin"}, Backend: "infra-backend-v2", Namespace: ns, }, { Request: http.Request{Path: "/?animal=dolphin&color=blue"}, Backend: "infra-backend-v3", Namespace: ns, }, { Request: http.Request{Path: "/?ANIMAL=Whale"}, Backend: "infra-backend-v3", Namespace: ns, }, { Request: http.Request{Path: "/?animal=whale&otherparam=irrelevant"}, Backend: "infra-backend-v1", Namespace: ns, }, { Request: http.Request{Path: "/?animal=dolphin&color=yellow"}, Backend: "infra-backend-v2", Namespace: ns, }, { Request: http.Request{Path: "/?color=blue"}, Response: http.Response{StatusCode: 404}, }, { Request: http.Request{Path: "/?animal=dog"}, Response: http.Response{StatusCode: 404}, }, { Request: http.Request{Path: "/?animal=whaledolphin"}, Response: http.Response{StatusCode: 404}, }, { Request: http.Request{Path: "/"}, Response: http.Response{StatusCode: 404}, }} for i := range testCases { tc := testCases[i] t.Run(tc.GetTestCaseName(i), func(t *testing.T) { t.Parallel() http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, tc) }) } }, }
View Source
var HTTPRouteReferenceGrant = suite.ConformanceTest{ ShortName: "HTTPRouteReferenceGrant", Description: "A single HTTPRoute in the gateway-conformance-infra namespace, with a backendRef in the gateway-conformance-web-backend namespace, should attach to Gateway in the gateway-conformance-infra namespace", Features: []suite.SupportedFeature{suite.SupportReferenceGrant}, Manifests: []string{"tests/httproute-reference-grant.yaml"}, Test: func(t *testing.T, s *suite.ConformanceTestSuite) { routeNN := types.NamespacedName{Name: "reference-grant", Namespace: "gateway-conformance-infra"} gwNN := types.NamespacedName{Name: "same-namespace", Namespace: "gateway-conformance-infra"} gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, s.Client, s.TimeoutConfig, s.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN) t.Run("Simple HTTP request should reach web-backend", func(t *testing.T) { http.MakeRequestAndExpectEventuallyConsistentResponse(t, s.RoundTripper, s.TimeoutConfig, gwAddr, http.ExpectedResponse{ Request: http.Request{ Method: "GET", Path: "/", }, Response: http.Response{StatusCode: 200}, Backend: "web-backend", Namespace: "gateway-conformance-web-backend", }) }) }, }
View Source
var HTTPRouteRequestHeaderModifier = suite.ConformanceTest{ ShortName: "HTTPRouteRequestHeaderModifier", Description: "An HTTPRoute has request header modifier filters applied correctly", Manifests: []string{"tests/httproute-request-header-modifier.yaml"}, Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { ns := "gateway-conformance-infra" routeNN := types.NamespacedName{Name: "request-header-modifier", Namespace: ns} gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns} gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN) testCases := []http.ExpectedResponse{{ Request: http.Request{ Path: "/set", Headers: map[string]string{ "Some-Other-Header": "val", }, }, ExpectedRequest: &http.ExpectedRequest{ Request: http.Request{ Path: "/set", Headers: map[string]string{ "Some-Other-Header": "val", "X-Header-Set": "set-overwrites-values", }, }, }, Backend: "infra-backend-v1", Namespace: ns, }, { Request: http.Request{ Path: "/set", Headers: map[string]string{ "Some-Other-Header": "val", "X-Header-Set": "some-other-value", }, }, ExpectedRequest: &http.ExpectedRequest{ Request: http.Request{ Path: "/set", Headers: map[string]string{ "Some-Other-Header": "val", "X-Header-Set": "set-overwrites-values", }, }, }, Backend: "infra-backend-v1", Namespace: ns, }, { Request: http.Request{ Path: "/add", Headers: map[string]string{ "Some-Other-Header": "val", }, }, ExpectedRequest: &http.ExpectedRequest{ Request: http.Request{ Path: "/add", Headers: map[string]string{ "Some-Other-Header": "val", "X-Header-Add": "add-appends-values", }, }, }, Backend: "infra-backend-v1", Namespace: ns, }, { Request: http.Request{ Path: "/add", Headers: map[string]string{ "Some-Other-Header": "val", "X-Header-Add": "some-other-value", }, }, ExpectedRequest: &http.ExpectedRequest{ Request: http.Request{ Path: "/add", Headers: map[string]string{ "Some-Other-Header": "val", "X-Header-Add": "some-other-value,add-appends-values", }, }, }, Backend: "infra-backend-v1", Namespace: ns, }, { Request: http.Request{ Path: "/remove", Headers: map[string]string{ "X-Header-Remove": "val", }, }, ExpectedRequest: &http.ExpectedRequest{ Request: http.Request{ Path: "/remove", }, AbsentHeaders: []string{"X-Header-Remove"}, }, Backend: "infra-backend-v1", Namespace: ns, }, { Request: http.Request{ Path: "/multiple", Headers: map[string]string{ "X-Header-Set-2": "set-val-2", "X-Header-Add-2": "add-val-2", "X-Header-Remove-2": "remove-val-2", "Another-Header": "another-header-val", }, }, ExpectedRequest: &http.ExpectedRequest{ Request: http.Request{ Path: "/multiple", Headers: map[string]string{ "X-Header-Set-1": "header-set-1", "X-Header-Set-2": "header-set-2", "X-Header-Add-1": "header-add-1", "X-Header-Add-2": "add-val-2,header-add-2", "X-Header-Add-3": "header-add-3", "Another-Header": "another-header-val", }, }, AbsentHeaders: []string{"X-Header-Remove-1", "X-Header-Remove-2"}, }, Backend: "infra-backend-v1", Namespace: ns, }, { Request: http.Request{ Path: "/case-insensitivity", Headers: map[string]string{ "x-header-set": "original-val-set", "x-header-add": "original-val-add", "x-header-remove": "original-val-remove", "Another-Header": "another-header-val", }, }, ExpectedRequest: &http.ExpectedRequest{ Request: http.Request{ Path: "/case-insensitivity", Headers: map[string]string{ "X-Header-Set": "header-set", "X-Header-Add": "original-val-add,header-add", "Another-Header": "another-header-val", }, }, AbsentHeaders: []string{"x-header-remove", "X-Header-Remove"}, }, Backend: "infra-backend-v1", Namespace: ns, }} for i := range testCases { tc := testCases[i] t.Run(tc.GetTestCaseName(i), func(t *testing.T) { t.Parallel() http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, tc) }) } }, }
View Source
var HTTPRouteRequestRedirect = suite.ConformanceTest{ ShortName: "HTTPRouteRequestRedirect", Description: "An HTTPRoute with hostname and statusCode redirect filters", Manifests: []string{"tests/httproute-request-redirect.yaml"}, Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { ns := "gateway-conformance-infra" routeNN := types.NamespacedName{Name: "request-redirect", Namespace: ns} gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns} gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN) testCases := []http.ExpectedResponse{{ Request: http.Request{ Path: "/hostname-redirect", UnfollowRedirect: true, }, Response: http.Response{ StatusCode: 302, }, RedirectRequest: &roundtripper.RedirectRequest{ Hostname: "example.org", }, Backend: "infra-backend-v1", Namespace: ns, }, { Request: http.Request{ Path: "/status-code-301", UnfollowRedirect: true, }, Response: http.Response{ StatusCode: 301, }, Backend: "infra-backend-v1", Namespace: ns, }, { Request: http.Request{ Path: "/host-and-status", UnfollowRedirect: true, }, Response: http.Response{ StatusCode: 301, }, RedirectRequest: &roundtripper.RedirectRequest{ Hostname: "example.org", }, Backend: "infra-backend-v1", Namespace: ns, }, } for i := range testCases { tc := testCases[i] t.Run(tc.GetTestCaseName(i), func(t *testing.T) { t.Parallel() http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, tc) }) } }, }
View Source
var HTTPRouteResponseHeaderModifier = suite.ConformanceTest{ ShortName: "HTTPRouteResponseHeaderModifier", Description: "An HTTPRoute has response header modifier filters applied correctly", Features: []suite.SupportedFeature{suite.SupportHTTPResponseHeaderModification}, Manifests: []string{"tests/httproute-response-header-modifier.yaml"}, Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { ns := "gateway-conformance-infra" routeNN := types.NamespacedName{Name: "response-header-modifier", Namespace: ns} gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns} gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN) testCases := []http.ExpectedResponse{{ Request: http.Request{ Path: "/set", }, BackendSetResponseHeaders: map[string]string{ "Some-Other-Header": "val", }, Response: http.Response{ Headers: map[string]string{ "Some-Other-Header": "val", "X-Header-Set": "set-overwrites-values", }, }, Backend: "infra-backend-v1", Namespace: ns, }, { Request: http.Request{ Path: "/set", }, BackendSetResponseHeaders: map[string]string{ "Some-Other-Header": "val", "X-Header-Set": "some-other-value", }, Response: http.Response{ Headers: map[string]string{ "Some-Other-Header": "val", "X-Header-Set": "set-overwrites-values", }, }, Backend: "infra-backend-v1", Namespace: ns, }, { Request: http.Request{ Path: "/add", }, BackendSetResponseHeaders: map[string]string{ "Some-Other-Header": "val", }, Response: http.Response{ Headers: map[string]string{ "Some-Other-Header": "val", "X-Header-Add": "add-appends-values", }, }, Backend: "infra-backend-v1", Namespace: ns, }, { Request: http.Request{ Path: "/add", }, BackendSetResponseHeaders: map[string]string{ "Some-Other-Header": "val", "X-Header-Add": "some-other-value", }, Response: http.Response{ Headers: map[string]string{ "Some-Other-Header": "val", "X-Header-Add": "some-other-value,add-appends-values", }, }, Backend: "infra-backend-v1", Namespace: ns, }, { Request: http.Request{ Path: "/remove", }, BackendSetResponseHeaders: map[string]string{ "X-Header-Remove": "val", }, Response: http.Response{ AbsentHeaders: []string{"X-Header-Remove"}, }, Backend: "infra-backend-v1", Namespace: ns, }, { Request: http.Request{ Path: "/multiple", }, BackendSetResponseHeaders: map[string]string{ "X-Header-Set-2": "set-val-2", "X-Header-Add-2": "add-val-2", "X-Header-Remove-2": "remove-val-2", "Another-Header": "another-header-val", "X-Header-Remove-1": "val", }, Response: http.Response{ Headers: map[string]string{ "X-Header-Set-1": "header-set-1", "X-Header-Set-2": "header-set-2", "X-Header-Add-1": "header-add-1", "X-Header-Add-2": "add-val-2,header-add-2", "X-Header-Add-3": "header-add-3", "Another-Header": "another-header-val", }, AbsentHeaders: []string{"X-Header-Remove-1", "X-Header-Remove-2"}, }, Backend: "infra-backend-v1", Namespace: ns, }, { Request: http.Request{ Path: "/case-insensitivity", }, BackendSetResponseHeaders: map[string]string{ "x-header-set": "original-val-set", "x-header-add": "original-val-add", "x-header-remove": "original-val-remove", "Another-Header": "another-header-val", }, Response: http.Response{ Headers: map[string]string{ "X-Header-Set": "header-set", "X-Header-Add": "original-val-add,header-add", "X-Lowercase-Add": "lowercase-add", "X-Mixedcase-Add-1": "mixedcase-add-1", "X-Mixedcase-Add-2": "mixedcase-add-2", "X-Uppercase-Add": "uppercase-add", "Another-Header": "another-header-val", }, AbsentHeaders: []string{"x-header-remove", "X-Header-Remove"}, }, Backend: "infra-backend-v1", Namespace: ns, }} for i := range testCases { tc := testCases[i] t.Run(tc.GetTestCaseName(i), func(t *testing.T) { t.Parallel() http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, tc) }) } }, }
View Source
var HTTPRouteSimpleSameNamespace = suite.ConformanceTest{ ShortName: "HTTPRouteSimpleSameNamespace", Description: "A single HTTPRoute in the gateway-conformance-infra namespace attaches to a Gateway in the same namespace", Manifests: []string{"tests/httproute-simple-same-namespace.yaml"}, Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { ns := v1beta1.Namespace("gateway-conformance-infra") routeNN := types.NamespacedName{Name: "gateway-conformance-infra-test", Namespace: string(ns)} gwNN := types.NamespacedName{Name: "same-namespace", Namespace: string(ns)} gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN) t.Run("Simple HTTP request should reach infra-backend", func(t *testing.T) { http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, http.ExpectedResponse{ Request: http.Request{Path: "/"}, Response: http.Response{StatusCode: 200}, Backend: "infra-backend-v1", Namespace: "gateway-conformance-infra", }) }) }, }
Functions ¶
This section is empty.
Types ¶
This section is empty.
Source Files ¶
- gateway-invalid-route-kind.go
- gateway-invalid-tls-certificateref.go
- gateway-secret-invalid-reference-grant.go
- gateway-secret-missing-reference-grant.go
- gateway-secret-reference-grant-all-in-namespace.go
- gateway-secret-reference-grant-specific.go
- httproute-cross-namespace.go
- httproute-disallowed-kind.go
- httproute-exact-path-matching.go
- httproute-header-matching.go
- httproute-hostname-intersection.go
- httproute-invalid-backendref-nonexistent.go
- httproute-invalid-backendref-unknown-kind.go
- httproute-invalid-cross-namespace-backend-ref.go
- httproute-invalid-cross-namespace-parent-ref.go
- httproute-invalid-parentref-not-matching-listener-port.go
- httproute-listener-hostname-matching.go
- httproute-matching-across-routes.go
- httproute-matching.go
- httproute-method-matching.go
- httproute-partially-invalid-via-reference-grant.go
- httproute-query-param-matching.go
- httproute-reference-grant.go
- httproute-request-header-modifier.go
- httproute-request-redirect.go
- httproute-response-header-modifier.go
- httproute-simple-same-namespace.go
- main.go
Click to show internal directories.
Click to hide internal directories.