Documentation ¶
Index ¶
Constants ¶
This section is empty.
Variables ¶
View Source
var ConformanceTests []suite.ConformanceTest
View Source
var GatewayClassObservedGenerationBump = suite.ConformanceTest{ ShortName: "GatewayClassObservedGenerationBump", Features: []suite.SupportedFeature{ suite.SupportGateway, }, Description: "A GatewayClass should update the observedGeneration in all of it's Status.Conditions after an update to the spec", Manifests: []string{"tests/gatewayclass-observed-generation-bump.yaml"}, Test: func(t *testing.T, s *suite.ConformanceTestSuite) { gwc := types.NamespacedName{Name: "gatewayclass-observed-generation-bump"} t.Run("observedGeneration should increment", func(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), time.Minute) defer cancel() kubernetes.GWCMustHaveAcceptedConditionAny(t, s.Client, s.TimeoutConfig, gwc.Name) original := &v1beta1.GatewayClass{} err := s.Client.Get(ctx, gwc, original) require.NoErrorf(t, err, "error getting GatewayClass: %v", err) kubernetes.GatewayClassMustHaveLatestConditions(t, original) mutate := original.DeepCopy() desc := "new" mutate.Spec.Description = &desc err = s.Client.Patch(ctx, mutate, client.MergeFrom(original)) require.NoErrorf(t, err, "error patching the GatewayClass: %v", err) kubernetes.GWCMustHaveAcceptedConditionAny(t, s.Client, s.TimeoutConfig, gwc.Name) updated := &v1beta1.GatewayClass{} err = s.Client.Get(ctx, gwc, updated) require.NoErrorf(t, err, "error getting GatewayClass: %v", err) kubernetes.GatewayClassMustHaveLatestConditions(t, updated) require.NotEqual(t, original.Generation, updated.Generation, "generation should change after an update") }) }, }
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.", Features: []suite.SupportedFeature{ suite.SupportGateway, }, 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), }}, AttachedRoutes: 0, }} 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), }}, AttachedRoutes: 0, }} 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", Features: []suite.SupportedFeature{ suite.SupportGateway, }, 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), }}, AttachedRoutes: 0, }} 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 GatewayModifyListeners = suite.ConformanceTest{ ShortName: "GatewayModifyListeners", Description: "A Gateway in the gateway-conformance-infra namespace should handle adding and removing listeners.", Features: []suite.SupportedFeature{ suite.SupportGateway, }, Manifests: []string{"tests/gateway-modify-listeners.yaml"}, Test: func(t *testing.T, s *suite.ConformanceTestSuite) { t.Run("should be able to add a listener that then becomes available for routing traffic", func(t *testing.T) { gwNN := types.NamespacedName{Name: "gateway-add-listener", Namespace: "gateway-conformance-infra"} ctx, cancel := context.WithTimeout(context.Background(), time.Minute) defer cancel() namespaces := []string{"gateway-conformance-infra"} kubernetes.NamespacesMustBeReady(t, s.Client, s.TimeoutConfig, namespaces) kubernetes.GatewayMustHaveLatestConditions(t, s.Client, s.TimeoutConfig, gwNN) original := &v1beta1.Gateway{} err := s.Client.Get(ctx, gwNN, original) require.NoErrorf(t, err, "error getting Gateway: %v", err) all := v1beta1.NamespacesFromAll mutate := original.DeepCopy() hostname := v1beta1.Hostname("data.test.com") mutate.Spec.Listeners = append(mutate.Spec.Listeners, v1beta1.Listener{ Name: "http", Port: 80, Protocol: v1beta1.HTTPProtocolType, Hostname: &hostname, AllowedRoutes: &v1beta1.AllowedRoutes{ Namespaces: &v1beta1.RouteNamespaces{From: &all}, }, }) err = s.Client.Patch(ctx, mutate, client.MergeFrom(original)) require.NoErrorf(t, err, "error patching the Gateway: %v", err) kubernetes.NamespacesMustBeReady(t, s.Client, s.TimeoutConfig, namespaces) 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.ListenerConditionAccepted), Status: metav1.ConditionTrue, Reason: "", }}, AttachedRoutes: 1, }, { Name: v1beta1.SectionName("http"), SupportedKinds: []v1beta1.RouteGroupKind{{ Group: (*v1beta1.Group)(&v1beta1.GroupVersion.Group), Kind: v1beta1.Kind("HTTPRoute"), }}, Conditions: []metav1.Condition{{ Type: string(v1beta1.ListenerConditionAccepted), Status: metav1.ConditionTrue, Reason: "", }}, AttachedRoutes: 1, }, } kubernetes.GatewayStatusMustHaveListeners(t, s.Client, s.TimeoutConfig, gwNN, listeners) kubernetes.GatewayMustHaveLatestConditions(t, s.Client, s.TimeoutConfig, gwNN) updated := &v1beta1.Gateway{} err = s.Client.Get(ctx, gwNN, updated) require.NoErrorf(t, err, "error getting Gateway: %v", err) require.NotEqual(t, original.Generation, updated.Generation, "generation should change after an update") }) t.Run("should be able to remove listeners, which would then stop routing the relevant traffic", func(t *testing.T) { gwNN := types.NamespacedName{Name: "gateway-remove-listener", Namespace: "gateway-conformance-infra"} ctx, cancel := context.WithTimeout(context.Background(), time.Minute) defer cancel() namespaces := []string{"gateway-conformance-infra"} kubernetes.NamespacesMustBeReady(t, s.Client, s.TimeoutConfig, namespaces) kubernetes.GatewayMustHaveLatestConditions(t, s.Client, s.TimeoutConfig, gwNN) original := &v1beta1.Gateway{} err := s.Client.Get(ctx, gwNN, original) require.NoErrorf(t, err, "error getting Gateway: %v", err) mutate := original.DeepCopy() require.Equalf(t, 2, len(mutate.Spec.Listeners), "the gateway must have 2 listeners") // remove the "https" Gateway listener, leaving only the "http" listener var newListeners []v1beta1.Listener for _, listener := range mutate.Spec.Listeners { if listener.Name == "http" { newListeners = append(newListeners, listener) } } mutate.Spec.Listeners = newListeners err = s.Client.Patch(ctx, mutate, client.MergeFrom(original)) require.NoErrorf(t, err, "error patching the Gateway: %v", err) kubernetes.NamespacesMustBeReady(t, s.Client, s.TimeoutConfig, namespaces) 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.ListenerConditionAccepted), Status: metav1.ConditionTrue, Reason: "", }}, AttachedRoutes: 1, }, } kubernetes.GatewayStatusMustHaveListeners(t, s.Client, s.TimeoutConfig, gwNN, listeners) kubernetes.GatewayMustHaveLatestConditions(t, s.Client, s.TimeoutConfig, gwNN) updated := &v1beta1.Gateway{} err = s.Client.Get(ctx, gwNN, updated) require.NoErrorf(t, err, "error getting Gateway: %v", err) require.NotEqual(t, original.Generation, updated.Generation, "generation should change after an update") }) }, }
View Source
var GatewayObservedGenerationBump = suite.ConformanceTest{ ShortName: "GatewayObservedGenerationBump", Description: "A Gateway in the gateway-conformance-infra namespace should update the observedGeneration in all of its Status.Conditions after an update to the spec", Features: []suite.SupportedFeature{ suite.SupportGateway, suite.SupportGatewayPort8080, }, Manifests: []string{"tests/gateway-observed-generation-bump.yaml"}, Test: func(t *testing.T, s *suite.ConformanceTestSuite) { gwNN := types.NamespacedName{Name: "gateway-observed-generation-bump", Namespace: "gateway-conformance-infra"} t.Run("observedGeneration should increment", func(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), time.Minute) defer cancel() namespaces := []string{"gateway-conformance-infra"} kubernetes.NamespacesMustBeReady(t, s.Client, s.TimeoutConfig, namespaces) kubernetes.GatewayMustHaveLatestConditions(t, s.Client, s.TimeoutConfig, gwNN) original := &v1beta1.Gateway{} err := s.Client.Get(ctx, gwNN, original) require.NoErrorf(t, err, "error getting Gateway: %v", err) all := v1beta1.NamespacesFromAll mutate := original.DeepCopy() mutate.Spec.Listeners = append(mutate.Spec.Listeners, v1beta1.Listener{ Name: "alternate", Port: 8080, Protocol: v1beta1.HTTPProtocolType, AllowedRoutes: &v1beta1.AllowedRoutes{ Namespaces: &v1beta1.RouteNamespaces{From: &all}, }, }) err = s.Client.Patch(ctx, mutate, client.MergeFrom(original)) require.NoErrorf(t, err, "error patching the Gateway: %v", err) kubernetes.NamespacesMustBeReady(t, s.Client, s.TimeoutConfig, namespaces) kubernetes.GatewayMustHaveLatestConditions(t, s.Client, s.TimeoutConfig, gwNN) updated := &v1beta1.Gateway{} err = s.Client.Get(ctx, gwNN, updated) require.NoErrorf(t, err, "error getting Gateway: %v", err) require.NotEqual(t, original.Generation, updated.Generation, "generation should change after an update") }) }, }
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.SupportGateway, 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), }}, AttachedRoutes: 0, }} 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.SupportGateway, 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), }}, AttachedRoutes: 0, }} 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.SupportGateway, 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-all-in-namespace", 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), }, }, AttachedRoutes: 0, }} 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.SupportGateway, 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-specific", 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), }, }, AttachedRoutes: 0, }} kubernetes.GatewayStatusMustHaveListeners(t, s.Client, s.TimeoutConfig, gwNN, listeners) }) }, }
View Source
var GatewayWithAttachedRoutes = suite.ConformanceTest{ ShortName: "GatewayWithAttachedRoutes", Description: "A Gateway in the gateway-conformance-infra namespace should be attached to routes.", Features: []suite.SupportedFeature{ suite.SupportGateway, }, Manifests: []string{"tests/gateway-with-attached-routes.yaml"}, Test: func(t *testing.T, s *suite.ConformanceTestSuite) { t.Run("Gateway listener should have one valid http routes attached", func(t *testing.T) { gwNN := types.NamespacedName{Name: "gateway-with-one-attached-route", 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.ListenerConditionAccepted), Status: metav1.ConditionTrue, Reason: "", }}, AttachedRoutes: 1, }} kubernetes.GatewayStatusMustHaveListeners(t, s.Client, s.TimeoutConfig, gwNN, listeners) }) t.Run("Gateway listener should have two valid http routes attached", func(t *testing.T) { gwNN := types.NamespacedName{Name: "gateway-with-two-attached-routes", 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.ListenerConditionAccepted), Status: metav1.ConditionTrue, Reason: "", }}, AttachedRoutes: 2, }} kubernetes.GatewayStatusMustHaveListeners(t, s.Client, s.TimeoutConfig, gwNN, listeners) }) t.Run("Gateway listener should have attached route by specifying the sectionName", func(t *testing.T) { gwNN := types.NamespacedName{Name: "gateway-with-two-listeners-and-one-attached-route", Namespace: "gateway-conformance-infra"} listeners := []v1beta1.ListenerStatus{ { Name: v1beta1.SectionName("http-unattached"), SupportedKinds: []v1beta1.RouteGroupKind{{ Group: (*v1beta1.Group)(&v1beta1.GroupVersion.Group), Kind: v1beta1.Kind("HTTPRoute"), }}, Conditions: []metav1.Condition{{ Type: string(v1beta1.ListenerConditionAccepted), Status: metav1.ConditionTrue, Reason: "", }}, AttachedRoutes: 0, }, { Name: v1beta1.SectionName("http"), SupportedKinds: []v1beta1.RouteGroupKind{{ Group: (*v1beta1.Group)(&v1beta1.GroupVersion.Group), Kind: v1beta1.Kind("HTTPRoute"), }}, Conditions: []metav1.Condition{{ Type: string(v1beta1.ListenerConditionAccepted), Status: metav1.ConditionTrue, Reason: "", }}, AttachedRoutes: 1, }, } 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", Features: []suite.SupportedFeature{ suite.SupportGateway, suite.SupportHTTPRoute, }, 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) kubernetes.HTTPRouteMustHaveResolvedRefsConditionsTrue(t, suite.Client, suite.TimeoutConfig, routeNN, gwNN) 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}, }, { 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", Features: []suite.SupportedFeature{ suite.SupportGateway, suite.SupportHTTPRoute, }, 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) kubernetes.HTTPRouteMustHaveResolvedRefsConditionsTrue(t, suite.Client, suite.TimeoutConfig, routeNN, gwNN) 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 Gateway with no listeners that allow the HTTPRoute kind", Features: []suite.SupportedFeature{ suite.SupportGateway, suite.SupportHTTPRoute, suite.SupportTLSRoute, }, Manifests: []string{"tests/httproute-disallowed-kind.yaml"}, Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { kubernetes.NamespacesMustBeReady(t, suite.Client, suite.TimeoutConfig, []string{"gateway-conformance-infra"}) routeNN := types.NamespacedName{Name: "disallowed-kind", Namespace: "gateway-conformance-infra"} gwNN := types.NamespacedName{Name: "tlsroutes-only", Namespace: "gateway-conformance-infra"} kubernetes.HTTPRouteMustHaveResolvedRefsConditionsTrue(t, suite.Client, suite.TimeoutConfig, routeNN, gwNN) t.Run("Route should not have been accepted with reason NotAllowedByListeners", func(t *testing.T) { kubernetes.HTTPRouteMustHaveCondition(t, suite.Client, suite.TimeoutConfig, routeNN, gwNN, metav1.Condition{ Type: string(v1beta1.RouteConditionAccepted), Status: metav1.ConditionFalse, Reason: string(v1beta1.RouteReasonNotAllowedByListeners), }) }) t.Run("Route should not have Parents set 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 HTTPRouteHeaderMatching = suite.ConformanceTest{ ShortName: "HTTPRouteHeaderMatching", Description: "A single HTTPRoute with header matching for different backends", Features: []suite.SupportedFeature{ suite.SupportGateway, suite.SupportHTTPRoute, }, 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) kubernetes.HTTPRouteMustHaveResolvedRefsConditionsTrue(t, suite.Client, suite.TimeoutConfig, routeNN, gwNN) 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", Features: []suite.SupportedFeature{ suite.SupportGateway, suite.SupportHTTPRoute, }, 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.NamespacesMustBeReady(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...) for _, routeNN := range routes { kubernetes.HTTPRouteMustHaveResolvedRefsConditionsTrue(t, suite.Client, suite.TimeoutConfig, routeNN, gwNN) } 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: "very.specific.com:1234", 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)) routeNN := 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, routeNN, 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.", Features: []suite.SupportedFeature{ suite.SupportGateway, suite.SupportHTTPRoute, }, 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.SupportGateway, suite.SupportHTTPRoute, 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", Features: []suite.SupportedFeature{ suite.SupportGateway, suite.SupportHTTPRoute, }, Manifests: []string{"tests/httproute-invalid-cross-namespace-parent-ref.yaml"}, Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { gwNN := types.NamespacedName{Name: "same-namespace", Namespace: "gateway-conformance-infra"} routeNN := types.NamespacedName{Name: "invalid-cross-namespace-parent-ref", Namespace: "gateway-conformance-web-backend"} kubernetes.HTTPRouteMustHaveResolvedRefsConditionsTrue(t, suite.Client, suite.TimeoutConfig, routeNN, gwNN) t.Run("HTTPRoute should have an Accepted: false condition with reason NotAllowedByListeners", func(t *testing.T) { acceptedCond := metav1.Condition{ Type: string(v1beta1.RouteConditionAccepted), Status: metav1.ConditionFalse, Reason: string(v1beta1.RouteReasonNotAllowedByListeners), } kubernetes.HTTPRouteMustHaveCondition(t, suite.Client, suite.TimeoutConfig, routeNN, gwNN, acceptedCond) }) t.Run("Route should not have Parents set 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 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", Features: []suite.SupportedFeature{ suite.SupportGateway, suite.SupportHTTPRoute, }, 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.SupportGateway, suite.SupportHTTPRoute, 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"} kubernetes.HTTPRouteMustHaveResolvedRefsConditionsTrue(t, suite.Client, suite.TimeoutConfig, routeNN, gwNN) t.Run("HTTPRoute with no matching port in ParentRef has an Accepted Condition with status False and Reason NoMatchingParent", func(t *testing.T) { acceptedCond := metav1.Condition{ Type: string(v1beta1.RouteConditionAccepted), Status: metav1.ConditionFalse, Reason: string(v1beta1.RouteReasonNoMatchingParent), } kubernetes.HTTPRouteMustHaveCondition(t, suite.Client, suite.TimeoutConfig, routeNN, gwNN, acceptedCond) }) 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 HTTPRouteInvalidParentRefNotMatchingSectionName = suite.ConformanceTest{ ShortName: "HTTPRouteInvalidParentRefNotMatchingSectionName", 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 SectionName.", Features: []suite.SupportedFeature{ suite.SupportGateway, suite.SupportHTTPRoute, }, Manifests: []string{"tests/httproute-invalid-parentref-not-matching-section-name.yaml"}, Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { routeNN := types.NamespacedName{Name: "httproute-listener-not-matching-section-name", Namespace: "gateway-conformance-infra"} gwNN := types.NamespacedName{Name: "same-namespace", Namespace: "gateway-conformance-infra"} t.Run("HTTPRoute with no matching sectionName 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 HTTPRouteInvalidReferenceGrant = suite.ConformanceTest{ ShortName: "HTTPRouteInvalidReferenceGrant", Description: "A single HTTPRoute in the gateway-conformance-infra namespace, with a backendRef in another namespace without valid ReferenceGrant, should have the ResolvedRefs condition set to False and not forward HTTP requests to any backend", Features: []suite.SupportedFeature{ suite.SupportGateway, suite.SupportHTTPRoute, suite.SupportReferenceGrant, }, Manifests: []string{"tests/httproute-invalid-reference-grant.yaml"}, Test: func(t *testing.T, suite *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, suite.Client, suite.TimeoutConfig, suite.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, suite.Client, suite.TimeoutConfig, routeNN, gwNN, resolvedRefsCond) }) t.Run("Simple HTTP request not should reach web-backend", 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}, Backend: "web-backend", Namespace: "gateway-conformance-web-backend", }) }) }, }
View Source
var HTTPRouteListenerHostnameMatching = suite.ConformanceTest{ ShortName: "HTTPRouteListenerHostnameMatching", Description: "Multiple HTTP listeners with the same port and different hostnames, each with a different HTTPRoute", Features: []suite.SupportedFeature{ suite.SupportGateway, suite.SupportHTTPRoute, }, Manifests: []string{"tests/httproute-listener-hostname-matching.yaml"}, Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { ns := "gateway-conformance-infra" kubernetes.NamespacesMustBeReady(t, suite.Client, suite.TimeoutConfig, []string{ns}) routeNN1 := types.NamespacedName{Name: "backend-v1", Namespace: ns} routeNN2 := types.NamespacedName{Name: "backend-v2", Namespace: ns} routeNN3 := types.NamespacedName{Name: "backend-v3", Namespace: 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"), routeNN1) kubernetes.HTTPRouteMustHaveResolvedRefsConditionsTrue(t, suite.Client, suite.TimeoutConfig, routeNN1, gwNN) kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN, "listener-2"), routeNN2) kubernetes.HTTPRouteMustHaveResolvedRefsConditionsTrue(t, suite.Client, suite.TimeoutConfig, routeNN2, gwNN) gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN, "listener-3", "listener-4"), routeNN3) kubernetes.HTTPRouteMustHaveResolvedRefsConditionsTrue(t, suite.Client, suite.TimeoutConfig, routeNN3, gwNN) 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", Features: []suite.SupportedFeature{ suite.SupportGateway, suite.SupportHTTPRoute, }, 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) kubernetes.HTTPRouteMustHaveResolvedRefsConditionsTrue(t, suite.Client, suite.TimeoutConfig, routeNN, gwNN) 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, }, { Request: http.Request{Path: "/v2/"}, Backend: "infra-backend-v2", Namespace: ns, }, { Request: http.Request{Path: "/v2example"}, Backend: "infra-backend-v1", Namespace: ns, }, { Request: http.Request{Path: "/foo/v2/example"}, 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 HTTPRouteMatchingAcrossRoutes = suite.ConformanceTest{ ShortName: "HTTPRouteMatchingAcrossRoutes", Description: "Two HTTPRoutes with path matching for different backends", Features: []suite.SupportedFeature{ suite.SupportGateway, suite.SupportHTTPRoute, }, 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) kubernetes.HTTPRouteMustHaveResolvedRefsConditionsTrue(t, suite.Client, suite.TimeoutConfig, routeNN1, gwNN) kubernetes.HTTPRouteMustHaveResolvedRefsConditionsTrue(t, suite.Client, suite.TimeoutConfig, routeNN2, gwNN) 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.SupportGateway, suite.SupportHTTPRoute, 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) kubernetes.HTTPRouteMustHaveResolvedRefsConditionsTrue(t, suite.Client, suite.TimeoutConfig, routeNN, gwNN) 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}, }, } testCases = append(testCases, []http.ExpectedResponse{ { Request: http.Request{Path: "/path1", Method: "GET"}, Backend: "infra-backend-v1", Namespace: ns, }, { Request: http.Request{Headers: map[string]string{"version": "one"}, Path: "/", Method: "PUT"}, Backend: "infra-backend-v2", Namespace: ns, }, { Request: http.Request{Headers: map[string]string{"version": "two"}, Path: "/path2", Method: "POST"}, Backend: "infra-backend-v3", Namespace: ns, }, }...) testCases = append(testCases, []http.ExpectedResponse{ { Request: http.Request{Path: "/path3", Method: "PATCH"}, Backend: "infra-backend-v1", Namespace: ns, }, { Request: http.Request{Headers: map[string]string{"version": "three"}, Path: "/path4", Method: "DELETE"}, Backend: "infra-backend-v1", Namespace: ns, }, }...) testCases = append(testCases, []http.ExpectedResponse{ { Request: http.Request{Path: "/", Method: "PUT"}, Response: http.Response{StatusCode: 404}, }, { Request: http.Request{Path: "/path4", Method: "DELETE"}, Response: http.Response{StatusCode: 404}, }, }...) testCases = append(testCases, []http.ExpectedResponse{ { Request: http.Request{Path: "/path5", Method: "PATCH"}, Backend: "infra-backend-v1", Namespace: ns, }, { Request: http.Request{Headers: map[string]string{"version": "four"}, Path: "/", Method: "PATCH"}, 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 HTTPRouteObservedGenerationBump = suite.ConformanceTest{ ShortName: "HTTPRouteObservedGenerationBump", Description: "A HTTPRoute in the gateway-conformance-infra namespace should update the observedGeneration in all of it's Status.Conditions after an update to the spec", Features: []suite.SupportedFeature{ suite.SupportGateway, suite.SupportHTTPRoute, }, Manifests: []string{"tests/httproute-observed-generation-bump.yaml"}, Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { routeNN := types.NamespacedName{Name: "observed-generation-bump", Namespace: "gateway-conformance-infra"} gwNN := types.NamespacedName{Name: "same-namespace", Namespace: "gateway-conformance-infra"} t.Run("observedGeneration should increment", func(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), time.Minute) defer cancel() namespaces := []string{"gateway-conformance-infra"} kubernetes.NamespacesMustBeReady(t, suite.Client, suite.TimeoutConfig, namespaces) original := &v1beta1.HTTPRoute{} err := suite.Client.Get(ctx, routeNN, original) require.NoErrorf(t, err, "error getting HTTPRoute: %v", err) kubernetes.HTTPRouteMustHaveLatestConditions(t, original) mutate := original.DeepCopy() mutate.Spec.Rules[0].BackendRefs[0].Name = "infra-backend-v2" err = suite.Client.Patch(ctx, mutate, client.MergeFrom(original)) require.NoErrorf(t, err, "error patching the HTTPRoute: %v", err) kubernetes.HTTPRouteMustHaveCondition(t, suite.Client, suite.TimeoutConfig, routeNN, gwNN, metav1.Condition{ Type: string(v1beta1.RouteConditionAccepted), Status: metav1.ConditionTrue, Reason: "", }) kubernetes.HTTPRouteMustHaveResolvedRefsConditionsTrue(t, suite.Client, suite.TimeoutConfig, routeNN, gwNN) updated := &v1beta1.HTTPRoute{} err = suite.Client.Get(ctx, routeNN, updated) require.NoErrorf(t, err, "error getting Gateway: %v", err) kubernetes.HTTPRouteMustHaveLatestConditions(t, updated) require.NotEqual(t, original.Generation, updated.Generation, "generation should change after an update") }) }, }
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.SupportGateway, suite.SupportHTTPRoute, 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 HTTPRoutePathMatchOrder = suite.ConformanceTest{ ShortName: "HTTPRoutePathMatchOrder", Description: "An HTTPRoute where there are multiple matches routing to any given backend follows match order precedence", Features: []suite.SupportedFeature{ suite.SupportGateway, suite.SupportHTTPRoute, }, Manifests: []string{"tests/httproute-path-match-order.yaml"}, Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { ns := "gateway-conformance-infra" routeNN := types.NamespacedName{Namespace: ns, Name: "path-matching-order"} gwNN := types.NamespacedName{Namespace: ns, Name: "same-namespace"} gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN) kubernetes.HTTPRouteMustHaveResolvedRefsConditionsTrue(t, suite.Client, suite.TimeoutConfig, routeNN, gwNN) testCases := []http.ExpectedResponse{ { Request: http.Request{Path: "/match/exact/one"}, Backend: "infra-backend-v3", Namespace: ns, }, { Request: http.Request{Path: "/match/exact"}, Backend: "infra-backend-v2", Namespace: ns, }, { Request: http.Request{Path: "/match"}, Backend: "infra-backend-v1", Namespace: ns, }, { Request: http.Request{Path: "/match/prefix/one/any"}, Backend: "infra-backend-v2", Namespace: ns, }, { Request: http.Request{Path: "/match/prefix/any"}, Backend: "infra-backend-v1", Namespace: ns, }, { Request: http.Request{Path: "/match/any"}, Backend: "infra-backend-v3", 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 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.SupportGateway, suite.SupportHTTPRoute, suite.SupportHTTPRouteQueryParamMatching, }, Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { 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) kubernetes.HTTPRouteMustHaveResolvedRefsConditionsTrue(t, suite.Client, suite.TimeoutConfig, routeNN, gwNN) 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}, }} testCases = append(testCases, []http.ExpectedResponse{ { Request: http.Request{Path: "/path1?animal=whale"}, Backend: "infra-backend-v1", Namespace: ns, }, { Request: http.Request{Headers: map[string]string{"version": "one"}, Path: "/?animal=whale"}, Backend: "infra-backend-v2", Namespace: ns, }, { Request: http.Request{Headers: map[string]string{"version": "two"}, Path: "/path2?animal=whale"}, Backend: "infra-backend-v3", Namespace: ns, }, }...) testCases = append(testCases, []http.ExpectedResponse{ { Request: http.Request{Path: "/path3?animal=shark"}, Backend: "infra-backend-v1", Namespace: ns, }, { Request: http.Request{Headers: map[string]string{"version": "three"}, Path: "/path4?animal=kraken"}, Backend: "infra-backend-v1", Namespace: ns, }, }...) testCases = append(testCases, []http.ExpectedResponse{ { Request: http.Request{Path: "/?animal=shark"}, Response: http.Response{StatusCode: 404}, }, { Request: http.Request{Path: "/path4?animal=kraken"}, Response: http.Response{StatusCode: 404}, }, }...) testCases = append(testCases, []http.ExpectedResponse{ { Request: http.Request{Path: "/path5?animal=hydra"}, Backend: "infra-backend-v1", Namespace: ns, }, { Request: http.Request{Headers: map[string]string{"version": "four"}, Path: "/?animal=hydra"}, Backend: "infra-backend-v3", 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 HTTPRouteRedirectHostAndStatus = suite.ConformanceTest{ ShortName: "HTTPRouteRedirectHostAndStatus", Description: "An HTTPRoute with hostname and statusCode redirect filters", Features: []suite.SupportedFeature{ suite.SupportGateway, suite.SupportHTTPRoute, }, Manifests: []string{"tests/httproute-redirect-host-and-status.yaml"}, Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { ns := "gateway-conformance-infra" routeNN := types.NamespacedName{Name: "redirect-host-and-status", Namespace: ns} gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns} gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN) kubernetes.HTTPRouteMustHaveResolvedRefsConditionsTrue(t, suite.Client, suite.TimeoutConfig, routeNN, gwNN) testCases := []http.ExpectedResponse{ { Request: http.Request{ Path: "/hostname-redirect", UnfollowRedirect: true, }, Response: http.Response{ StatusCode: 302, }, RedirectRequest: &roundtripper.RedirectRequest{ Host: "example.org", }, Namespace: ns, }, { Request: http.Request{ Path: "/host-and-status", UnfollowRedirect: true, }, Response: http.Response{ StatusCode: 301, }, RedirectRequest: &roundtripper.RedirectRequest{ Host: "example.org", }, 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 HTTPRouteRedirectPath = suite.ConformanceTest{ ShortName: "HTTPRouteRedirectPath", Description: "An HTTPRoute with scheme redirect filter", Manifests: []string{"tests/httproute-redirect-path.yaml"}, Features: []suite.SupportedFeature{ suite.SupportGateway, suite.SupportHTTPRoute, suite.SupportHTTPRoutePathRedirect, }, Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { ns := "gateway-conformance-infra" routeNN := types.NamespacedName{Name: "redirect-path", Namespace: ns} gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns} gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN) kubernetes.HTTPRouteMustHaveResolvedRefsConditionsTrue(t, suite.Client, suite.TimeoutConfig, routeNN, gwNN) testCases := []http.ExpectedResponse{ { Request: http.Request{ Path: "/original-prefix/lemon", UnfollowRedirect: true, }, Response: http.Response{ StatusCode: 302, }, RedirectRequest: &roundtripper.RedirectRequest{ Path: "/replacement-prefix/lemon", }, Namespace: ns, }, { Request: http.Request{ Path: "/full/path/original", UnfollowRedirect: true, }, Response: http.Response{ StatusCode: 302, }, RedirectRequest: &roundtripper.RedirectRequest{ Path: "/full-path-replacement", }, Namespace: ns, }, { Request: http.Request{ Path: "/path-and-host", UnfollowRedirect: true, }, Response: http.Response{ StatusCode: 302, }, RedirectRequest: &roundtripper.RedirectRequest{ Host: "example.org", Path: "/replacement-prefix", }, Namespace: ns, }, { Request: http.Request{ Path: "/path-and-status", UnfollowRedirect: true, }, Response: http.Response{ StatusCode: 301, }, RedirectRequest: &roundtripper.RedirectRequest{ Path: "/replacement-prefix", }, Namespace: ns, }, { Request: http.Request{ Path: "/full-path-and-host", UnfollowRedirect: true, }, Response: http.Response{ StatusCode: 302, }, RedirectRequest: &roundtripper.RedirectRequest{ Host: "example.org", Path: "/replacement-full", }, Namespace: ns, }, { Request: http.Request{ Path: "/full-path-and-status", UnfollowRedirect: true, }, Response: http.Response{ StatusCode: 301, }, RedirectRequest: &roundtripper.RedirectRequest{ Path: "/replacement-full", }, 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 HTTPRouteRedirectPort = suite.ConformanceTest{ ShortName: "HTTPRouteRedirectPort", Description: "An HTTPRoute with a port redirect filter", Manifests: []string{"tests/httproute-redirect-port.yaml"}, Features: []suite.SupportedFeature{ suite.SupportGateway, suite.SupportHTTPRoute, suite.SupportHTTPRoutePortRedirect, }, Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { ns := "gateway-conformance-infra" routeNN := types.NamespacedName{Name: "redirect-port", Namespace: ns} gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns} gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN) kubernetes.HTTPRouteMustHaveResolvedRefsConditionsTrue(t, suite.Client, suite.TimeoutConfig, routeNN, gwNN) testCases := []http.ExpectedResponse{ { Request: http.Request{ Path: "/port", UnfollowRedirect: true, }, Response: http.Response{ StatusCode: 302, }, RedirectRequest: &roundtripper.RedirectRequest{ Port: "8083", }, Namespace: ns, }, { Request: http.Request{ Path: "/port-and-host", UnfollowRedirect: true, }, Response: http.Response{ StatusCode: 302, }, RedirectRequest: &roundtripper.RedirectRequest{ Host: "example.org", Port: "8083", }, Namespace: ns, }, { Request: http.Request{ Path: "/port-and-status", UnfollowRedirect: true, }, Response: http.Response{ StatusCode: 301, }, RedirectRequest: &roundtripper.RedirectRequest{ Port: "8083", }, Namespace: ns, }, { Request: http.Request{ Path: "/port-and-host-and-status", UnfollowRedirect: true, }, Response: http.Response{ StatusCode: 302, }, RedirectRequest: &roundtripper.RedirectRequest{ Port: "8083", Host: "example.org", }, 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 HTTPRouteRedirectPortAndScheme = suite.ConformanceTest{ ShortName: "HTTPRouteRedirectPortAndScheme", Description: "An HTTPRoute with port and scheme redirect filter", Manifests: []string{"tests/httproute-redirect-port-and-scheme.yaml"}, Features: []suite.SupportedFeature{ suite.SupportGateway, suite.SupportHTTPRoute, suite.SupportHTTPRoutePortRedirect, suite.SupportGatewayPort8080, }, Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { ns := "gateway-conformance-infra" gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns} routeNN := types.NamespacedName{Name: "http-route-for-listener-on-port-80", Namespace: ns} gwAddr80 := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN) kubernetes.HTTPRouteMustHaveResolvedRefsConditionsTrue(t, suite.Client, suite.TimeoutConfig, routeNN, gwNN) gwNN = types.NamespacedName{Name: "same-namespace-with-http-listener-on-8080", Namespace: ns} routeNN = types.NamespacedName{Name: "http-route-for-listener-on-port-8080", Namespace: ns} gwAddr8080 := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN) kubernetes.HTTPRouteMustHaveResolvedRefsConditionsTrue(t, suite.Client, suite.TimeoutConfig, routeNN, gwNN) gwNN = types.NamespacedName{Name: "same-namespace-with-https-listener", Namespace: ns} routeNN = types.NamespacedName{Name: "http-route-for-listener-on-port-443", Namespace: ns} gwAddr443 := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN) kubernetes.HTTPRouteMustHaveResolvedRefsConditionsTrue(t, suite.Client, suite.TimeoutConfig, routeNN, gwNN) certNN := types.NamespacedName{Name: "tls-validity-checks-certificate", Namespace: ns} cPem, keyPem, err := GetTLSSecret(suite.Client, certNN) if err != nil { t.Fatalf("unexpected error finding TLS secret: %v", err) } testCases := []http.ExpectedResponse{ { Request: http.Request{ Path: "/scheme-nil-and-port-nil", UnfollowRedirect: true, }, Response: http.Response{StatusCode: 302}, RedirectRequest: &roundtripper.RedirectRequest{ Scheme: "http", Host: "example.org", }, Namespace: ns, }, { Request: http.Request{ Path: "/scheme-nil-and-port-80", UnfollowRedirect: true, }, Response: http.Response{StatusCode: 302}, RedirectRequest: &roundtripper.RedirectRequest{ Scheme: "http", Host: "example.org", }, Namespace: ns, }, { Request: http.Request{ Path: "/scheme-nil-and-port-8080", UnfollowRedirect: true, }, Response: http.Response{StatusCode: 302}, RedirectRequest: &roundtripper.RedirectRequest{ Scheme: "http", Port: "8080", Host: "example.org", }, Namespace: ns, }, { Request: http.Request{ Path: "/scheme-https-and-port-nil", UnfollowRedirect: true, }, Response: http.Response{StatusCode: 302}, RedirectRequest: &roundtripper.RedirectRequest{ Scheme: "https", Host: "example.org", }, Namespace: ns, }, { Request: http.Request{ Path: "/scheme-https-and-port-443", UnfollowRedirect: true, }, Response: http.Response{StatusCode: 302}, RedirectRequest: &roundtripper.RedirectRequest{ Scheme: "https", Host: "example.org", }, Namespace: ns, }, { Request: http.Request{ Path: "/scheme-https-and-port-8443", UnfollowRedirect: true, }, Response: http.Response{StatusCode: 302}, RedirectRequest: &roundtripper.RedirectRequest{ Scheme: "https", Port: "8443", Host: "example.org", }, Namespace: ns, }, } for i := range testCases { tc := testCases[i] t.Run("http-listener-on-80/"+tc.GetTestCaseName(i), func(t *testing.T) { t.Parallel() http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr80, tc) }) } testCases = []http.ExpectedResponse{ { Request: http.Request{ Path: "/scheme-nil-and-port-nil", UnfollowRedirect: true, }, Response: http.Response{StatusCode: 302}, RedirectRequest: &roundtripper.RedirectRequest{ Scheme: "http", Port: "8080", Host: "example.org", }, Namespace: ns, }, { Request: http.Request{ Path: "/scheme-nil-and-port-80", UnfollowRedirect: true, }, Response: http.Response{StatusCode: 302}, RedirectRequest: &roundtripper.RedirectRequest{ Scheme: "http", Host: "example.org", }, Namespace: ns, }, { Request: http.Request{ Path: "/scheme-https-and-port-nil", UnfollowRedirect: true, }, Response: http.Response{StatusCode: 302}, RedirectRequest: &roundtripper.RedirectRequest{ Scheme: "https", Host: "example.org", }, Namespace: ns, }, } for i := range testCases { tc := testCases[i] t.Run("http-listener-on-8080/"+tc.GetTestCaseName(i), func(t *testing.T) { t.Parallel() http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr8080, tc) }) } testCases = []http.ExpectedResponse{ { Request: http.Request{ Host: "example.org", Path: "/scheme-nil-and-port-nil", UnfollowRedirect: true, }, Response: http.Response{StatusCode: 302}, RedirectRequest: &roundtripper.RedirectRequest{ Scheme: "https", Host: "example.org", }, Namespace: ns, }, { Request: http.Request{ Host: "example.org", Path: "/scheme-nil-and-port-443", UnfollowRedirect: true, }, Response: http.Response{StatusCode: 302}, RedirectRequest: &roundtripper.RedirectRequest{ Scheme: "https", Host: "example.org", }, Namespace: ns, }, { Request: http.Request{ Host: "example.org", Path: "/scheme-nil-and-port-8443", UnfollowRedirect: true, }, Response: http.Response{StatusCode: 302}, RedirectRequest: &roundtripper.RedirectRequest{ Scheme: "https", Port: "8443", Host: "example.org", }, Namespace: ns, }, { Request: http.Request{ Host: "example.org", Path: "/scheme-http-and-port-nil", UnfollowRedirect: true, }, Response: http.Response{StatusCode: 302}, RedirectRequest: &roundtripper.RedirectRequest{ Scheme: "http", Host: "example.org", }, Namespace: ns, }, { Request: http.Request{ Host: "example.org", Path: "/scheme-http-and-port-80", UnfollowRedirect: true, }, Response: http.Response{StatusCode: 302}, RedirectRequest: &roundtripper.RedirectRequest{ Scheme: "http", Host: "example.org", }, Namespace: ns, }, { Request: http.Request{ Host: "example.org", Path: "/scheme-http-and-port-8080", UnfollowRedirect: true, }, Response: http.Response{StatusCode: 302}, RedirectRequest: &roundtripper.RedirectRequest{ Scheme: "http", Port: "8080", Host: "example.org", }, Namespace: ns, }, } for i := range testCases { tc := testCases[i] t.Run("https-listener-on-443/"+tc.GetTestCaseName(i), func(t *testing.T) { t.Parallel() tls.MakeTLSRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr443, cPem, keyPem, "example.org", tc) }) } }, }
View Source
var HTTPRouteRedirectScheme = suite.ConformanceTest{ ShortName: "HTTPRouteRedirectScheme", Description: "An HTTPRoute with a scheme redirect filter", Manifests: []string{"tests/httproute-redirect-scheme.yaml"}, Features: []suite.SupportedFeature{ suite.SupportGateway, suite.SupportHTTPRoute, suite.SupportHTTPRouteSchemeRedirect, }, Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { ns := "gateway-conformance-infra" routeNN := types.NamespacedName{Name: "redirect-scheme", Namespace: ns} gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns} gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN) kubernetes.HTTPRouteMustHaveResolvedRefsConditionsTrue(t, suite.Client, suite.TimeoutConfig, routeNN, gwNN) testCases := []http.ExpectedResponse{ { Request: http.Request{ Path: "/scheme", UnfollowRedirect: true, }, Response: http.Response{ StatusCode: 302, }, RedirectRequest: &roundtripper.RedirectRequest{ Scheme: "https", }, Namespace: ns, }, { Request: http.Request{ Path: "/scheme-and-host", UnfollowRedirect: true, }, Response: http.Response{ StatusCode: 302, }, RedirectRequest: &roundtripper.RedirectRequest{ Host: "example.org", Scheme: "https", }, Namespace: ns, }, { Request: http.Request{ Path: "/scheme-and-status", UnfollowRedirect: true, }, Response: http.Response{ StatusCode: 301, }, RedirectRequest: &roundtripper.RedirectRequest{ Scheme: "https", }, Namespace: ns, }, { Request: http.Request{ Path: "/scheme-and-host-and-status", UnfollowRedirect: true, }, Response: http.Response{ StatusCode: 302, }, RedirectRequest: &roundtripper.RedirectRequest{ Scheme: "https", Host: "example.org", }, 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 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.SupportGateway, suite.SupportHTTPRoute, suite.SupportReferenceGrant, }, Manifests: []string{"tests/httproute-reference-grant.yaml"}, Test: func(t *testing.T, suite *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, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN) kubernetes.HTTPRouteMustHaveResolvedRefsConditionsTrue(t, suite.Client, suite.TimeoutConfig, routeNN, gwNN) 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{ Method: "GET", Path: "/", }, Response: http.Response{StatusCode: 200}, Backend: "web-backend", Namespace: "gateway-conformance-web-backend", }) }) ctx, cancel := context.WithTimeout(context.Background(), suite.TimeoutConfig.DeleteTimeout) defer cancel() rg := v1beta1.ReferenceGrant{ ObjectMeta: metav1.ObjectMeta{ Name: "reference-grant", Namespace: "gateway-conformance-web-backend", }, } require.NoError(t, suite.Client.Delete(ctx, &rg)) t.Run("Simple HTTP request should return 500 after deleting the relevant reference grant", 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 HTTPRouteRequestHeaderModifier = suite.ConformanceTest{ ShortName: "HTTPRouteRequestHeaderModifier", Description: "An HTTPRoute has request header modifier filters applied correctly", Features: []suite.SupportedFeature{ suite.SupportGateway, suite.SupportHTTPRoute, }, 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) kubernetes.HTTPRouteMustHaveResolvedRefsConditionsTrue(t, suite.Client, suite.TimeoutConfig, routeNN, gwNN) 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 HTTPRouteRequestMirror = suite.ConformanceTest{ ShortName: "HTTPRouteRequestMirror", Description: "An HTTPRoute with request mirror filter", Manifests: []string{"tests/httproute-request-mirror.yaml"}, Features: []suite.SupportedFeature{ suite.SupportGateway, suite.SupportHTTPRoute, suite.SupportHTTPRouteRequestMirror, }, Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { ns := "gateway-conformance-infra" routeNN := types.NamespacedName{Name: "request-mirror", 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: "/mirror", }, ExpectedRequest: &http.ExpectedRequest{ Request: http.Request{ Path: "/mirror", }, }, Backend: "infra-backend-v1", MirroredTo: "infra-backend-v2", Namespace: ns, }, { Request: http.Request{ Path: "/mirror-and-modify-headers", Headers: map[string]string{ "X-Header-Remove": "remove-val", "X-Header-Add-Append": "append-val-1", }, }, ExpectedRequest: &http.ExpectedRequest{ Request: http.Request{ Path: "/mirror-and-modify-headers", Headers: map[string]string{ "X-Header-Add": "header-val-1", "X-Header-Add-Append": "append-val-1,header-val-2", "X-Header-Set": "set-overwrites-values", }, }, AbsentHeaders: []string{"X-Header-Remove"}, }, Namespace: ns, Backend: "infra-backend-v1", MirroredTo: "infra-backend-v2", }, } 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) http.ExpectMirroredRequest(t, suite.Client, suite.Clientset, ns, tc.MirroredTo, tc.Request.Path) }) } }, }
View Source
var HTTPRouteResponseHeaderModifier = suite.ConformanceTest{ ShortName: "HTTPRouteResponseHeaderModifier", Description: "An HTTPRoute has response header modifier filters applied correctly", Features: []suite.SupportedFeature{ suite.SupportGateway, suite.SupportHTTPRoute, 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) kubernetes.HTTPRouteMustHaveResolvedRefsConditionsTrue(t, suite.Client, suite.TimeoutConfig, routeNN, gwNN) 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, }, { Request: http.Request{ Path: "/response-and-request-header-modifiers", Headers: map[string]string{ "X-Header-Remove": "remove-val", "X-Header-Add-Append": "append-val-1", "X-Header-Echo": "echo", }, }, 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": "remove-val-1", "X-Header-Echo": "echo", }, ExpectedRequest: &http.ExpectedRequest{ Request: http.Request{ Path: "/response-and-request-header-modifiers", Headers: map[string]string{ "X-Header-Add": "header-val-1", "X-Header-Set": "set-overwrites-values", "X-Header-Add-Append": "append-val-1,header-val-2", "X-Header-Echo": "echo", }, }, AbsentHeaders: []string{"X-Header-Remove"}, }, 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", "Another-Header": "another-header-val", "X-Header-Echo": "echo", }, AbsentHeaders: []string{"X-Header-Remove-1", "X-Header-Remove-2"}, }, 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 HTTPRouteRewriteHost = suite.ConformanceTest{ ShortName: "HTTPRouteRewriteHost", Description: "An HTTPRoute with hostname rewrite filter", Manifests: []string{"tests/httproute-rewrite-host.yaml"}, Features: []suite.SupportedFeature{ suite.SupportGateway, suite.SupportHTTPRoute, suite.SupportHTTPRouteHostRewrite, }, Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { ns := "gateway-conformance-infra" routeNN := types.NamespacedName{Name: "rewrite-host", Namespace: ns} gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns} gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN) kubernetes.HTTPRouteMustHaveResolvedRefsConditionsTrue(t, suite.Client, suite.TimeoutConfig, routeNN, gwNN) testCases := []http.ExpectedResponse{ { Request: http.Request{ Path: "/one", Host: "rewrite.example", }, ExpectedRequest: &http.ExpectedRequest{ Request: http.Request{ Path: "/one", Host: "one.example.org", }, }, Backend: "infra-backend-v1", Namespace: ns, }, { Request: http.Request{ Path: "/two", Host: "rewrite.example", }, ExpectedRequest: &http.ExpectedRequest{ Request: http.Request{ Path: "/two", Host: "example.org", }, }, Backend: "infra-backend-v2", Namespace: ns, }, { Request: http.Request{ Path: "/rewrite-host-and-modify-headers", Host: "rewrite.example", Headers: map[string]string{ "X-Header-Remove": "remove-val", "X-Header-Add-Append": "append-val-1", }, }, ExpectedRequest: &http.ExpectedRequest{ Request: http.Request{ Path: "/rewrite-host-and-modify-headers", Host: "test.example.org", Headers: map[string]string{ "X-Header-Add": "header-val-1", "X-Header-Add-Append": "append-val-1,header-val-2", "X-Header-Set": "set-overwrites-values", }, }, AbsentHeaders: []string{"X-Header-Remove"}, }, 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 HTTPRouteRewritePath = suite.ConformanceTest{ ShortName: "HTTPRouteRewritePath", Description: "An HTTPRoute with path rewrite filter", Manifests: []string{"tests/httproute-rewrite-path.yaml"}, Features: []suite.SupportedFeature{ suite.SupportGateway, suite.SupportHTTPRoute, suite.SupportHTTPRoutePathRewrite, }, Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { ns := "gateway-conformance-infra" routeNN := types.NamespacedName{Name: "rewrite-path", Namespace: ns} gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns} gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN) kubernetes.HTTPRouteMustHaveResolvedRefsConditionsTrue(t, suite.Client, suite.TimeoutConfig, routeNN, gwNN) testCases := []http.ExpectedResponse{ { Request: http.Request{ Path: "/prefix/one/two", }, ExpectedRequest: &http.ExpectedRequest{ Request: http.Request{ Path: "/one/two", }, }, Backend: "infra-backend-v1", Namespace: ns, }, { Request: http.Request{ Path: "/full/one/two", }, ExpectedRequest: &http.ExpectedRequest{ Request: http.Request{ Path: "/one", }, }, Backend: "infra-backend-v1", Namespace: ns, }, { Request: http.Request{ Path: "/full/rewrite-path-and-modify-headers/test", Headers: map[string]string{ "X-Header-Remove": "remove-val", "X-Header-Add-Append": "append-val-1", "X-Header-Set": "set-val", }, }, ExpectedRequest: &http.ExpectedRequest{ Request: http.Request{ Path: "/test", Headers: map[string]string{ "X-Header-Add": "header-val-1", "X-Header-Add-Append": "append-val-1,header-val-2", "X-Header-Set": "set-overwrites-values", }, }, AbsentHeaders: []string{"X-Header-Remove"}, }, Backend: "infra-backend-v1", Namespace: ns, }, { Request: http.Request{ Path: "/prefix/rewrite-path-and-modify-headers/one", Headers: map[string]string{ "X-Header-Remove": "remove-val", "X-Header-Add-Append": "append-val-1", "X-Header-Set": "set-val", }, }, ExpectedRequest: &http.ExpectedRequest{ Request: http.Request{ Path: "/prefix/one", Headers: map[string]string{ "X-Header-Add": "header-val-1", "X-Header-Add-Append": "append-val-1,header-val-2", "X-Header-Set": "set-overwrites-values", }, }, AbsentHeaders: []string{"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", Features: []suite.SupportedFeature{ suite.SupportGateway, suite.SupportHTTPRoute, }, 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) kubernetes.HTTPRouteMustHaveResolvedRefsConditionsTrue(t, suite.Client, suite.TimeoutConfig, routeNN, gwNN) 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", }) }) }, }
View Source
var MeshBasic = suite.ConformanceTest{ ShortName: "MeshBasic", Description: "A mesh client can communicate with a mesh server. This tests basic reachability with no configuration applied.", Features: []suite.SupportedFeature{ suite.SupportMesh, }, Manifests: []string{}, Test: func(t *testing.T, s *suite.ConformanceTestSuite) { client := echo.ConnectToApp(t, s, echo.MeshAppEchoV1) cases := []http.ExpectedResponse{{ Request: http.Request{ Host: "echo", Method: "GET", }, Response: http.Response{ StatusCode: 200, }, }} for i := range cases { tc := cases[i] t.Run(tc.GetTestCaseName(i), func(t *testing.T) { client.MakeRequestAndExpectEventuallyConsistentResponse(t, tc, s.TimeoutConfig) }) } }, }
View Source
var MeshConsumerRoute = suite.ConformanceTest{ ShortName: "MeshConsumerRoute", Description: "An HTTPRoute in a namespace other than its parentRef's namespace only affects requests from the route's namespace", Features: []suite.SupportedFeature{ suite.SupportMesh, suite.SupportHTTPRoute, suite.SupportHTTPResponseHeaderModification, }, Manifests: []string{"tests/mesh-consumer-route.yaml"}, Test: func(t *testing.T, s *suite.ConformanceTestSuite) { consumerClient := echo.ConnectToAppInNamespace(t, s, echo.MeshAppEchoV1, "gateway-conformance-mesh-consumer") consumerCases := []http.ExpectedResponse{ { TestCaseName: "request from consumer route's namespace modified by HTTPRoute", Request: http.Request{ Host: "echo-v1.gateway-conformance-mesh", Method: "GET", Path: "/", }, Response: http.Response{ StatusCode: 200, Headers: map[string]string{ "X-Header-Set": "set", }, }, Backend: "echo-v1", }, } producerClient := echo.ConnectToAppInNamespace(t, s, echo.MeshAppEchoV1, "gateway-conformance-mesh") producerCases := []http.ExpectedResponse{ { TestCaseName: "request not from consumer route's namespace not modified by HTTPRoute", Request: http.Request{ Host: "echo-v1.gateway-conformance-mesh", Method: "GET", Path: "/", }, Response: http.Response{ StatusCode: 200, AbsentHeaders: []string{"X-Header-Set"}, }, Backend: "echo-v1", }, } for i, tc := range consumerCases { t.Run(tc.GetTestCaseName(i), func(t *testing.T) { consumerClient.MakeRequestAndExpectEventuallyConsistentResponse(t, tc, s.TimeoutConfig) }) } for i, tc := range producerCases { t.Run(tc.GetTestCaseName(i), func(t *testing.T) { producerClient.MakeRequestAndExpectEventuallyConsistentResponse(t, tc, s.TimeoutConfig) }) } }, }
View Source
var MeshFrontend = suite.ConformanceTest{ ShortName: "MeshFrontend", Description: "Mesh rules should only apply to the associated frontend", Features: []suite.SupportedFeature{ suite.SupportMesh, suite.SupportHTTPRoute, suite.SupportHTTPResponseHeaderModification, }, Manifests: []string{"tests/mesh-frontend.yaml"}, Test: func(t *testing.T, s *suite.ConformanceTestSuite) { client := echo.ConnectToApp(t, s, echo.MeshAppEchoV1) v2 := echo.ConnectToApp(t, s, echo.MeshAppEchoV2) cases := []http.ExpectedResponse{ { TestCaseName: "Send to service", Request: http.Request{ Host: "echo-v2", Method: "GET", }, Response: http.Response{ StatusCode: 200, Headers: map[string]string{ "X-Header-Set": "set", }, }, Backend: "echo-v2", }, { TestCaseName: "Send to pod IP", Request: http.Request{ Host: v2.Address, Method: "GET", }, Response: http.Response{ StatusCode: 200, AbsentHeaders: []string{"X-Header-Set"}, }, Backend: "echo-v2", }, } for i := range cases { tc := cases[i] t.Run(tc.GetTestCaseName(i), func(t *testing.T) { client.MakeRequestAndExpectEventuallyConsistentResponse(t, tc, s.TimeoutConfig) }) } }, }
View Source
var MeshFrontendHostname = suite.ConformanceTest{ ShortName: "MeshFrontendHostname", Description: "Mesh parentRef matches Service IP (not Host)", Features: []suite.SupportedFeature{ suite.SupportMesh, }, Manifests: []string{"tests/mesh-frontend.yaml"}, Test: func(t *testing.T, s *suite.ConformanceTestSuite) { client := echo.ConnectToApp(t, s, echo.MeshAppEchoV1) cases := []http.ExpectedResponse{ { TestCaseName: "Send to service with wrong hostname", Request: http.Request{ Host: "echo-v2", Headers: map[string]string{ "Host": "echo-v1", }, Method: "GET", }, Response: http.Response{ StatusCode: 200, Headers: map[string]string{ "X-Header-Set": "set", }, }, Backend: "echo-v2", }, { TestCaseName: "Send to other service with matching hostname", Request: http.Request{ Host: "echo-v1", Headers: map[string]string{ "Host": "echo-v2", }, Method: "GET", }, Response: http.Response{ StatusCode: 200, AbsentHeaders: []string{"X-Header-Set"}, }, Backend: "echo-v1", }, } for i := range cases { tc := cases[i] t.Run(tc.GetTestCaseName(i), func(t *testing.T) { client.MakeRequestAndExpectEventuallyConsistentResponse(t, tc, s.TimeoutConfig) }) } }, }
View Source
var MeshPorts = suite.ConformanceTest{ ShortName: "MeshPorts", Description: "A mesh route can optionally configure 'port' in parentRef", Features: []suite.SupportedFeature{ suite.SupportMesh, suite.SupportHTTPRoute, suite.SupportHTTPResponseHeaderModification, }, Manifests: []string{"tests/mesh-ports.yaml"}, Test: func(t *testing.T, s *suite.ConformanceTestSuite) { client := echo.ConnectToApp(t, s, echo.MeshAppEchoV1) cases := []http.ExpectedResponse{ { TestCaseName: "Explicit port set, send to that port", Request: http.Request{ Host: "echo-v1", Method: "GET", }, Response: http.Response{ StatusCode: 200, Headers: map[string]string{ "X-Header-Set": "v1", }, }, Backend: "echo-v1", }, { TestCaseName: "Explicit port, send to an excluded port", Request: http.Request{ Host: "echo-v1:8080", Method: "GET", }, Response: http.Response{ StatusCode: 200, AbsentHeaders: []string{"X-Header-Set"}, }, Backend: "echo-v1", }, { TestCaseName: "No port set", Request: http.Request{ Host: "echo-v2", Method: "GET", }, Response: http.Response{ StatusCode: 200, Headers: map[string]string{ "X-Header-Set": "v2", }, }, Backend: "echo-v2", }, { TestCaseName: "No port set", Request: http.Request{ Host: "echo-v2:8080", Method: "GET", }, Response: http.Response{ StatusCode: 200, Headers: map[string]string{ "X-Header-Set": "v2", }, }, Backend: "echo-v2", }, } for i := range cases { tc := cases[i] t.Run(tc.GetTestCaseName(i), func(t *testing.T) { client.MakeRequestAndExpectEventuallyConsistentResponse(t, tc, s.TimeoutConfig) }) } }, }
View Source
var MeshTrafficSplit = suite.ConformanceTest{ ShortName: "MeshTrafficSplit", Description: "A mesh client can send traffic to a Service which is split between two versions", Features: []suite.SupportedFeature{ suite.SupportMesh, }, Manifests: []string{"tests/mesh-split.yaml"}, Test: func(t *testing.T, s *suite.ConformanceTestSuite) { client := echo.ConnectToApp(t, s, echo.MeshAppEchoV1) cases := []http.ExpectedResponse{ { Request: http.Request{ Host: "echo", Method: "GET", Path: "/v1", }, Response: http.Response{ StatusCode: 200, }, Backend: "echo-v1", }, { Request: http.Request{ Host: "echo", Method: "GET", Path: "/v2", }, Response: http.Response{ StatusCode: 200, }, Backend: "echo-v2", }, } for i := range cases { tc := cases[i] t.Run(tc.GetTestCaseName(i), func(t *testing.T) { client.MakeRequestAndExpectEventuallyConsistentResponse(t, tc, s.TimeoutConfig) }) } }, }
View Source
var TLSRouteInvalidReferenceGrant = suite.ConformanceTest{ ShortName: "TLSRouteInvalidReferenceGrant", Description: "A single TLSRoute in the gateway-conformance-infra namespace, with a backendRef in another namespace without valid ReferenceGrant, should have the ResolvedRefs condition set to False", Features: []suite.SupportedFeature{ suite.SupportGateway, suite.SupportTLSRoute, suite.SupportReferenceGrant, }, Manifests: []string{"tests/tlsroute-invalid-reference-grant.yaml"}, Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { routeNN := types.NamespacedName{Name: "gateway-conformance-infra-test", Namespace: "gateway-conformance-infra"} gwNN := types.NamespacedName{Name: "gateway-tlsroute-referencegrant", Namespace: "gateway-conformance-infra"} kubernetes.GatewayAndTLSRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN) t.Run("TLSRoute 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.TLSRouteMustHaveCondition(t, suite.Client, suite.TimeoutConfig, routeNN, gwNN, resolvedRefsCond) }) }, }
View Source
var TLSRouteSimpleSameNamespace = suite.ConformanceTest{ ShortName: "TLSRouteSimpleSameNamespace", Description: "A single TLSRoute in the gateway-conformance-infra namespace attaches to a Gateway in the same namespace", Features: []suite.SupportedFeature{ suite.SupportGateway, suite.SupportTLSRoute, }, Manifests: []string{"tests/tlsroute-simple-same-namespace.yaml"}, Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { ns := "gateway-conformance-infra" routeNN := types.NamespacedName{Name: "gateway-conformance-infra-test", Namespace: ns} gwNN := types.NamespacedName{Name: "gateway-tlsroute", Namespace: ns} certNN := types.NamespacedName{Name: "tls-passthrough-checks-certificate", Namespace: ns} kubernetes.NamespacesMustBeReady(t, suite.Client, suite.TimeoutConfig, []string{ns}) gwAddr, hostnames := kubernetes.GatewayAndTLSRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN) if len(hostnames) != 1 { t.Fatalf("unexpected error in test configuration, found %d hostnames", len(hostnames)) } serverStr := string(hostnames[0]) cPem, keyPem, err := GetTLSSecret(suite.Client, certNN) if err != nil { t.Fatalf("unexpected error finding TLS secret: %v", err) } t.Run("Simple TLS request matching TLSRoute should reach infra-backend", func(t *testing.T) { tls.MakeTLSRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, cPem, keyPem, serverStr, http.ExpectedResponse{ Request: http.Request{Host: serverStr, Path: "/"}, Backend: "tls-backend", Namespace: "gateway-conformance-infra", }) }) }, }
Functions ¶
func GetTLSSecret ¶ added in v0.6.1
GetTLSSecret fetches the named Secret and converts both cert and key to []byte
Types ¶
This section is empty.
Source Files ¶
- gateway-invalid-route-kind.go
- gateway-invalid-tls-certificateref.go
- gateway-modify-listeners.go
- gateway-observed-generation-bump.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
- gateway-with-attached-routes.go
- gatewayclass-observed-generation-bump.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-invalid-parentref-not-matching-section-name.go
- httproute-invalid-reference-grant.go
- httproute-listener-hostname-matching.go
- httproute-matching-across-routes.go
- httproute-matching.go
- httproute-method-matching.go
- httproute-observed-generation-bump.go
- httproute-partially-invalid-via-reference-grant.go
- httproute-path-match-order.go
- httproute-query-param-matching.go
- httproute-redirect-host-and-status.go
- httproute-redirect-path.go
- httproute-redirect-port-and-scheme.go
- httproute-redirect-port.go
- httproute-redirect-scheme.go
- httproute-reference-grant.go
- httproute-request-header-modifier.go
- httproute-request-mirror.go
- httproute-response-header-modifier.go
- httproute-rewrite-host.go
- httproute-rewrite-path.go
- httproute-simple-same-namespace.go
- main.go
- mesh-basic.go
- mesh-consumer-route.go
- mesh-frontend-hostname.go
- mesh-frontend.go
- mesh-ports.go
- mesh-split.go
- tlsroute-invalid-reference-grant.go
- tlsroute-simple-same-namespace.go
Click to show internal directories.
Click to hide internal directories.