diff --git a/ako-gateway-api/nodes/avi_model_l4_translator.go b/ako-gateway-api/nodes/avi_model_l4_translator.go index f8525b22a..70fb36cc0 100644 --- a/ako-gateway-api/nodes/avi_model_l4_translator.go +++ b/ako-gateway-api/nodes/avi_model_l4_translator.go @@ -19,7 +19,7 @@ import ( ) func (o *AviObjectGraph) ProcessL4Routes(key string, routeModel RouteModel, parentNsName string) { - for _, rule := range routeModel.ParseRouteConfig().Rules { + for _, rule := range routeModel.ParseRouteConfig(key).Rules { parentNode := o.GetAviEvhVS() // create L4 policyset per rule o.BuildL4PolicySet(key, parentNode[0], routeModel, rule) diff --git a/ako-gateway-api/nodes/avi_model_l7_translator.go b/ako-gateway-api/nodes/avi_model_l7_translator.go index c12d2f006..688f192fa 100644 --- a/ako-gateway-api/nodes/avi_model_l7_translator.go +++ b/ako-gateway-api/nodes/avi_model_l7_translator.go @@ -72,7 +72,7 @@ func (o *AviObjectGraph) AddDefaultHTTPPolicySet(key string) { } func (o *AviObjectGraph) ProcessL7Routes(key string, routeModel RouteModel, parentNsName string, childVSes map[string]struct{}, fullsync bool) { - httpRouteConfig := routeModel.ParseRouteConfig() + httpRouteConfig := routeModel.ParseRouteConfig(key) noHostsOnRoute := len(httpRouteConfig.Hosts) == 0 httpRouteRules := httpRouteConfig.Rules if noHostsOnRoute { @@ -244,6 +244,7 @@ func (o *AviObjectGraph) BuildPGPool(key, parentNsName string, childVsNode *node Name: PGName, Tenant: lib.GetTenant(), } + for _, httpbackend := range rule.Backends { poolName := akogatewayapilib.GetPoolName(parentNs, parentName, routeModel.GetNamespace(), routeModel.GetName(), diff --git a/ako-gateway-api/nodes/route_model.go b/ako-gateway-api/nodes/route_model.go index 0b21b6d6c..ced0cb445 100644 --- a/ako-gateway-api/nodes/route_model.go +++ b/ako-gateway-api/nodes/route_model.go @@ -22,6 +22,7 @@ import ( gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" akogatewayapilib "github.com/vmware/load-balancer-and-ingress-services-for-kubernetes/ako-gateway-api/lib" + akogatewayapistatus "github.com/vmware/load-balancer-and-ingress-services-for-kubernetes/ako-gateway-api/status" "github.com/vmware/load-balancer-and-ingress-services-for-kubernetes/internal/lib" ) @@ -30,7 +31,7 @@ type RouteModel interface { GetNamespace() string GetType() string GetSpec() interface{} - ParseRouteConfig() *RouteConfig + ParseRouteConfig(key string) *RouteConfig Exists() bool GetParents() sets.Set[string] } @@ -105,6 +106,7 @@ type Backend struct { Namespace string Port int32 Weight int32 + Kind string } type HTTPBackend struct { @@ -162,7 +164,7 @@ func (hr *httpRoute) GetSpec() interface{} { return hr.spec } -func (hr *httpRoute) ParseRouteConfig() *RouteConfig { +func (hr *httpRoute) ParseRouteConfig(key string) *RouteConfig { if hr.routeConfig != nil { return hr.routeConfig } @@ -172,7 +174,7 @@ func (hr *httpRoute) ParseRouteConfig() *RouteConfig { for i := range hr.spec.Hostnames { routeConfig.Hosts[i] = string(hr.spec.Hostnames[i]) } - + var resolvedRefCondition akogatewayapistatus.Condition routeConfig.Rules = make([]*Rule, 0, len(hr.spec.Rules)) for _, rule := range hr.spec.Rules { routeConfigRule := &Rule{} @@ -282,6 +284,7 @@ func (hr *httpRoute) ParseRouteConfig() *RouteConfig { } routeConfigRule.Filters = append(routeConfigRule.Filters, filter) } + hasInvalidBackend := false for _, ruleBackend := range rule.BackendRefs { httpBackend := &HTTPBackend{} backend := &Backend{} @@ -295,16 +298,29 @@ func (hr *httpRoute) ParseRouteConfig() *RouteConfig { //Default 0 backend.Port = int32(*ruleBackend.Port) } + if ruleBackend.BackendRef.Kind != nil { + backend.Kind = string(*ruleBackend.Kind) + } backend.Weight = 1 if ruleBackend.Weight != nil { backend.Weight = *ruleBackend.Weight } httpBackend.Backend = backend - routeConfigRule.Backends = append(routeConfigRule.Backends, httpBackend) + isValidBackend, resolvedRefConditionforBackend := validateBackendReference(key, *backend, hr) + if isValidBackend { + routeConfigRule.Backends = append(routeConfigRule.Backends, httpBackend) + if !hasInvalidBackend { + resolvedRefCondition = resolvedRefConditionforBackend + } + } else { + hasInvalidBackend = true + resolvedRefCondition = resolvedRefConditionforBackend + } } routeConfig.Rules = append(routeConfig.Rules, routeConfigRule) } hr.routeConfig = routeConfig + setResolvedRefConditionInHTTPRouteStatus(key, resolvedRefCondition, lib.HTTPRoute+"/"+hr.GetNamespace()+"/"+hr.GetName()) return hr.routeConfig } diff --git a/ako-gateway-api/nodes/route_validator.go b/ako-gateway-api/nodes/route_validator.go index 864304f44..c568a2efc 100644 --- a/ako-gateway-api/nodes/route_validator.go +++ b/ako-gateway-api/nodes/route_validator.go @@ -71,6 +71,45 @@ func IsHTTPRouteValid(key string, obj *gatewayv1.HTTPRoute) bool { return true } +func validateBackendReference(key string, backend Backend, httpRoute *httpRoute) (bool, akogatewayapistatus.Condition) { + routeConditionResolvedRef := akogatewayapistatus.NewCondition(). + Type(string(gatewayv1.RouteConditionResolvedRefs)). + Status(metav1.ConditionFalse) + if backend.Kind != "" && backend.Kind != "Service" { + utils.AviLog.Errorf("key: %s, msg: BackendRef %s has invalid kind %s.", key, backend.Name, backend.Kind) + err := fmt.Errorf("BackendRef %s has invalid kind %s.", backend.Name, backend.Kind) + routeConditionResolvedRef. + Reason(string(gatewayv1.RouteReasonInvalidKind)). + Message(err.Error()) + return false, routeConditionResolvedRef + } + //TODO: other backendRef related conditions should go here + + // Valid route case + routeConditionResolvedRef. + Status(metav1.ConditionTrue). + Reason(string(gatewayv1.RouteReasonResolvedRefs)) + return true, routeConditionResolvedRef +} + +func setResolvedRefConditionInHTTPRouteStatus(key string, routeConditionResolvedRef akogatewayapistatus.Condition, routeTypeNamespaceName string) { + if routeConditionResolvedRef == nil { + return + } + httpRouteStatus := akogatewayapiobjects.GatewayApiLister().GetRouteToRouteStatusMapping(routeTypeNamespaceName) + routeConditionResolvedRef.ObservedGeneration(httpRouteStatus.Parents[0].Conditions[0].ObservedGeneration) + for parentRefIndex := range httpRouteStatus.Parents { + routeConditionResolvedRef.SetIn(&httpRouteStatus.Parents[parentRefIndex].Conditions) + } + _, namespace, name := lib.ExtractTypeNameNamespace(routeTypeNamespaceName) + httpRoute, err := akogatewayapilib.AKOControlConfig().GatewayApiInformers().HTTPRouteInformer.Lister().HTTPRoutes(namespace).Get(name) + if err != nil { + utils.AviLog.Warnf("key: %s, msg: Unable to extract the HTTPRoute object %s for BackendRef validation", key, name) + return + } + akogatewayapistatus.Record(key, httpRoute, &status.Status{HTTPRouteStatus: httpRouteStatus}) +} + func validateParentReference(key string, httpRoute *gatewayv1.HTTPRoute, httpRouteStatus *gatewayv1.HTTPRouteStatus, parentRefIndexFromSpec int, parentRefIndexInHttpRouteStatus *int) error { name := string(httpRoute.Spec.ParentRefs[parentRefIndexFromSpec].Name) diff --git a/ako-gateway-api/objects/gateway_store.go b/ako-gateway-api/objects/gateway_store.go index e45d18111..44aa11321 100644 --- a/ako-gateway-api/objects/gateway_store.go +++ b/ako-gateway-api/objects/gateway_store.go @@ -263,7 +263,7 @@ func (g *GWLister) GetGatewayToGatewayStatusMapping(gwName string) *gatewayv1.Ga return gatewayList.(*gatewayv1.GatewayStatus) } -func (g *GWLister) UpdateRouteToRouteStatusMapping(routeTypeNamespaceName string, routeStatus *gatewayv1.RouteStatus) { +func (g *GWLister) UpdateRouteToRouteStatusMapping(routeTypeNamespaceName string, routeStatus *gatewayv1.HTTPRouteStatus) { g.gwLock.Lock() defer g.gwLock.Unlock() g.routeToStatus.AddOrUpdate(routeTypeNamespaceName, routeStatus) @@ -275,14 +275,14 @@ func (g *GWLister) DeleteRouteToRouteStatusMapping(routeTypeNamespaceName string g.routeToStatus.Delete(routeTypeNamespaceName) } -func (g *GWLister) GetRouteToRouteStatusMapping(routeTypeNamespaceName string) *gatewayv1.RouteStatus { +func (g *GWLister) GetRouteToRouteStatusMapping(routeTypeNamespaceName string) *gatewayv1.HTTPRouteStatus { g.gwLock.RLock() defer g.gwLock.RUnlock() found, routeList := g.routeToStatus.Get(routeTypeNamespaceName) if !found { return nil } - return routeList.(*gatewayv1.RouteStatus) + return routeList.(*gatewayv1.HTTPRouteStatus) } //=====All route <-> gateway mappings go here. diff --git a/ako-gateway-api/status/status.go b/ako-gateway-api/status/status.go index f6fe9e2fb..4dc7f6167 100644 --- a/ako-gateway-api/status/status.go +++ b/ako-gateway-api/status/status.go @@ -95,7 +95,7 @@ func Record(key string, obj runtime.Object, objStatus *status.Status) { objectType = lib.HTTPRoute serviceMetadata.HTTPRoute = gwObject.Namespace + "/" + gwObject.Name key = serviceMetadata.HTTPRoute - akogatewayapiobjects.GatewayApiLister().UpdateRouteToRouteStatusMapping(objectType+"/"+serviceMetadata.HTTPRoute, &objStatus.RouteStatus) + akogatewayapiobjects.GatewayApiLister().UpdateRouteToRouteStatusMapping(objectType+"/"+serviceMetadata.HTTPRoute, objStatus.HTTPRouteStatus) default: utils.AviLog.Warnf("key %s, msg: Unsupported object received at the status layer, %T", key, obj) return diff --git a/tests/gatewayapitests/graphlayer/httproute_test.go b/tests/gatewayapitests/graphlayer/httproute_test.go index a4aec5cfa..af7092fe5 100644 --- a/tests/gatewayapitests/graphlayer/httproute_test.go +++ b/tests/gatewayapitests/graphlayer/httproute_test.go @@ -571,7 +571,7 @@ func TestHTTPRouteWithValidConfig(t *testing.T) { return false } nodes := aviModel.(*avinodes.AviObjectGraph).GetAviEvhVS() - return len(nodes[0].VSVIPRefs[0].FQDNs) > 0 + return len(nodes[0].VSVIPRefs[0].FQDNs) > 0 && len(nodes[0].EvhNodes[0].PoolGroupRefs) > 0 }, 25*time.Second).Should(gomega.Equal(true)) @@ -766,7 +766,7 @@ func TestHTTPRouteBackendServiceCDC(t *testing.T) { } nodes := aviModel.(*avinodes.AviObjectGraph).GetAviEvhVS() return len(nodes[0].EvhNodes[0].PoolGroupRefs[0].Members) - }, 25*time.Second).Should(gomega.Equal(1)) + }, 30*time.Second).Should(gomega.Equal(1)) _, aviModel = objects.SharedAviGraphLister().Get(modelName) nodes = aviModel.(*avinodes.AviObjectGraph).GetAviEvhVS() diff --git a/tests/gatewayapitests/status/httproute_test.go b/tests/gatewayapitests/status/httproute_test.go index 5ded4e7eb..20e8c4c80 100644 --- a/tests/gatewayapitests/status/httproute_test.go +++ b/tests/gatewayapitests/status/httproute_test.go @@ -21,12 +21,14 @@ import ( "time" "github.com/onsi/gomega" + corev1 "k8s.io/api/core/v1" apimeta "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" akogatewayapilib "github.com/vmware/load-balancer-and-ingress-services-for-kubernetes/ako-gateway-api/lib" akogatewayapitests "github.com/vmware/load-balancer-and-ingress-services-for-kubernetes/tests/gatewayapitests" + "github.com/vmware/load-balancer-and-ingress-services-for-kubernetes/tests/integrationtest" ) /* Positive test cases @@ -39,9 +41,12 @@ func TestHTTPRouteWithValidConfig(t *testing.T) { gatewayName := "gateway-hr-01" httpRouteName := "httproute-01" namespace := "default" + svcName := "avisvc-hr-01" ports := []int32{8080, 8081} akogatewayapitests.SetupGatewayClass(t, gatewayClassName, akogatewayapilib.GatewayController) + integrationtest.CreateSVC(t, DEFAULT_NAMESPACE, svcName, "TCP", corev1.ServiceTypeClusterIP, false) + integrationtest.CreateEPorEPS(t, "default", svcName, false, false, "1.1.1") listeners := akogatewayapitests.GetListenersV1(ports, false, false) akogatewayapitests.SetupGateway(t, gatewayName, namespace, gatewayClassName, nil, listeners) @@ -58,8 +63,12 @@ func TestHTTPRouteWithValidConfig(t *testing.T) { parentRefs := akogatewayapitests.GetParentReferencesV1([]string{gatewayName}, namespace, ports) hostnames := []gatewayv1.Hostname{"foo-8080.com", "foo-8081.com"} + rule := akogatewayapitests.GetHTTPRouteRuleV1([]string{"/foo"}, []string{}, + map[string][]string{"RequestHeaderModifier": {"add", "remove", "replace"}}, + [][]string{{svcName, namespace, "8080", "1"}}, nil) + rules := []gatewayv1.HTTPRouteRule{rule} - akogatewayapitests.SetupHTTPRoute(t, httpRouteName, namespace, parentRefs, hostnames, nil) + akogatewayapitests.SetupHTTPRoute(t, httpRouteName, namespace, parentRefs, hostnames, rules) g.Eventually(func() bool { httpRoute, err := akogatewayapitests.GatewayClient.GatewayV1().HTTPRoutes(namespace).Get(context.TODO(), httpRouteName, metav1.GetOptions{}) @@ -70,21 +79,23 @@ func TestHTTPRouteWithValidConfig(t *testing.T) { if len(httpRoute.Status.Parents) != len(ports) { return false } - return apimeta.FindStatusCondition(httpRoute.Status.Parents[0].Conditions, string(gatewayv1.RouteConditionAccepted)) != nil && - apimeta.FindStatusCondition(httpRoute.Status.Parents[1].Conditions, string(gatewayv1.RouteConditionAccepted)) != nil + return apimeta.FindStatusCondition(httpRoute.Status.Parents[0].Conditions, string(gatewayv1.RouteConditionResolvedRefs)) != nil && + apimeta.FindStatusCondition(httpRoute.Status.Parents[1].Conditions, string(gatewayv1.RouteConditionResolvedRefs)) != nil }, 30*time.Second).Should(gomega.Equal(true)) conditionMap := make(map[string][]metav1.Condition) for _, port := range ports { - conditions := make([]metav1.Condition, 0, 1) - condition := metav1.Condition{ + conditions := []metav1.Condition{{ Type: string(gatewayv1.RouteConditionAccepted), Reason: string(gatewayv1.RouteReasonAccepted), Status: metav1.ConditionTrue, Message: "Parent reference is valid", - } - conditions = append(conditions, condition) + }, { + Type: string(gatewayv1.RouteConditionResolvedRefs), + Reason: string(gatewayv1.RouteReasonResolvedRefs), + Status: metav1.ConditionTrue, + }} conditionMap[fmt.Sprintf("%s-%d", gatewayName, port)] = conditions } expectedRouteStatus := akogatewayapitests.GetRouteStatusV1([]string{gatewayName}, namespace, ports, conditionMap) @@ -1019,3 +1030,154 @@ func TestHttpRouteWithValidAndInvalidGatewayListeners(t *testing.T) { akogatewayapitests.TeardownGateway(t, gatewayName, namespace) akogatewayapitests.TeardownGatewayClass(t, gatewayClassName) } +func TestHTTPRouteWithInvalidBackendKind(t *testing.T) { + gatewayClassName := "gateway-class-hr-16" + gatewayName := "gateway-hr-16" + httpRouteName := "httproute-16" + namespace := "default" + ports := []int32{8080} + + akogatewayapitests.SetupGatewayClass(t, gatewayClassName, akogatewayapilib.GatewayController) + + listeners := akogatewayapitests.GetListenersV1(ports, false, false) + akogatewayapitests.SetupGateway(t, gatewayName, namespace, gatewayClassName, nil, listeners) + + g := gomega.NewGomegaWithT(t) + g.Eventually(func() bool { + gateway, err := akogatewayapitests.GatewayClient.GatewayV1().Gateways(namespace).Get(context.TODO(), gatewayName, metav1.GetOptions{}) + if err != nil || gateway == nil { + t.Logf("Couldn't get the gateway, err: %+v", err) + return false + } + return apimeta.FindStatusCondition(gateway.Status.Conditions, string(gatewayv1.GatewayConditionAccepted)) != nil + }, 30*time.Second).Should(gomega.Equal(true)) + + parentRefs := akogatewayapitests.GetParentReferencesV1([]string{gatewayName}, namespace, ports) + rule := akogatewayapitests.GetHTTPRouteRuleV1([]string{"/foo"}, []string{}, + map[string][]string{"RequestHeaderModifier": {"add", "remove", "replace"}}, + [][]string{{"avisvc", "default", "8080", "1"}}, nil) + kind := gatewayv1.Kind("InvalidKind") + rule.BackendRefs[0].BackendRef.Kind = &kind + rules := []gatewayv1.HTTPRouteRule{rule} + hostnames := []gatewayv1.Hostname{"foo-8080.com"} + + akogatewayapitests.SetupHTTPRoute(t, httpRouteName, namespace, parentRefs, hostnames, rules) + + g.Eventually(func() bool { + httpRoute, err := akogatewayapitests.GatewayClient.GatewayV1().HTTPRoutes(namespace).Get(context.TODO(), httpRouteName, metav1.GetOptions{}) + if err != nil || httpRoute == nil { + t.Logf("Couldn't get the HTTPRoute, err: %+v", err) + return false + } + if len(httpRoute.Status.Parents) != len(ports) { + return false + } + return apimeta.FindStatusCondition(httpRoute.Status.Parents[0].Conditions, string(gatewayv1.RouteConditionAccepted)) != nil + }, 30*time.Second).Should(gomega.Equal(true)) + + conditionMap := make(map[string][]metav1.Condition) + + for _, port := range ports { + conditions := []metav1.Condition{{ + Type: string(gatewayv1.RouteConditionAccepted), + Reason: string(gatewayv1.RouteReasonAccepted), + Status: metav1.ConditionTrue, + Message: "Parent reference is valid", + }, { + Type: string(gatewayv1.RouteConditionResolvedRefs), + Reason: string(gatewayv1.RouteReasonInvalidKind), + Status: metav1.ConditionFalse, + Message: "BackendRef avisvc has invalid kind InvalidKind.", + }, + } + conditionMap[fmt.Sprintf("%s-%d", gatewayName, port)] = conditions + } + expectedRouteStatus := akogatewayapitests.GetRouteStatusV1([]string{gatewayName}, namespace, ports, conditionMap) + + httpRoute, err := akogatewayapitests.GatewayClient.GatewayV1().HTTPRoutes(namespace).Get(context.TODO(), httpRouteName, metav1.GetOptions{}) + if err != nil || httpRoute == nil { + t.Fatalf("Couldn't get the HTTPRoute, err: %+v", err) + } + akogatewayapitests.ValidateHTTPRouteStatus(t, &httpRoute.Status, &gatewayv1.HTTPRouteStatus{RouteStatus: *expectedRouteStatus}) + + akogatewayapitests.TeardownHTTPRoute(t, httpRouteName, namespace) + akogatewayapitests.TeardownGateway(t, gatewayName, namespace) + akogatewayapitests.TeardownGatewayClass(t, gatewayClassName) +} +func TestHTTPRouteWithValidAndInvalidBackendKind(t *testing.T) { + gatewayClassName := "gateway-class-hr-17" + gatewayName := "gateway-hr-17" + httpRouteName := "httproute-17" + namespace := "default" + ports := []int32{8080} + svcName := "avisvc-hr-17" + + akogatewayapitests.SetupGatewayClass(t, gatewayClassName, akogatewayapilib.GatewayController) + integrationtest.CreateSVC(t, DEFAULT_NAMESPACE, svcName, "TCP", corev1.ServiceTypeClusterIP, false) + integrationtest.CreateEPorEPS(t, "default", svcName, false, false, "1.1.1") + + listeners := akogatewayapitests.GetListenersV1(ports, false, false) + akogatewayapitests.SetupGateway(t, gatewayName, namespace, gatewayClassName, nil, listeners) + + g := gomega.NewGomegaWithT(t) + g.Eventually(func() bool { + gateway, err := akogatewayapitests.GatewayClient.GatewayV1().Gateways(namespace).Get(context.TODO(), gatewayName, metav1.GetOptions{}) + if err != nil || gateway == nil { + t.Logf("Couldn't get the gateway, err: %+v", err) + return false + } + return apimeta.FindStatusCondition(gateway.Status.Conditions, string(gatewayv1.GatewayConditionAccepted)) != nil + }, 30*time.Second).Should(gomega.Equal(true)) + + parentRefs := akogatewayapitests.GetParentReferencesV1([]string{gatewayName}, namespace, ports) + rule := akogatewayapitests.GetHTTPRouteRuleV1([]string{"/foo"}, []string{}, + map[string][]string{"RequestHeaderModifier": {"add", "remove", "replace"}}, + [][]string{{"avisvc", "default", "8080", "1"}, {svcName, "default", "8080", "1"}}, nil) + kind := gatewayv1.Kind("InvalidKind") + rule.BackendRefs[0].BackendRef.Kind = &kind + rules := []gatewayv1.HTTPRouteRule{rule} + hostnames := []gatewayv1.Hostname{"foo-8080.com"} + + akogatewayapitests.SetupHTTPRoute(t, httpRouteName, namespace, parentRefs, hostnames, rules) + + g.Eventually(func() bool { + httpRoute, err := akogatewayapitests.GatewayClient.GatewayV1().HTTPRoutes(namespace).Get(context.TODO(), httpRouteName, metav1.GetOptions{}) + if err != nil || httpRoute == nil { + t.Logf("Couldn't get the HTTPRoute, err: %+v", err) + return false + } + if len(httpRoute.Status.Parents) != len(ports) { + return false + } + return apimeta.FindStatusCondition(httpRoute.Status.Parents[0].Conditions, string(gatewayv1.RouteConditionAccepted)) != nil + }, 30*time.Second).Should(gomega.Equal(true)) + + conditionMap := make(map[string][]metav1.Condition) + + for _, port := range ports { + conditions := []metav1.Condition{{ + Type: string(gatewayv1.RouteConditionAccepted), + Reason: string(gatewayv1.RouteReasonAccepted), + Status: metav1.ConditionTrue, + Message: "Parent reference is valid", + }, { + Type: string(gatewayv1.RouteConditionResolvedRefs), + Reason: string(gatewayv1.RouteReasonInvalidKind), + Status: metav1.ConditionFalse, + Message: "BackendRef avisvc has invalid kind InvalidKind.", + }, + } + conditionMap[fmt.Sprintf("%s-%d", gatewayName, port)] = conditions + } + expectedRouteStatus := akogatewayapitests.GetRouteStatusV1([]string{gatewayName}, namespace, ports, conditionMap) + + httpRoute, err := akogatewayapitests.GatewayClient.GatewayV1().HTTPRoutes(namespace).Get(context.TODO(), httpRouteName, metav1.GetOptions{}) + if err != nil || httpRoute == nil { + t.Fatalf("Couldn't get the HTTPRoute, err: %+v", err) + } + akogatewayapitests.ValidateHTTPRouteStatus(t, &httpRoute.Status, &gatewayv1.HTTPRouteStatus{RouteStatus: *expectedRouteStatus}) + + akogatewayapitests.TeardownHTTPRoute(t, httpRouteName, namespace) + akogatewayapitests.TeardownGateway(t, gatewayName, namespace) + akogatewayapitests.TeardownGatewayClass(t, gatewayClassName) +}