From 1c442df99c3c7b4dad6229a584905bc74789425e Mon Sep 17 00:00:00 2001 From: priyakoshta Date: Tue, 24 Sep 2024 12:52:25 +0530 Subject: [PATCH 1/2] AV-206839 Gateway status fixes --- ako-gateway-api/k8s/validator.go | 10 ++++++++-- ako-gateway-api/status/gateway_status.go | 3 ++- ako-gateway-api/status/gatewayclass_status.go | 3 ++- ako-gateway-api/status/httproute_status.go | 3 ++- ako-gateway-api/status/status.go | 6 +++++- 5 files changed, 19 insertions(+), 6 deletions(-) diff --git a/ako-gateway-api/k8s/validator.go b/ako-gateway-api/k8s/validator.go index 24c9a80d4..69376f315 100644 --- a/ako-gateway-api/k8s/validator.go +++ b/ako-gateway-api/k8s/validator.go @@ -124,6 +124,7 @@ 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 } else if validListenerCount < len(spec.Listeners) { defaultCondition. @@ -140,9 +141,14 @@ func IsValidGateway(key string, gateway *gatewayv1.Gateway) bool { Status(metav1.ConditionTrue). Message("Gateway configuration is valid"). SetIn(&gatewayStatus.Conditions) - akogatewayapistatus.Record(key, gateway, &status.Status{GatewayStatus: gatewayStatus}) + _, err := akogatewayapistatus.Record(key, gateway, &status.Status{GatewayStatus: gatewayStatus}) utils.AviLog.Infof("key: %s, msg: Gateway %s is valid", key, gateway.Name) - return true + if err == nil { + return true + } else { + utils.AviLog.Errorf("key: %s, msg: Gateway status patch was not successful :%s ", key, err.Error()) + return false + } } func isValidListener(key string, gateway *gatewayv1.Gateway, gatewayStatus *gatewayv1.GatewayStatus, index int) bool { diff --git a/ako-gateway-api/status/gateway_status.go b/ako-gateway-api/status/gateway_status.go index 383a9e2b8..f98c7be44 100644 --- a/ako-gateway-api/status/gateway_status.go +++ b/ako-gateway-api/status/gateway_status.go @@ -18,6 +18,7 @@ import ( "context" "encoding/json" "errors" + "errors" "reflect" "strings" @@ -237,7 +238,7 @@ func (o *gateway) Patch(key string, obj runtime.Object, status *status.Status, r patchPayload, _ := json.Marshal(map[string]interface{}{ "status": status.GatewayStatus, }) - _, err := akogatewayapilib.AKOControlConfig().GatewayAPIClientset().GatewayV1().Gateways(gw.Namespace).Patch(context.TODO(), gw.Name, types.MergePatchType, patchPayload, metav1.PatchOptions{}, "status") + updatedGateway, 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 e312130d0..9756504e5 100644 --- a/ako-gateway-api/status/gatewayclass_status.go +++ b/ako-gateway-api/status/gatewayclass_status.go @@ -18,6 +18,7 @@ import ( "context" "encoding/json" "errors" + "errors" "reflect" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -91,7 +92,7 @@ func (o *gatewayClass) Patch(key string, obj runtime.Object, status *status.Stat patchPayload, _ := json.Marshal(map[string]interface{}{ "status": status.GatewayClassStatus, }) - _, err := akogatewayapilib.AKOControlConfig().GatewayAPIClientset().GatewayV1().GatewayClasses().Patch(context.TODO(), gatewayClass.Name, types.MergePatchType, patchPayload, metav1.PatchOptions{}, "status") + updatedObject, 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 99a528ed1..07dbc20d4 100644 --- a/ako-gateway-api/status/httproute_status.go +++ b/ako-gateway-api/status/httproute_status.go @@ -18,6 +18,7 @@ import ( "context" "encoding/json" "errors" + "errors" "reflect" "strings" @@ -102,7 +103,7 @@ func (o *httproute) Patch(key string, obj runtime.Object, status *status.Status, patchPayload, _ := json.Marshal(map[string]interface{}{ "status": status.HTTPRouteStatus, }) - _, err := akogatewayapilib.AKOControlConfig().GatewayAPIClientset().GatewayV1().HTTPRoutes(httpRoute.Namespace).Patch(context.TODO(), httpRoute.Name, types.MergePatchType, patchPayload, metav1.PatchOptions{}, "status") + updatedObject, 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 7f7d2a58c..5fde5a032 100644 --- a/ako-gateway-api/status/status.go +++ b/ako-gateway-api/status/status.go @@ -15,9 +15,13 @@ 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" @@ -97,7 +101,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 + return obj, errors.New("Unsupported object received at the status layer") } updateOption.Status = objStatus updateOption.ServiceMetadata = serviceMetadata From edd9cff9785dfe3456fa10472f80ff584382d876 Mon Sep 17 00:00:00 2001 From: priyakoshta Date: Fri, 4 Oct 2024 11:22:50 +0530 Subject: [PATCH 2/2] 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 | 56 +- ako-gateway-api/k8s/validator.go | 37 +- ako-gateway-api/nodes/gateway_model.go | 33 +- ako-gateway-api/nodes/gateway_model_rel.go | 23 +- ako-gateway-api/nodes/route_validator.go | 11 + ako-gateway-api/objects/gateway_store.go | 26 + 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 | 7 +- .../graphlayer/httproute_test.go | 1175 ++++++++++++++++- tests/gatewayapitests/status/gateway_test.go | 8 +- .../gatewayapitests/status/httproute_test.go | 176 ++- 14 files changed, 1480 insertions(+), 112 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..41cd3a6a6 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) + } } }, } @@ -666,6 +689,7 @@ func (c *GatewayController) SetupGatewayApiEventHandlers(numWorkers uint32) { namespace, _, _ := cache.SplitMetaNamespaceKey(utils.ObjKey(httpRoute)) bkt := utils.Bkt(namespace, numWorkers) c.workqueue[bkt].AddRateLimited(key) + akogatewayapiobjects.GatewayApiLister().DeleteRouteToRouteStatusMapping(utils.ObjKey(httpRoute)) utils.AviLog.Debugf("key: %s, msg: DELETE", key) }, UpdateFunc: func(old, obj interface{}) { @@ -714,3 +738,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..33ba6bfe0 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 true, 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 { @@ -247,9 +249,8 @@ func isValidListener(key string, gateway *gatewayv1.Gateway, gatewayStatus *gate return false } name := string(certRef.Name) - cs := utils.GetInformers().ClientSet - secretObj, err := cs.CoreV1().Secrets(gateway.ObjectMeta.Namespace).Get(context.TODO(), name, metav1.GetOptions{}) - if err != nil || secretObj == nil { + _, err := utils.GetInformers().ClientSet.CoreV1().Secrets(gateway.ObjectMeta.Namespace).Get(context.TODO(), name, metav1.GetOptions{}) + if err != nil { utils.AviLog.Errorf("key: %s, msg: Secret specified in CertificateRef does not exist %+v/%+v", key, gateway.Name, listener.Name) defaultCondition.SetIn(&gatewayStatus.Listeners[index].Conditions) resolvedRefCondition. diff --git a/ako-gateway-api/nodes/gateway_model.go b/ako-gateway-api/nodes/gateway_model.go index f574daa03..0bfa215fd 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" @@ -75,10 +76,20 @@ func (o *AviObjectGraph) BuildGatewayParent(gateway *gatewayv1.Gateway, key stri return parentVsNode } +func IsListenerInvalid(gwStatus *gatewayv1.GatewayStatus, listenerIndex int) bool { + if len(gwStatus.Listeners) > int(listenerIndex) && gwStatus.Listeners[listenerIndex].Conditions[0].Type == string(gatewayv1.ListenerConditionAccepted) && gwStatus.Listeners[listenerIndex].Conditions[0].Status == "False" { + return true + } + return false +} + 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 IsListenerInvalid(gwStatus, i) { + 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 +107,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 IsListenerInvalid(gwStatus, i) { + continue + } if listener.TLS != nil { for _, certRef := range listener.TLS.CertificateRefs { //kind is validated at ingestion @@ -161,7 +176,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 IsListenerInvalid(gwStatus, i) { + continue + } if listener.TLS != nil { for _, certRef := range listener.TLS.CertificateRefs { name := string(certRef.Name) @@ -188,7 +207,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 IsListenerInvalid(gwStatus, i) { + 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..1b2f06f8b 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 IsListenerInvalid(gwStatus, i) { + continue + } gwListener := akogatewayapiobjects.GatewayListenerStore{} gwListener.Name = string(listenerObj.Name) gwListener.Gateway = gwNsName @@ -258,7 +264,21 @@ func HTTPRouteToGateway(namespace, name, key string) ([]string, bool) { var gatewayList []string var gwNsNameList []string parentNameToHostnameMap := make(map[string][]string) + statusIndex := 0 + httpRouteStatus := akogatewayapiobjects.GatewayApiLister().GetRouteToRouteStatusMapping(routeTypeNsName) for _, parentRef := range hrObj.Spec.ParentRefs { + if statusIndex >= len(httpRouteStatus.Parents) { + break + } + if httpRouteStatus.Parents[statusIndex].ParentRef.Name != parentRef.Name { + continue + } + for statusIndex < len(httpRouteStatus.Parents) && (parentRef.SectionName != nil && *httpRouteStatus.Parents[statusIndex].ParentRef.SectionName != *parentRef.SectionName) { + statusIndex += 1 + } + if httpRouteStatus.Parents[statusIndex].Conditions[0].Type == string(gatewayv1.RouteConditionAccepted) && httpRouteStatus.Parents[statusIndex].Conditions[0].Status == metav1.ConditionFalse { + continue + } hostnameIntersection, _ := parentNameToHostnameMap[string(parentRef.Name)] ns := namespace if parentRef.Namespace != nil { @@ -332,6 +352,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..864304f44 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 IsListenerInvalid(gwStatus, i) { + // 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/objects/gateway_store.go b/ako-gateway-api/objects/gateway_store.go index f7203e654..a22f926a3 100644 --- a/ako-gateway-api/objects/gateway_store.go +++ b/ako-gateway-api/objects/gateway_store.go @@ -50,6 +50,7 @@ func GatewayApiLister() *GWLister { gatewayRouteToHTTPSPGPoolStore: objects.NewObjectMapStore(), podToServiceStore: objects.NewObjectMapStore(), gatewayToStatus: objects.NewObjectMapStore(), + routeToStatus: objects.NewObjectMapStore(), } }) return gwLister @@ -119,6 +120,9 @@ type GWLister struct { // namespace/gateway -> gateway Status gatewayToStatus *objects.ObjectMapStore + + // routeType/routeNs/routeName -> route Status + routeToStatus *objects.ObjectMapStore } type GatewayRouteKind struct { @@ -259,6 +263,28 @@ func (g *GWLister) GetGatewayToGatewayStatusMapping(gwName string) *gatewayv1.Ga return gatewayList.(*gatewayv1.GatewayStatus) } +func (g *GWLister) UpdateRouteToRouteStatusMapping(routeTypeNamespaceName string, routeStatus *gatewayv1.RouteStatus) { + g.gwLock.Lock() + defer g.gwLock.Unlock() + g.routeToStatus.AddOrUpdate(routeTypeNamespaceName, routeStatus) +} + +func (g *GWLister) DeleteRouteToRouteStatusMapping(routeTypeNamespaceName string) { + g.gwLock.Lock() + defer g.gwLock.Unlock() + g.routeToStatus.Delete(routeTypeNamespaceName) +} + +func (g *GWLister) GetRouteToRouteStatusMapping(routeTypeNamespaceName string) *gatewayv1.RouteStatus { + g.gwLock.RLock() + defer g.gwLock.RUnlock() + found, routeList := g.routeToStatus.Get(routeTypeNamespaceName) + if !found { + return nil + } + return routeList.(*gatewayv1.RouteStatus) +} + //=====All route <-> gateway mappings go here. func (g *GWLister) GetRouteToGateway(routeTypeNsName string) (bool, []string) { 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..f6fe9e2fb 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" @@ -99,9 +95,10 @@ 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) 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..4a6f1d3f6 100644 --- a/tests/gatewayapitests/graphlayer/httproute_test.go +++ b/tests/gatewayapitests/graphlayer/httproute_test.go @@ -141,9 +141,9 @@ func TestHTTPRouteCRUD(t *testing.T) { func TestHTTPRouteRuleCRUD(t *testing.T) { - gatewayName := "gateway-hrr-01" - gatewayClassName := "gateway-class-hrr-01" - httpRouteName := "http-route-hrr-01" + gatewayName := "gateway-hr-02" + gatewayClassName := "gateway-class-hr-02" + httpRouteName := "http-route-hr-02" ports := []int32{8080} modelName, _ := akogatewayapitests.GetModelName(DEFAULT_NAMESPACE, gatewayName) @@ -209,9 +209,9 @@ func TestHTTPRouteRuleCRUD(t *testing.T) { func TestHTTPRouteFilterCRUD(t *testing.T) { - gatewayName := "gateway-hrf-01" - gatewayClassName := "gateway-class-hrf-01" - httpRouteName := "http-route-hrf-01" + gatewayName := "gateway-hr-03" + gatewayClassName := "gateway-class-hr-03" + httpRouteName := "http-route-hr-03" ports := []int32{8080} modelName, _ := akogatewayapitests.GetModelName(DEFAULT_NAMESPACE, gatewayName) @@ -285,9 +285,9 @@ func TestHTTPRouteFilterCRUD(t *testing.T) { func TestHTTPRouteFilterWithRequestHeaderModifier(t *testing.T) { - gatewayName := "gateway-hrf-02" - gatewayClassName := "gateway-class-hrf-02" - httpRouteName := "http-route-hrf-02" + gatewayName := "gateway-hr-04" + gatewayClassName := "gateway-class-hr-04" + httpRouteName := "http-route-hr-04" ports := []int32{8080} modelName, _ := akogatewayapitests.GetModelName(DEFAULT_NAMESPACE, gatewayName) @@ -365,9 +365,9 @@ func TestHTTPRouteFilterWithRequestHeaderModifier(t *testing.T) { func TestHTTPRouteFilterWithResponseHeaderModifier(t *testing.T) { - gatewayName := "gateway-hrf-03" - gatewayClassName := "gateway-class-hrf-03" - httpRouteName := "http-route-hrf-03" + gatewayName := "gateway-hr-05" + gatewayClassName := "gateway-class-hr-05" + httpRouteName := "http-route-hr-05" ports := []int32{8080} modelName, _ := akogatewayapitests.GetModelName(DEFAULT_NAMESPACE, gatewayName) @@ -445,9 +445,9 @@ func TestHTTPRouteFilterWithResponseHeaderModifier(t *testing.T) { func TestHTTPRouteFilterWithRequestRedirect(t *testing.T) { - gatewayName := "gateway-hrf-04" - gatewayClassName := "gateway-class-hrf-04" - httpRouteName := "http-route-hrf-04" + gatewayName := "gateway-hr-06" + gatewayClassName := "gateway-class-hr-06" + httpRouteName := "http-route-hr-06" ports := []int32{8080} modelName, _ := akogatewayapitests.GetModelName(DEFAULT_NAMESPACE, gatewayName) @@ -518,9 +518,9 @@ func TestHTTPRouteFilterWithRequestRedirect(t *testing.T) { } func TestHTTPRouteWithValidConfig(t *testing.T) { - gatewayClassName := "gateway-class-hr-01" - gatewayName := "gateway-hr-01" - httpRouteName := "httproute-01" + gatewayClassName := "gateway-class-hr-07" + gatewayName := "gateway-hr-07" + httpRouteName := "httproute-07" namespace := "default" ports := []int32{8080, 8081} @@ -590,10 +590,10 @@ func TestHTTPRouteWithValidConfig(t *testing.T) { func TestHTTPRouteBackendRefCRUD(t *testing.T) { - gatewayName := "gateway-hr-02" - gatewayClassName := "gateway-class-hr-02" - httpRouteName := "http-route-hr-02" - svcName := "avisvc-hr-02" + gatewayName := "gateway-hr-08" + gatewayClassName := "gateway-class-hr-08" + httpRouteName := "http-route-hr-08" + svcName := "avisvc-hr-08" ports := []int32{8080} modelName, _ := akogatewayapitests.GetModelName(DEFAULT_NAMESPACE, gatewayName) @@ -689,10 +689,10 @@ func TestHTTPRouteBackendRefCRUD(t *testing.T) { func TestHTTPRouteBackendServiceCDC(t *testing.T) { - gatewayName := "gateway-hr-03" - gatewayClassName := "gateway-class-hr-03" - httpRouteName := "http-route-hr-03" - svcName := "avisvc-hr-03" + gatewayName := "gateway-hr-09" + gatewayClassName := "gateway-class-hr-09" + httpRouteName := "http-route-hr-09" + svcName := "avisvc-hr-09" ports := []int32{8080} modelName, _ := akogatewayapitests.GetModelName(DEFAULT_NAMESPACE, gatewayName) @@ -775,11 +775,11 @@ func TestHTTPRouteBackendServiceCDC(t *testing.T) { func TestHTTPRouteBackendServiceUpdate(t *testing.T) { - gatewayName := "gateway-hr-04" - gatewayClassName := "gateway-class-hr-04" - httpRouteName := "http-route-hr-04" - svcName1 := "avisvc-hr-04-1" - svcName2 := "avisvc-hr-04-2" + gatewayName := "gateway-hr-10" + gatewayClassName := "gateway-class-hr-10" + httpRouteName := "http-route-hr-10" + svcName1 := "avisvc-hr-04-10a" + svcName2 := "avisvc-hr-04-10b" ports := []int32{8080} modelName, _ := akogatewayapitests.GetModelName(DEFAULT_NAMESPACE, gatewayName) @@ -875,10 +875,10 @@ func TestHTTPRouteBackendServiceUpdate(t *testing.T) { func TestHTTPRouteMultiportBackendSvc(t *testing.T) { - gatewayName := "gateway-hr-05" - gatewayClassName := "gateway-class-hr-05" - httpRouteName := "http-route-hr-05" - svcName := "avisvc-hr-05" + gatewayName := "gateway-hr-11" + gatewayClassName := "gateway-class-hr-11" + httpRouteName := "http-route-hr-11" + svcName := "avisvc-hr-11" ports := []int32{8080} modelName, _ := akogatewayapitests.GetModelName(DEFAULT_NAMESPACE, gatewayName) @@ -934,10 +934,10 @@ func TestHTTPRouteMultiportBackendSvc(t *testing.T) { func TestHTTPRouteInvalidHostname(t *testing.T) { - gatewayName := "gateway-hr-06" - gatewayClassName := "gateway-class-hr-06" - httpRouteName := "http-route-hr-06" - svcName := "avisvc-hr-056" + gatewayName := "gateway-hr-12" + gatewayClassName := "gateway-class-hr-12" + httpRouteName := "http-route-hr-12" + svcName := "avisvc-hr-12" ports := []int32{8080} modelName, parentVSName := akogatewayapitests.GetModelName(DEFAULT_NAMESPACE, gatewayName) @@ -1002,15 +1002,15 @@ func TestHTTPRouteInvalidHostname(t *testing.T) { } func TestHTTPRouteGatewayWithEmptyHostnameInGatewayHTTPRoute(t *testing.T) { - gatewayName := "gateway-hr-08" - gatewayClassName := "gateway-class-hr-08" - httpRouteName := "http-route-hr-08" - svcName := "avisvc-hr-058" + gatewayName := "gateway-hr-13" + gatewayClassName := "gateway-class-hr-13" + httpRouteName := "http-route-hr-13" + svcName := "avisvc-hr-13" ports := []int32{8080} modelName, _ := akogatewayapitests.GetModelName(DEFAULT_NAMESPACE, gatewayName) integrationtest.CreateSVC(t, DEFAULT_NAMESPACE, svcName, corev1.ProtocolTCP, corev1.ServiceTypeClusterIP, false) - integrationtest.CreateEP(t, DEFAULT_NAMESPACE, svcName, false, false, "1.2.3") + integrationtest.CreateEPorEPS(t, DEFAULT_NAMESPACE, svcName, false, false, "1.2.3") akogatewayapitests.SetupGatewayClass(t, gatewayClassName, akogatewayapilib.GatewayController) listeners := akogatewayapitests.GetListenersV1(ports, true, false) @@ -1061,16 +1061,16 @@ func TestHTTPRouteGatewayWithEmptyHostnameInGatewayHTTPRoute(t *testing.T) { g.Expect(len(nodes[0].PoolGroupRefs)).To(gomega.Equal(0)) integrationtest.DelSVC(t, DEFAULT_NAMESPACE, svcName) - integrationtest.DelEP(t, DEFAULT_NAMESPACE, svcName) + integrationtest.DelEPorEPS(t, DEFAULT_NAMESPACE, svcName) akogatewayapitests.TeardownGateway(t, gatewayName, DEFAULT_NAMESPACE) akogatewayapitests.TeardownGatewayClass(t, gatewayClassName) } func TestHTTPRouteWithMultipleListenerGateway(t *testing.T) { - gatewayName := "gateway-hr-09" - gatewayClassName := "gateway-class-hr-09" - httpRouteName := "http-route-hr-09" - svcName := "avisvc-hr-078" + gatewayName := "gateway-hr-14" + gatewayClassName := "gateway-class-hr-14" + httpRouteName := "http-route-hr-14" + svcName := "avisvc-hr-14" ports := []int32{8080, 8082} modelName, parentVSName := akogatewayapitests.GetModelName(DEFAULT_NAMESPACE, gatewayName) @@ -1160,11 +1160,11 @@ func TestHTTPRouteWithMultipleListenerGateway(t *testing.T) { akogatewayapitests.TeardownGatewayClass(t, gatewayClassName) } func TestHTTPRouteWithMultipleGateways(t *testing.T) { - gatewayName1 := "gateway-hr-18a" - gatewayName2 := "gateway-hr-18b" - gatewayClassName := "gateway-class-hr-18" - httpRouteName := "http-route-hr-18" - svcName := "avisvc-hr-018" + gatewayName1 := "gateway-hr-15a" + gatewayName2 := "gateway-hr-15b" + gatewayClassName := "gateway-class-hr-15" + httpRouteName := "http-route-hr-15" + svcName := "avisvc-hr-15" ports1 := []int32{8080} ports2 := []int32{8081} modelName1, _ := akogatewayapitests.GetModelName(DEFAULT_NAMESPACE, gatewayName1) @@ -1273,12 +1273,12 @@ func TestHTTPRouteParentFQDN(t *testing.T) { // delete httproutes // validate parent FQDN - gatewayName1 := "gateway-hr-19" + gatewayName1 := "gateway-hr-16" - gatewayClassName := "gateway-class-hr-19" - httpRouteName1 := "http-route-hr-19a" - httpRouteName2 := "http-route-hr-19b" - svcName := "avisvc-hr-019" + gatewayClassName := "gateway-class-hr-16" + httpRouteName1 := "http-route-hr-16a" + httpRouteName2 := "http-route-hr-16b" + svcName := "avisvc-hr-16" modelName, _ := akogatewayapitests.GetModelName(DEFAULT_NAMESPACE, gatewayName1) @@ -1417,3 +1417,1060 @@ func TestHTTPRouteParentFQDN(t *testing.T) { akogatewayapitests.TeardownGateway(t, gatewayName1, DEFAULT_NAMESPACE) akogatewayapitests.TeardownGatewayClass(t, gatewayClassName) } +func TestHttpRouteWithValidAndInvalidGatewayListeners(t *testing.T) { + gatewayName := "gateway-hr-17" + gatewayClassName := "gateway-class-hr-17" + httpRouteName := "http-route-hr-17" + svcName1 := "avisvc-hr-17-a" + svcName2 := "avisvc-hr-17-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 + }, 30*time.Second).Should(gomega.Equal(true)) + + integrationtest.CreateSVC(t, DEFAULT_NAMESPACE, svcName1, corev1.ProtocolTCP, corev1.ServiceTypeClusterIP, false) + integrationtest.CreateEPorEPS(t, DEFAULT_NAMESPACE, svcName1, false, false, "1.2.3") + + integrationtest.CreateSVC(t, DEFAULT_NAMESPACE, svcName2, corev1.ProtocolTCP, corev1.ServiceTypeClusterIP, false) + integrationtest.CreateEPorEPS(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, 5*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.DelEPorEPS(t, DEFAULT_NAMESPACE, svcName1) + integrationtest.DelSVC(t, DEFAULT_NAMESPACE, svcName2) + integrationtest.DelEPorEPS(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-18" + gatewayClassName := "gateway-class-hr-18" + httpRouteName1 := "http-route-hr-18-a" + httpRouteName2 := "http-route-hr-18-b" + svcName := "avisvc-hr-18" + 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.CreateEPorEPS(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.DelEPorEPS(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-19" + gatewayClassName := "gateway-class-hr-19" + httpRouteName := "http-route-hr-19" + svcName1 := "avisvc-hr-19-a" + svcName2 := "avisvc-hr-19-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.CreateEPorEPS(t, DEFAULT_NAMESPACE, svcName1, false, false, "1.2.3") + + integrationtest.CreateSVC(t, DEFAULT_NAMESPACE, svcName2, corev1.ProtocolTCP, corev1.ServiceTypeClusterIP, false) + integrationtest.CreateEPorEPS(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, 5*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 + }, 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)) + + _, 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.DelEPorEPS(t, DEFAULT_NAMESPACE, svcName1) + integrationtest.DelSVC(t, DEFAULT_NAMESPACE, svcName2) + integrationtest.DelEPorEPS(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-20" + gatewayClassName := "gateway-class-hr-20" + httpRouteName := "http-route-hr-20" + svcName1 := "avisvc-hr-20-a" + svcName2 := "avisvc-hr-20-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.CreateEPorEPS(t, DEFAULT_NAMESPACE, svcName1, false, false, "1.2.3") + + integrationtest.CreateSVC(t, DEFAULT_NAMESPACE, svcName2, corev1.ProtocolTCP, corev1.ServiceTypeClusterIP, false) + integrationtest.CreateEPorEPS(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, 5*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, 5*time.Second).Should(gomega.Equal(2)) + nodes = aviModel.(*avinodes.AviObjectGraph).GetAviEvhVS() + + integrationtest.DelSVC(t, DEFAULT_NAMESPACE, svcName1) + integrationtest.DelEPorEPS(t, DEFAULT_NAMESPACE, svcName1) + integrationtest.DelSVC(t, DEFAULT_NAMESPACE, svcName2) + integrationtest.DelEPorEPS(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-21" + gatewayClassName := "gateway-class-hr-21" + httpRouteName := "http-route-hr-21" + svcName1 := "avisvc-hr-21-a" + svcName2 := "avisvc-hr-21-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.CreateEPorEPS(t, DEFAULT_NAMESPACE, svcName1, false, false, "1.2.3") + + integrationtest.CreateSVC(t, DEFAULT_NAMESPACE, svcName2, corev1.ProtocolTCP, corev1.ServiceTypeClusterIP, false) + integrationtest.CreateEPorEPS(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, 5*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.DelEPorEPS(t, DEFAULT_NAMESPACE, svcName1) + integrationtest.DelSVC(t, DEFAULT_NAMESPACE, svcName2) + integrationtest.DelEPorEPS(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-22" + gatewayClassName := "gateway-class-hr-22" + httpRouteName := "http-route-hr-22" + svcName1 := "avisvc-hr-22-a" + svcName2 := "avisvc-hr-22-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.CreateEPorEPS(t, DEFAULT_NAMESPACE, svcName1, false, false, "1.2.3") + + integrationtest.CreateSVC(t, DEFAULT_NAMESPACE, svcName2, corev1.ProtocolTCP, corev1.ServiceTypeClusterIP, false) + integrationtest.CreateEPorEPS(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, 5*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, 5*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.DelEPorEPS(t, DEFAULT_NAMESPACE, svcName1) + integrationtest.DelSVC(t, DEFAULT_NAMESPACE, svcName2) + integrationtest.DelEPorEPS(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-23" + gatewayClassName := "gateway-class-hr-23" + httpRoute1Name := "http-route-hr-23a" + httpRoute2Name := "http-route-hr-23b" + svcName1 := "avisvc-hr-23-a" + svcName2 := "avisvc-hr-23-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.CreateEPorEPS(t, DEFAULT_NAMESPACE, svcName1, false, false, "1.2.3") + + integrationtest.CreateSVC(t, DEFAULT_NAMESPACE, svcName2, corev1.ProtocolTCP, corev1.ServiceTypeClusterIP, false) + integrationtest.CreateEPorEPS(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, 5*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, 5*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.DelEPorEPS(t, DEFAULT_NAMESPACE, svcName1) + integrationtest.DelSVC(t, DEFAULT_NAMESPACE, svcName2) + integrationtest.DelEPorEPS(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-24" + gatewayClassName := "gateway-class-hr-24" + httpRoute1Name := "http-route-hr-24a" + httpRoute2Name := "http-route-hr-24b" + svcName1 := "avisvc-hr-24-a" + svcName2 := "avisvc-hr-24-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.CreateEPorEPS(t, DEFAULT_NAMESPACE, svcName1, false, false, "1.2.3") + + integrationtest.CreateSVC(t, DEFAULT_NAMESPACE, svcName2, corev1.ProtocolTCP, corev1.ServiceTypeClusterIP, false) + integrationtest.CreateEPorEPS(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, 5*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.DelEPorEPS(t, DEFAULT_NAMESPACE, svcName1) + integrationtest.DelSVC(t, DEFAULT_NAMESPACE, svcName2) + integrationtest.DelEPorEPS(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 TestHttpRouteCreationBeforeGateway(t *testing.T) { + // 1: Two HTTPRoute with invalid gateway + gatewayName := "gateway-hr-25" + gatewayClassName := "gateway-class-hr-25" + httpRouteName := "http-route-hr-25" + svcName := "avisvc-hr-25" + ports := []int32{8080} + modelName, _ := akogatewayapitests.GetModelName(DEFAULT_NAMESPACE, gatewayName) + + akogatewayapitests.SetupGatewayClass(t, gatewayClassName, akogatewayapilib.GatewayController) + listeners := akogatewayapitests.GetListenersV1(ports, false, false) + + g := gomega.NewGomegaWithT(t) + integrationtest.CreateSVC(t, DEFAULT_NAMESPACE, svcName, corev1.ProtocolTCP, corev1.ServiceTypeClusterIP, false) + integrationtest.CreateEPorEPS(t, DEFAULT_NAMESPACE, svcName, false, false, "1.2.3") + + parentRefs := akogatewayapitests.GetParentReferencesV1([]string{gatewayName}, DEFAULT_NAMESPACE, []int32{ports[0]}) + rule := akogatewayapitests.GetHTTPRouteRuleV1([]string{"/foo"}, []string{}, + map[string][]string{"RequestHeaderModifier": {"add", "remove", "replace"}}, + [][]string{{svcName, DEFAULT_NAMESPACE, "8080", "1"}}, nil) + + rules := []gatewayv1.HTTPRouteRule{rule} + hostnames := []gatewayv1.Hostname{"foo-8080.com"} + akogatewayapitests.SetupHTTPRoute(t, httpRouteName, DEFAULT_NAMESPACE, parentRefs, hostnames, rules) + g.Eventually(func() bool { + httpRoute, err := akogatewayapitests.GatewayClient.GatewayV1().HTTPRoutes(DEFAULT_NAMESPACE).Get(context.TODO(), httpRouteName, metav1.GetOptions{}) + if err != nil || httpRoute == nil { + t.Logf("Couldn't get the HTTPRoute, err: %+v", err) + return false + } + return httpRoute.Status.RouteStatus.Parents != nil + }, 30*time.Second).Should(gomega.Equal(true)) + + akogatewayapitests.SetupGateway(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) + }, 300*time.Second, 5*time.Second).Should(gomega.Equal(1)) + _, aviModel := objects.SharedAviGraphLister().Get(modelName) + nodes := aviModel.(*avinodes.AviObjectGraph).GetAviEvhVS() + childNode := nodes[0].EvhNodes[0] + g.Expect(childNode.PoolGroupRefs).To(gomega.HaveLen(1)) + g.Expect(childNode.PoolGroupRefs[0].Members).To(gomega.HaveLen(1)) + g.Expect(childNode.DefaultPoolGroup).NotTo(gomega.Equal("")) + g.Expect(childNode.PoolRefs).To(gomega.HaveLen(1)) + g.Expect(childNode.PoolRefs[0].Port).To(gomega.Equal(int32(8080))) + g.Expect(len(childNode.PoolRefs[0].Servers)).To(gomega.Equal(1)) + g.Expect(len(childNode.VHMatches)).To(gomega.Equal(1)) + g.Expect(*childNode.VHMatches[0].Host).To(gomega.Equal("foo-8080.com")) + g.Expect(len(childNode.VHMatches[0].Rules)).To(gomega.Equal(1)) + g.Expect(childNode.VHMatches[0].Rules[0].Matches.Path.MatchStr[0]).To(gomega.Equal("/foo")) + g.Expect(len(childNode.VHMatches[0].Rules[0].Matches.VsPort.Ports)).To(gomega.Equal(1)) + g.Expect(childNode.VHMatches[0].Rules[0].Matches.VsPort.Ports[0]).To(gomega.Equal(int64(8080))) + + integrationtest.DelSVC(t, DEFAULT_NAMESPACE, svcName) + integrationtest.DelEPorEPS(t, DEFAULT_NAMESPACE, svcName) + akogatewayapitests.TeardownHTTPRoute(t, httpRouteName, DEFAULT_NAMESPACE) + akogatewayapitests.TeardownGateway(t, gatewayName, DEFAULT_NAMESPACE) + akogatewayapitests.TeardownGatewayClass(t, gatewayClassName) +} diff --git a/tests/gatewayapitests/status/gateway_test.go b/tests/gatewayapitests/status/gateway_test.go index f32a1225b..87923ab21 100644 --- a/tests/gatewayapitests/status/gateway_test.go +++ b/tests/gatewayapitests/status/gateway_test.go @@ -695,7 +695,7 @@ func TestGatewayWithUnsupportedProtocolInListeners(t *testing.T) { Conditions: []metav1.Condition{ { Type: string(gatewayv1.GatewayConditionAccepted), - Status: metav1.ConditionFalse, + Status: metav1.ConditionTrue, Message: "Gateway contains atleast one valid listener", ObservedGeneration: 1, Reason: string(gatewayv1.GatewayReasonListenersNotValid), @@ -707,6 +707,10 @@ func TestGatewayWithUnsupportedProtocolInListeners(t *testing.T) { expectedStatus.Listeners[0].Conditions[0].Status = metav1.ConditionFalse expectedStatus.Listeners[0].Conditions[0].Message = "Unsupported protocol" + expectedStatus.Listeners[1].Conditions[0].Reason = string(gatewayv1.ListenerReasonAccepted) + expectedStatus.Listeners[1].Conditions[0].Status = metav1.ConditionTrue + expectedStatus.Listeners[1].Conditions[0].Message = "Listener is valid" + gateway, err := tests.GatewayClient.GatewayV1().Gateways(DEFAULT_NAMESPACE).Get(context.TODO(), gatewayName, metav1.GetOptions{}) if err != nil || gateway == nil { t.Fatalf("Couldn't get the gateway, err: %+v", err) @@ -799,7 +803,7 @@ func TestGatewayWithInvalidTLSConfigInListeners(t *testing.T) { Conditions: []metav1.Condition{ { Type: string(gatewayv1.GatewayConditionAccepted), - Status: metav1.ConditionFalse, + Status: metav1.ConditionTrue, Message: "Gateway contains atleast one valid listener", ObservedGeneration: 1, Reason: string(gatewayv1.GatewayReasonListenersNotValid), diff --git a/tests/gatewayapitests/status/httproute_test.go b/tests/gatewayapitests/status/httproute_test.go index f24d0d2c5..5ded4e7eb 100644 --- a/tests/gatewayapitests/status/httproute_test.go +++ b/tests/gatewayapitests/status/httproute_test.go @@ -404,8 +404,6 @@ func TestHTTPRouteWithNoParentReference(t *testing.T) { akogatewayapitests.SetupHTTPRoute(t, httpRouteName, namespace, nil, hostnames, nil) - time.Sleep(10 * time.Second) - g.Eventually(func() bool { httpRoute, err := akogatewayapitests.GatewayClient.GatewayV1().HTTPRoutes(namespace).Get(context.TODO(), httpRouteName, metav1.GetOptions{}) if err != nil || httpRoute == nil { @@ -506,8 +504,6 @@ func TestHTTPRouteWithNonExistingGatewayReference(t *testing.T) { akogatewayapitests.SetupHTTPRoute(t, httpRouteName, namespace, parentRefs, hostnames, nil) - time.Sleep(10 * time.Second) - g := gomega.NewGomegaWithT(t) g.Eventually(func() bool { httpRoute, err := akogatewayapitests.GatewayClient.GatewayV1().HTTPRoutes(namespace).Get(context.TODO(), httpRouteName, metav1.GetOptions{}) @@ -851,3 +847,175 @@ 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 := []metav1.Condition{{ + Type: string(gatewayv1.RouteConditionAccepted), + Reason: string(gatewayv1.RouteReasonAccepted), + Status: metav1.ConditionTrue, + Message: "Parent reference is valid", + }} + 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) +}