diff --git a/ako-gateway-api/k8s/validator.go b/ako-gateway-api/k8s/validator.go index f433aad21..e655ede75 100644 --- a/ako-gateway-api/k8s/validator.go +++ b/ako-gateway-api/k8s/validator.go @@ -15,6 +15,7 @@ package k8s import ( + "context" "fmt" "regexp" "strings" @@ -73,6 +74,12 @@ func IsValidGateway(key string, gateway *gatewayv1.Gateway) bool { Reason(string(gatewayv1.GatewayReasonInvalid)). Status(metav1.ConditionFalse). ObservedGeneration(gateway.ObjectMeta.Generation) + programmedCondition := akogatewayapistatus.NewCondition(). + Type(string(gatewayv1.GatewayConditionProgrammed)). + Reason(string(gatewayv1.GatewayReasonInvalid)). + Status(metav1.ConditionFalse). + ObservedGeneration(gateway.ObjectMeta.Generation). + Message("Gateway not programmed") gatewayStatus := gateway.Status.DeepCopy() @@ -82,7 +89,12 @@ func IsValidGateway(key string, gateway *gatewayv1.Gateway) bool { defaultCondition. Message("No listeners found"). SetIn(&gatewayStatus.Conditions) - akogatewayapistatus.Record(key, gateway, &akogatewayapistatus.Status{GatewayStatus: gatewayStatus}) + programmedCondition. + SetIn(&gatewayStatus.Conditions) + _, err := akogatewayapistatus.Record(key, gateway, &akogatewayapistatus.Status{GatewayStatus: gatewayStatus}) + if err != nil { + utils.AviLog.Errorf("key: %s, msg: Gateway status patch was not successful :%s ", key, err.Error()) + } return false } @@ -92,37 +104,66 @@ func IsValidGateway(key string, gateway *gatewayv1.Gateway) bool { defaultCondition. Message("More than one address is not supported"). SetIn(&gatewayStatus.Conditions) - akogatewayapistatus.Record(key, gateway, &akogatewayapistatus.Status{GatewayStatus: gatewayStatus}) + programmedCondition. + Reason(string(gatewayv1.GatewayReasonAddressNotUsable)). + SetIn(&gatewayStatus.Conditions) + _, err := akogatewayapistatus.Record(key, gateway, &akogatewayapistatus.Status{GatewayStatus: gatewayStatus}) + if err != nil { + utils.AviLog.Errorf("key: %s, msg: Gateway status patch was not successful :%s ", key, err.Error()) + } return false } if len(spec.Addresses) == 1 && *spec.Addresses[0].Type != "IPAddress" { utils.AviLog.Errorf("key: %s, msg: gateway address is not of type IPAddress %+v", key, gateway.Name) defaultCondition. + Reason(string(gatewayv1.GatewayReasonUnsupportedAddress)). Message("Only IPAddress as AddressType is supported"). SetIn(&gatewayStatus.Conditions) - akogatewayapistatus.Record(key, gateway, &akogatewayapistatus.Status{GatewayStatus: gatewayStatus}) + programmedCondition. + Reason(string(gatewayv1.GatewayReasonAddressNotUsable)). + SetIn(&gatewayStatus.Conditions) + _, err := akogatewayapistatus.Record(key, gateway, &akogatewayapistatus.Status{GatewayStatus: gatewayStatus}) + if err != nil { + utils.AviLog.Errorf("key: %s, msg: Gateway status patch was not successful :%s ", key, err.Error()) + } return false } gatewayStatus.Listeners = make([]gatewayv1.ListenerStatus, len(gateway.Spec.Listeners)) - var invalidListenerCount int + var validListenerCount int for index := range spec.Listeners { - if !isValidListener(key, gateway, gatewayStatus, index) { - invalidListenerCount++ + if isValidListener(key, gateway, gatewayStatus, index) { + validListenerCount++ } } - if invalidListenerCount > 0 { - utils.AviLog.Errorf("key: %s, msg: Gateway %s contains %d invalid listeners", key, gateway.Name, invalidListenerCount) + if validListenerCount == 0 { + utils.AviLog.Errorf("key: %s, msg: Gateway %s does not contain any valid listener", key, gateway.Name) defaultCondition. Type(string(gatewayv1.GatewayConditionAccepted)). Reason(string(gatewayv1.GatewayReasonListenersNotValid)). - Message(fmt.Sprintf("Gateway contains %d invalid listener(s)", invalidListenerCount)). + Message("Gateway does not contain any valid listener"). + SetIn(&gatewayStatus.Conditions) + programmedCondition. SetIn(&gatewayStatus.Conditions) akogatewayapistatus.Record(key, gateway, &akogatewayapistatus.Status{GatewayStatus: gatewayStatus}) + gateway.Status = *gatewayStatus.DeepCopy() return false + } else if validListenerCount < len(spec.Listeners) { + defaultCondition. + Reason(string(gatewayv1.GatewayReasonListenersNotValid)). + Message("Gateway contains atleast one valid listener"). + SetIn(&gatewayStatus.Conditions) + _, err := akogatewayapistatus.Record(key, gateway, &akogatewayapistatus.Status{GatewayStatus: gatewayStatus}) + utils.AviLog.Infof("key: %s, msg: Gateway %s contains atleast one valid listener", key, gateway.Name) + if err == nil { + return false + } else { + utils.AviLog.Errorf("key: %s, msg: Gateway status patch was not successful :%s ", key, err.Error()) + return false + } } defaultCondition. @@ -130,9 +171,14 @@ func IsValidGateway(key string, gateway *gatewayv1.Gateway) bool { Status(metav1.ConditionTrue). Message("Gateway configuration is valid"). SetIn(&gatewayStatus.Conditions) - akogatewayapistatus.Record(key, gateway, &akogatewayapistatus.Status{GatewayStatus: gatewayStatus}) + _, err := akogatewayapistatus.Record(key, gateway, &akogatewayapistatus.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 { @@ -143,8 +189,16 @@ func isValidListener(key string, gateway *gatewayv1.Gateway, gatewayStatus *gate gatewayStatus.Listeners[index].AttachedRoutes = akogatewayapilib.ZeroAttachedRoutes defaultCondition := akogatewayapistatus.NewCondition(). - Type(string(gatewayv1.GatewayConditionAccepted)). - Reason(string(gatewayv1.GatewayReasonListenersNotValid)). + Type(string(gatewayv1.ListenerConditionAccepted)). + Reason(string(gatewayv1.ListenerReasonInvalid)). + Message("Listener is Invalid"). + Status(metav1.ConditionFalse). + ObservedGeneration(gateway.ObjectMeta.Generation) + + programmedCondition := akogatewayapistatus.NewCondition(). + Type(string(gatewayv1.ListenerConditionProgrammed)). + Reason(string(gatewayv1.ListenerReasonInvalid)). + Message("Virtual service not configured/updated for this listener"). Status(metav1.ConditionFalse). ObservedGeneration(gateway.ObjectMeta.Generation) @@ -165,6 +219,7 @@ func isValidListener(key string, gateway *gatewayv1.Gateway, gatewayStatus *gate defaultCondition. Message("Hostname is same as an existing gateway hostname"). SetIn(&gatewayStatus.Listeners[index].Conditions) + programmedCondition.SetIn(&gatewayStatus.Listeners[index].Conditions) return false } } @@ -176,6 +231,7 @@ func isValidListener(key string, gateway *gatewayv1.Gateway, gatewayStatus *gate defaultCondition. Message(fmt.Sprintf("Didn't find match for hostname :%s in available sub-domains", string(*listener.Hostname))). SetIn(&gatewayStatus.Listeners[index].Conditions) + programmedCondition.SetIn(&gatewayStatus.Listeners[index].Conditions) return false } } @@ -188,18 +244,24 @@ func isValidListener(key string, gateway *gatewayv1.Gateway, gatewayStatus *gate Reason(string(gatewayv1.ListenerReasonUnsupportedProtocol)). Message("Unsupported protocol"). SetIn(&gatewayStatus.Listeners[index].Conditions) + programmedCondition.SetIn(&gatewayStatus.Listeners[index].Conditions) gatewayStatus.Listeners[index].SupportedKinds = akogatewayapilib.SupportedKinds[gatewayv1.HTTPSProtocolType] return false } + resolvedRefCondition := akogatewayapistatus.NewCondition(). + Type(string(gatewayv1.ListenerConditionResolvedRefs)). + Status(metav1.ConditionFalse). + ObservedGeneration(gateway.ObjectMeta.Generation) // has valid TLS config if listener.TLS != nil { if (listener.TLS.Mode != nil && *listener.TLS.Mode != gatewayv1.TLSModeTerminate) || len(listener.TLS.CertificateRefs) == 0 { utils.AviLog.Errorf("key: %s, msg: tls mode/ref not valid %+v/%+v", key, gateway.Name, listener.Name) - defaultCondition. - Reason(string(gatewayv1.ListenerReasonInvalidCertificateRef)). + defaultCondition.SetIn(&gatewayStatus.Listeners[index].Conditions) + resolvedRefCondition.Reason(string(gatewayv1.ListenerReasonInvalidCertificateRef)). Message("TLS mode or reference not valid"). SetIn(&gatewayStatus.Listeners[index].Conditions) + programmedCondition.SetIn(&gatewayStatus.Listeners[index].Conditions) return false } for _, certRef := range listener.TLS.CertificateRefs { @@ -207,13 +269,26 @@ func isValidListener(key string, gateway *gatewayv1.Gateway, gatewayStatus *gate if (certRef.Group != nil && string(*certRef.Group) != "") || certRef.Kind != nil && string(*certRef.Kind) != utils.Secret { utils.AviLog.Errorf("key: %s, msg: CertificateRef is not valid %+v/%+v, must be Secret", key, gateway.Name, listener.Name) - defaultCondition. - Reason(string(gatewayv1.ListenerReasonInvalidCertificateRef)). + defaultCondition.SetIn(&gatewayStatus.Listeners[index].Conditions) + resolvedRefCondition.Reason(string(gatewayv1.ListenerReasonInvalidCertificateRef)). Message("TLS mode or reference not valid"). SetIn(&gatewayStatus.Listeners[index].Conditions) + programmedCondition.SetIn(&gatewayStatus.Listeners[index].Conditions) + 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 { + 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. + Reason(string(gatewayv1.ListenerReasonInvalidCertificateRef)). + Message("Secret does not exist"). + SetIn(&gatewayStatus.Listeners[index].Conditions) + programmedCondition.SetIn(&gatewayStatus.Listeners[index].Conditions) return false } - } } @@ -223,20 +298,22 @@ func isValidListener(key string, gateway *gatewayv1.Gateway, gatewayStatus *gate for _, kindInAllowedRoute := range listener.AllowedRoutes.Kinds { if kindInAllowedRoute.Kind != "" && string(kindInAllowedRoute.Kind) != utils.HTTPRoute { utils.AviLog.Errorf("key: %s, msg: AllowedRoute kind is invalid %+v/%+v. Supported AllowedRoute kind is HTTPRoute.", key, gateway.Name, listener.Name) - defaultCondition. - Type(string(gatewayv1.ListenerConditionResolvedRefs)). + defaultCondition.SetIn(&gatewayStatus.Listeners[index].Conditions) + resolvedRefCondition. Reason(string(gatewayv1.ListenerReasonInvalidRouteKinds)). Message("AllowedRoute kind is invalid. Only HTTPRoute is supported currently"). SetIn(&gatewayStatus.Listeners[index].Conditions) + programmedCondition.SetIn(&gatewayStatus.Listeners[index].Conditions) return false } if kindInAllowedRoute.Group != nil && *kindInAllowedRoute.Group != "" && string(*kindInAllowedRoute.Group) != gatewayv1.GroupName { utils.AviLog.Errorf("key: %s, msg: AllowedRoute Group is invalid %+v/%+v.", key, gateway.Name, listener.Name) - defaultCondition. - Type(string(gatewayv1.ListenerConditionResolvedRefs)). + defaultCondition.SetIn(&gatewayStatus.Listeners[index].Conditions) + resolvedRefCondition. Reason(string(gatewayv1.ListenerReasonInvalidRouteKinds)). Message("AllowedRoute Group is invalid."). SetIn(&gatewayStatus.Listeners[index].Conditions) + programmedCondition.SetIn(&gatewayStatus.Listeners[index].Conditions) return false } } @@ -245,10 +322,18 @@ func isValidListener(key string, gateway *gatewayv1.Gateway, gatewayStatus *gate // Valid listener defaultCondition. - Reason(string(gatewayv1.GatewayReasonAccepted)). + Reason(string(gatewayv1.ListenerReasonAccepted)). Status(metav1.ConditionTrue). Message("Listener is valid"). SetIn(&gatewayStatus.Listeners[index].Conditions) + + // Setting the resolvedRef condition + resolvedRefCondition. + Status(metav1.ConditionTrue). + Reason(string(gatewayv1.ListenerReasonResolvedRefs)). + Message("All the references are valid"). + SetIn(&gatewayStatus.Listeners[index].Conditions) + utils.AviLog.Infof("key: %s, msg: Listener %s/%s is valid", key, gateway.Name, listener.Name) return true } @@ -317,8 +402,7 @@ func validateParentReference(key string, httpRoute *gatewayv1.HTTPRoute, httpRou } defaultCondition := akogatewayapistatus.NewCondition(). - Type(string(gatewayv1.GatewayConditionAccepted)). - Reason(string(gatewayv1.GatewayReasonInvalid)). + Type(string(gatewayv1.RouteConditionAccepted)). Status(metav1.ConditionFalse). ObservedGeneration(httpRoute.ObjectMeta.Generation) @@ -327,6 +411,7 @@ func validateParentReference(key string, httpRoute *gatewayv1.HTTPRoute, httpRou utils.AviLog.Errorf("key: %s, msg: AKO is yet to process Gateway %s for parent reference %s.", key, gateway.Name, name) err := fmt.Errorf("AKO is yet to process Gateway %s for parent reference %s", gateway.Name, name) defaultCondition. + Reason(string(gatewayv1.RouteReasonPending)). Message(err.Error()). SetIn(&httpRouteStatus.Parents[*parentRefIndexInHttpRouteStatus].Conditions) *parentRefIndexInHttpRouteStatus = *parentRefIndexInHttpRouteStatus + 1 @@ -340,6 +425,7 @@ func validateParentReference(key string, httpRoute *gatewayv1.HTTPRoute, httpRou utils.AviLog.Errorf("key: %s, msg: Gateway %s for parent reference %s is in Invalid State", key, gateway.Name, name) err := fmt.Errorf("Gateway %s is in Invalid State", gateway.Name) defaultCondition. + Reason(string(gatewayv1.RouteReasonPending)). Message(err.Error()). SetIn(&httpRouteStatus.Parents[*parentRefIndexInHttpRouteStatus].Conditions) *parentRefIndexInHttpRouteStatus = *parentRefIndexInHttpRouteStatus + 1 @@ -356,6 +442,7 @@ func validateParentReference(key string, httpRoute *gatewayv1.HTTPRoute, httpRou utils.AviLog.Errorf("key: %s, msg: unable to find the listener from the Section Name %s in Parent Reference %s", key, name, listenerName) err := fmt.Errorf("Invalid listener name provided") defaultCondition. + Reason(string(gatewayv1.RouteReasonNoMatchingParent)). Message(err.Error()). SetIn(&httpRouteStatus.Parents[*parentRefIndexInHttpRouteStatus].Conditions) *parentRefIndexInHttpRouteStatus = *parentRefIndexInHttpRouteStatus + 1 @@ -435,6 +522,7 @@ func validateParentReference(key string, httpRoute *gatewayv1.HTTPRoute, httpRou if len(listenersMatchedToRoute) == 0 { err := fmt.Errorf("Hostname in Gateway Listener doesn't match with any of the hostnames in HTTPRoute") defaultCondition. + Reason(string(gatewayv1.RouteReasonNoMatchingListenerHostname)). Message(err.Error()). SetIn(&httpRouteStatus.Parents[*parentRefIndexInHttpRouteStatus].Conditions) *parentRefIndexInHttpRouteStatus = *parentRefIndexInHttpRouteStatus + 1 @@ -447,6 +535,9 @@ func validateParentReference(key string, httpRoute *gatewayv1.HTTPRoute, httpRou } return err } + + //TODO: Add a condition to check whether this route is allowed by the parent gateways allowedroute field and set gatewayv1.RouteReasonNotAllowedByListeners reason while implemenating gateway->listener->allowedRoutes->Selector + gatewayStatus := gateway.Status.DeepCopy() for _, listenerObj := range listenersMatchedToRoute { listenerName := listenerObj.Name @@ -457,6 +548,7 @@ func validateParentReference(key string, httpRoute *gatewayv1.HTTPRoute, httpRou utils.AviLog.Errorf("key: %s, msg: Gateway status is missing for the listener with name %s", key, listenerName) err := fmt.Errorf("Couldn't find the listener %s in the Gateway status", listenerName) defaultCondition. + Reason(string(gatewayv1.RouteReasonNoMatchingParent)). Message(err.Error()). SetIn(&httpRouteStatus.Parents[*parentRefIndexInHttpRouteStatus].Conditions) *parentRefIndexInHttpRouteStatus = *parentRefIndexInHttpRouteStatus + 1 @@ -468,7 +560,7 @@ func validateParentReference(key string, httpRoute *gatewayv1.HTTPRoute, httpRou akogatewayapistatus.Record(key, gateway, &akogatewayapistatus.Status{GatewayStatus: gatewayStatus}) defaultCondition. - Reason(string(gatewayv1.GatewayReasonAccepted)). + Reason(string(gatewayv1.RouteReasonAccepted)). Status(metav1.ConditionTrue). Message("Parent reference is valid"). SetIn(&httpRouteStatus.Parents[*parentRefIndexInHttpRouteStatus].Conditions) diff --git a/ako-gateway-api/status/gateway_status.go b/ako-gateway-api/status/gateway_status.go index 55e3bd855..8596c7c3b 100644 --- a/ako-gateway-api/status/gateway_status.go +++ b/ako-gateway-api/status/gateway_status.go @@ -17,6 +17,7 @@ package status import ( "context" "encoding/json" + "errors" "reflect" "strings" @@ -154,13 +155,12 @@ func (o *gateway) Update(key string, option status.StatusOptions) { conditionStatus := metav1.ConditionTrue if option.Options.Message != "" { - conditionType = string(gatewayv1.GatewayConditionAccepted) + conditionType = string(gatewayv1.GatewayConditionProgrammed) conditionStatus = metav1.ConditionFalse reason = string(gatewayv1.GatewayReasonInvalid) message = option.Options.Message } else { conditionType = string(gatewayv1.GatewayConditionProgrammed) - conditionStatus = metav1.ConditionTrue reason = string(gatewayv1.GatewayReasonProgrammed) message = "Virtual service configured/updated" } @@ -175,9 +175,9 @@ func (o *gateway) Update(key string, option status.StatusOptions) { for i := range status.Listeners { listenerCondition := NewCondition() listenerCondition. - Type(conditionType). + Type(string(gatewayv1.ListenerConditionProgrammed)). Status(conditionStatus). - Reason(reason). + Reason(string(gatewayv1.ListenerReasonProgrammed)). ObservedGeneration(gw.ObjectMeta.Generation). Message(message). SetIn(&status.Listeners[i].Conditions) @@ -213,37 +213,37 @@ func (o *gateway) BulkUpdate(key string, options []status.StatusOptions) { } } -func (o *gateway) Patch(key string, obj runtime.Object, status *Status, retryNum ...int) { +func (o *gateway) Patch(key string, obj runtime.Object, status *Status, retryNum ...int) (runtime.Object, error) { retry := 0 if len(retryNum) > 0 { retry = retryNum[0] if retry >= 5 { utils.AviLog.Errorf("key: %s, msg: Patch retried 5 times, aborting", key) - return + return obj, errors.New("Patch retried 5 times, aborting") } } gw := obj.(*gatewayv1.Gateway) if o.isStatusEqual(&gw.Status, status.GatewayStatus) { - return + return obj, nil } 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) if err != nil { utils.AviLog.Warnf("gateway not found %v", err) - return + return updatedGW, err } - o.Patch(key, updatedGW, status, retry+1) - return + return o.Patch(key, updatedGW, status, retry+1) } utils.AviLog.Infof("key: %s, msg: Successfully updated the gateway %s/%s status %+v", key, gw.Namespace, gw.Name, utils.Stringify(status)) + return updatedGateway, nil } func (o *gateway) isStatusEqual(old, new *gatewayv1.GatewayStatus) bool { diff --git a/ako-gateway-api/status/gatewayclass_status.go b/ako-gateway-api/status/gatewayclass_status.go index 698862d78..775fc990b 100644 --- a/ako-gateway-api/status/gatewayclass_status.go +++ b/ako-gateway-api/status/gatewayclass_status.go @@ -17,6 +17,7 @@ package status import ( "context" "encoding/json" + "errors" "reflect" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -72,37 +73,36 @@ func (o *gatewayClass) BulkUpdate(key string, options []status.StatusOptions) { // TODO: Add this code when we publish the status from the rest layer } -func (o *gatewayClass) Patch(key string, obj runtime.Object, status *Status, retryNum ...int) { +func (o *gatewayClass) Patch(key string, obj runtime.Object, status *Status, retryNum ...int) (runtime.Object, error) { retry := 0 if len(retryNum) > 0 { retry = retryNum[0] if retry >= 5 { utils.AviLog.Errorf("key: %s, msg: Patch retried 5 times, aborting", key) - return + return obj, errors.New("Patch retried 5 times, aborting") } } gatewayClass := obj.(*gatewayv1.GatewayClass) if o.isStatusEqual(&gatewayClass.Status, status.GatewayClassStatus) { - return + return obj, nil } 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) if err != nil { utils.AviLog.Warnf("GatewayClass not found %v", err) - return + return updatedObj, err } - o.Patch(key, updatedObj, status, retry+1) - return + return o.Patch(key, updatedObj, status, retry+1) } - utils.AviLog.Infof("key: %s, msg: Successfully updated the GatewayClass %s status %+v %v", key, gatewayClass.Name, utils.Stringify(status), err) + return updatedObject, nil } func (o *gatewayClass) isStatusEqual(old, new *gatewayv1.GatewayClassStatus) bool { diff --git a/ako-gateway-api/status/httproute_status.go b/ako-gateway-api/status/httproute_status.go index cd8975326..ce5b46a9e 100644 --- a/ako-gateway-api/status/httproute_status.go +++ b/ako-gateway-api/status/httproute_status.go @@ -17,6 +17,7 @@ package status import ( "context" "encoding/json" + "errors" "reflect" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -72,37 +73,37 @@ func (o *httproute) BulkUpdate(key string, options []status.StatusOptions) { // TODO: Add this code when we publish the status from the rest layer } -func (o *httproute) Patch(key string, obj runtime.Object, status *Status, retryNum ...int) { +func (o *httproute) Patch(key string, obj runtime.Object, status *Status, retryNum ...int) (runtime.Object, error) { retry := 0 if len(retryNum) > 0 { retry = retryNum[0] if retry >= 5 { utils.AviLog.Errorf("key: %s, msg: Patch retried 5 times, aborting", key) - return + return obj, errors.New("Patch retried 5 times, aborting") } } httpRoute := obj.(*gatewayv1.HTTPRoute) if o.isStatusEqual(&httpRoute.Status, status.HTTPRouteStatus) { - return + return obj, nil } 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) if err != nil { utils.AviLog.Warnf("HTTPRoute not found %v", err) - return + return updatedObj, err } - o.Patch(key, updatedObj, status, retry+1) - return + return o.Patch(key, updatedObj, status, retry+1) } utils.AviLog.Infof("key: %s, msg: Successfully updated the HTTPRoute %s/%s status %+v", key, httpRoute.Namespace, httpRoute.Name, utils.Stringify(status)) + return updatedObject, nil } func (o *httproute) isStatusEqual(old, new *gatewayv1.HTTPRouteStatus) bool { diff --git a/ako-gateway-api/status/status.go b/ako-gateway-api/status/status.go index 6835406ad..ee57e5d0f 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" "github.com/vmware/load-balancer-and-ingress-services-for-kubernetes/internal/lib" "github.com/vmware/load-balancer-and-ingress-services-for-kubernetes/internal/status" "github.com/vmware/load-balancer-and-ingress-services-for-kubernetes/pkg/utils" @@ -26,7 +30,7 @@ import ( type StatusUpdater interface { Update(key string, option status.StatusOptions) BulkUpdate(key string, options []status.StatusOptions) - Patch(key string, obj runtime.Object, status *Status, retryNum ...int) + Patch(key string, obj runtime.Object, status *Status, retryNum ...int) (runtime.Object, error) Delete(key string, option status.StatusOptions) } @@ -80,7 +84,7 @@ func BulkUpdate(key string, objectType string, options []status.StatusOptions) e return nil } -func Record(key string, obj runtime.Object, status *Status) { +func Record(key string, obj runtime.Object, status *Status) (runtime.Object, error) { var objectType string switch obj.(type) { case *gatewayv1.GatewayClass: @@ -91,8 +95,13 @@ func Record(key string, obj runtime.Object, status *Status) { objectType = lib.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") } o := New(objectType) - o.Patch(key, obj, status) + updatedObject, err := o.Patch(key, obj, status) + if err != nil { + akogatewayapilib.AKOControlConfig().EventRecorder().Eventf(obj, corev1.EventTypeWarning, + lib.PatchFailed, "Patch of status failed after multiple retries") + } + return updatedObject, err } diff --git a/internal/lib/constants.go b/internal/lib/constants.go index 6bd462cfb..9edd03680 100644 --- a/internal/lib/constants.go +++ b/internal/lib/constants.go @@ -222,6 +222,7 @@ const ( Synced = "Synced" Attached = "Attached" Detached = "Detached" + PatchFailed = "PatchFailed" InvalidConfiguration = "InvalidConfiguration" AKODeleteConfigSet = "AKODeleteConfigSet" AKODeleteConfigUnset = "AKODeleteConfigUnset" diff --git a/tests/gatewayapitests/graphlayer/gateway_test.go b/tests/gatewayapitests/graphlayer/gateway_test.go index 9eee5d3a7..954b6dea9 100644 --- a/tests/gatewayapitests/graphlayer/gateway_test.go +++ b/tests/gatewayapitests/graphlayer/gateway_test.go @@ -427,19 +427,17 @@ func TestSecretCreateDelete(t *testing.T) { g.Eventually(func() bool { found, _ := objects.SharedAviGraphLister().Get(modelName) return found - }, 30*time.Second).Should(gomega.Equal(true)) + }, 30*time.Second).Should(gomega.Equal(false)) _, aviModel := objects.SharedAviGraphLister().Get(modelName) - nodes := aviModel.(*avinodes.AviObjectGraph).GetAviEvhVS() - g.Expect(nodes).To(gomega.HaveLen(1)) - g.Expect(nodes[0].SSLKeyCertRefs).To(gomega.HaveLen(0)) + g.Expect(aviModel).To(gomega.BeNil()) integrationtest.AddSecret(secrets[0], DEFAULT_NAMESPACE, "cert", "key") g.Eventually(func() bool { found, aviModel := objects.SharedAviGraphLister().Get(modelName) if found { - nodes = aviModel.(*avinodes.AviObjectGraph).GetAviEvhVS() + nodes := aviModel.(*avinodes.AviObjectGraph).GetAviEvhVS() g.Expect(nodes).To(gomega.HaveLen(1)) g.Expect(nodes[0].SSLKeyCertRefs).To(gomega.HaveLen(1)) return true @@ -453,7 +451,7 @@ func TestSecretCreateDelete(t *testing.T) { g.Eventually(func() bool { found, aviModel := objects.SharedAviGraphLister().Get(modelName) if found { - nodes = aviModel.(*avinodes.AviObjectGraph).GetAviEvhVS() + nodes := aviModel.(*avinodes.AviObjectGraph).GetAviEvhVS() g.Expect(nodes).To(gomega.HaveLen(1)) g.Expect(nodes[0].SSLKeyCertRefs).To(gomega.HaveLen(0)) return true diff --git a/tests/gatewayapitests/graphlayer/httproute_test.go b/tests/gatewayapitests/graphlayer/httproute_test.go index 930fa2782..88528ba34 100644 --- a/tests/gatewayapitests/graphlayer/httproute_test.go +++ b/tests/gatewayapitests/graphlayer/httproute_test.go @@ -1256,6 +1256,7 @@ func TestHTTPRouteWithMultipleGateways(t *testing.T) { integrationtest.DelSVC(t, DEFAULT_NAMESPACE, svcName) integrationtest.DelEPorEPS(t, DEFAULT_NAMESPACE, svcName) akogatewayapitests.TeardownGateway(t, gatewayName1, DEFAULT_NAMESPACE) + akogatewayapitests.TeardownGateway(t, gatewayName2, DEFAULT_NAMESPACE) akogatewayapitests.TeardownGatewayClass(t, gatewayClassName) } diff --git a/tests/gatewayapitests/status/gateway_test.go b/tests/gatewayapitests/status/gateway_test.go index 5ee759832..f32a1225b 100644 --- a/tests/gatewayapitests/status/gateway_test.go +++ b/tests/gatewayapitests/status/gateway_test.go @@ -164,7 +164,7 @@ func TestGatewayWithValidListenersAndGatewayClass(t *testing.T) { Reason: string(gatewayv1.GatewayReasonProgrammed), }, }, - Listeners: tests.GetListenerStatusV1(ports, []int32{0, 0}), + Listeners: tests.GetListenerStatusV1(ports, []int32{0, 0}, true, true), } gateway, err := tests.GatewayClient.GatewayV1().Gateways(DEFAULT_NAMESPACE).Get(context.TODO(), gatewayName, metav1.GetOptions{}) @@ -210,7 +210,7 @@ func TestGatewayWithTLSListeners(t *testing.T) { Reason: string(gatewayv1.GatewayReasonAccepted), }, }, - Listeners: tests.GetListenerStatusV1(ports, []int32{0, 0}), + Listeners: tests.GetListenerStatusV1(ports, []int32{0, 0}, true, false), } gateway, err := tests.GatewayClient.GatewayV1().Gateways(DEFAULT_NAMESPACE).Get(context.TODO(), gatewayName, metav1.GetOptions{}) @@ -256,7 +256,7 @@ func TestGatewayListenerUpdate(t *testing.T) { Reason: string(gatewayv1.GatewayReasonAccepted), }, }, - Listeners: tests.GetListenerStatusV1(ports, []int32{0, 0, 0}), + Listeners: tests.GetListenerStatusV1(ports, []int32{0, 0, 0}, true, false), } gateway, err := tests.GatewayClient.GatewayV1().Gateways(DEFAULT_NAMESPACE).Get(context.TODO(), gatewayName, metav1.GetOptions{}) @@ -280,7 +280,7 @@ func TestGatewayListenerUpdate(t *testing.T) { return len(gateway.Status.Listeners) == len(ports) }, 30*time.Second).Should(gomega.Equal(true)) - expectedStatus.Listeners = tests.GetListenerStatusV1(ports, []int32{0, 0}) + expectedStatus.Listeners = tests.GetListenerStatusV1(ports, []int32{0, 0}, true, false) 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) @@ -299,7 +299,7 @@ Transition test cases * - Non AKO gateway controller to AKO gateway controller * - AKO gateway controller to non AKO gateway controller */ -func TestGatewayTransitionFromValidToInvalid(t *testing.T) { +func TestGatewayTransitionFromValidToPartiallyValid(t *testing.T) { t.Skip("This is invalid test case as Hostname in listener can not be *.") gatewayName := "gateway-trans-01" @@ -330,7 +330,7 @@ func TestGatewayTransitionFromValidToInvalid(t *testing.T) { Reason: string(gatewayv1.GatewayReasonAccepted), }, }, - Listeners: tests.GetListenerStatusV1(ports, []int32{0, 0}), + Listeners: tests.GetListenerStatusV1(ports, []int32{0, 0}, true, false), } gateway, err := tests.GatewayClient.GatewayV1().Gateways(DEFAULT_NAMESPACE).Get(context.TODO(), gatewayName, metav1.GetOptions{}) @@ -354,13 +354,27 @@ func TestGatewayTransitionFromValidToInvalid(t *testing.T) { return len(gateway.Status.Listeners) == len(ports) }, 30*time.Second).Should(gomega.Equal(true)) - expectedStatus.Conditions[0].Status = metav1.ConditionFalse - expectedStatus.Conditions[0].Reason = string(gatewayv1.GatewayReasonListenersNotValid) - expectedStatus.Conditions[0].Message = "Gateway contains 1 invalid listener(s)" - expectedStatus.Listeners[0].Conditions[0].Reason = string(gatewayv1.GatewayReasonListenersNotValid) + expectedStatus = &gatewayv1.GatewayStatus{ + Conditions: []metav1.Condition{ + { + Type: string(gatewayv1.GatewayConditionAccepted), + Status: metav1.ConditionTrue, + Message: "Gateway contains atleast one valid listener", + ObservedGeneration: 1, + Reason: string(gatewayv1.GatewayReasonListenersNotValid), + }, + }, + Listeners: tests.GetListenerStatusV1(ports, []int32{0, 0}, true, false), + } + expectedStatus.Listeners[0].Conditions[0].Reason = string(gatewayv1.ListenerReasonInvalid) expectedStatus.Listeners[0].Conditions[0].Status = metav1.ConditionFalse expectedStatus.Listeners[0].Conditions[0].Message = "Hostname not found or Hostname has invalid configuration" + expectedStatus.Listeners[0].Conditions[1].Type = string(gatewayv1.ListenerConditionProgrammed) + expectedStatus.Listeners[0].Conditions[1].Status = metav1.ConditionFalse + expectedStatus.Listeners[0].Conditions[1].Reason = string(gatewayv1.ListenerReasonInvalid) + expectedStatus.Listeners[0].Conditions[1].Message = "Virtual service not configured/updated for this listener" + 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) @@ -370,7 +384,7 @@ func TestGatewayTransitionFromValidToInvalid(t *testing.T) { tests.TeardownGatewayClass(t, gatewayClassName) } -func TestGatewayTransitionFromInvalidToValid(t *testing.T) { +func TestGatewayTransitionFromPartiallyValidToValid(t *testing.T) { gatewayName := "gateway-trans-02" gatewayClassName := "gateway-class-trans-02" @@ -424,7 +438,7 @@ func TestGatewayTransitionFromInvalidToValid(t *testing.T) { expectedStatus.Conditions[0].Status = metav1.ConditionTrue expectedStatus.Conditions[0].Reason = string(gatewayv1.GatewayReasonAccepted) expectedStatus.Conditions[0].Message = "Gateway configuration is valid" - expectedStatus.Listeners = tests.GetListenerStatusV1(ports, []int32{0, 0}) + expectedStatus.Listeners = tests.GetListenerStatusV1(ports, []int32{0, 0}, true, false) gateway, err = tests.GatewayClient.GatewayV1().Gateways(DEFAULT_NAMESPACE).Get(context.TODO(), gatewayName, metav1.GetOptions{}) if err != nil || gateway == nil { @@ -479,7 +493,7 @@ func TestGatewayTransitionFromNonAKOControllerToAKOController(t *testing.T) { Reason: string(gatewayv1.GatewayReasonAccepted), }, }, - Listeners: tests.GetListenerStatusV1(ports, []int32{0, 0}), + Listeners: tests.GetListenerStatusV1(ports, []int32{0, 0}, true, false), } gateway, err := tests.GatewayClient.GatewayV1().Gateways(DEFAULT_NAMESPACE).Get(context.TODO(), gatewayName, metav1.GetOptions{}) @@ -522,7 +536,7 @@ func TestGatewayTransitionFromAKOControllerToNonAKOController(t *testing.T) { Reason: string(gatewayv1.GatewayReasonAccepted), }, }, - Listeners: tests.GetListenerStatusV1(ports, []int32{0, 0}), + Listeners: tests.GetListenerStatusV1(ports, []int32{0, 0}, true, false), } gateway, err := tests.GatewayClient.GatewayV1().Gateways(DEFAULT_NAMESPACE).Get(context.TODO(), gatewayName, metav1.GetOptions{}) @@ -584,6 +598,13 @@ func TestGatewayWithNoListeners(t *testing.T) { ObservedGeneration: 1, Reason: string(gatewayv1.GatewayReasonInvalid), }, + { + Type: string(gatewayv1.GatewayConditionProgrammed), + Status: metav1.ConditionFalse, + Message: "Gateway not programmed", + ObservedGeneration: 1, + Reason: string(gatewayv1.GatewayReasonInvalid), + }, }, } @@ -629,6 +650,13 @@ func TestGatewayWithMoreThanOneAddress(t *testing.T) { ObservedGeneration: 1, Reason: string(gatewayv1.GatewayReasonInvalid), }, + { + Type: string(gatewayv1.GatewayConditionProgrammed), + Status: metav1.ConditionFalse, + Message: "Gateway not programmed", + ObservedGeneration: 1, + Reason: string(gatewayv1.GatewayReasonAddressNotUsable), + }, }, } @@ -668,12 +696,12 @@ func TestGatewayWithUnsupportedProtocolInListeners(t *testing.T) { { Type: string(gatewayv1.GatewayConditionAccepted), Status: metav1.ConditionFalse, - Message: "Gateway contains 1 invalid listener(s)", + Message: "Gateway contains atleast one valid listener", ObservedGeneration: 1, Reason: string(gatewayv1.GatewayReasonListenersNotValid), }, }, - Listeners: tests.GetListenerStatusV1(ports, []int32{0, 0}), + Listeners: tests.GetListenerStatusV1(ports, []int32{0, 0}, true, false), } expectedStatus.Listeners[0].Conditions[0].Reason = string(gatewayv1.ListenerReasonUnsupportedProtocol) expectedStatus.Listeners[0].Conditions[0].Status = metav1.ConditionFalse @@ -715,18 +743,23 @@ func TestGatewayWithInvalidHostnameInListeners(t *testing.T) { Conditions: []metav1.Condition{ { Type: string(gatewayv1.GatewayConditionAccepted), - Status: metav1.ConditionFalse, - Message: "Gateway contains 1 invalid listener(s)", + Status: metav1.ConditionTrue, + Message: "Gateway contains atleast one valid listener", ObservedGeneration: 1, Reason: string(gatewayv1.GatewayReasonListenersNotValid), }, }, - Listeners: tests.GetListenerStatusV1(ports, []int32{0, 0}), + Listeners: tests.GetListenerStatusV1(ports, []int32{0, 0}, true, false), } - expectedStatus.Listeners[0].Conditions[0].Reason = string(gatewayv1.GatewayReasonListenersNotValid) + expectedStatus.Listeners[0].Conditions[0].Reason = string(gatewayv1.ListenerReasonInvalid) expectedStatus.Listeners[0].Conditions[0].Status = metav1.ConditionFalse expectedStatus.Listeners[0].Conditions[0].Message = "Hostname not found or Hostname has invalid configuration" + expectedStatus.Listeners[0].Conditions[1].Reason = string(gatewayv1.ListenerReasonInvalid) + expectedStatus.Listeners[0].Conditions[1].Status = metav1.ConditionFalse + expectedStatus.Listeners[0].Conditions[1].Type = string(gatewayv1.GatewayConditionProgrammed) + expectedStatus.Listeners[0].Conditions[1].Message = "Virtual service not configured/updated for this listener" + 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) @@ -767,16 +800,24 @@ func TestGatewayWithInvalidTLSConfigInListeners(t *testing.T) { { Type: string(gatewayv1.GatewayConditionAccepted), Status: metav1.ConditionFalse, - Message: "Gateway contains 1 invalid listener(s)", + Message: "Gateway contains atleast one valid listener", ObservedGeneration: 1, Reason: string(gatewayv1.GatewayReasonListenersNotValid), }, }, - Listeners: tests.GetListenerStatusV1(ports, []int32{0, 0}), + Listeners: tests.GetListenerStatusV1(ports, []int32{0, 0}, true, true), } - expectedStatus.Listeners[0].Conditions[0].Reason = string(gatewayv1.ListenerReasonInvalidCertificateRef) + expectedStatus.Listeners[0].Conditions[0].Reason = string(gatewayv1.ListenerReasonInvalid) expectedStatus.Listeners[0].Conditions[0].Status = metav1.ConditionFalse - expectedStatus.Listeners[0].Conditions[0].Message = "TLS mode or reference not valid" + expectedStatus.Listeners[0].Conditions[0].Message = "Listener is Invalid" + + expectedStatus.Listeners[0].Conditions[1].Reason = string(gatewayv1.ListenerReasonInvalidCertificateRef) + expectedStatus.Listeners[0].Conditions[1].Status = metav1.ConditionFalse + expectedStatus.Listeners[0].Conditions[1].Message = "TLS mode or reference not valid" + + expectedStatus.Listeners[0].Conditions[2].Reason = string(gatewayv1.ListenerReasonInvalid) + expectedStatus.Listeners[0].Conditions[2].Status = metav1.ConditionFalse + expectedStatus.Listeners[0].Conditions[2].Message = "Virtual service not configured/updated for this listener" gateway, err := tests.GatewayClient.GatewayV1().Gateways(DEFAULT_NAMESPACE).Get(context.TODO(), gatewayName, metav1.GetOptions{}) if err != nil || gateway == nil { @@ -824,17 +865,33 @@ func TestGatewayWithInvalidAllowedRoute(t *testing.T) { { Type: string(gatewayv1.GatewayConditionAccepted), Status: metav1.ConditionFalse, - Message: "Gateway contains 1 invalid listener(s)", + Message: "Gateway does not contain any valid listener", ObservedGeneration: 1, Reason: string(gatewayv1.GatewayReasonListenersNotValid), }, + { + Type: string(gatewayv1.GatewayConditionProgrammed), + Status: metav1.ConditionFalse, + Message: "Gateway not programmed", + ObservedGeneration: 1, + Reason: string(gatewayv1.GatewayReasonInvalid), + }, }, - Listeners: tests.GetListenerStatusV1(ports, []int32{0, 0}), + Listeners: tests.GetListenerStatusV1(ports, []int32{0, 0}, true, true), } - expectedStatus.Listeners[0].Conditions[0].Reason = string(gatewayv1.ListenerReasonInvalidRouteKinds) + expectedStatus.Listeners[0].Conditions[0].Reason = string(gatewayv1.ListenerReasonInvalid) expectedStatus.Listeners[0].Conditions[0].Status = metav1.ConditionFalse - expectedStatus.Listeners[0].Conditions[0].Message = "AllowedRoute kind is invalid. Only HTTPRoute is supported currently" - expectedStatus.Listeners[0].Conditions[0].Type = string(gatewayv1.ListenerConditionResolvedRefs) + expectedStatus.Listeners[0].Conditions[0].Message = "Listener is Invalid" + //expectedStatus.Listeners[0].Conditions[0].Type = string(gatewayv1.ListenerConditionAccepted) + + expectedStatus.Listeners[0].Conditions[1].Reason = string(gatewayv1.ListenerReasonInvalidRouteKinds) + expectedStatus.Listeners[0].Conditions[1].Status = metav1.ConditionFalse + expectedStatus.Listeners[0].Conditions[1].Message = "AllowedRoute kind is invalid. Only HTTPRoute is supported currently" + //expectedStatus.Listeners[0].Conditions[1].Type = string(gatewayv1.ListenerConditionResolvedRefs) + + expectedStatus.Listeners[0].Conditions[2].Message = "Virtual service not configured/updated for this listener" + expectedStatus.Listeners[0].Conditions[2].Status = metav1.ConditionFalse + expectedStatus.Listeners[0].Conditions[2].Reason = string(gatewayv1.ListenerReasonInvalid) gateway, err := tests.GatewayClient.GatewayV1().Gateways(DEFAULT_NAMESPACE).Get(context.TODO(), gatewayName, metav1.GetOptions{}) if err != nil || gateway == nil { @@ -866,17 +923,34 @@ func TestGatewayWithInvalidAllowedRoute(t *testing.T) { { Type: string(gatewayv1.GatewayConditionAccepted), Status: metav1.ConditionFalse, - Message: "Gateway contains 1 invalid listener(s)", + Message: "Gateway does not contain any valid listener", ObservedGeneration: 1, Reason: string(gatewayv1.GatewayReasonListenersNotValid), }, + { + Type: string(gatewayv1.GatewayConditionProgrammed), + Status: metav1.ConditionFalse, + Message: "Gateway not programmed", + ObservedGeneration: 1, + Reason: string(gatewayv1.GatewayReasonInvalid), + }, }, - Listeners: tests.GetListenerStatusV1(ports, []int32{0, 0}), + Listeners: tests.GetListenerStatusV1(ports, []int32{0, 0}, true, true), } - expectedStatus.Listeners[0].Conditions[0].Reason = string(gatewayv1.ListenerReasonInvalidRouteKinds) + + expectedStatus.Listeners[0].Conditions[0].Reason = string(gatewayv1.ListenerReasonInvalid) expectedStatus.Listeners[0].Conditions[0].Status = metav1.ConditionFalse - expectedStatus.Listeners[0].Conditions[0].Message = "AllowedRoute Group is invalid." - expectedStatus.Listeners[0].Conditions[0].Type = string(gatewayv1.ListenerConditionResolvedRefs) + expectedStatus.Listeners[0].Conditions[0].Message = "Listener is Invalid" + expectedStatus.Listeners[0].Conditions[0].Type = string(gatewayv1.ListenerConditionAccepted) + + expectedStatus.Listeners[0].Conditions[1].Reason = string(gatewayv1.ListenerReasonInvalidRouteKinds) + expectedStatus.Listeners[0].Conditions[1].Status = metav1.ConditionFalse + expectedStatus.Listeners[0].Conditions[1].Message = "AllowedRoute Group is invalid." + expectedStatus.Listeners[0].Conditions[1].Type = string(gatewayv1.ListenerConditionResolvedRefs) + + expectedStatus.Listeners[0].Conditions[2].Message = "Virtual service not configured/updated for this listener" + expectedStatus.Listeners[0].Conditions[2].Reason = string(gatewayv1.ListenerReasonInvalid) + expectedStatus.Listeners[0].Conditions[2].Status = metav1.ConditionFalse gateway, err = tests.GatewayClient.GatewayV1().Gateways(DEFAULT_NAMESPACE).Get(context.TODO(), gatewayName, metav1.GetOptions{}) if err != nil || gateway == nil { @@ -927,12 +1001,16 @@ func TestGatewayWithValidAllowedRoute(t *testing.T) { Reason: string(gatewayv1.GatewayReasonAccepted), }, }, - Listeners: tests.GetListenerStatusV1(ports, []int32{0, 0}), + Listeners: tests.GetListenerStatusV1(ports, []int32{0, 0}, true, false), } expectedStatus.Listeners[0].Conditions[0].Reason = string(gatewayv1.ListenerConditionAccepted) expectedStatus.Listeners[0].Conditions[0].Status = metav1.ConditionTrue expectedStatus.Listeners[0].Conditions[0].Message = "Listener is valid" + expectedStatus.Listeners[0].Conditions[1].Reason = string(gatewayv1.ListenerConditionResolvedRefs) + expectedStatus.Listeners[0].Conditions[1].Status = metav1.ConditionTrue + expectedStatus.Listeners[0].Conditions[1].Message = "All the references are 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) @@ -971,7 +1049,7 @@ func TestGatewayWithValidAllowedRoute(t *testing.T) { Reason: string(gatewayv1.GatewayReasonAccepted), }, }, - Listeners: tests.GetListenerStatusV1(ports, []int32{0, 0}), + Listeners: tests.GetListenerStatusV1(ports, []int32{0, 0}, true, false), } expectedStatus.Listeners[0].Conditions[0].Reason = string(gatewayv1.ListenerReasonAccepted) expectedStatus.Listeners[0].Conditions[0].Status = metav1.ConditionTrue @@ -1010,7 +1088,7 @@ func TestGatewayWithValidAllowedRoute(t *testing.T) { Reason: string(gatewayv1.GatewayReasonAccepted), }, }, - Listeners: tests.GetListenerStatusV1(ports, []int32{0, 0}), + Listeners: tests.GetListenerStatusV1(ports, []int32{0, 0}, true, false), } expectedStatus.Listeners[0].Conditions[0].Reason = string(gatewayv1.ListenerReasonAccepted) expectedStatus.Listeners[0].Conditions[0].Status = metav1.ConditionTrue @@ -1048,8 +1126,15 @@ func TestGatewayWithValidAllowedRoute(t *testing.T) { ObservedGeneration: 1, Reason: string(gatewayv1.GatewayReasonAccepted), }, + { + Type: string(gatewayv1.GatewayConditionProgrammed), + Status: metav1.ConditionTrue, + Message: "Gateway configuration is valid", + ObservedGeneration: 1, + Reason: string(gatewayv1.GatewayReasonProgrammed), + }, }, - Listeners: tests.GetListenerStatusV1(ports, []int32{0, 0}), + Listeners: tests.GetListenerStatusV1(ports, []int32{0, 0}, true, true), } expectedStatus.Listeners[0].Conditions[0].Reason = string(gatewayv1.ListenerReasonAccepted) expectedStatus.Listeners[0].Conditions[0].Status = metav1.ConditionTrue @@ -1095,12 +1180,16 @@ func TestMultipleGatewaySameHostname(t *testing.T) { Reason: string(gatewayv1.GatewayReasonAccepted), }, }, - Listeners: tests.GetListenerStatusV1(ports, []int32{0, 0}), + Listeners: tests.GetListenerStatusV1(ports, []int32{0, 0}, true, false), } - expectedStatus.Listeners[0].Conditions[0].Reason = string(gatewayv1.GatewayReasonAccepted) + expectedStatus.Listeners[0].Conditions[0].Reason = string(gatewayv1.ListenerReasonAccepted) expectedStatus.Listeners[0].Conditions[0].Status = metav1.ConditionTrue expectedStatus.Listeners[0].Conditions[0].Message = "Listener is valid" + expectedStatus.Listeners[0].Conditions[1].Reason = string(gatewayv1.ListenerReasonResolvedRefs) + expectedStatus.Listeners[0].Conditions[1].Status = metav1.ConditionTrue + expectedStatus.Listeners[0].Conditions[1].Message = "All the references are valid" + gateway, err := tests.GatewayClient.GatewayV1().Gateways(DEFAULT_NAMESPACE).Get(context.TODO(), gatewayName1, metav1.GetOptions{}) if err != nil || gateway == nil { t.Fatalf("Couldn't get the gateway, err: %+v", err) @@ -1125,15 +1214,27 @@ func TestMultipleGatewaySameHostname(t *testing.T) { { Type: string(gatewayv1.GatewayConditionAccepted), Status: metav1.ConditionFalse, - Message: "Gateway contains 1 invalid listener(s)", + Message: "Gateway does not contain any valid listener", ObservedGeneration: 1, Reason: string(gatewayv1.GatewayReasonListenersNotValid), }, + { + Type: string(gatewayv1.GatewayConditionProgrammed), + Status: metav1.ConditionFalse, + Message: "Gateway not programmed", + ObservedGeneration: 1, + Reason: string(gatewayv1.GatewayReasonInvalid), + }, }, - Listeners: tests.GetListenerStatusV1(ports, []int32{0, 0}), + Listeners: tests.GetListenerStatusV1(ports, []int32{0, 0}, false, true), } - expectedStatus.Listeners[0].Conditions[0].Reason = string(gatewayv1.GatewayReasonListenersNotValid) + expectedStatus.Listeners[0].Conditions[0].Reason = string(gatewayv1.ListenerReasonInvalid) expectedStatus.Listeners[0].Conditions[0].Status = metav1.ConditionFalse + expectedStatus.Listeners[0].Conditions[0].Message = "Hostname overlaps or is same as an existing gateway hostname" + + expectedStatus.Listeners[0].Conditions[1].Reason = string(gatewayv1.ListenerReasonInvalid) + expectedStatus.Listeners[0].Conditions[1].Status = metav1.ConditionFalse + expectedStatus.Listeners[0].Conditions[1].Message = "Virtual service not configured/updated for this listener" expectedStatus.Listeners[0].Conditions[0].Message = "Hostname is same as an existing gateway hostname" gateway, err = tests.GatewayClient.GatewayV1().Gateways(DEFAULT_NAMESPACE).Get(context.TODO(), gatewayName2, metav1.GetOptions{}) @@ -1178,7 +1279,7 @@ func TestMultipleGatewayOverlappingHostname(t *testing.T) { Reason: string(gatewayv1.GatewayReasonAccepted), }, }, - Listeners: tests.GetListenerStatusV1(ports, []int32{0, 0}), + Listeners: tests.GetListenerStatusV1(ports, []int32{0, 0}, true, true), } expectedStatus.Listeners[0].Conditions[0].Reason = string(gatewayv1.GatewayReasonAccepted) expectedStatus.Listeners[0].Conditions[0].Status = metav1.ConditionTrue @@ -1214,8 +1315,15 @@ func TestMultipleGatewayOverlappingHostname(t *testing.T) { ObservedGeneration: 1, Reason: string(gatewayv1.GatewayReasonAccepted), }, + { + Type: string(gatewayv1.GatewayConditionProgrammed), + Status: metav1.ConditionFalse, + Message: "Gateway not programmed", + ObservedGeneration: 1, + Reason: string(gatewayv1.GatewayReasonInvalid), + }, }, - Listeners: tests.GetListenerStatusV1(ports, []int32{0, 0}), + Listeners: tests.GetListenerStatusV1(ports, []int32{0, 0}, false, true), } expectedStatus.Listeners[0].Conditions[0].Reason = string(gatewayv1.GatewayReasonAccepted) expectedStatus.Listeners[0].Conditions[0].Status = metav1.ConditionTrue diff --git a/tests/gatewayapitests/status/httproute_test.go b/tests/gatewayapitests/status/httproute_test.go index 64afb8e84..f24d0d2c5 100644 --- a/tests/gatewayapitests/status/httproute_test.go +++ b/tests/gatewayapitests/status/httproute_test.go @@ -70,8 +70,8 @@ func TestHTTPRouteWithValidConfig(t *testing.T) { if len(httpRoute.Status.Parents) != len(ports) { return false } - return apimeta.FindStatusCondition(httpRoute.Status.Parents[0].Conditions, string(gatewayv1.GatewayConditionAccepted)) != nil && - apimeta.FindStatusCondition(httpRoute.Status.Parents[1].Conditions, string(gatewayv1.GatewayConditionAccepted)) != nil + return apimeta.FindStatusCondition(httpRoute.Status.Parents[0].Conditions, string(gatewayv1.RouteConditionAccepted)) != nil && + apimeta.FindStatusCondition(httpRoute.Status.Parents[1].Conditions, string(gatewayv1.RouteConditionAccepted)) != nil }, 30*time.Second).Should(gomega.Equal(true)) conditionMap := make(map[string][]metav1.Condition) @@ -79,8 +79,8 @@ func TestHTTPRouteWithValidConfig(t *testing.T) { for _, port := range ports { conditions := make([]metav1.Condition, 0, 1) condition := metav1.Condition{ - Type: string(gatewayv1.GatewayConditionAccepted), - Reason: string(gatewayv1.GatewayReasonAccepted), + Type: string(gatewayv1.RouteConditionAccepted), + Reason: string(gatewayv1.RouteReasonAccepted), Status: metav1.ConditionTrue, Message: "Parent reference is valid", } @@ -138,23 +138,23 @@ func TestHTTPRouteWithAtleastOneParentReferenceValid(t *testing.T) { if len(httpRoute.Status.Parents) != len(ports) { return false } - return apimeta.IsStatusConditionTrue(httpRoute.Status.Parents[0].Conditions, string(gatewayv1.GatewayConditionAccepted)) && - apimeta.IsStatusConditionFalse(httpRoute.Status.Parents[1].Conditions, string(gatewayv1.GatewayConditionAccepted)) + return apimeta.IsStatusConditionTrue(httpRoute.Status.Parents[0].Conditions, string(gatewayv1.RouteConditionAccepted)) && + apimeta.IsStatusConditionFalse(httpRoute.Status.Parents[1].Conditions, string(gatewayv1.RouteConditionAccepted)) }, 30*time.Second).Should(gomega.Equal(true)) conditionMap := make(map[string][]metav1.Condition) conditionMap[fmt.Sprintf("%s-%d", gatewayName, 8080)] = []metav1.Condition{ { - Type: string(gatewayv1.GatewayConditionAccepted), - Reason: string(gatewayv1.GatewayReasonAccepted), + Type: string(gatewayv1.RouteConditionAccepted), + Reason: string(gatewayv1.RouteReasonAccepted), Status: metav1.ConditionTrue, Message: "Parent reference is valid", }, } conditionMap[fmt.Sprintf("%s-%d", gatewayName, 8081)] = []metav1.Condition{ { - Type: string(gatewayv1.GatewayConditionAccepted), - Reason: string(gatewayv1.GatewayReasonInvalid), + Type: string(gatewayv1.RouteConditionAccepted), + Reason: string(gatewayv1.RouteReasonNoMatchingParent), Status: metav1.ConditionFalse, Message: "Invalid listener name provided", }, @@ -215,14 +215,14 @@ func TestHTTPRouteTransitionFromInvalidToValid(t *testing.T) { if len(httpRoute.Status.Parents) != len(ports) { return false } - return apimeta.IsStatusConditionFalse(httpRoute.Status.Parents[0].Conditions, string(gatewayv1.GatewayConditionAccepted)) + return apimeta.IsStatusConditionFalse(httpRoute.Status.Parents[0].Conditions, string(gatewayv1.RouteConditionAccepted)) }, 30*time.Second).Should(gomega.Equal(true)) conditionMap := make(map[string][]metav1.Condition) conditionMap[fmt.Sprintf("%s-%d", gatewayName, 8081)] = []metav1.Condition{ { - Type: string(gatewayv1.GatewayConditionAccepted), - Reason: string(gatewayv1.GatewayReasonInvalid), + Type: string(gatewayv1.RouteConditionAccepted), + Reason: string(gatewayv1.RouteReasonNoMatchingParent), Status: metav1.ConditionFalse, Message: "Invalid listener name provided", }, @@ -250,13 +250,13 @@ func TestHTTPRouteTransitionFromInvalidToValid(t *testing.T) { if len(httpRoute.Status.Parents) != len(ports) { return false } - return apimeta.IsStatusConditionTrue(httpRoute.Status.Parents[0].Conditions, string(gatewayv1.GatewayConditionAccepted)) + return apimeta.IsStatusConditionTrue(httpRoute.Status.Parents[0].Conditions, string(gatewayv1.RouteConditionAccepted)) }, 30*time.Second).Should(gomega.Equal(true)) conditionMap[fmt.Sprintf("%s-%d", gatewayName, 8080)] = []metav1.Condition{ { - Type: string(gatewayv1.GatewayConditionAccepted), - Reason: string(gatewayv1.GatewayReasonAccepted), + Type: string(gatewayv1.RouteConditionAccepted), + Reason: string(gatewayv1.RouteReasonAccepted), Status: metav1.ConditionTrue, Message: "Parent reference is valid", }, @@ -311,14 +311,14 @@ func TestHTTPRouteTransitionFromValidToInvalid(t *testing.T) { if len(httpRoute.Status.Parents) != len(ports) { return false } - return apimeta.IsStatusConditionTrue(httpRoute.Status.Parents[0].Conditions, string(gatewayv1.GatewayConditionAccepted)) + return apimeta.IsStatusConditionTrue(httpRoute.Status.Parents[0].Conditions, string(gatewayv1.RouteConditionAccepted)) }, 30*time.Second).Should(gomega.Equal(true)) conditionMap := make(map[string][]metav1.Condition) - conditionMap[fmt.Sprintf("%s-%d", gatewayName, 8081)] = []metav1.Condition{ + conditionMap[fmt.Sprintf("%s-%d", gatewayName, 8080)] = []metav1.Condition{ { - Type: string(gatewayv1.GatewayConditionAccepted), - Reason: string(gatewayv1.GatewayReasonAccepted), + Type: string(gatewayv1.RouteConditionAccepted), + Reason: string(gatewayv1.RouteReasonAccepted), Status: metav1.ConditionTrue, Message: "Parent reference is valid", }, @@ -345,13 +345,13 @@ func TestHTTPRouteTransitionFromValidToInvalid(t *testing.T) { if len(httpRoute.Status.Parents) != len(ports) { return false } - return apimeta.IsStatusConditionFalse(httpRoute.Status.Parents[0].Conditions, string(gatewayv1.GatewayConditionAccepted)) + return apimeta.IsStatusConditionFalse(httpRoute.Status.Parents[0].Conditions, string(gatewayv1.RouteConditionAccepted)) }, 30*time.Second).Should(gomega.Equal(true)) conditionMap[fmt.Sprintf("%s-%d", gatewayName, 8081)] = []metav1.Condition{ { - Type: string(gatewayv1.GatewayConditionAccepted), - Reason: string(gatewayv1.GatewayReasonInvalid), + Type: string(gatewayv1.RouteConditionAccepted), + Reason: string(gatewayv1.RouteReasonNoMatchingParent), Status: metav1.ConditionFalse, Message: "Invalid listener name provided", }, @@ -458,23 +458,23 @@ func TestHTTPRouteWithAllParentReferenceInvalid(t *testing.T) { if len(httpRoute.Status.Parents) != len(ports) { return false } - return apimeta.IsStatusConditionFalse(httpRoute.Status.Parents[0].Conditions, string(gatewayv1.GatewayConditionAccepted)) && - apimeta.IsStatusConditionFalse(httpRoute.Status.Parents[1].Conditions, string(gatewayv1.GatewayConditionAccepted)) + return apimeta.IsStatusConditionFalse(httpRoute.Status.Parents[0].Conditions, string(gatewayv1.RouteConditionAccepted)) && + apimeta.IsStatusConditionFalse(httpRoute.Status.Parents[1].Conditions, string(gatewayv1.RouteConditionAccepted)) }, 30*time.Second).Should(gomega.Equal(true)) conditionMap := map[string][]metav1.Condition{ fmt.Sprintf("%s-%d", gatewayName, 8080): { { - Type: string(gatewayv1.GatewayConditionAccepted), - Reason: string(gatewayv1.GatewayReasonInvalid), + Type: string(gatewayv1.RouteConditionAccepted), + Reason: string(gatewayv1.RouteReasonNoMatchingParent), Status: metav1.ConditionFalse, Message: "Invalid listener name provided", }, }, fmt.Sprintf("%s-%d", gatewayName, 8081): { { - Type: string(gatewayv1.GatewayConditionAccepted), - Reason: string(gatewayv1.GatewayReasonInvalid), + Type: string(gatewayv1.RouteConditionAccepted), + Reason: string(gatewayv1.RouteReasonNoMatchingParent), Status: metav1.ConditionFalse, Message: "Invalid listener name provided", }, @@ -559,23 +559,23 @@ func TestHTTPRouteWithNonExistingListenerReference(t *testing.T) { if len(httpRoute.Status.Parents) != len(ports) { return false } - return apimeta.IsStatusConditionFalse(httpRoute.Status.Parents[0].Conditions, string(gatewayv1.GatewayConditionAccepted)) && - apimeta.IsStatusConditionFalse(httpRoute.Status.Parents[1].Conditions, string(gatewayv1.GatewayConditionAccepted)) + return apimeta.IsStatusConditionFalse(httpRoute.Status.Parents[0].Conditions, string(gatewayv1.RouteConditionAccepted)) && + apimeta.IsStatusConditionFalse(httpRoute.Status.Parents[1].Conditions, string(gatewayv1.RouteConditionAccepted)) }, 30*time.Second).Should(gomega.Equal(true)) conditionMap := map[string][]metav1.Condition{ fmt.Sprintf("%s-%d", gatewayName, 8080): { { - Type: string(gatewayv1.GatewayConditionAccepted), - Reason: string(gatewayv1.GatewayReasonInvalid), + Type: string(gatewayv1.RouteConditionAccepted), + Reason: string(gatewayv1.RouteReasonNoMatchingParent), Status: metav1.ConditionFalse, Message: "Invalid listener name provided", }, }, fmt.Sprintf("%s-%d", gatewayName, 8081): { { - Type: string(gatewayv1.GatewayConditionAccepted), - Reason: string(gatewayv1.GatewayReasonInvalid), + Type: string(gatewayv1.RouteConditionAccepted), + Reason: string(gatewayv1.RouteReasonNoMatchingParent), Status: metav1.ConditionFalse, Message: "Invalid listener name provided", }, @@ -694,7 +694,7 @@ func TestHTTPRouteUnprocessedGateway(t *testing.T) { if len(httpRoute.Status.Parents) != len(ports) { return false } - return apimeta.FindStatusCondition(httpRoute.Status.Parents[0].Conditions, string(gatewayv1.GatewayConditionAccepted)) != nil + 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) @@ -702,8 +702,8 @@ func TestHTTPRouteUnprocessedGateway(t *testing.T) { for _, port := range ports { conditions := make([]metav1.Condition, 0, 1) condition := metav1.Condition{ - Type: string(gatewayv1.GatewayConditionAccepted), - Reason: string(gatewayv1.GatewayReasonInvalid), + Type: string(gatewayv1.RouteConditionAccepted), + Reason: string(gatewayv1.RouteReasonPending), Status: metav1.ConditionFalse, Message: "AKO is yet to process Gateway gateway-hr-11 for parent reference gateway-hr-11", } @@ -759,7 +759,7 @@ func TestHTTPRouteWithInvalidGatewayListener(t *testing.T) { if len(httpRoute.Status.Parents) != len(ports) { return false } - return apimeta.FindStatusCondition(httpRoute.Status.Parents[0].Conditions, string(gatewayv1.GatewayConditionAccepted)) != nil + 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) @@ -823,7 +823,7 @@ func TestHTTPRouteWithOneExistingAndOneNonExistingGateway(t *testing.T) { if len(httpRoute.Status.Parents) != 1 { return false } - return apimeta.FindStatusCondition(httpRoute.Status.Parents[0].Conditions, string(gatewayv1.GatewayConditionAccepted)) != nil + 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) @@ -831,8 +831,8 @@ func TestHTTPRouteWithOneExistingAndOneNonExistingGateway(t *testing.T) { for _, port := range ports { conditions := make([]metav1.Condition, 0, 1) condition := metav1.Condition{ - Type: string(gatewayv1.GatewayConditionAccepted), - Reason: string(gatewayv1.GatewayReasonAccepted), + Type: string(gatewayv1.RouteConditionAccepted), + Reason: string(gatewayv1.RouteReasonAccepted), Status: metav1.ConditionTrue, Message: "Parent reference is valid", } diff --git a/tests/gatewayapitests/utils.go b/tests/gatewayapitests/utils.go index 50bd27c1c..85f76eb2f 100644 --- a/tests/gatewayapitests/utils.go +++ b/tests/gatewayapitests/utils.go @@ -177,7 +177,7 @@ func GetListenersOnHostname(hostnames []string) []gatewayv1.Listener { return listeners } -func GetListenerStatusV1(ports []int32, attachedRoutes []int32) []gatewayv1.ListenerStatus { +func GetListenerStatusV1(ports []int32, attachedRoutes []int32, getResolvedRefCondition bool, getProgrammedCondition bool) []gatewayv1.ListenerStatus { listeners := make([]gatewayv1.ListenerStatus, 0, len(ports)) for i, port := range ports { listener := gatewayv1.ListenerStatus{ @@ -186,14 +186,34 @@ func GetListenerStatusV1(ports []int32, attachedRoutes []int32) []gatewayv1.List AttachedRoutes: attachedRoutes[i], Conditions: []metav1.Condition{ { - Type: string(gatewayv1.GatewayConditionAccepted), + Type: string(gatewayv1.ListenerConditionAccepted), Status: metav1.ConditionTrue, Message: "Listener is valid", ObservedGeneration: 1, - Reason: string(gatewayv1.GatewayReasonAccepted), + Reason: string(gatewayv1.ListenerReasonAccepted), }, }, } + if getResolvedRefCondition { + resolvedRefCondition := &metav1.Condition{ + Type: string(gatewayv1.ListenerConditionResolvedRefs), + Status: metav1.ConditionTrue, + Message: "All the references are valid", + ObservedGeneration: 1, + Reason: string(gatewayv1.ListenerReasonResolvedRefs), + } + listener.Conditions = append(listener.Conditions, *resolvedRefCondition) + } + if getProgrammedCondition { + programmedCondition := &metav1.Condition{ + Type: string(gatewayv1.ListenerConditionProgrammed), + Status: metav1.ConditionTrue, + Message: "Virtual service configured/updated", + ObservedGeneration: 1, + Reason: string(gatewayv1.ListenerReasonProgrammed), + } + listener.Conditions = append(listener.Conditions, *programmedCondition) + } listeners = append(listeners, listener) } return listeners @@ -603,9 +623,9 @@ func ValidateGatewayStatus(t *testing.T, actualStatus, expectedStatus *gatewayv1 g.Expect(actualStatus.Addresses[0]).Should(gomega.Equal(expectedStatus.Addresses[0])) } + g.Expect(actualStatus.Listeners).To(gomega.HaveLen(len(expectedStatus.Listeners))) ValidateConditions(t, actualStatus.Conditions, expectedStatus.Conditions) - g.Expect(actualStatus.Listeners).To(gomega.HaveLen(len(expectedStatus.Listeners))) for _, actualListenerStatus := range actualStatus.Listeners { for _, expectedListenerStatus := range expectedStatus.Listeners { if actualListenerStatus.Name == expectedListenerStatus.Name {