From aa1cb49f3b5e2d389038ffe0c83d4ed3438b900c Mon Sep 17 00:00:00 2001 From: priyakoshta Date: Fri, 4 Oct 2024 11:22:50 +0530 Subject: [PATCH] AV-214603 Changes for accepting Gateway with some valid and some invalid listener --- ako-gateway-api/k8s/ako_init.go | 2 +- ako-gateway-api/k8s/gateway_controller.go | 55 +- ako-gateway-api/k8s/validator.go | 32 +- ako-gateway-api/nodes/gateway_model.go | 26 +- ako-gateway-api/nodes/gateway_model_rel.go | 22 +- ako-gateway-api/nodes/route_validator.go | 11 + ako-gateway-api/status/gateway_status.go | 32 +- ako-gateway-api/status/gatewayclass_status.go | 3 +- ako-gateway-api/status/httproute_status.go | 3 +- ako-gateway-api/status/status.go | 6 +- .../graphlayer/httproute_test.go | 983 ++++++++++++++++++ .../gatewayapitests/status/httproute_test.go | 174 ++++ 12 files changed, 1305 insertions(+), 44 deletions(-) diff --git a/ako-gateway-api/k8s/ako_init.go b/ako-gateway-api/k8s/ako_init.go index ad330dd12..582aa9bb2 100644 --- a/ako-gateway-api/k8s/ako_init.go +++ b/ako-gateway-api/k8s/ako_init.go @@ -274,7 +274,7 @@ func (c *GatewayController) FullSyncK8s(sync bool) error { resVer := meta.GetResourceVersion() objects.SharedResourceVerInstanceLister().Save(key, resVer) } - if IsValidGateway(key, gatewayObj) { + if valid, _ := IsValidGateway(key, gatewayObj); valid { filteredGateways = append(filteredGateways, gatewayObj) } } diff --git a/ako-gateway-api/k8s/gateway_controller.go b/ako-gateway-api/k8s/gateway_controller.go index f6beca038..9db7294e4 100644 --- a/ako-gateway-api/k8s/gateway_controller.go +++ b/ako-gateway-api/k8s/gateway_controller.go @@ -17,11 +17,14 @@ package k8s import ( "fmt" "reflect" + "sort" "sync" "time" corev1 "k8s.io/api/core/v1" discovery "k8s.io/api/discovery/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/client-go/tools/cache" "k8s.io/client-go/util/workqueue" @@ -500,13 +503,23 @@ func (c *GatewayController) SetupGatewayApiEventHandlers(numWorkers uint32) { utils.AviLog.Debugf("key: %s, msg: same resource version returning", key) return } - if !IsValidGateway(key, gw) { + valid, allowedRoutesAll := IsValidGateway(key, gw) + if !valid { return } + listRoutes, err := validateReferredHTTPRoute(key, allowedRoutesAll, gw) + if err != nil { + utils.AviLog.Errorf("Validation of Referred HTTPRoutes Failed due to error : %s", err.Error()) + } namespace, _, _ := cache.SplitMetaNamespaceKey(utils.ObjKey(gw)) bkt := utils.Bkt(namespace, numWorkers) c.workqueue[bkt].AddRateLimited(key) utils.AviLog.Debugf("key: %s, msg: ADD", key) + for _, route := range listRoutes { + key := lib.HTTPRoute + "/" + utils.ObjKey(route) + c.workqueue[bkt].AddRateLimited(key) + utils.AviLog.Debugf("key: %s, msg: UPDATE", key) + } }, DeleteFunc: func(obj interface{}) { if c.DisableSync { @@ -542,13 +555,23 @@ func (c *GatewayController) SetupGatewayApiEventHandlers(numWorkers uint32) { gw := obj.(*gatewayv1.Gateway) if IsGatewayUpdated(oldGw, gw) { key := lib.Gateway + "/" + utils.ObjKey(gw) - if !IsValidGateway(key, gw) { + valid, allowedRoutesAll := IsValidGateway(key, gw) + if !valid { return } + listRoutes, err := validateReferredHTTPRoute(key, allowedRoutesAll, gw) + if err != nil { + utils.AviLog.Errorf("Validation of Referred HTTPRoutes Failed due to error : %s", err.Error()) + } namespace, _, _ := cache.SplitMetaNamespaceKey(utils.ObjKey(gw)) bkt := utils.Bkt(namespace, numWorkers) c.workqueue[bkt].AddRateLimited(key) utils.AviLog.Debugf("key: %s, msg: UPDATE", key) + for _, route := range listRoutes { + key := lib.HTTPRoute + "/" + utils.ObjKey(route) + c.workqueue[bkt].AddRateLimited(key) + utils.AviLog.Debugf("key: %s, msg: UPDATE", key) + } } }, } @@ -714,3 +737,31 @@ func validateAviConfigMap(obj interface{}) (*corev1.ConfigMap, bool) { } return nil, false } +func validateReferredHTTPRoute(key string, allowedRoutesAll bool, gateway *gatewayv1.Gateway) ([]*gatewayv1.HTTPRoute, error) { + namespace := gateway.Namespace + if allowedRoutesAll { + namespace = metav1.NamespaceAll + } + hrObjs, err := akogatewayapilib.AKOControlConfig().GatewayApiInformers().HTTPRouteInformer.Lister().HTTPRoutes(namespace).List(labels.Set(nil).AsSelector()) + httpRoutes := make([]*gatewayv1.HTTPRoute, 0) + if err != nil { + return nil, err + } + for _, httpRoute := range hrObjs { + for _, parentRef := range httpRoute.Spec.ParentRefs { + if parentRef.Name == gatewayv1.ObjectName(gateway.Name) { + if IsHTTPRouteConfigValid(key, httpRoute) { + httpRoutes = append(httpRoutes, httpRoute) + } + break + } + } + } + sort.Slice(httpRoutes, func(i, j int) bool { + if httpRoutes[i].GetCreationTimestamp().Unix() == httpRoutes[j].GetCreationTimestamp().Unix() { + return httpRoutes[i].Namespace+"/"+httpRoutes[i].Name < httpRoutes[j].Namespace+"/"+httpRoutes[j].Name + } + return httpRoutes[i].GetCreationTimestamp().Unix() < httpRoutes[j].GetCreationTimestamp().Unix() + }) + return httpRoutes, nil +} diff --git a/ako-gateway-api/k8s/validator.go b/ako-gateway-api/k8s/validator.go index 69376f315..0638ba93f 100644 --- a/ako-gateway-api/k8s/validator.go +++ b/ako-gateway-api/k8s/validator.go @@ -50,9 +50,9 @@ func IsGatewayClassValid(key string, gatewayClass *gatewayv1.GatewayClass) bool return true } -func IsValidGateway(key string, gateway *gatewayv1.Gateway) bool { +func IsValidGateway(key string, gateway *gatewayv1.Gateway) (bool, bool) { spec := gateway.Spec - + allowedRoutesAll := false defaultCondition := akogatewayapistatus.NewCondition(). Type(string(gatewayv1.GatewayConditionAccepted)). Reason(string(gatewayv1.GatewayReasonInvalid)). @@ -76,7 +76,7 @@ func IsValidGateway(key string, gateway *gatewayv1.Gateway) bool { programmedCondition. SetIn(&gatewayStatus.Conditions) akogatewayapistatus.Record(key, gateway, &status.Status{GatewayStatus: gatewayStatus}) - return false + return false, allowedRoutesAll } // has 1 or none addresses @@ -89,7 +89,7 @@ func IsValidGateway(key string, gateway *gatewayv1.Gateway) bool { Reason(string(gatewayv1.GatewayReasonAddressNotUsable)). SetIn(&gatewayStatus.Conditions) akogatewayapistatus.Record(key, gateway, &status.Status{GatewayStatus: gatewayStatus}) - return false + return false, allowedRoutesAll } if len(spec.Addresses) == 1 && *spec.Addresses[0].Type != "IPAddress" { @@ -102,7 +102,7 @@ func IsValidGateway(key string, gateway *gatewayv1.Gateway) bool { Reason(string(gatewayv1.GatewayReasonAddressNotUsable)). SetIn(&gatewayStatus.Conditions) akogatewayapistatus.Record(key, gateway, &status.Status{GatewayStatus: gatewayStatus}) - return false + return false, allowedRoutesAll } gatewayStatus.Listeners = make([]gatewayv1.ListenerStatus, len(gateway.Spec.Listeners)) @@ -110,6 +110,13 @@ func IsValidGateway(key string, gateway *gatewayv1.Gateway) bool { var validListenerCount int for index := range spec.Listeners { if isValidListener(key, gateway, gatewayStatus, index) { + if !allowedRoutesAll { + if spec.Listeners[index].AllowedRoutes != nil && spec.Listeners[index].AllowedRoutes.Namespaces != nil && spec.Listeners[index].AllowedRoutes.Namespaces.From != nil { + if string(*spec.Listeners[index].AllowedRoutes.Namespaces.From) == akogatewayapilib.AllowedRoutesNamespaceFromAll { + allowedRoutesAll = true + } + } + } validListenerCount++ } } @@ -124,16 +131,16 @@ func IsValidGateway(key string, gateway *gatewayv1.Gateway) bool { programmedCondition. SetIn(&gatewayStatus.Conditions) akogatewayapistatus.Record(key, gateway, &status.Status{GatewayStatus: gatewayStatus}) - gateway.Status = *gatewayStatus.DeepCopy() - return false + return false, allowedRoutesAll } else if validListenerCount < len(spec.Listeners) { defaultCondition. Reason(string(gatewayv1.GatewayReasonListenersNotValid)). + Status(metav1.ConditionTrue). Message("Gateway contains atleast one valid listener"). SetIn(&gatewayStatus.Conditions) akogatewayapistatus.Record(key, gateway, &status.Status{GatewayStatus: gatewayStatus}) utils.AviLog.Infof("key: %s, msg: Gateway %s contains atleast one valid listener", key, gateway.Name) - return false + return false, allowedRoutesAll } defaultCondition. @@ -141,14 +148,9 @@ func IsValidGateway(key string, gateway *gatewayv1.Gateway) bool { Status(metav1.ConditionTrue). Message("Gateway configuration is valid"). SetIn(&gatewayStatus.Conditions) - _, err := akogatewayapistatus.Record(key, gateway, &status.Status{GatewayStatus: gatewayStatus}) + akogatewayapistatus.Record(key, gateway, &status.Status{GatewayStatus: gatewayStatus}) utils.AviLog.Infof("key: %s, msg: Gateway %s is valid", key, gateway.Name) - if err == nil { - return true - } else { - utils.AviLog.Errorf("key: %s, msg: Gateway status patch was not successful :%s ", key, err.Error()) - return false - } + return true, allowedRoutesAll } func isValidListener(key string, gateway *gatewayv1.Gateway, gatewayStatus *gatewayv1.GatewayStatus, index int) bool { diff --git a/ako-gateway-api/nodes/gateway_model.go b/ako-gateway-api/nodes/gateway_model.go index f574daa03..5fd5bb29d 100644 --- a/ako-gateway-api/nodes/gateway_model.go +++ b/ako-gateway-api/nodes/gateway_model.go @@ -23,6 +23,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" + akogatewayapiobjects "github.com/vmware/load-balancer-and-ingress-services-for-kubernetes/ako-gateway-api/objects" "github.com/vmware/load-balancer-and-ingress-services-for-kubernetes/internal/lib" "github.com/vmware/load-balancer-and-ingress-services-for-kubernetes/internal/nodes" "github.com/vmware/load-balancer-and-ingress-services-for-kubernetes/pkg/utils" @@ -77,8 +78,11 @@ func (o *AviObjectGraph) BuildGatewayParent(gateway *gatewayv1.Gateway, key stri func BuildPortProtocols(gateway *gatewayv1.Gateway, key string) []nodes.AviPortHostProtocol { var portProtocols []nodes.AviPortHostProtocol - for _, listener := range gateway.Spec.Listeners { - + gwStatus := akogatewayapiobjects.GatewayApiLister().GetGatewayToGatewayStatusMapping(gateway.Namespace + "/" + gateway.Name) + for i, listener := range gateway.Spec.Listeners { + if gwStatus.Listeners[i].Conditions[0].Type == string(gatewayv1.ListenerConditionAccepted) && gwStatus.Listeners[i].Conditions[0].Status == "False" { + continue + } pp := nodes.AviPortHostProtocol{Port: int32(listener.Port), Protocol: string(listener.Protocol)} //TLS config on listener is present if listener.TLS != nil && len(listener.TLS.CertificateRefs) > 0 { @@ -96,7 +100,11 @@ func BuildTLSNodesForGateway(gateway *gatewayv1.Gateway, key string) []*nodes.Av var tlsNodes []*nodes.AviTLSKeyCertNode var ns, name string cs := utils.GetInformers().ClientSet - for _, listener := range gateway.Spec.Listeners { + gwStatus := akogatewayapiobjects.GatewayApiLister().GetGatewayToGatewayStatusMapping(gateway.Namespace + "/" + gateway.Name) + for i, listener := range gateway.Spec.Listeners { + if gwStatus.Listeners[i].Conditions[0].Type == string(gatewayv1.ListenerConditionAccepted) && gwStatus.Listeners[i].Conditions[0].Status == "False" { + continue + } if listener.TLS != nil { for _, certRef := range listener.TLS.CertificateRefs { //kind is validated at ingestion @@ -161,7 +169,11 @@ func DeleteTLSNode(key string, object *AviObjectGraph, gateway *gatewayv1.Gatewa var tlsNodes []*nodes.AviTLSKeyCertNode _, _, secretName := lib.ExtractTypeNameNamespace(key) evhVsCertRefs := object.GetAviEvhVS()[0].SSLKeyCertRefs - for _, listener := range gateway.Spec.Listeners { + gwStatus := akogatewayapiobjects.GatewayApiLister().GetGatewayToGatewayStatusMapping(gateway.Namespace + "/" + gateway.Name) + for i, listener := range gateway.Spec.Listeners { + if gwStatus.Listeners[i].Conditions[0].Type == string(gatewayv1.ListenerConditionAccepted) && gwStatus.Listeners[i].Conditions[0].Status == "False" { + continue + } if listener.TLS != nil { for _, certRef := range listener.TLS.CertificateRefs { name := string(certRef.Name) @@ -188,7 +200,11 @@ func AddTLSNode(key string, object *AviObjectGraph, gateway *gatewayv1.Gateway, var tlsNodes []*nodes.AviTLSKeyCertNode _, _, secretName := lib.ExtractTypeNameNamespace(key) evhVsCertRefs := object.GetAviEvhVS()[0].SSLKeyCertRefs - for _, listener := range gateway.Spec.Listeners { + gwStatus := akogatewayapiobjects.GatewayApiLister().GetGatewayToGatewayStatusMapping(gateway.Namespace + "/" + gateway.Name) + for i, listener := range gateway.Spec.Listeners { + if gwStatus.Listeners[i].Conditions[0].Type == string(gatewayv1.ListenerConditionAccepted) && gwStatus.Listeners[i].Conditions[0].Status == "False" { + continue + } if listener.TLS != nil { for _, certRef := range listener.TLS.CertificateRefs { name := string(certRef.Name) diff --git a/ako-gateway-api/nodes/gateway_model_rel.go b/ako-gateway-api/nodes/gateway_model_rel.go index 35c100761..b16a0787e 100644 --- a/ako-gateway-api/nodes/gateway_model_rel.go +++ b/ako-gateway-api/nodes/gateway_model_rel.go @@ -19,7 +19,9 @@ import ( "fmt" "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/sets" + gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" akogatewayapilib "github.com/vmware/load-balancer-and-ingress-services-for-kubernetes/ako-gateway-api/lib" akogatewayapiobjects "github.com/vmware/load-balancer-and-ingress-services-for-kubernetes/ako-gateway-api/objects" @@ -126,8 +128,12 @@ func GatewayGetGw(namespace, name, key string) ([]string, bool) { hostnames := make(map[string]string, 0) var gwHostnames []string //var hostnames map[string]string + gwStatus := akogatewayapiobjects.GatewayApiLister().GetGatewayToGatewayStatusMapping(gwNsName) - for _, listenerObj := range gwObj.Spec.Listeners { + for i, listenerObj := range gwObj.Spec.Listeners { + if gwStatus.Listeners[i].Conditions[0].Type == string(gatewayv1.ListenerConditionAccepted) && gwStatus.Listeners[i].Conditions[0].Status != "True" { + continue + } gwListener := akogatewayapiobjects.GatewayListenerStore{} gwListener.Name = string(listenerObj.Name) gwListener.Gateway = gwNsName @@ -258,7 +264,20 @@ func HTTPRouteToGateway(namespace, name, key string) ([]string, bool) { var gatewayList []string var gwNsNameList []string parentNameToHostnameMap := make(map[string][]string) + statusIndex := 0 for _, parentRef := range hrObj.Spec.ParentRefs { + if statusIndex >= len(hrObj.Status.Parents) { + break + } + if hrObj.Status.RouteStatus.Parents[statusIndex].ParentRef.Name != parentRef.Name { + continue + } + for statusIndex < len(hrObj.Status.Parents) && (parentRef.SectionName != nil && *hrObj.Status.RouteStatus.Parents[statusIndex].ParentRef.SectionName != *parentRef.SectionName) { + statusIndex += 1 + } + if hrObj.Status.Parents[statusIndex].Conditions[0].Type == string(gatewayv1.RouteConditionAccepted) && hrObj.Status.Parents[statusIndex].Conditions[0].Status == metav1.ConditionFalse { + continue + } hostnameIntersection, _ := parentNameToHostnameMap[string(parentRef.Name)] ns := namespace if parentRef.Namespace != nil { @@ -332,6 +351,7 @@ func HTTPRouteToGateway(namespace, name, key string) ([]string, bool) { gwNsNameList = append(gwNsNameList, gwNsName) } parentNameToHostnameMap[string(parentRef.Name)] = hostnameIntersection + statusIndex += 1 } utils.AviLog.Debugf("key: %s, msg: Gateways retrieved %s", key, gwNsNameList) diff --git a/ako-gateway-api/nodes/route_validator.go b/ako-gateway-api/nodes/route_validator.go index 767dded9a..08b2fb92e 100644 --- a/ako-gateway-api/nodes/route_validator.go +++ b/ako-gateway-api/nodes/route_validator.go @@ -149,6 +149,17 @@ func validateParentReference(key string, httpRoute *gatewayv1.HTTPRoute, httpRou *parentRefIndexInHttpRouteStatus = *parentRefIndexInHttpRouteStatus + 1 return err } + if gwStatus.Listeners[i].Conditions[0].Type == string(gatewayv1.GatewayConditionAccepted) && gwStatus.Listeners[i].Conditions[0].Status == metav1.ConditionFalse { + // listener is present in gateway but is in invalid state + utils.AviLog.Errorf("key: %s, msg: Matching gateway listener %s in Parent Reference is in invalid state", key, listenerName) + err := fmt.Errorf("Matching gateway listener is in Invalid state") + defaultCondition. + Reason(string(gatewayv1.RouteReasonPending)). + Message(err.Error()). + SetIn(&httpRouteStatus.Parents[*parentRefIndexInHttpRouteStatus].Conditions) + *parentRefIndexInHttpRouteStatus = *parentRefIndexInHttpRouteStatus + 1 + return err + } listenersForRoute = append(listenersForRoute, gateway.Spec.Listeners[i]) } else { listenersForRoute = append(listenersForRoute, gateway.Spec.Listeners...) diff --git a/ako-gateway-api/status/gateway_status.go b/ako-gateway-api/status/gateway_status.go index f98c7be44..ae923ce68 100644 --- a/ako-gateway-api/status/gateway_status.go +++ b/ako-gateway-api/status/gateway_status.go @@ -18,7 +18,6 @@ import ( "context" "encoding/json" "errors" - "errors" "reflect" "strings" @@ -30,6 +29,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" + akogatewayapiobjects "github.com/vmware/load-balancer-and-ingress-services-for-kubernetes/ako-gateway-api/objects" "github.com/vmware/load-balancer-and-ingress-services-for-kubernetes/internal/status" "github.com/vmware/load-balancer-and-ingress-services-for-kubernetes/pkg/utils" ) @@ -145,7 +145,7 @@ func (o *gateway) Update(key string, option status.StatusOptions) { return } - gatewaystatus := gw.Status.DeepCopy() + gatewaystatus := akogatewayapiobjects.GatewayApiLister().GetGatewayToGatewayStatusMapping(gw.Namespace + "/" + gw.Name) addressType := gatewayv1.IPAddressType ipAddrs := []gatewayv1.GatewayStatusAddress{} for _, vip := range option.Options.Vip { @@ -178,15 +178,25 @@ func (o *gateway) Update(key string, option status.StatusOptions) { Message(message). SetIn(&gatewaystatus.Conditions) - for i := range gatewaystatus.Listeners { + for i, listener := range gatewaystatus.Listeners { listenerCondition := NewCondition() - listenerCondition. - Type(string(gatewayv1.ListenerConditionProgrammed)). - Status(conditionStatus). - Reason(string(gatewayv1.ListenerReasonProgrammed)). - ObservedGeneration(gw.ObjectMeta.Generation). - Message(message). - SetIn(&gatewaystatus.Listeners[i].Conditions) + if listener.Conditions[0].Type == string(gatewayv1.ListenerConditionAccepted) && listener.Conditions[0].Status == metav1.ConditionTrue && listener.Conditions[1].Type == string(gatewayv1.ListenerConditionResolvedRefs) && listener.Conditions[1].Status == metav1.ConditionTrue { + listenerCondition. + Type(string(gatewayv1.ListenerConditionProgrammed)). + Status(conditionStatus). + Reason(string(gatewayv1.ListenerReasonProgrammed)). + ObservedGeneration(gw.ObjectMeta.Generation). + Message(message). + SetIn(&gatewaystatus.Listeners[i].Conditions) + } else { + listenerCondition. + Type(string(gatewayv1.ListenerConditionProgrammed)). + Status(metav1.ConditionFalse). + Reason(string(gatewayv1.ListenerReasonInvalid)). + ObservedGeneration(gw.ObjectMeta.Generation). + Message("Virtual service not configured/updated for this listener"). + SetIn(&gatewaystatus.Listeners[i].Conditions) + } } o.Patch(key, gw, &status.Status{GatewayStatus: gatewaystatus}) @@ -238,7 +248,7 @@ func (o *gateway) Patch(key string, obj runtime.Object, status *status.Status, r patchPayload, _ := json.Marshal(map[string]interface{}{ "status": status.GatewayStatus, }) - updatedGateway, err := akogatewayapilib.AKOControlConfig().GatewayAPIClientset().GatewayV1().Gateways(gw.Namespace).Patch(context.TODO(), gw.Name, types.MergePatchType, patchPayload, metav1.PatchOptions{}, "status") + _, err := akogatewayapilib.AKOControlConfig().GatewayAPIClientset().GatewayV1().Gateways(gw.Namespace).Patch(context.TODO(), gw.Name, types.MergePatchType, patchPayload, metav1.PatchOptions{}, "status") if err != nil { utils.AviLog.Warnf("key: %s, msg: there was an error in updating the gateway status. err: %+v, retry: %d", key, err, retry) updatedGW, err := akogatewayapilib.AKOControlConfig().GatewayApiInformers().GatewayInformer.Lister().Gateways(gw.Namespace).Get(gw.Name) diff --git a/ako-gateway-api/status/gatewayclass_status.go b/ako-gateway-api/status/gatewayclass_status.go index 9756504e5..e312130d0 100644 --- a/ako-gateway-api/status/gatewayclass_status.go +++ b/ako-gateway-api/status/gatewayclass_status.go @@ -18,7 +18,6 @@ import ( "context" "encoding/json" "errors" - "errors" "reflect" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -92,7 +91,7 @@ func (o *gatewayClass) Patch(key string, obj runtime.Object, status *status.Stat patchPayload, _ := json.Marshal(map[string]interface{}{ "status": status.GatewayClassStatus, }) - updatedObject, err := akogatewayapilib.AKOControlConfig().GatewayAPIClientset().GatewayV1().GatewayClasses().Patch(context.TODO(), gatewayClass.Name, types.MergePatchType, patchPayload, metav1.PatchOptions{}, "status") + _, err := akogatewayapilib.AKOControlConfig().GatewayAPIClientset().GatewayV1().GatewayClasses().Patch(context.TODO(), gatewayClass.Name, types.MergePatchType, patchPayload, metav1.PatchOptions{}, "status") if err != nil { utils.AviLog.Warnf("key: %s, msg: there was an error in updating the GatewayClass status. err: %+v, retry: %d", key, err, retry) updatedObj, err := akogatewayapilib.AKOControlConfig().GatewayApiInformers().GatewayClassInformer.Lister().Get(gatewayClass.Name) diff --git a/ako-gateway-api/status/httproute_status.go b/ako-gateway-api/status/httproute_status.go index 07dbc20d4..99a528ed1 100644 --- a/ako-gateway-api/status/httproute_status.go +++ b/ako-gateway-api/status/httproute_status.go @@ -18,7 +18,6 @@ import ( "context" "encoding/json" "errors" - "errors" "reflect" "strings" @@ -103,7 +102,7 @@ func (o *httproute) Patch(key string, obj runtime.Object, status *status.Status, patchPayload, _ := json.Marshal(map[string]interface{}{ "status": status.HTTPRouteStatus, }) - updatedObject, err := akogatewayapilib.AKOControlConfig().GatewayAPIClientset().GatewayV1().HTTPRoutes(httpRoute.Namespace).Patch(context.TODO(), httpRoute.Name, types.MergePatchType, patchPayload, metav1.PatchOptions{}, "status") + _, err := akogatewayapilib.AKOControlConfig().GatewayAPIClientset().GatewayV1().HTTPRoutes(httpRoute.Namespace).Patch(context.TODO(), httpRoute.Name, types.MergePatchType, patchPayload, metav1.PatchOptions{}, "status") if err != nil { utils.AviLog.Warnf("key: %s, msg: there was an error in updating the HTTPRoute status. err: %+v, retry: %d", key, err, retry) updatedObj, err := akogatewayapilib.AKOControlConfig().GatewayApiInformers().HTTPRouteInformer.Lister().HTTPRoutes(httpRoute.Namespace).Get(httpRoute.Name) diff --git a/ako-gateway-api/status/status.go b/ako-gateway-api/status/status.go index 5fde5a032..7f7d2a58c 100644 --- a/ako-gateway-api/status/status.go +++ b/ako-gateway-api/status/status.go @@ -15,13 +15,9 @@ package status import ( - "errors" - - corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/runtime" gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" - akogatewayapilib "github.com/vmware/load-balancer-and-ingress-services-for-kubernetes/ako-gateway-api/lib" akogatewayapiobjects "github.com/vmware/load-balancer-and-ingress-services-for-kubernetes/ako-gateway-api/objects" "github.com/vmware/load-balancer-and-ingress-services-for-kubernetes/internal/lib" "github.com/vmware/load-balancer-and-ingress-services-for-kubernetes/internal/status" @@ -101,7 +97,7 @@ func Record(key string, obj runtime.Object, objStatus *status.Status) { key = serviceMetadata.HTTPRoute default: utils.AviLog.Warnf("key %s, msg: Unsupported object received at the status layer, %T", key, obj) - return obj, errors.New("Unsupported object received at the status layer") + return } updateOption.Status = objStatus updateOption.ServiceMetadata = serviceMetadata diff --git a/tests/gatewayapitests/graphlayer/httproute_test.go b/tests/gatewayapitests/graphlayer/httproute_test.go index 88528ba34..3580c2f49 100644 --- a/tests/gatewayapitests/graphlayer/httproute_test.go +++ b/tests/gatewayapitests/graphlayer/httproute_test.go @@ -1417,3 +1417,986 @@ func TestHTTPRouteParentFQDN(t *testing.T) { akogatewayapitests.TeardownGateway(t, gatewayName1, DEFAULT_NAMESPACE) akogatewayapitests.TeardownGatewayClass(t, gatewayClassName) } +func TestHttpRouteWithValidAndInvalidGatewayListeners(t *testing.T) { + gatewayName := "gateway-hr-08" + gatewayClassName := "gateway-class-hr-08" + httpRouteName := "http-route-hr-08" + svcName1 := "avisvc-hr-08-a" + svcName2 := "avisvc-hr-08-b" + ports := []int32{8080, 8081} + modelName, _ := akogatewayapitests.GetModelName(DEFAULT_NAMESPACE, gatewayName) + + akogatewayapitests.SetupGatewayClass(t, gatewayClassName, akogatewayapilib.GatewayController) + listeners := akogatewayapitests.GetListenersV1(ports, false, false) + listeners[1].Protocol = "TCP" + akogatewayapitests.SetupGateway(t, gatewayName, DEFAULT_NAMESPACE, gatewayClassName, nil, listeners) + + g := gomega.NewGomegaWithT(t) + + g.Eventually(func() bool { + found, _ := objects.SharedAviGraphLister().Get(modelName) + return found + }, 25*time.Second).Should(gomega.Equal(true)) + + integrationtest.CreateSVC(t, DEFAULT_NAMESPACE, svcName1, corev1.ProtocolTCP, corev1.ServiceTypeClusterIP, false) + integrationtest.CreateEP(t, DEFAULT_NAMESPACE, svcName1, false, false, "1.2.3") + + integrationtest.CreateSVC(t, DEFAULT_NAMESPACE, svcName2, corev1.ProtocolTCP, corev1.ServiceTypeClusterIP, false) + integrationtest.CreateEP(t, DEFAULT_NAMESPACE, svcName2, false, false, "1.2.3") + + parentRefs := akogatewayapitests.GetParentReferencesV1([]string{gatewayName}, DEFAULT_NAMESPACE, ports) + rule1 := akogatewayapitests.GetHTTPRouteRuleV1([]string{"/foo"}, []string{}, + map[string][]string{"RequestHeaderModifier": {"add", "remove", "replace"}}, + [][]string{{svcName1, DEFAULT_NAMESPACE, "8080", "1"}}, nil) + rule2 := akogatewayapitests.GetHTTPRouteRuleV1([]string{"/bar"}, []string{}, + map[string][]string{"RequestHeaderModifier": {"add", "remove", "replace"}}, + [][]string{{svcName2, DEFAULT_NAMESPACE, "8081", "1"}}, nil) + rules := []gatewayv1.HTTPRouteRule{rule1, rule2} + + hostnames := []gatewayv1.Hostname{"foo-8080.com", "foo-8081.com"} + akogatewayapitests.SetupHTTPRoute(t, httpRouteName, DEFAULT_NAMESPACE, parentRefs, hostnames, rules) + + g.Eventually(func() int { + found, aviModel := objects.SharedAviGraphLister().Get(modelName) + if !found { + return 0 + } + nodes := aviModel.(*avinodes.AviObjectGraph).GetAviEvhVS() + return len(nodes[0].EvhNodes) + }, 50*time.Second).Should(gomega.Equal(2)) + + _, aviModel := objects.SharedAviGraphLister().Get(modelName) + nodes := aviModel.(*avinodes.AviObjectGraph).GetAviEvhVS() + + childNode1 := nodes[0].EvhNodes[0] + g.Expect(childNode1.PoolGroupRefs).To(gomega.HaveLen(1)) + g.Expect(childNode1.PoolGroupRefs[0].Members).To(gomega.HaveLen(1)) + g.Expect(childNode1.DefaultPoolGroup).NotTo(gomega.Equal("")) + g.Expect(childNode1.PoolRefs).To(gomega.HaveLen(1)) + g.Expect(childNode1.PoolRefs[0].Port).To(gomega.Equal(int32(8080))) + g.Expect(len(childNode1.PoolRefs[0].Servers)).To(gomega.Equal(1)) + g.Expect(len(childNode1.VHMatches)).To(gomega.Equal(1)) + g.Expect(*childNode1.VHMatches[0].Host).To(gomega.Equal("foo-8080.com")) + g.Expect(len(childNode1.VHMatches[0].Rules)).To(gomega.Equal(1)) + g.Expect(childNode1.VHMatches[0].Rules[0].Matches.Path.MatchStr[0]).To(gomega.Equal("/foo")) + g.Expect(len(childNode1.VHMatches[0].Rules[0].Matches.VsPort.Ports)).To(gomega.Equal(1)) + g.Expect(childNode1.VHMatches[0].Rules[0].Matches.VsPort.Ports[0]).To(gomega.Equal(int64(8080))) + + childNode2 := nodes[0].EvhNodes[1] + g.Expect(childNode2.PoolGroupRefs).To(gomega.HaveLen(1)) + g.Expect(childNode2.PoolGroupRefs[0].Members).To(gomega.HaveLen(1)) + g.Expect(childNode2.DefaultPoolGroup).NotTo(gomega.Equal("")) + g.Expect(childNode2.PoolRefs).To(gomega.HaveLen(1)) + g.Expect(childNode2.PoolRefs[0].Port).To(gomega.Equal(int32(8080))) + g.Expect(len(childNode2.PoolRefs[0].Servers)).To(gomega.Equal(1)) + g.Expect(len(childNode2.VHMatches)).To(gomega.Equal(1)) + g.Expect(*childNode2.VHMatches[0].Host).To(gomega.Equal("foo-8080.com")) + g.Expect(len(childNode2.VHMatches[0].Rules)).To(gomega.Equal(1)) + g.Expect(childNode2.VHMatches[0].Rules[0].Matches.Path.MatchStr[0]).To(gomega.Equal("/bar")) + g.Expect(len(childNode2.VHMatches[0].Rules[0].Matches.VsPort.Ports)).To(gomega.Equal(1)) + g.Expect(childNode2.VHMatches[0].Rules[0].Matches.VsPort.Ports[0]).To(gomega.Equal(int64(8080))) + + integrationtest.DelSVC(t, DEFAULT_NAMESPACE, svcName1) + integrationtest.DelEP(t, DEFAULT_NAMESPACE, svcName1) + integrationtest.DelSVC(t, DEFAULT_NAMESPACE, svcName2) + integrationtest.DelEP(t, DEFAULT_NAMESPACE, svcName2) + akogatewayapitests.TeardownHTTPRoute(t, httpRouteName, DEFAULT_NAMESPACE) + akogatewayapitests.TeardownGateway(t, gatewayName, DEFAULT_NAMESPACE) + akogatewayapitests.TeardownGatewayClass(t, gatewayClassName) +} + +func TestMultipleHttpRoutesWithValidAndInvalidGatewayListeners(t *testing.T) { + gatewayName := "gateway-hr-09" + gatewayClassName := "gateway-class-hr-09" + httpRouteName1 := "http-route-hr-09-a" + httpRouteName2 := "http-route-hr-09-b" + svcName := "avisvc-hr-09" + ports := []int32{8080, 8081} + modelName, _ := akogatewayapitests.GetModelName(DEFAULT_NAMESPACE, gatewayName) + + akogatewayapitests.SetupGatewayClass(t, gatewayClassName, akogatewayapilib.GatewayController) + listeners := akogatewayapitests.GetListenersV1(ports, false, false) + listeners[1].Protocol = "TCP" + akogatewayapitests.SetupGateway(t, gatewayName, DEFAULT_NAMESPACE, gatewayClassName, nil, listeners) + + g := gomega.NewGomegaWithT(t) + + g.Eventually(func() bool { + found, _ := objects.SharedAviGraphLister().Get(modelName) + return found + }, 25*time.Second).Should(gomega.Equal(true)) + + integrationtest.CreateSVC(t, DEFAULT_NAMESPACE, svcName, corev1.ProtocolTCP, corev1.ServiceTypeClusterIP, false) + integrationtest.CreateEP(t, DEFAULT_NAMESPACE, svcName, false, false, "1.2.3") + + parentRefs1 := akogatewayapitests.GetParentReferencesV1([]string{gatewayName}, DEFAULT_NAMESPACE, []int32{ports[0]}) + rule1 := akogatewayapitests.GetHTTPRouteRuleV1([]string{"/foo"}, []string{}, + map[string][]string{"RequestHeaderModifier": {"add", "remove", "replace"}}, + [][]string{{svcName, DEFAULT_NAMESPACE, "8080", "1"}}, nil) + rules1 := []gatewayv1.HTTPRouteRule{rule1} + hostnames1 := []gatewayv1.Hostname{"foo-8080.com"} + akogatewayapitests.SetupHTTPRoute(t, httpRouteName1, DEFAULT_NAMESPACE, parentRefs1, hostnames1, rules1) + + parentRefs2 := akogatewayapitests.GetParentReferencesV1([]string{gatewayName}, DEFAULT_NAMESPACE, []int32{ports[1]}) + rule2 := akogatewayapitests.GetHTTPRouteRuleV1([]string{"/bar"}, []string{}, + map[string][]string{"RequestHeaderModifier": {"add", "remove", "replace"}}, + [][]string{{svcName, DEFAULT_NAMESPACE, "8081", "1"}}, nil) + rules2 := []gatewayv1.HTTPRouteRule{rule2} + hostnames2 := []gatewayv1.Hostname{"foo-8081.com"} + akogatewayapitests.SetupHTTPRoute(t, httpRouteName2, DEFAULT_NAMESPACE, parentRefs2, hostnames2, rules2) + + g.Eventually(func() int { + found, aviModel := objects.SharedAviGraphLister().Get(modelName) + if !found { + return 0 + } + nodes := aviModel.(*avinodes.AviObjectGraph).GetAviEvhVS() + return len(nodes[0].EvhNodes) + }, 30*time.Second).Should(gomega.Equal(1)) + + _, aviModel := objects.SharedAviGraphLister().Get(modelName) + nodes := aviModel.(*avinodes.AviObjectGraph).GetAviEvhVS() + + childNode1 := nodes[0].EvhNodes[0] + g.Expect(childNode1.PoolGroupRefs).To(gomega.HaveLen(1)) + g.Expect(childNode1.PoolGroupRefs[0].Members).To(gomega.HaveLen(1)) + g.Expect(childNode1.DefaultPoolGroup).NotTo(gomega.Equal("")) + g.Expect(childNode1.PoolRefs).To(gomega.HaveLen(1)) + g.Expect(childNode1.PoolRefs[0].Port).To(gomega.Equal(int32(8080))) + g.Expect(len(childNode1.PoolRefs[0].Servers)).To(gomega.Equal(1)) + g.Expect(len(childNode1.VHMatches)).To(gomega.Equal(1)) + g.Expect(*childNode1.VHMatches[0].Host).To(gomega.Equal("foo-8080.com")) + g.Expect(len(childNode1.VHMatches[0].Rules)).To(gomega.Equal(1)) + g.Expect(childNode1.VHMatches[0].Rules[0].Matches.Path.MatchStr[0]).To(gomega.Equal("/foo")) + g.Expect(len(childNode1.VHMatches[0].Rules[0].Matches.VsPort.Ports)).To(gomega.Equal(1)) + g.Expect(childNode1.VHMatches[0].Rules[0].Matches.VsPort.Ports[0]).To(gomega.Equal(int64(8080))) + + integrationtest.DelSVC(t, DEFAULT_NAMESPACE, svcName) + integrationtest.DelEP(t, DEFAULT_NAMESPACE, svcName) + akogatewayapitests.TeardownHTTPRoute(t, httpRouteName1, DEFAULT_NAMESPACE) + akogatewayapitests.TeardownHTTPRoute(t, httpRouteName2, DEFAULT_NAMESPACE) + akogatewayapitests.TeardownGateway(t, gatewayName, DEFAULT_NAMESPACE) + akogatewayapitests.TeardownGatewayClass(t, gatewayClassName) +} +func TestTransitionsHttpRouteWithPartiallyValidGatewayToValidGateway(t *testing.T) { + //1: One HTTPRoute with partially valid gateway + gatewayName := "gateway-hr-10" + gatewayClassName := "gateway-class-hr-10" + httpRouteName := "http-route-hr-10" + svcName1 := "avisvc-hr-10-a" + svcName2 := "avisvc-hr-10-b" + ports := []int32{8080, 8081} + modelName, _ := akogatewayapitests.GetModelName(DEFAULT_NAMESPACE, gatewayName) + + akogatewayapitests.SetupGatewayClass(t, gatewayClassName, akogatewayapilib.GatewayController) + listeners := akogatewayapitests.GetListenersV1(ports, false, false) + listeners[1].Protocol = "TCP" + akogatewayapitests.SetupGateway(t, gatewayName, DEFAULT_NAMESPACE, gatewayClassName, nil, listeners) + + g := gomega.NewGomegaWithT(t) + + g.Eventually(func() bool { + found, _ := objects.SharedAviGraphLister().Get(modelName) + return found + }, 25*time.Second).Should(gomega.Equal(true)) + + integrationtest.CreateSVC(t, DEFAULT_NAMESPACE, svcName1, corev1.ProtocolTCP, corev1.ServiceTypeClusterIP, false) + integrationtest.CreateEP(t, DEFAULT_NAMESPACE, svcName1, false, false, "1.2.3") + + integrationtest.CreateSVC(t, DEFAULT_NAMESPACE, svcName2, corev1.ProtocolTCP, corev1.ServiceTypeClusterIP, false) + integrationtest.CreateEP(t, DEFAULT_NAMESPACE, svcName2, false, false, "1.2.3") + + parentRefs := akogatewayapitests.GetParentReferencesV1([]string{gatewayName}, DEFAULT_NAMESPACE, ports) + rule1 := akogatewayapitests.GetHTTPRouteRuleV1([]string{"/foo"}, []string{}, + map[string][]string{"RequestHeaderModifier": {"add", "remove", "replace"}}, + [][]string{{svcName1, DEFAULT_NAMESPACE, "8080", "1"}}, nil) + rule2 := akogatewayapitests.GetHTTPRouteRuleV1([]string{"/bar"}, []string{}, + map[string][]string{"RequestHeaderModifier": {"add", "remove", "replace"}}, + [][]string{{svcName2, DEFAULT_NAMESPACE, "8081", "1"}}, nil) + rules := []gatewayv1.HTTPRouteRule{rule1, rule2} + + hostnames := []gatewayv1.Hostname{"foo-8080.com", "foo-8081.com"} + akogatewayapitests.SetupHTTPRoute(t, httpRouteName, DEFAULT_NAMESPACE, parentRefs, hostnames, rules) + + g.Eventually(func() int { + found, aviModel := objects.SharedAviGraphLister().Get(modelName) + if !found { + return 0 + } + nodes := aviModel.(*avinodes.AviObjectGraph).GetAviEvhVS() + return len(nodes[0].EvhNodes) + }, 50*time.Second).Should(gomega.Equal(2)) + + _, aviModel := objects.SharedAviGraphLister().Get(modelName) + nodes := aviModel.(*avinodes.AviObjectGraph).GetAviEvhVS() + + childNode1 := nodes[0].EvhNodes[0] + g.Expect(childNode1.PoolGroupRefs).To(gomega.HaveLen(1)) + g.Expect(childNode1.PoolGroupRefs[0].Members).To(gomega.HaveLen(1)) + g.Expect(childNode1.DefaultPoolGroup).NotTo(gomega.Equal("")) + g.Expect(childNode1.PoolRefs).To(gomega.HaveLen(1)) + g.Expect(childNode1.PoolRefs[0].Port).To(gomega.Equal(int32(8080))) + g.Expect(len(childNode1.PoolRefs[0].Servers)).To(gomega.Equal(1)) + g.Expect(len(childNode1.VHMatches)).To(gomega.Equal(1)) + g.Expect(*childNode1.VHMatches[0].Host).To(gomega.Equal("foo-8080.com")) + g.Expect(len(childNode1.VHMatches[0].Rules)).To(gomega.Equal(1)) + g.Expect(childNode1.VHMatches[0].Rules[0].Matches.Path.MatchStr[0]).To(gomega.Equal("/foo")) + g.Expect(len(childNode1.VHMatches[0].Rules[0].Matches.VsPort.Ports)).To(gomega.Equal(1)) + g.Expect(childNode1.VHMatches[0].Rules[0].Matches.VsPort.Ports[0]).To(gomega.Equal(int64(8080))) + + childNode2 := nodes[0].EvhNodes[1] + g.Expect(childNode2.PoolGroupRefs).To(gomega.HaveLen(1)) + g.Expect(childNode2.PoolGroupRefs[0].Members).To(gomega.HaveLen(1)) + g.Expect(childNode2.DefaultPoolGroup).NotTo(gomega.Equal("")) + g.Expect(childNode2.PoolRefs).To(gomega.HaveLen(1)) + g.Expect(childNode2.PoolRefs[0].Port).To(gomega.Equal(int32(8080))) + g.Expect(len(childNode2.PoolRefs[0].Servers)).To(gomega.Equal(1)) + g.Expect(len(childNode2.VHMatches)).To(gomega.Equal(1)) + g.Expect(*childNode2.VHMatches[0].Host).To(gomega.Equal("foo-8080.com")) + g.Expect(len(childNode2.VHMatches[0].Rules)).To(gomega.Equal(1)) + g.Expect(childNode2.VHMatches[0].Rules[0].Matches.Path.MatchStr[0]).To(gomega.Equal("/bar")) + g.Expect(len(childNode2.VHMatches[0].Rules[0].Matches.VsPort.Ports)).To(gomega.Equal(1)) + g.Expect(childNode2.VHMatches[0].Rules[0].Matches.VsPort.Ports[0]).To(gomega.Equal(int64(8080))) + + listeners[1].Protocol = "HTTPS" + akogatewayapitests.UpdateGateway(t, gatewayName, DEFAULT_NAMESPACE, gatewayClassName, nil, listeners) + + g.Eventually(func() bool { + gateway, err := akogatewayapitests.GatewayClient.GatewayV1().Gateways(DEFAULT_NAMESPACE).Get(context.TODO(), gatewayName, metav1.GetOptions{}) + if err != nil || gateway == nil { + t.Logf("Couldn't get the gateway, err: %+v", err) + return false + } + if len(gateway.Status.Listeners) < 2 { + return false + } + return gateway.Status.Listeners[1].Conditions[0].Status == metav1.ConditionTrue + //apimeta.FindStatusCondition(gateway.Status.Conditions, string(gatewayv1.GatewayConditionAccepted)) != nil + }, 30*time.Second).Should(gomega.Equal(true)) + + gateway, _ := akogatewayapitests.GatewayClient.GatewayV1().Gateways(DEFAULT_NAMESPACE).Get(context.TODO(), gatewayName, metav1.GetOptions{}) + g.Expect(gateway.Status.Listeners[1].Conditions[0].Status).To(gomega.Equal(metav1.ConditionTrue)) + g.Eventually(func() int { + found, aviModel := objects.SharedAviGraphLister().Get(modelName) + if !found { + return 0 + } + nodes = aviModel.(*avinodes.AviObjectGraph).GetAviEvhVS() + if len(nodes[0].EvhNodes) != 2 { + return 0 + } + return len(nodes[0].EvhNodes[0].VHMatches) + }, 30*time.Second).Should(gomega.Equal(2)) + + g.Eventually(func() int { + found, aviModel := objects.SharedAviGraphLister().Get(modelName) + if !found { + return 0 + } + nodes = aviModel.(*avinodes.AviObjectGraph).GetAviEvhVS() + if len(nodes[0].EvhNodes) != 2 { + return 0 + } + return len(nodes[0].EvhNodes[1].VHMatches) + }, 30*time.Second).Should(gomega.Equal(2)) + time.Sleep(20 * time.Second) + + _, aviModel = objects.SharedAviGraphLister().Get(modelName) + nodes = aviModel.(*avinodes.AviObjectGraph).GetAviEvhVS() + + childNode1 = nodes[0].EvhNodes[0] + g.Expect(childNode1.PoolGroupRefs).To(gomega.HaveLen(1)) + g.Expect(childNode1.PoolGroupRefs[0].Members).To(gomega.HaveLen(1)) + g.Expect(childNode1.DefaultPoolGroup).NotTo(gomega.Equal("")) + g.Expect(childNode1.PoolRefs).To(gomega.HaveLen(1)) + g.Expect(childNode1.PoolRefs[0].Port).To(gomega.Equal(int32(8080))) + g.Expect(len(childNode1.PoolRefs[0].Servers)).To(gomega.Equal(1)) + g.Expect(len(childNode1.VHMatches)).To(gomega.Equal(2)) + g.Expect(*childNode1.VHMatches[0].Host).To(gomega.Equal("foo-8080.com")) + g.Expect(len(childNode1.VHMatches[0].Rules)).To(gomega.Equal(1)) + g.Expect(childNode1.VHMatches[0].Rules[0].Matches.Path.MatchStr[0]).To(gomega.Equal("/foo")) + g.Expect(len(childNode1.VHMatches[0].Rules[0].Matches.VsPort.Ports)).To(gomega.Equal(2)) + g.Expect(childNode1.VHMatches[0].Rules[0].Matches.VsPort.Ports[0]).To(gomega.Equal(int64(8080))) + g.Expect(childNode1.VHMatches[0].Rules[0].Matches.VsPort.Ports[1]).To(gomega.Equal(int64(8081))) + g.Expect(*childNode1.VHMatches[1].Host).To(gomega.Equal("foo-8081.com")) + g.Expect(len(childNode1.VHMatches[1].Rules)).To(gomega.Equal(1)) + g.Expect(childNode1.VHMatches[1].Rules[0].Matches.Path.MatchStr[0]).To(gomega.Equal("/foo")) + g.Expect(len(childNode1.VHMatches[1].Rules[0].Matches.VsPort.Ports)).To(gomega.Equal(2)) + g.Expect(childNode1.VHMatches[1].Rules[0].Matches.VsPort.Ports[0]).To(gomega.Equal(int64(8080))) + g.Expect(childNode1.VHMatches[1].Rules[0].Matches.VsPort.Ports[1]).To(gomega.Equal(int64(8081))) + + childNode2 = nodes[0].EvhNodes[1] + g.Expect(childNode2.PoolGroupRefs).To(gomega.HaveLen(1)) + g.Expect(childNode2.PoolGroupRefs[0].Members).To(gomega.HaveLen(1)) + g.Expect(childNode2.DefaultPoolGroup).NotTo(gomega.Equal("")) + g.Expect(childNode2.PoolRefs).To(gomega.HaveLen(1)) + g.Expect(childNode2.PoolRefs[0].Port).To(gomega.Equal(int32(8080))) + g.Expect(len(childNode2.PoolRefs[0].Servers)).To(gomega.Equal(1)) + g.Expect(len(childNode2.VHMatches)).To(gomega.Equal(2)) + g.Expect(*childNode2.VHMatches[0].Host).To(gomega.Equal("foo-8080.com")) + g.Expect(len(childNode2.VHMatches[0].Rules)).To(gomega.Equal(1)) + g.Expect(childNode2.VHMatches[0].Rules[0].Matches.Path.MatchStr[0]).To(gomega.Equal("/bar")) + g.Expect(len(childNode2.VHMatches[0].Rules[0].Matches.VsPort.Ports)).To(gomega.Equal(2)) + g.Expect(childNode2.VHMatches[0].Rules[0].Matches.VsPort.Ports[0]).To(gomega.Equal(int64(8080))) + g.Expect(childNode2.VHMatches[0].Rules[0].Matches.VsPort.Ports[1]).To(gomega.Equal(int64(8081))) + g.Expect(*childNode2.VHMatches[1].Host).To(gomega.Equal("foo-8081.com")) + g.Expect(len(childNode2.VHMatches[1].Rules)).To(gomega.Equal(1)) + g.Expect(childNode2.VHMatches[1].Rules[0].Matches.Path.MatchStr[0]).To(gomega.Equal("/bar")) + g.Expect(len(childNode2.VHMatches[1].Rules[0].Matches.VsPort.Ports)).To(gomega.Equal(2)) + g.Expect(childNode2.VHMatches[1].Rules[0].Matches.VsPort.Ports[0]).To(gomega.Equal(int64(8080))) + g.Expect(childNode2.VHMatches[1].Rules[0].Matches.VsPort.Ports[1]).To(gomega.Equal(int64(8081))) + + integrationtest.DelSVC(t, DEFAULT_NAMESPACE, svcName1) + integrationtest.DelEP(t, DEFAULT_NAMESPACE, svcName1) + integrationtest.DelSVC(t, DEFAULT_NAMESPACE, svcName2) + integrationtest.DelEP(t, DEFAULT_NAMESPACE, svcName2) + akogatewayapitests.TeardownHTTPRoute(t, httpRouteName, DEFAULT_NAMESPACE) + akogatewayapitests.TeardownGateway(t, gatewayName, DEFAULT_NAMESPACE) + akogatewayapitests.TeardownGatewayClass(t, gatewayClassName) +} + +func TestTransitionsHttpRouteWithPartiallyValidGatewayToInvalidGateway(t *testing.T) { + t.Skip("Skipping since current implementation is not supporting partially Valid to Invalid gateway transition") + gatewayName := "gateway-hr-11" + gatewayClassName := "gateway-class-hr-11" + httpRouteName := "http-route-hr-11" + svcName1 := "avisvc-hr-11-a" + svcName2 := "avisvc-hr-11-b" + ports := []int32{8080, 8081} + modelName, _ := akogatewayapitests.GetModelName(DEFAULT_NAMESPACE, gatewayName) + + akogatewayapitests.SetupGatewayClass(t, gatewayClassName, akogatewayapilib.GatewayController) + listeners := akogatewayapitests.GetListenersV1(ports, false, false) + listeners[1].Protocol = "TCP" + akogatewayapitests.SetupGateway(t, gatewayName, DEFAULT_NAMESPACE, gatewayClassName, nil, listeners) + + g := gomega.NewGomegaWithT(t) + + g.Eventually(func() bool { + found, _ := objects.SharedAviGraphLister().Get(modelName) + return found + }, 25*time.Second).Should(gomega.Equal(true)) + + integrationtest.CreateSVC(t, DEFAULT_NAMESPACE, svcName1, corev1.ProtocolTCP, corev1.ServiceTypeClusterIP, false) + integrationtest.CreateEP(t, DEFAULT_NAMESPACE, svcName1, false, false, "1.2.3") + + integrationtest.CreateSVC(t, DEFAULT_NAMESPACE, svcName2, corev1.ProtocolTCP, corev1.ServiceTypeClusterIP, false) + integrationtest.CreateEP(t, DEFAULT_NAMESPACE, svcName2, false, false, "1.2.3") + + parentRefs := akogatewayapitests.GetParentReferencesV1([]string{gatewayName}, DEFAULT_NAMESPACE, ports) + rule1 := akogatewayapitests.GetHTTPRouteRuleV1([]string{"/foo"}, []string{}, + map[string][]string{"RequestHeaderModifier": {"add", "remove", "replace"}}, + [][]string{{svcName1, DEFAULT_NAMESPACE, "8080", "1"}}, nil) + rule2 := akogatewayapitests.GetHTTPRouteRuleV1([]string{"/bar"}, []string{}, + map[string][]string{"RequestHeaderModifier": {"add", "remove", "replace"}}, + [][]string{{svcName2, DEFAULT_NAMESPACE, "8081", "1"}}, nil) + rules := []gatewayv1.HTTPRouteRule{rule1, rule2} + + hostnames := []gatewayv1.Hostname{"foo-8080.com", "foo-8081.com"} + akogatewayapitests.SetupHTTPRoute(t, httpRouteName, DEFAULT_NAMESPACE, parentRefs, hostnames, rules) + + g.Eventually(func() int { + found, aviModel := objects.SharedAviGraphLister().Get(modelName) + if !found { + return 0 + } + nodes := aviModel.(*avinodes.AviObjectGraph).GetAviEvhVS() + return len(nodes[0].EvhNodes) + }, 50*time.Second).Should(gomega.Equal(2)) + + _, aviModel := objects.SharedAviGraphLister().Get(modelName) + nodes := aviModel.(*avinodes.AviObjectGraph).GetAviEvhVS() + + childNode1 := nodes[0].EvhNodes[0] + g.Expect(childNode1.PoolGroupRefs).To(gomega.HaveLen(1)) + g.Expect(childNode1.PoolGroupRefs[0].Members).To(gomega.HaveLen(1)) + g.Expect(childNode1.DefaultPoolGroup).NotTo(gomega.Equal("")) + g.Expect(childNode1.PoolRefs).To(gomega.HaveLen(1)) + g.Expect(childNode1.PoolRefs[0].Port).To(gomega.Equal(int32(8080))) + g.Expect(len(childNode1.PoolRefs[0].Servers)).To(gomega.Equal(1)) + g.Expect(len(childNode1.VHMatches)).To(gomega.Equal(1)) + g.Expect(*childNode1.VHMatches[0].Host).To(gomega.Equal("foo-8080.com")) + g.Expect(len(childNode1.VHMatches[0].Rules)).To(gomega.Equal(1)) + g.Expect(childNode1.VHMatches[0].Rules[0].Matches.Path.MatchStr[0]).To(gomega.Equal("/foo")) + g.Expect(len(childNode1.VHMatches[0].Rules[0].Matches.VsPort.Ports)).To(gomega.Equal(1)) + g.Expect(childNode1.VHMatches[0].Rules[0].Matches.VsPort.Ports[0]).To(gomega.Equal(int64(8080))) + + childNode2 := nodes[0].EvhNodes[1] + g.Expect(childNode2.PoolGroupRefs).To(gomega.HaveLen(1)) + g.Expect(childNode2.PoolGroupRefs[0].Members).To(gomega.HaveLen(1)) + g.Expect(childNode2.DefaultPoolGroup).NotTo(gomega.Equal("")) + g.Expect(childNode2.PoolRefs).To(gomega.HaveLen(1)) + g.Expect(childNode2.PoolRefs[0].Port).To(gomega.Equal(int32(8080))) + g.Expect(len(childNode2.PoolRefs[0].Servers)).To(gomega.Equal(1)) + g.Expect(len(childNode2.VHMatches)).To(gomega.Equal(1)) + g.Expect(*childNode2.VHMatches[0].Host).To(gomega.Equal("foo-8080.com")) + g.Expect(len(childNode2.VHMatches[0].Rules)).To(gomega.Equal(1)) + g.Expect(childNode2.VHMatches[0].Rules[0].Matches.Path.MatchStr[0]).To(gomega.Equal("/bar")) + g.Expect(len(childNode2.VHMatches[0].Rules[0].Matches.VsPort.Ports)).To(gomega.Equal(1)) + g.Expect(childNode2.VHMatches[0].Rules[0].Matches.VsPort.Ports[0]).To(gomega.Equal(int64(8080))) + + listeners[0].Protocol = "TCP" + akogatewayapitests.UpdateGateway(t, gatewayName, DEFAULT_NAMESPACE, gatewayClassName, nil, listeners) + + g.Eventually(func() bool { + gateway, err := akogatewayapitests.GatewayClient.GatewayV1().Gateways(DEFAULT_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)) + + gateway, _ := akogatewayapitests.GatewayClient.GatewayV1().Gateways(DEFAULT_NAMESPACE).Get(context.TODO(), gatewayName, metav1.GetOptions{}) + g.Expect(gateway.Status.Listeners[1].Conditions[0].Status).To(gomega.Equal(metav1.ConditionTrue)) + + g.Eventually(func() int { + nodes = aviModel.(*avinodes.AviObjectGraph).GetAviEvhVS() + return len(nodes[0].EvhNodes[0].VHMatches) + }, 50*time.Second).Should(gomega.Equal(2)) + nodes = aviModel.(*avinodes.AviObjectGraph).GetAviEvhVS() + + integrationtest.DelSVC(t, DEFAULT_NAMESPACE, svcName1) + integrationtest.DelEP(t, DEFAULT_NAMESPACE, svcName1) + integrationtest.DelSVC(t, DEFAULT_NAMESPACE, svcName2) + integrationtest.DelEP(t, DEFAULT_NAMESPACE, svcName2) + akogatewayapitests.TeardownHTTPRoute(t, httpRouteName, DEFAULT_NAMESPACE) + akogatewayapitests.TeardownGateway(t, gatewayName, DEFAULT_NAMESPACE) + akogatewayapitests.TeardownGatewayClass(t, gatewayClassName) + +} + +func TestTransitionsHttpRouteWithInvalidGatewayToPartiallyValidGateway(t *testing.T) { + gatewayName := "gateway-hr-12" + gatewayClassName := "gateway-class-hr-12" + httpRouteName := "http-route-hr-12" + svcName1 := "avisvc-hr-12-a" + svcName2 := "avisvc-hr-12-b" + ports := []int32{8080, 8081} + modelName, _ := akogatewayapitests.GetModelName(DEFAULT_NAMESPACE, gatewayName) + + akogatewayapitests.SetupGatewayClass(t, gatewayClassName, akogatewayapilib.GatewayController) + listeners := akogatewayapitests.GetListenersV1(ports, false, false) + listeners[1].Protocol = "TCP" + listeners[0].Protocol = "TCP" + akogatewayapitests.SetupGateway(t, gatewayName, DEFAULT_NAMESPACE, gatewayClassName, nil, listeners) + + g := gomega.NewGomegaWithT(t) + + g.Eventually(func() bool { + found, _ := objects.SharedAviGraphLister().Get(modelName) + return found + }, 25*time.Second).Should(gomega.Equal(false)) + + integrationtest.CreateSVC(t, DEFAULT_NAMESPACE, svcName1, corev1.ProtocolTCP, corev1.ServiceTypeClusterIP, false) + integrationtest.CreateEP(t, DEFAULT_NAMESPACE, svcName1, false, false, "1.2.3") + + integrationtest.CreateSVC(t, DEFAULT_NAMESPACE, svcName2, corev1.ProtocolTCP, corev1.ServiceTypeClusterIP, false) + integrationtest.CreateEP(t, DEFAULT_NAMESPACE, svcName2, false, false, "1.2.3") + + parentRefs := akogatewayapitests.GetParentReferencesV1([]string{gatewayName}, DEFAULT_NAMESPACE, ports) + rule1 := akogatewayapitests.GetHTTPRouteRuleV1([]string{"/foo"}, []string{}, + map[string][]string{"RequestHeaderModifier": {"add", "remove", "replace"}}, + [][]string{{svcName1, DEFAULT_NAMESPACE, "8080", "1"}}, nil) + rule2 := akogatewayapitests.GetHTTPRouteRuleV1([]string{"/bar"}, []string{}, + map[string][]string{"RequestHeaderModifier": {"add", "remove", "replace"}}, + [][]string{{svcName2, DEFAULT_NAMESPACE, "8081", "1"}}, nil) + rules := []gatewayv1.HTTPRouteRule{rule1, rule2} + + hostnames := []gatewayv1.Hostname{"foo-8080.com", "foo-8081.com"} + akogatewayapitests.SetupHTTPRoute(t, httpRouteName, DEFAULT_NAMESPACE, parentRefs, hostnames, rules) + time.Sleep(10 * time.Second) + listeners[1].Protocol = "HTTPS" + akogatewayapitests.UpdateGateway(t, gatewayName, DEFAULT_NAMESPACE, gatewayClassName, nil, listeners) + g.Eventually(func() bool { + gateway, err := akogatewayapitests.GatewayClient.GatewayV1().Gateways(DEFAULT_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)) + gateway, _ := akogatewayapitests.GatewayClient.GatewayV1().Gateways(DEFAULT_NAMESPACE).Get(context.TODO(), gatewayName, metav1.GetOptions{}) + g.Expect(gateway.Status.Listeners[1].Conditions[0].Status).To(gomega.Equal(metav1.ConditionTrue)) + g.Eventually(func() int { + found, aviModel := objects.SharedAviGraphLister().Get(modelName) + if !found { + return 0 + } + nodes := aviModel.(*avinodes.AviObjectGraph).GetAviEvhVS() + return len(nodes[0].EvhNodes) + }, 50*time.Second).Should(gomega.Equal(2)) + + _, aviModel := objects.SharedAviGraphLister().Get(modelName) + nodes := aviModel.(*avinodes.AviObjectGraph).GetAviEvhVS() + + childNode1 := nodes[0].EvhNodes[0] + g.Expect(childNode1.PoolGroupRefs).To(gomega.HaveLen(1)) + g.Expect(childNode1.PoolGroupRefs[0].Members).To(gomega.HaveLen(1)) + g.Expect(childNode1.DefaultPoolGroup).NotTo(gomega.Equal("")) + g.Expect(childNode1.PoolRefs).To(gomega.HaveLen(1)) + g.Expect(childNode1.PoolRefs[0].Port).To(gomega.Equal(int32(8080))) + g.Expect(len(childNode1.PoolRefs[0].Servers)).To(gomega.Equal(1)) + g.Expect(len(childNode1.VHMatches)).To(gomega.Equal(1)) + g.Expect(*childNode1.VHMatches[0].Host).To(gomega.Equal("foo-8081.com")) + g.Expect(len(childNode1.VHMatches[0].Rules)).To(gomega.Equal(1)) + g.Expect(childNode1.VHMatches[0].Rules[0].Matches.Path.MatchStr[0]).To(gomega.Equal("/foo")) + g.Expect(len(childNode1.VHMatches[0].Rules[0].Matches.VsPort.Ports)).To(gomega.Equal(1)) + g.Expect(childNode1.VHMatches[0].Rules[0].Matches.VsPort.Ports[0]).To(gomega.Equal(int64(8081))) + + childNode2 := nodes[0].EvhNodes[1] + g.Expect(childNode2.PoolGroupRefs).To(gomega.HaveLen(1)) + g.Expect(childNode2.PoolGroupRefs[0].Members).To(gomega.HaveLen(1)) + g.Expect(childNode2.DefaultPoolGroup).NotTo(gomega.Equal("")) + g.Expect(childNode2.PoolRefs).To(gomega.HaveLen(1)) + g.Expect(childNode2.PoolRefs[0].Port).To(gomega.Equal(int32(8080))) + g.Expect(len(childNode2.PoolRefs[0].Servers)).To(gomega.Equal(1)) + g.Expect(len(childNode2.VHMatches)).To(gomega.Equal(1)) + g.Expect(*childNode2.VHMatches[0].Host).To(gomega.Equal("foo-8081.com")) + g.Expect(len(childNode2.VHMatches[0].Rules)).To(gomega.Equal(1)) + g.Expect(childNode2.VHMatches[0].Rules[0].Matches.Path.MatchStr[0]).To(gomega.Equal("/bar")) + g.Expect(len(childNode2.VHMatches[0].Rules[0].Matches.VsPort.Ports)).To(gomega.Equal(1)) + g.Expect(childNode2.VHMatches[0].Rules[0].Matches.VsPort.Ports[0]).To(gomega.Equal(int64(8081))) + + integrationtest.DelSVC(t, DEFAULT_NAMESPACE, svcName1) + integrationtest.DelEP(t, DEFAULT_NAMESPACE, svcName1) + integrationtest.DelSVC(t, DEFAULT_NAMESPACE, svcName2) + integrationtest.DelEP(t, DEFAULT_NAMESPACE, svcName2) + akogatewayapitests.TeardownHTTPRoute(t, httpRouteName, DEFAULT_NAMESPACE) + akogatewayapitests.TeardownGateway(t, gatewayName, DEFAULT_NAMESPACE) + akogatewayapitests.TeardownGatewayClass(t, gatewayClassName) + +} + +func TestTransitionsHttpRouteWithValidGatewayToPartiallyValidGateway(t *testing.T) { + t.Skip("Skipping since current implementation is not supporting Valid to partially valid gateway transition") + gatewayName := "gateway-hr-13" + gatewayClassName := "gateway-class-hr-13" + httpRouteName := "http-route-hr-13" + svcName1 := "avisvc-hr-13-a" + svcName2 := "avisvc-hr-13-b" + ports := []int32{8080, 8081} + modelName, _ := akogatewayapitests.GetModelName(DEFAULT_NAMESPACE, gatewayName) + + akogatewayapitests.SetupGatewayClass(t, gatewayClassName, akogatewayapilib.GatewayController) + listeners := akogatewayapitests.GetListenersV1(ports, false, false) + akogatewayapitests.SetupGateway(t, gatewayName, DEFAULT_NAMESPACE, gatewayClassName, nil, listeners) + + g := gomega.NewGomegaWithT(t) + + g.Eventually(func() bool { + found, _ := objects.SharedAviGraphLister().Get(modelName) + return found + }, 25*time.Second).Should(gomega.Equal(true)) + + integrationtest.CreateSVC(t, DEFAULT_NAMESPACE, svcName1, corev1.ProtocolTCP, corev1.ServiceTypeClusterIP, false) + integrationtest.CreateEP(t, DEFAULT_NAMESPACE, svcName1, false, false, "1.2.3") + + integrationtest.CreateSVC(t, DEFAULT_NAMESPACE, svcName2, corev1.ProtocolTCP, corev1.ServiceTypeClusterIP, false) + integrationtest.CreateEP(t, DEFAULT_NAMESPACE, svcName2, false, false, "1.2.3") + + parentRefs := akogatewayapitests.GetParentReferencesV1([]string{gatewayName}, DEFAULT_NAMESPACE, ports) + rule1 := akogatewayapitests.GetHTTPRouteRuleV1([]string{"/foo"}, []string{}, + map[string][]string{"RequestHeaderModifier": {"add", "remove", "replace"}}, + [][]string{{svcName1, DEFAULT_NAMESPACE, "8080", "1"}}, nil) + rule2 := akogatewayapitests.GetHTTPRouteRuleV1([]string{"/bar"}, []string{}, + map[string][]string{"RequestHeaderModifier": {"add", "remove", "replace"}}, + [][]string{{svcName2, DEFAULT_NAMESPACE, "8081", "1"}}, nil) + rules := []gatewayv1.HTTPRouteRule{rule1, rule2} + + hostnames := []gatewayv1.Hostname{"foo-8080.com", "foo-8081.com"} + akogatewayapitests.SetupHTTPRoute(t, httpRouteName, DEFAULT_NAMESPACE, parentRefs, hostnames, rules) + + g.Eventually(func() int { + found, aviModel := objects.SharedAviGraphLister().Get(modelName) + if !found { + return 0 + } + nodes := aviModel.(*avinodes.AviObjectGraph).GetAviEvhVS() + return len(nodes[0].EvhNodes) + }, 50*time.Second).Should(gomega.Equal(2)) + + _, aviModel := objects.SharedAviGraphLister().Get(modelName) + nodes := aviModel.(*avinodes.AviObjectGraph).GetAviEvhVS() + + childNode1 := nodes[0].EvhNodes[0] + g.Expect(childNode1.PoolGroupRefs).To(gomega.HaveLen(1)) + g.Expect(childNode1.PoolGroupRefs[0].Members).To(gomega.HaveLen(1)) + g.Expect(childNode1.DefaultPoolGroup).NotTo(gomega.Equal("")) + g.Expect(childNode1.PoolRefs).To(gomega.HaveLen(1)) + g.Expect(childNode1.PoolRefs[0].Port).To(gomega.Equal(int32(8080))) + g.Expect(len(childNode1.PoolRefs[0].Servers)).To(gomega.Equal(1)) + g.Expect(len(childNode1.VHMatches)).To(gomega.Equal(2)) + g.Expect(*childNode1.VHMatches[0].Host).To(gomega.Equal("foo-8080.com")) + g.Expect(len(childNode1.VHMatches[0].Rules)).To(gomega.Equal(1)) + g.Expect(childNode1.VHMatches[0].Rules[0].Matches.Path.MatchStr[0]).To(gomega.Equal("/foo")) + g.Expect(len(childNode1.VHMatches[0].Rules[0].Matches.VsPort.Ports)).To(gomega.Equal(2)) + g.Expect(childNode1.VHMatches[0].Rules[0].Matches.VsPort.Ports[0]).To(gomega.Equal(int64(8080))) + g.Expect(childNode1.VHMatches[0].Rules[0].Matches.VsPort.Ports[1]).To(gomega.Equal(int64(8081))) + g.Expect(*childNode1.VHMatches[1].Host).To(gomega.Equal("foo-8081.com")) + g.Expect(len(childNode1.VHMatches[1].Rules)).To(gomega.Equal(1)) + g.Expect(childNode1.VHMatches[1].Rules[0].Matches.Path.MatchStr[0]).To(gomega.Equal("/foo")) + g.Expect(len(childNode1.VHMatches[1].Rules[0].Matches.VsPort.Ports)).To(gomega.Equal(2)) + g.Expect(childNode1.VHMatches[1].Rules[0].Matches.VsPort.Ports[0]).To(gomega.Equal(int64(8080))) + g.Expect(childNode1.VHMatches[1].Rules[0].Matches.VsPort.Ports[1]).To(gomega.Equal(int64(8081))) + + childNode2 := nodes[0].EvhNodes[1] + g.Expect(childNode2.PoolGroupRefs).To(gomega.HaveLen(1)) + g.Expect(childNode2.PoolGroupRefs[0].Members).To(gomega.HaveLen(1)) + g.Expect(childNode2.DefaultPoolGroup).NotTo(gomega.Equal("")) + g.Expect(childNode2.PoolRefs).To(gomega.HaveLen(1)) + g.Expect(childNode2.PoolRefs[0].Port).To(gomega.Equal(int32(8080))) + g.Expect(len(childNode2.PoolRefs[0].Servers)).To(gomega.Equal(1)) + g.Expect(len(childNode2.VHMatches)).To(gomega.Equal(2)) + g.Expect(*childNode2.VHMatches[0].Host).To(gomega.Equal("foo-8080.com")) + g.Expect(len(childNode2.VHMatches[0].Rules)).To(gomega.Equal(1)) + g.Expect(childNode2.VHMatches[0].Rules[0].Matches.Path.MatchStr[0]).To(gomega.Equal("/bar")) + g.Expect(len(childNode2.VHMatches[0].Rules[0].Matches.VsPort.Ports)).To(gomega.Equal(2)) + g.Expect(childNode2.VHMatches[0].Rules[0].Matches.VsPort.Ports[0]).To(gomega.Equal(int64(8080))) + g.Expect(childNode2.VHMatches[0].Rules[0].Matches.VsPort.Ports[1]).To(gomega.Equal(int64(8081))) + g.Expect(*childNode2.VHMatches[1].Host).To(gomega.Equal("foo-8081.com")) + g.Expect(len(childNode2.VHMatches[1].Rules)).To(gomega.Equal(1)) + g.Expect(childNode2.VHMatches[1].Rules[0].Matches.Path.MatchStr[0]).To(gomega.Equal("/bar")) + g.Expect(len(childNode2.VHMatches[1].Rules[0].Matches.VsPort.Ports)).To(gomega.Equal(2)) + g.Expect(childNode2.VHMatches[1].Rules[0].Matches.VsPort.Ports[0]).To(gomega.Equal(int64(8080))) + g.Expect(childNode2.VHMatches[1].Rules[0].Matches.VsPort.Ports[1]).To(gomega.Equal(int64(8081))) + + listeners[1].Protocol = "TCP" + akogatewayapitests.UpdateGateway(t, gatewayName, DEFAULT_NAMESPACE, gatewayClassName, nil, listeners) + + g.Eventually(func() bool { + gateway, err := akogatewayapitests.GatewayClient.GatewayV1().Gateways(DEFAULT_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)) + + gateway, _ := akogatewayapitests.GatewayClient.GatewayV1().Gateways(DEFAULT_NAMESPACE).Get(context.TODO(), gatewayName, metav1.GetOptions{}) + g.Expect(gateway.Status.Listeners[1].Conditions[0].Status).To(gomega.Equal(metav1.ConditionFalse)) + + g.Eventually(func() int { + nodes = aviModel.(*avinodes.AviObjectGraph).GetAviEvhVS() + return len(nodes[0].EvhNodes[0].VHMatches) + }, 50*time.Second).Should(gomega.Equal(1)) + nodes = aviModel.(*avinodes.AviObjectGraph).GetAviEvhVS() + + childNode1 = nodes[0].EvhNodes[0] + g.Expect(childNode1.PoolGroupRefs).To(gomega.HaveLen(1)) + g.Expect(childNode1.PoolGroupRefs[0].Members).To(gomega.HaveLen(1)) + g.Expect(childNode1.DefaultPoolGroup).NotTo(gomega.Equal("")) + g.Expect(childNode1.PoolRefs).To(gomega.HaveLen(1)) + g.Expect(childNode1.PoolRefs[0].Port).To(gomega.Equal(int32(8080))) + g.Expect(len(childNode1.PoolRefs[0].Servers)).To(gomega.Equal(1)) + g.Expect(len(childNode1.VHMatches)).To(gomega.Equal(2)) + g.Expect(*childNode1.VHMatches[0].Host).To(gomega.Equal("foo-8080.com")) + g.Expect(len(childNode1.VHMatches[0].Rules)).To(gomega.Equal(1)) + g.Expect(childNode1.VHMatches[0].Rules[0].Matches.Path.MatchStr[0]).To(gomega.Equal("/foo")) + g.Expect(len(childNode1.VHMatches[0].Rules[0].Matches.VsPort.Ports)).To(gomega.Equal(2)) + g.Expect(childNode1.VHMatches[0].Rules[0].Matches.VsPort.Ports[0]).To(gomega.Equal(int64(8080))) + g.Expect(childNode1.VHMatches[0].Rules[0].Matches.VsPort.Ports[1]).To(gomega.Equal(int64(8081))) + g.Expect(*childNode1.VHMatches[1].Host).To(gomega.Equal("foo-8081.com")) + g.Expect(len(childNode1.VHMatches[1].Rules)).To(gomega.Equal(1)) + g.Expect(childNode1.VHMatches[1].Rules[0].Matches.Path.MatchStr[0]).To(gomega.Equal("/foo")) + g.Expect(len(childNode1.VHMatches[1].Rules[0].Matches.VsPort.Ports)).To(gomega.Equal(2)) + g.Expect(childNode1.VHMatches[1].Rules[0].Matches.VsPort.Ports[0]).To(gomega.Equal(int64(8080))) + g.Expect(childNode1.VHMatches[1].Rules[0].Matches.VsPort.Ports[1]).To(gomega.Equal(int64(8081))) + + childNode2 = nodes[0].EvhNodes[1] + g.Expect(childNode2.PoolGroupRefs).To(gomega.HaveLen(1)) + g.Expect(childNode2.PoolGroupRefs[0].Members).To(gomega.HaveLen(1)) + g.Expect(childNode2.DefaultPoolGroup).NotTo(gomega.Equal("")) + g.Expect(childNode2.PoolRefs).To(gomega.HaveLen(1)) + g.Expect(childNode2.PoolRefs[0].Port).To(gomega.Equal(int32(8080))) + g.Expect(len(childNode2.PoolRefs[0].Servers)).To(gomega.Equal(1)) + g.Expect(len(childNode2.VHMatches)).To(gomega.Equal(2)) + g.Expect(*childNode2.VHMatches[0].Host).To(gomega.Equal("foo-8080.com")) + g.Expect(len(childNode2.VHMatches[0].Rules)).To(gomega.Equal(1)) + g.Expect(childNode2.VHMatches[0].Rules[0].Matches.Path.MatchStr[0]).To(gomega.Equal("/bar")) + g.Expect(len(childNode2.VHMatches[0].Rules[0].Matches.VsPort.Ports)).To(gomega.Equal(2)) + g.Expect(childNode2.VHMatches[0].Rules[0].Matches.VsPort.Ports[0]).To(gomega.Equal(int64(8080))) + g.Expect(childNode2.VHMatches[0].Rules[0].Matches.VsPort.Ports[1]).To(gomega.Equal(int64(8081))) + g.Expect(*childNode2.VHMatches[1].Host).To(gomega.Equal("foo-8081.com")) + g.Expect(len(childNode2.VHMatches[1].Rules)).To(gomega.Equal(1)) + g.Expect(childNode2.VHMatches[1].Rules[0].Matches.Path.MatchStr[0]).To(gomega.Equal("/bar")) + g.Expect(len(childNode2.VHMatches[1].Rules[0].Matches.VsPort.Ports)).To(gomega.Equal(2)) + g.Expect(childNode2.VHMatches[1].Rules[0].Matches.VsPort.Ports[0]).To(gomega.Equal(int64(8080))) + g.Expect(childNode2.VHMatches[1].Rules[0].Matches.VsPort.Ports[1]).To(gomega.Equal(int64(8081))) + + integrationtest.DelSVC(t, DEFAULT_NAMESPACE, svcName1) + integrationtest.DelEP(t, DEFAULT_NAMESPACE, svcName1) + integrationtest.DelSVC(t, DEFAULT_NAMESPACE, svcName2) + integrationtest.DelEP(t, DEFAULT_NAMESPACE, svcName2) + akogatewayapitests.TeardownHTTPRoute(t, httpRouteName, DEFAULT_NAMESPACE) + akogatewayapitests.TeardownGateway(t, gatewayName, DEFAULT_NAMESPACE) + akogatewayapitests.TeardownGatewayClass(t, gatewayClassName) +} + +func TestTransitionsMultipleHttpRoutesWithPartiallyValidGatewayToValidGateway(t *testing.T) { + // 1: Two HTTPRoute with partially valid gateway + gatewayName := "gateway-hr-14" + gatewayClassName := "gateway-class-hr-14" + httpRoute1Name := "http-route-hr-14a" + httpRoute2Name := "http-route-hr-14b" + svcName1 := "avisvc-hr-14-a" + svcName2 := "avisvc-hr-14-b" + ports := []int32{8080, 8081} + modelName, _ := akogatewayapitests.GetModelName(DEFAULT_NAMESPACE, gatewayName) + + akogatewayapitests.SetupGatewayClass(t, gatewayClassName, akogatewayapilib.GatewayController) + listeners := akogatewayapitests.GetListenersV1(ports, false, false) + listeners[1].Protocol = "TCP" + akogatewayapitests.SetupGateway(t, gatewayName, DEFAULT_NAMESPACE, gatewayClassName, nil, listeners) + + g := gomega.NewGomegaWithT(t) + + g.Eventually(func() bool { + found, _ := objects.SharedAviGraphLister().Get(modelName) + return found + }, 25*time.Second).Should(gomega.Equal(true)) + + integrationtest.CreateSVC(t, DEFAULT_NAMESPACE, svcName1, corev1.ProtocolTCP, corev1.ServiceTypeClusterIP, false) + integrationtest.CreateEP(t, DEFAULT_NAMESPACE, svcName1, false, false, "1.2.3") + + integrationtest.CreateSVC(t, DEFAULT_NAMESPACE, svcName2, corev1.ProtocolTCP, corev1.ServiceTypeClusterIP, false) + integrationtest.CreateEP(t, DEFAULT_NAMESPACE, svcName2, false, false, "1.2.3") + + parentRefs := akogatewayapitests.GetParentReferencesV1([]string{gatewayName}, DEFAULT_NAMESPACE, []int32{ports[0]}) + rule1 := akogatewayapitests.GetHTTPRouteRuleV1([]string{"/foo"}, []string{}, + map[string][]string{"RequestHeaderModifier": {"add", "remove", "replace"}}, + [][]string{{svcName1, DEFAULT_NAMESPACE, "8080", "1"}}, nil) + rule2 := akogatewayapitests.GetHTTPRouteRuleV1([]string{"/bar"}, []string{}, + map[string][]string{"RequestHeaderModifier": {"add", "remove", "replace"}}, + [][]string{{svcName2, DEFAULT_NAMESPACE, "8081", "1"}}, nil) + rules := []gatewayv1.HTTPRouteRule{rule1, rule2} + + hostnames := []gatewayv1.Hostname{"foo-8080.com"} + akogatewayapitests.SetupHTTPRoute(t, httpRoute1Name, DEFAULT_NAMESPACE, parentRefs, hostnames, rules) + hostnames = []gatewayv1.Hostname{"foo-8081.com"} + parentRefs = akogatewayapitests.GetParentReferencesV1([]string{gatewayName}, DEFAULT_NAMESPACE, []int32{ports[1]}) + akogatewayapitests.SetupHTTPRoute(t, httpRoute2Name, DEFAULT_NAMESPACE, parentRefs, hostnames, rules) + + g.Eventually(func() int { + found, aviModel := objects.SharedAviGraphLister().Get(modelName) + if !found { + return 0 + } + nodes := aviModel.(*avinodes.AviObjectGraph).GetAviEvhVS() + return len(nodes[0].EvhNodes) + }, 50*time.Second).Should(gomega.Equal(2)) + + _, aviModel := objects.SharedAviGraphLister().Get(modelName) + nodes := aviModel.(*avinodes.AviObjectGraph).GetAviEvhVS() + childNode1 := nodes[0].EvhNodes[0] + g.Expect(childNode1.PoolGroupRefs).To(gomega.HaveLen(1)) + g.Expect(childNode1.PoolGroupRefs[0].Members).To(gomega.HaveLen(1)) + g.Expect(childNode1.DefaultPoolGroup).NotTo(gomega.Equal("")) + g.Expect(childNode1.PoolRefs).To(gomega.HaveLen(1)) + g.Expect(childNode1.PoolRefs[0].Port).To(gomega.Equal(int32(8080))) + g.Expect(len(childNode1.PoolRefs[0].Servers)).To(gomega.Equal(1)) + g.Expect(len(childNode1.VHMatches)).To(gomega.Equal(1)) + g.Expect(*childNode1.VHMatches[0].Host).To(gomega.Equal("foo-8080.com")) + g.Expect(len(childNode1.VHMatches[0].Rules)).To(gomega.Equal(1)) + g.Expect(childNode1.VHMatches[0].Rules[0].Matches.Path.MatchStr[0]).To(gomega.Equal("/foo")) + g.Expect(len(childNode1.VHMatches[0].Rules[0].Matches.VsPort.Ports)).To(gomega.Equal(1)) + g.Expect(childNode1.VHMatches[0].Rules[0].Matches.VsPort.Ports[0]).To(gomega.Equal(int64(8080))) + + childNode2 := nodes[0].EvhNodes[1] + g.Expect(childNode2.PoolGroupRefs).To(gomega.HaveLen(1)) + g.Expect(childNode2.PoolGroupRefs[0].Members).To(gomega.HaveLen(1)) + g.Expect(childNode2.DefaultPoolGroup).NotTo(gomega.Equal("")) + g.Expect(childNode2.PoolRefs).To(gomega.HaveLen(1)) + g.Expect(childNode2.PoolRefs[0].Port).To(gomega.Equal(int32(8080))) + g.Expect(len(childNode2.PoolRefs[0].Servers)).To(gomega.Equal(1)) + g.Expect(len(childNode2.VHMatches)).To(gomega.Equal(1)) + g.Expect(*childNode2.VHMatches[0].Host).To(gomega.Equal("foo-8080.com")) + g.Expect(len(childNode2.VHMatches[0].Rules)).To(gomega.Equal(1)) + g.Expect(childNode2.VHMatches[0].Rules[0].Matches.Path.MatchStr[0]).To(gomega.Equal("/bar")) + g.Expect(len(childNode2.VHMatches[0].Rules[0].Matches.VsPort.Ports)).To(gomega.Equal(1)) + g.Expect(childNode2.VHMatches[0].Rules[0].Matches.VsPort.Ports[0]).To(gomega.Equal(int64(8080))) + + listeners[1].Protocol = "HTTPS" + akogatewayapitests.UpdateGateway(t, gatewayName, DEFAULT_NAMESPACE, gatewayClassName, nil, listeners) + + g.Eventually(func() bool { + gateway, err := akogatewayapitests.GatewayClient.GatewayV1().Gateways(DEFAULT_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)) + + gateway, _ := akogatewayapitests.GatewayClient.GatewayV1().Gateways(DEFAULT_NAMESPACE).Get(context.TODO(), gatewayName, metav1.GetOptions{}) + g.Expect(gateway.Status.Listeners[1].Conditions[0].Status).To(gomega.Equal(metav1.ConditionTrue)) + g.Eventually(func() int { + _, aviModel = objects.SharedAviGraphLister().Get(modelName) + nodes = aviModel.(*avinodes.AviObjectGraph).GetAviEvhVS() + return len(nodes[0].EvhNodes) + }, 50*time.Second).Should(gomega.Equal(4)) + + childNode1 = nodes[0].EvhNodes[0] + g.Expect(childNode1.PoolGroupRefs).To(gomega.HaveLen(1)) + g.Expect(childNode1.PoolGroupRefs[0].Members).To(gomega.HaveLen(1)) + g.Expect(childNode1.DefaultPoolGroup).NotTo(gomega.Equal("")) + g.Expect(childNode1.PoolRefs).To(gomega.HaveLen(1)) + g.Expect(childNode1.PoolRefs[0].Port).To(gomega.Equal(int32(8080))) + g.Expect(len(childNode1.PoolRefs[0].Servers)).To(gomega.Equal(1)) + g.Expect(len(childNode1.VHMatches)).To(gomega.Equal(1)) + g.Expect(*childNode1.VHMatches[0].Host).To(gomega.Equal("foo-8080.com")) + g.Expect(len(childNode1.VHMatches[0].Rules)).To(gomega.Equal(1)) + g.Expect(childNode1.VHMatches[0].Rules[0].Matches.Path.MatchStr[0]).To(gomega.Equal("/foo")) + g.Expect(len(childNode1.VHMatches[0].Rules[0].Matches.VsPort.Ports)).To(gomega.Equal(1)) + g.Expect(childNode1.VHMatches[0].Rules[0].Matches.VsPort.Ports[0]).To(gomega.Equal(int64(8080))) + + childNode2 = nodes[0].EvhNodes[1] + g.Expect(childNode2.PoolGroupRefs).To(gomega.HaveLen(1)) + g.Expect(childNode2.PoolGroupRefs[0].Members).To(gomega.HaveLen(1)) + g.Expect(childNode2.DefaultPoolGroup).NotTo(gomega.Equal("")) + g.Expect(childNode2.PoolRefs).To(gomega.HaveLen(1)) + g.Expect(childNode2.PoolRefs[0].Port).To(gomega.Equal(int32(8080))) + g.Expect(len(childNode2.PoolRefs[0].Servers)).To(gomega.Equal(1)) + g.Expect(len(childNode2.VHMatches)).To(gomega.Equal(1)) + g.Expect(*childNode2.VHMatches[0].Host).To(gomega.Equal("foo-8080.com")) + g.Expect(len(childNode2.VHMatches[0].Rules)).To(gomega.Equal(1)) + g.Expect(childNode2.VHMatches[0].Rules[0].Matches.Path.MatchStr[0]).To(gomega.Equal("/bar")) + g.Expect(len(childNode2.VHMatches[0].Rules[0].Matches.VsPort.Ports)).To(gomega.Equal(1)) + g.Expect(childNode2.VHMatches[0].Rules[0].Matches.VsPort.Ports[0]).To(gomega.Equal(int64(8080))) + + childNode3 := nodes[0].EvhNodes[2] + g.Expect(childNode3.PoolGroupRefs).To(gomega.HaveLen(1)) + g.Expect(childNode3.PoolGroupRefs[0].Members).To(gomega.HaveLen(1)) + g.Expect(childNode3.DefaultPoolGroup).NotTo(gomega.Equal("")) + g.Expect(childNode3.PoolRefs).To(gomega.HaveLen(1)) + g.Expect(childNode3.PoolRefs[0].Port).To(gomega.Equal(int32(8080))) + g.Expect(len(childNode3.PoolRefs[0].Servers)).To(gomega.Equal(1)) + g.Expect(len(childNode3.VHMatches)).To(gomega.Equal(1)) + g.Expect(*childNode3.VHMatches[0].Host).To(gomega.Equal("foo-8081.com")) + g.Expect(len(childNode3.VHMatches[0].Rules)).To(gomega.Equal(1)) + g.Expect(childNode3.VHMatches[0].Rules[0].Matches.Path.MatchStr[0]).To(gomega.Equal("/foo")) + g.Expect(len(childNode3.VHMatches[0].Rules[0].Matches.VsPort.Ports)).To(gomega.Equal(1)) + g.Expect(childNode3.VHMatches[0].Rules[0].Matches.VsPort.Ports[0]).To(gomega.Equal(int64(8081))) + + childNode4 := nodes[0].EvhNodes[3] + g.Expect(childNode4.PoolGroupRefs).To(gomega.HaveLen(1)) + g.Expect(childNode4.PoolGroupRefs[0].Members).To(gomega.HaveLen(1)) + g.Expect(childNode4.DefaultPoolGroup).NotTo(gomega.Equal("")) + g.Expect(childNode4.PoolRefs).To(gomega.HaveLen(1)) + g.Expect(childNode4.PoolRefs[0].Port).To(gomega.Equal(int32(8080))) + g.Expect(len(childNode4.PoolRefs[0].Servers)).To(gomega.Equal(1)) + g.Expect(len(childNode4.VHMatches)).To(gomega.Equal(1)) + g.Expect(*childNode4.VHMatches[0].Host).To(gomega.Equal("foo-8081.com")) + g.Expect(len(childNode4.VHMatches[0].Rules)).To(gomega.Equal(1)) + g.Expect(childNode4.VHMatches[0].Rules[0].Matches.Path.MatchStr[0]).To(gomega.Equal("/bar")) + g.Expect(len(childNode4.VHMatches[0].Rules[0].Matches.VsPort.Ports)).To(gomega.Equal(1)) + g.Expect(childNode4.VHMatches[0].Rules[0].Matches.VsPort.Ports[0]).To(gomega.Equal(int64(8081))) + + integrationtest.DelSVC(t, DEFAULT_NAMESPACE, svcName1) + integrationtest.DelEP(t, DEFAULT_NAMESPACE, svcName1) + integrationtest.DelSVC(t, DEFAULT_NAMESPACE, svcName2) + integrationtest.DelEP(t, DEFAULT_NAMESPACE, svcName2) + akogatewayapitests.TeardownHTTPRoute(t, httpRoute1Name, DEFAULT_NAMESPACE) + akogatewayapitests.TeardownHTTPRoute(t, httpRoute2Name, DEFAULT_NAMESPACE) + akogatewayapitests.TeardownGateway(t, gatewayName, DEFAULT_NAMESPACE) + akogatewayapitests.TeardownGatewayClass(t, gatewayClassName) +} +func TestTransitionsMultipleHttpRouteWithInvalidGatewayToPartiallyValidGateway(t *testing.T) { + // 1: Two HTTPRoute with invalid gateway + gatewayName := "gateway-hr-16" + gatewayClassName := "gateway-class-hr-16" + httpRoute1Name := "http-route-hr-16a" + httpRoute2Name := "http-route-hr-16b" + svcName1 := "avisvc-hr-16-a" + svcName2 := "avisvc-hr-16-b" + ports := []int32{8080, 8081} + modelName, _ := akogatewayapitests.GetModelName(DEFAULT_NAMESPACE, gatewayName) + + akogatewayapitests.SetupGatewayClass(t, gatewayClassName, akogatewayapilib.GatewayController) + listeners := akogatewayapitests.GetListenersV1(ports, false, false) + listeners[0].Protocol = "TCP" + listeners[1].Protocol = "TCP" + akogatewayapitests.SetupGateway(t, gatewayName, DEFAULT_NAMESPACE, gatewayClassName, nil, listeners) + + g := gomega.NewGomegaWithT(t) + integrationtest.CreateSVC(t, DEFAULT_NAMESPACE, svcName1, corev1.ProtocolTCP, corev1.ServiceTypeClusterIP, false) + integrationtest.CreateEP(t, DEFAULT_NAMESPACE, svcName1, false, false, "1.2.3") + + integrationtest.CreateSVC(t, DEFAULT_NAMESPACE, svcName2, corev1.ProtocolTCP, corev1.ServiceTypeClusterIP, false) + integrationtest.CreateEP(t, DEFAULT_NAMESPACE, svcName2, false, false, "1.2.3") + + parentRefs := akogatewayapitests.GetParentReferencesV1([]string{gatewayName}, DEFAULT_NAMESPACE, []int32{ports[0]}) + rule1 := akogatewayapitests.GetHTTPRouteRuleV1([]string{"/foo"}, []string{}, + map[string][]string{"RequestHeaderModifier": {"add", "remove", "replace"}}, + [][]string{{svcName1, DEFAULT_NAMESPACE, "8080", "1"}}, nil) + rule2 := akogatewayapitests.GetHTTPRouteRuleV1([]string{"/bar"}, []string{}, + map[string][]string{"RequestHeaderModifier": {"add", "remove", "replace"}}, + [][]string{{svcName2, DEFAULT_NAMESPACE, "8081", "1"}}, nil) + rules := []gatewayv1.HTTPRouteRule{rule1, rule2} + hostnames := []gatewayv1.Hostname{"foo-8080.com"} + akogatewayapitests.SetupHTTPRoute(t, httpRoute1Name, DEFAULT_NAMESPACE, parentRefs, hostnames, rules) + hostnames = []gatewayv1.Hostname{"foo-8081.com"} + parentRefs = akogatewayapitests.GetParentReferencesV1([]string{gatewayName}, DEFAULT_NAMESPACE, []int32{ports[1]}) + akogatewayapitests.SetupHTTPRoute(t, httpRoute2Name, DEFAULT_NAMESPACE, parentRefs, hostnames, rules) + listeners[0].Protocol = "HTTPS" + time.Sleep(10 * time.Second) + akogatewayapitests.UpdateGateway(t, gatewayName, DEFAULT_NAMESPACE, gatewayClassName, nil, listeners) + + g.Eventually(func() bool { + gateway, err := akogatewayapitests.GatewayClient.GatewayV1().Gateways(DEFAULT_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)) + + gateway, _ := akogatewayapitests.GatewayClient.GatewayV1().Gateways(DEFAULT_NAMESPACE).Get(context.TODO(), gatewayName, metav1.GetOptions{}) + g.Expect(gateway.Status.Listeners[0].Conditions[0].Status).To(gomega.Equal(metav1.ConditionTrue)) + g.Eventually(func() int { + found, aviModel := objects.SharedAviGraphLister().Get(modelName) + if !found { + return 0 + } + nodes := aviModel.(*avinodes.AviObjectGraph).GetAviEvhVS() + return len(nodes[0].EvhNodes) + }, 50*time.Second).Should(gomega.Equal(2)) + _, aviModel := objects.SharedAviGraphLister().Get(modelName) + nodes := aviModel.(*avinodes.AviObjectGraph).GetAviEvhVS() + childNode1 := nodes[0].EvhNodes[0] + g.Expect(childNode1.PoolGroupRefs).To(gomega.HaveLen(1)) + g.Expect(childNode1.PoolGroupRefs[0].Members).To(gomega.HaveLen(1)) + g.Expect(childNode1.DefaultPoolGroup).NotTo(gomega.Equal("")) + g.Expect(childNode1.PoolRefs).To(gomega.HaveLen(1)) + g.Expect(childNode1.PoolRefs[0].Port).To(gomega.Equal(int32(8080))) + g.Expect(len(childNode1.PoolRefs[0].Servers)).To(gomega.Equal(1)) + g.Expect(len(childNode1.VHMatches)).To(gomega.Equal(1)) + g.Expect(*childNode1.VHMatches[0].Host).To(gomega.Equal("foo-8080.com")) + g.Expect(len(childNode1.VHMatches[0].Rules)).To(gomega.Equal(1)) + g.Expect(childNode1.VHMatches[0].Rules[0].Matches.Path.MatchStr[0]).To(gomega.Equal("/foo")) + g.Expect(len(childNode1.VHMatches[0].Rules[0].Matches.VsPort.Ports)).To(gomega.Equal(1)) + g.Expect(childNode1.VHMatches[0].Rules[0].Matches.VsPort.Ports[0]).To(gomega.Equal(int64(8080))) + + childNode2 := nodes[0].EvhNodes[1] + g.Expect(childNode2.PoolGroupRefs).To(gomega.HaveLen(1)) + g.Expect(childNode2.PoolGroupRefs[0].Members).To(gomega.HaveLen(1)) + g.Expect(childNode2.DefaultPoolGroup).NotTo(gomega.Equal("")) + g.Expect(childNode2.PoolRefs).To(gomega.HaveLen(1)) + g.Expect(childNode2.PoolRefs[0].Port).To(gomega.Equal(int32(8080))) + g.Expect(len(childNode2.PoolRefs[0].Servers)).To(gomega.Equal(1)) + g.Expect(len(childNode2.VHMatches)).To(gomega.Equal(1)) + g.Expect(*childNode2.VHMatches[0].Host).To(gomega.Equal("foo-8080.com")) + g.Expect(len(childNode2.VHMatches[0].Rules)).To(gomega.Equal(1)) + g.Expect(childNode2.VHMatches[0].Rules[0].Matches.Path.MatchStr[0]).To(gomega.Equal("/bar")) + g.Expect(len(childNode2.VHMatches[0].Rules[0].Matches.VsPort.Ports)).To(gomega.Equal(1)) + g.Expect(childNode2.VHMatches[0].Rules[0].Matches.VsPort.Ports[0]).To(gomega.Equal(int64(8080))) + + integrationtest.DelSVC(t, DEFAULT_NAMESPACE, svcName1) + integrationtest.DelEP(t, DEFAULT_NAMESPACE, svcName1) + integrationtest.DelSVC(t, DEFAULT_NAMESPACE, svcName2) + integrationtest.DelEP(t, DEFAULT_NAMESPACE, svcName2) + akogatewayapitests.TeardownHTTPRoute(t, httpRoute1Name, DEFAULT_NAMESPACE) + akogatewayapitests.TeardownHTTPRoute(t, httpRoute2Name, DEFAULT_NAMESPACE) + akogatewayapitests.TeardownGateway(t, gatewayName, DEFAULT_NAMESPACE) + akogatewayapitests.TeardownGatewayClass(t, gatewayClassName) +} diff --git a/tests/gatewayapitests/status/httproute_test.go b/tests/gatewayapitests/status/httproute_test.go index f24d0d2c5..d9bb02e61 100644 --- a/tests/gatewayapitests/status/httproute_test.go +++ b/tests/gatewayapitests/status/httproute_test.go @@ -851,3 +851,177 @@ func TestHTTPRouteWithOneExistingAndOneNonExistingGateway(t *testing.T) { akogatewayapitests.TeardownGateway(t, gatewayName2, namespace) akogatewayapitests.TeardownGatewayClass(t, gatewayClassName) } + +func TestMultipleHttpRoutesWithValidAndInvalidGatewayListeners(t *testing.T) { + gatewayClassName := "gateway-class-hr-14" + gatewayName := "gateway-hr-14" + httpRouteName1 := "httproute-14a" + httpRouteName2 := "httproute-14b" + namespace := "default" + ports := []int32{8080, 8081} + + akogatewayapitests.SetupGatewayClass(t, gatewayClassName, akogatewayapilib.GatewayController) + + listeners := akogatewayapitests.GetListenersV1(ports, false, false) + listeners[1].Protocol = "TCP" + + g := gomega.NewGomegaWithT(t) + akogatewayapitests.SetupGateway(t, gatewayName, namespace, gatewayClassName, nil, listeners) + 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, []int32{ports[0]}) + hostnames := []gatewayv1.Hostname{"foo-8080.com"} + + akogatewayapitests.SetupHTTPRoute(t, httpRouteName1, namespace, parentRefs, hostnames, nil) + g.Eventually(func() bool { + httpRoute, err := akogatewayapitests.GatewayClient.GatewayV1().HTTPRoutes(namespace).Get(context.TODO(), httpRouteName1, metav1.GetOptions{}) + if err != nil || httpRoute == nil { + t.Logf("Couldn't get the HTTPRoute, err: %+v", err) + return false + } + if len(httpRoute.Status.Parents) != 1 { + return false + } + return apimeta.FindStatusCondition(httpRoute.Status.Parents[0].Conditions, string(gatewayv1.RouteConditionAccepted)) != nil + }, 30*time.Second).Should(gomega.Equal(true)) + + httpRoute, err := akogatewayapitests.GatewayClient.GatewayV1().HTTPRoutes(namespace).Get(context.TODO(), httpRouteName1, metav1.GetOptions{}) + if err != nil || httpRoute == nil { + t.Fatalf("Couldn't get the HTTPRoute, err: %+v", err) + } + + conditionMap := make(map[string][]metav1.Condition) + + conditions := make([]metav1.Condition, 0) + condition := metav1.Condition{ + Type: string(gatewayv1.RouteConditionAccepted), + Reason: string(gatewayv1.RouteReasonAccepted), + Status: metav1.ConditionTrue, + Message: "Parent reference is valid", + } + conditions = append(conditions, condition) + conditionMap[fmt.Sprintf("%s-%d", gatewayName, ports[0])] = conditions + + expectedRouteStatus := akogatewayapitests.GetRouteStatusV1([]string{gatewayName}, namespace, []int32{ports[0]}, conditionMap) + akogatewayapitests.ValidateHTTPRouteStatus(t, &httpRoute.Status, &gatewayv1.HTTPRouteStatus{RouteStatus: *expectedRouteStatus}) + + parentRefs = akogatewayapitests.GetParentReferencesV1([]string{gatewayName}, namespace, []int32{ports[1]}) + hostnames = []gatewayv1.Hostname{"foo-8081.com"} + + akogatewayapitests.SetupHTTPRoute(t, httpRouteName2, namespace, parentRefs, hostnames, nil) + g.Eventually(func() bool { + httpRoute, err := akogatewayapitests.GatewayClient.GatewayV1().HTTPRoutes(namespace).Get(context.TODO(), httpRouteName2, metav1.GetOptions{}) + if err != nil || httpRoute == nil { + t.Logf("Couldn't get the HTTPRoute, err: %+v", err) + return false + } + if len(httpRoute.Status.Parents) != 1 { + return false + } + return apimeta.FindStatusCondition(httpRoute.Status.Parents[0].Conditions, string(gatewayv1.RouteConditionAccepted)) != nil + }, 30*time.Second).Should(gomega.Equal(true)) + + httpRoute, err = akogatewayapitests.GatewayClient.GatewayV1().HTTPRoutes(namespace).Get(context.TODO(), httpRouteName2, metav1.GetOptions{}) + if err != nil || httpRoute == nil { + t.Fatalf("Couldn't get the HTTPRoute, err: %+v", err) + } + + conditionMap = make(map[string][]metav1.Condition) + conditions = make([]metav1.Condition, 0, 1) + condition = metav1.Condition{ + Type: string(gatewayv1.RouteConditionAccepted), + Reason: string(gatewayv1.RouteReasonAccepted), + Status: metav1.ConditionTrue, + Message: "Parent reference is valid", + } + + conditions = append(conditions, condition) + conditionMap[fmt.Sprintf("%s-%d", gatewayName, ports[1])] = conditions + + conditionMap["gateway-hr-14-8081"][0].Message = "Matching gateway listener is in Invalid state" + conditionMap["gateway-hr-14-8081"][0].Status = metav1.ConditionFalse + conditionMap["gateway-hr-14-8081"][0].Reason = string(gatewayv1.RouteReasonPending) + + expectedRouteStatus = akogatewayapitests.GetRouteStatusV1([]string{gatewayName}, namespace, []int32{ports[1]}, conditionMap) + akogatewayapitests.ValidateHTTPRouteStatus(t, &httpRoute.Status, &gatewayv1.HTTPRouteStatus{RouteStatus: *expectedRouteStatus}) + + akogatewayapitests.TeardownHTTPRoute(t, httpRouteName2, namespace) + akogatewayapitests.TeardownGateway(t, gatewayName, namespace) + akogatewayapitests.TeardownGatewayClass(t, gatewayClassName) +} + +func TestHttpRouteWithValidAndInvalidGatewayListeners(t *testing.T) { + gatewayClassName := "gateway-class-hr-15" + gatewayName := "gateway-hr-15" + httpRouteName := "httproute-15" + namespace := "default" + ports := []int32{8080, 8081} + + akogatewayapitests.SetupGatewayClass(t, gatewayClassName, akogatewayapilib.GatewayController) + + listeners := akogatewayapitests.GetListenersV1(ports, false, false) + listeners[1].Protocol = "TCP" + + g := gomega.NewGomegaWithT(t) + akogatewayapitests.SetupGateway(t, gatewayName, namespace, gatewayClassName, nil, listeners) + 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) + hostnames := []gatewayv1.Hostname{"foo-8080.com", "foo-8081.com"} + + akogatewayapitests.SetupHTTPRoute(t, httpRouteName, namespace, parentRefs, hostnames, nil) + 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) != 2 { + 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 := make([]metav1.Condition, 0, 1) + condition := metav1.Condition{ + Type: string(gatewayv1.RouteConditionAccepted), + Reason: string(gatewayv1.RouteReasonAccepted), + Status: metav1.ConditionTrue, + Message: "Parent reference is valid", + } + conditions = append(conditions, condition) + conditionMap[fmt.Sprintf("%s-%d", gatewayName, port)] = conditions + } + conditionMap["gateway-hr-15-8081"][0].Message = "Matching gateway listener is in Invalid state" + conditionMap["gateway-hr-15-8081"][0].Status = metav1.ConditionFalse + conditionMap["gateway-hr-15-8081"][0].Reason = string(gatewayv1.RouteReasonPending) + + 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) +}