diff --git a/internal/controller/httproute_controller.go b/internal/controller/httproute_controller.go index f4f9b7f60..b55a23be1 100644 --- a/internal/controller/httproute_controller.go +++ b/internal/controller/httproute_controller.go @@ -7,11 +7,13 @@ import ( "github.com/go-logr/logr" "github.com/pkg/errors" + "golang.org/x/exp/slices" corev1 "k8s.io/api/core/v1" discoveryv1 "k8s.io/api/discovery/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" + "k8s.io/utils/ptr" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/builder" "sigs.k8s.io/controller-runtime/pkg/client" @@ -95,6 +97,9 @@ func (r *HTTPRouteReconciler) Reconcile(ctx context.Context, req ctrl.Request) ( hr := new(gatewayv1.HTTPRoute) if err := r.Get(ctx, req.NamespacedName, hr); err != nil { if client.IgnoreNotFound(err) == nil { + if err := r.updateHTTPRoutePolicyStatusOnDeleting(req.NamespacedName); err != nil { + return ctrl.Result{}, err + } hr.Namespace = req.Namespace hr.Name = req.Name @@ -511,21 +516,14 @@ func httpRoutePolicyPredicateFuncs(channel chan event.GenericEvent) predicate.Pr if !ok0 || !ok1 { return false } - var discardsRefs = make(map[string]v1alpha2.LocalPolicyTargetReferenceWithSectionName) - for _, ref := range oldPolicy.Spec.TargetRefs { - key := indexer.GenHTTPRoutePolicyIndexKey(string(ref.Group), string(ref.Kind), e.ObjectOld.GetNamespace(), string(ref.Name), "") - discardsRefs[key] = ref - } - for _, ref := range newPolicy.Spec.TargetRefs { - key := indexer.GenHTTPRoutePolicyIndexKey(string(ref.Group), string(ref.Kind), e.ObjectOld.GetNamespace(), string(ref.Name), "") - delete(discardsRefs, key) - } + discardsRefs := slices.DeleteFunc(oldPolicy.Spec.TargetRefs, func(oldRef v1alpha2.LocalPolicyTargetReferenceWithSectionName) bool { + return slices.ContainsFunc(newPolicy.Spec.TargetRefs, func(newRef v1alpha2.LocalPolicyTargetReferenceWithSectionName) bool { + return oldRef.LocalPolicyTargetReference == newRef.LocalPolicyTargetReference && ptr.Equal(oldRef.SectionName, newRef.SectionName) + }) + }) if len(discardsRefs) > 0 { dump := oldPolicy.DeepCopy() - dump.Spec.TargetRefs = make([]v1alpha2.LocalPolicyTargetReferenceWithSectionName, 0, len(discardsRefs)) - for _, ref := range discardsRefs { - dump.Spec.TargetRefs = append(dump.Spec.TargetRefs, ref) - } + dump.Spec.TargetRefs = discardsRefs channel <- event.GenericEvent{Object: dump} } return true diff --git a/internal/controller/httproutepolicy.go b/internal/controller/httproutepolicy.go index 8b2a9bd41..dd9502672 100644 --- a/internal/controller/httproutepolicy.go +++ b/internal/controller/httproutepolicy.go @@ -2,10 +2,12 @@ package controller import ( "context" - "time" + "slices" + "github.com/go-logr/logr" networkingv1 "k8s.io/api/networking/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" @@ -19,79 +21,78 @@ import ( func (r *HTTPRouteReconciler) processHTTPRoutePolicies(tctx *provider.TranslateContext, httpRoute *gatewayv1.HTTPRoute) error { // list HTTPRoutePolices which sectionName is not specified var ( - checker = conflictChecker{ - object: httpRoute, - policies: make(map[targetRefKey][]v1alpha1.HTTPRoutePolicy), - } - listForAllRules v1alpha1.HTTPRoutePolicyList - key = indexer.GenHTTPRoutePolicyIndexKey(gatewayv1.GroupName, "HTTPRoute", httpRoute.GetNamespace(), httpRoute.GetName(), "") + list v1alpha1.HTTPRoutePolicyList + key = indexer.GenIndexKeyWithGK(gatewayv1.GroupName, "HTTPRoute", httpRoute.GetNamespace(), httpRoute.GetName()) ) - if err := r.List(context.Background(), &listForAllRules, client.MatchingFields{indexer.PolicyTargetRefs: key}); err != nil { + if err := r.List(context.Background(), &list, client.MatchingFields{indexer.PolicyTargetRefs: key}); err != nil { return err } - for _, item := range listForAllRules.Items { - checker.append("", item) - tctx.HTTPRoutePolicies["*"] = append(tctx.HTTPRoutePolicies["*"], item) + if len(list.Items) == 0 { + return nil } + var conflicts = make(map[types.NamespacedName]v1alpha1.HTTPRoutePolicy) for _, rule := range httpRoute.Spec.Rules { - if rule.Name == nil { - continue + var policies = findPoliciesWhichTargetRefTheRule(rule.Name, "HTTPRoute", list) + if conflict := checkPoliciesConflict(policies); conflict { + for _, policy := range policies { + namespacedName := types.NamespacedName{Namespace: policy.GetNamespace(), Name: policy.GetName()} + conflicts[namespacedName] = policy + } } + } + for i := range list.Items { var ( - ruleName = string(*rule.Name) - listForSectionRules v1alpha1.HTTPRoutePolicyList - key = indexer.GenHTTPRoutePolicyIndexKey(gatewayv1.GroupName, "HTTPRoute", httpRoute.GetNamespace(), httpRoute.GetName(), ruleName) + policy = list.Items[i] + namespacedName = types.NamespacedName{Namespace: policy.GetNamespace(), Name: policy.GetName()} + + status = false + reason = string(v1alpha2.PolicyReasonConflicted) + message = "HTTPRoutePolicy conflict with others target to the HTTPRoute" ) - if err := r.List(context.Background(), &listForSectionRules, client.MatchingFields{indexer.PolicyTargetRefs: key}); err != nil { - continue - } - for _, item := range listForSectionRules.Items { - checker.append(ruleName, item) - tctx.HTTPRoutePolicies[ruleName] = append(tctx.HTTPRoutePolicies[ruleName], item) + if _, conflict := conflicts[namespacedName]; !conflict { + status = true + reason = string(v1alpha2.PolicyReasonAccepted) + message = "" + + tctx.HTTPRoutePolicies = append(tctx.HTTPRoutePolicies, policy) } + modifyHTTPRoutePolicyStatus(httpRoute.Spec.ParentRefs, &policy, status, reason, message) + tctx.StatusUpdaters = append(tctx.StatusUpdaters, &policy) } - // todo: unreachable - // if the HTTPRoute is deleted, clear tctx.HTTPRoutePolicies and delete Ancestors from HTTPRoutePolicies status - // if !httpRoute.GetDeletionTimestamp().IsZero() { - // for _, policies := range checker.policies { - // for i := range policies { - // policy := policies[i] - // _ = DeleteAncestors(&policy.Status, httpRoute.Spec.ParentRefs) - // data, _ := json.Marshal(policy.Status) - // r.Log.Info("policy status after delete ancestor", "data", string(data)) - // if err := r.Status().Update(context.Background(), &policy); err != nil { - // r.Log.Error(err, "failed to Update policy status") - // } - // // tctx.StatusUpdaters = append(tctx.StatusUpdaters, &policy) - // } - // } - // return nil - // } + return nil +} +func (r *HTTPRouteReconciler) updateHTTPRoutePolicyStatusOnDeleting(nn types.NamespacedName) error { var ( - status = true - reason = string(v1alpha2.PolicyReasonAccepted) - message string + list v1alpha1.HTTPRoutePolicyList + key = indexer.GenIndexKeyWithGK(gatewayv1.GroupName, "HTTPRoute", nn.Namespace, nn.Name) ) - if checker.conflict { - status = false - reason = string(v1alpha2.PolicyReasonConflicted) - message = "HTTPRoutePolicy conflict with others target to the HTTPRoute" - - // clear HTTPRoutePolices from TranslateContext - tctx.HTTPRoutePolicies = make(map[string][]v1alpha1.HTTPRoutePolicy) + if err := r.List(context.Background(), &list, client.MatchingFields{indexer.PolicyTargetRefs: key}); err != nil { + return err } - - for _, policies := range checker.policies { - for i := range policies { - policy := policies[i] - modifyHTTPRoutePolicyStatus(httpRoute.Spec.ParentRefs, &policy, status, reason, message) - tctx.StatusUpdaters = append(tctx.StatusUpdaters, &policy) + var ( + httpRoutes = make(map[types.NamespacedName]gatewayv1.HTTPRoute) + ) + for _, policy := range list.Items { + // collect all parentRefs for the HTTPRoutePolicy + var parentRefs []gatewayv1.ParentReference + for _, ref := range policy.Spec.TargetRefs { + var namespacedName = types.NamespacedName{Namespace: policy.GetNamespace(), Name: string(ref.Name)} + httpRoute, ok := httpRoutes[namespacedName] + if !ok { + if err := r.Get(context.Background(), namespacedName, &httpRoute); err != nil { + continue + } + httpRoutes[namespacedName] = httpRoute + } + parentRefs = append(parentRefs, httpRoute.Spec.ParentRefs...) } + // delete AncestorRef which is not exist in the all parentRefs for each policy + updateDeleteAncestors(r.Client, r.Log, policy, parentRefs) } return nil @@ -99,35 +100,28 @@ func (r *HTTPRouteReconciler) processHTTPRoutePolicies(tctx *provider.TranslateC func (r *IngressReconciler) processHTTPRoutePolicies(tctx *provider.TranslateContext, ingress *networkingv1.Ingress) error { var ( - checker = conflictChecker{ - object: ingress, - policies: make(map[targetRefKey][]v1alpha1.HTTPRoutePolicy), - conflict: false, - } list v1alpha1.HTTPRoutePolicyList - key = indexer.GenHTTPRoutePolicyIndexKey(networkingv1.GroupName, "Ingress", ingress.GetNamespace(), ingress.GetName(), "") + key = indexer.GenIndexKeyWithGK(networkingv1.GroupName, "Ingress", ingress.GetNamespace(), ingress.GetName()) ) if err := r.List(context.Background(), &list, client.MatchingFields{indexer.PolicyTargetRefs: key}); err != nil { return err } - for _, item := range list.Items { - checker.append("", item) - tctx.HTTPRoutePolicies["*"] = append(tctx.HTTPRoutePolicies["*"], item) + if len(list.Items) == 0 { + return nil } var ( - status = true - reason = string(v1alpha2.PolicyReasonAccepted) - message string - ) - if checker.conflict { - status = false - reason = string(v1alpha2.PolicyReasonConflicted) + status = false + reason = string(v1alpha2.PolicyReasonConflicted) message = "HTTPRoutePolicy conflict with others target to the Ingress" + ) + if conflict := checkPoliciesConflict(list.Items); !conflict { + status = true + reason = string(v1alpha2.PolicyReasonAccepted) + message = "" - // clear HTTPRoutePolicies from TranslateContext - tctx.HTTPRoutePolicies = make(map[string][]v1alpha1.HTTPRoutePolicy) + tctx.HTTPRoutePolicies = list.Items } for i := range list.Items { @@ -139,12 +133,54 @@ func (r *IngressReconciler) processHTTPRoutePolicies(tctx *provider.TranslateCon return nil } +func (r *IngressReconciler) updateHTTPRoutePolicyStatusOnDeleting(nn types.NamespacedName) error { + var ( + list v1alpha1.HTTPRoutePolicyList + key = indexer.GenIndexKeyWithGK(networkingv1.GroupName, "Ingress", nn.Namespace, nn.Name) + ) + if err := r.List(context.Background(), &list, client.MatchingFields{indexer.PolicyTargetRefs: key}); err != nil { + return err + } + var ( + ingress2ParentRef = make(map[types.NamespacedName]gatewayv1.ParentReference) + ) + for _, policy := range list.Items { + // collect all parentRefs for the HTTPRoutePolicy + var parentRefs []gatewayv1.ParentReference + for _, ref := range policy.Spec.TargetRefs { + var namespacedName = types.NamespacedName{Namespace: policy.GetNamespace(), Name: string(ref.Name)} + parentRef, ok := ingress2ParentRef[namespacedName] + if !ok { + var ingress networkingv1.Ingress + if err := r.Get(context.Background(), namespacedName, &ingress); err != nil { + continue + } + ingressClass, err := r.getIngressClass(&ingress) + if err != nil { + continue + } + parentRef = gatewayv1.ParentReference{ + Group: ptr.To(gatewayv1.Group(ingressClass.GroupVersionKind().Group)), + Kind: ptr.To(gatewayv1.Kind("IngressClass")), + Name: gatewayv1.ObjectName(ingressClass.Name), + } + ingress2ParentRef[namespacedName] = parentRef + } + parentRefs = append(parentRefs, parentRef) + } + // delete AncestorRef which is not exist in the all parentRefs + updateDeleteAncestors(r.Client, r.Log, policy, parentRefs) + } + + return nil +} + func modifyHTTPRoutePolicyStatus(parentRefs []gatewayv1.ParentReference, policy *v1alpha1.HTTPRoutePolicy, status bool, reason, message string) { condition := metav1.Condition{ Type: string(v1alpha2.PolicyConditionAccepted), Status: metav1.ConditionTrue, ObservedGeneration: policy.GetGeneration(), - LastTransitionTime: metav1.Time{Time: time.Now()}, + LastTransitionTime: metav1.Now(), Reason: reason, Message: message, } @@ -154,37 +190,48 @@ func modifyHTTPRoutePolicyStatus(parentRefs []gatewayv1.ParentReference, policy _ = SetAncestors(&policy.Status, parentRefs, condition) } -type conflictChecker struct { - object client.Object - policies map[targetRefKey][]v1alpha1.HTTPRoutePolicy - conflict bool +// checkPoliciesConflict determines if there is a conflict among the given HTTPRoutePolicy objects based on their priority values. +// It returns true if any policy has a different priority than the first policy in the list, otherwise false. +// An empty or single-element policies slice is considered non-conflicting. +// The function assumes all policies have a valid Spec.Priority field for comparison. +func checkPoliciesConflict(policies []v1alpha1.HTTPRoutePolicy) bool { + if len(policies) == 0 { + return false + } + priority := policies[0].Spec.Priority + for _, policy := range policies { + if !ptr.Equal(policy.Spec.Priority, priority) { + return true + } + } + return false } -type targetRefKey struct { - Group gatewayv1.Group - Namespace gatewayv1.Namespace - Name gatewayv1.ObjectName - SectionName gatewayv1.SectionName +// findPoliciesWhichTargetRefTheRule filters HTTPRoutePolicy objects whose TargetRefs match the given ruleName and kind. +// A match occurs if the TargetRef's Kind equals the provided kind and its SectionName is nil, empty, or equal to ruleName. +func findPoliciesWhichTargetRefTheRule(ruleName *gatewayv1.SectionName, kind string, list v1alpha1.HTTPRoutePolicyList) (policies []v1alpha1.HTTPRoutePolicy) { + for _, policy := range list.Items { + for _, ref := range policy.Spec.TargetRefs { + if string(ref.Kind) == kind && (ref.SectionName == nil || *ref.SectionName == "" || ptr.Equal(ref.SectionName, ruleName)) { + policies = append(policies, policy) + break + } + } + } + return } -func (c *conflictChecker) append(sectionName string, policy v1alpha1.HTTPRoutePolicy) { - key := targetRefKey{ - Group: gatewayv1.GroupName, - Namespace: gatewayv1.Namespace(c.object.GetNamespace()), - Name: gatewayv1.ObjectName(c.object.GetName()), - SectionName: gatewayv1.SectionName(sectionName), - } - c.policies[key] = append(c.policies[key], policy) - - if !c.conflict { - Loop: - for _, items := range c.policies { - for _, item := range items { - if !ptr.Equal(item.Spec.Priority, policy.Spec.Priority) { - c.conflict = true - break Loop - } - } +// updateDeleteAncestors removes ancestor references from HTTPRoutePolicy statuses that are no longer present in the provided parentRefs. +func updateDeleteAncestors(client client.Client, logger logr.Logger, policy v1alpha1.HTTPRoutePolicy, parentRefs []gatewayv1.ParentReference) { + length := len(policy.Status.Ancestors) + policy.Status.Ancestors = slices.DeleteFunc(policy.Status.Ancestors, func(status v1alpha2.PolicyAncestorStatus) bool { + return !slices.ContainsFunc(parentRefs, func(ref gatewayv1.ParentReference) bool { + return parentRefValueEqual(status.AncestorRef, ref) + }) + }) + if length != len(policy.Status.Ancestors) { + if err := client.Status().Update(context.Background(), &policy); err != nil { + logger.Error(err, "failed to update HTTPRoutePolicy status") } } } diff --git a/internal/controller/indexer/indexer.go b/internal/controller/indexer/indexer.go index 7a606b274..3b959b6d5 100644 --- a/internal/controller/indexer/indexer.go +++ b/internal/controller/indexer/indexer.go @@ -322,19 +322,16 @@ func HTTPRouteExtensionIndexFunc(rawObj client.Object) []string { return keys } -func GenHTTPRoutePolicyIndexKey(group, kind, namespace, name, sectionName string) string { - return schema.GroupKind{Group: group, Kind: kind}.String() + "/" + client.ObjectKey{Namespace: namespace, Name: name}.String() + "/" + sectionName -} - func HTTPRoutePolicyIndexFunc(rawObj client.Object) []string { hrp := rawObj.(*v1alpha1.HTTPRoutePolicy) var keys = make([]string, 0, len(hrp.Spec.TargetRefs)) + var m = make(map[string]struct{}) for _, ref := range hrp.Spec.TargetRefs { - var sectionName string - if ref.SectionName != nil { - sectionName = string(*ref.SectionName) + key := GenIndexKeyWithGK(string(ref.Group), string(ref.Kind), hrp.GetNamespace(), string(ref.Name)) + if _, ok := m[key]; !ok { + m[key] = struct{}{} + keys = append(keys, key) } - keys = append(keys, GenHTTPRoutePolicyIndexKey(string(ref.Group), string(ref.Kind), hrp.GetNamespace(), string(ref.Name), sectionName)) } return keys } diff --git a/internal/controller/ingress_controller.go b/internal/controller/ingress_controller.go index 8a49b00c5..35c810e7c 100644 --- a/internal/controller/ingress_controller.go +++ b/internal/controller/ingress_controller.go @@ -97,6 +97,10 @@ func (r *IngressReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct ingress := new(networkingv1.Ingress) if err := r.Get(ctx, req.NamespacedName, ingress); err != nil { if client.IgnoreNotFound(err) == nil { + if err := r.updateHTTPRoutePolicyStatusOnDeleting(req.NamespacedName); err != nil { + return ctrl.Result{}, err + } + // Ingress was deleted, clean up corresponding resources ingress.Namespace = req.Namespace ingress.Name = req.Name diff --git a/internal/controller/policies.go b/internal/controller/policies.go index 2ef04a3b4..477b09221 100644 --- a/internal/controller/policies.go +++ b/internal/controller/policies.go @@ -2,20 +2,18 @@ package controller import ( "fmt" - "slices" - - "k8s.io/utils/ptr" - gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" - gatewayv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2" "github.com/go-logr/logr" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/types" + "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/event" "sigs.k8s.io/controller-runtime/pkg/predicate" + gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" + gatewayv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2" "github.com/api7/api7-ingress-controller/api/v1alpha1" "github.com/api7/api7-ingress-controller/internal/controller/config" @@ -192,16 +190,6 @@ func SetAncestorStatus(status *v1alpha1.PolicyStatus, ancestorStatus gatewayv1al return true } -func DeleteAncestors(status *v1alpha1.PolicyStatus, parentRefs []gatewayv1.ParentReference) bool { - var length = len(status.Ancestors) - for _, parentRef := range parentRefs { - status.Ancestors = slices.DeleteFunc(status.Ancestors, func(status gatewayv1alpha2.PolicyAncestorStatus) bool { - return parentRefValueEqual(parentRef, status.AncestorRef) - }) - } - return length != len(status.Ancestors) -} - func parentRefValueEqual(a, b gatewayv1.ParentReference) bool { return ptr.Equal(a.Group, b.Group) && ptr.Equal(a.Kind, b.Kind) && diff --git a/internal/provider/adc/translator/httproute.go b/internal/provider/adc/translator/httproute.go index f7af81bb5..0f59a9b53 100644 --- a/internal/provider/adc/translator/httproute.go +++ b/internal/provider/adc/translator/httproute.go @@ -233,23 +233,24 @@ func (t *Translator) fillPluginFromHTTPRequestRedirectFilter(plugins adctypes.Pl } func (t *Translator) fillHTTPRoutePoliciesForHTTPRoute(tctx *provider.TranslateContext, routes []*adctypes.Route, rule gatewayv1.HTTPRouteRule) { - var keys = []string{"*"} - if rule.Name != nil { - keys = append(keys, string(*rule.Name)) + var policies []v1alpha1.HTTPRoutePolicy + for _, policy := range tctx.HTTPRoutePolicies { + for _, ref := range policy.Spec.TargetRefs { + if string(ref.Kind) == "HTTPRoute" && (ref.SectionName == nil || *ref.SectionName == "" || ptr.Equal(ref.SectionName, rule.Name)) { + policies = append(policies, policy) + break + } + } } - t.fillHTTPRoutePolicies(tctx, routes, keys...) + + t.fillHTTPRoutePolicies(routes, policies) } func (t *Translator) fillHTTPRoutePoliciesForIngress(tctx *provider.TranslateContext, routes []*adctypes.Route) { - t.fillHTTPRoutePolicies(tctx, routes, "*") + t.fillHTTPRoutePolicies(routes, tctx.HTTPRoutePolicies) } -func (t *Translator) fillHTTPRoutePolicies(tctx *provider.TranslateContext, routes []*adctypes.Route, ctxKeys ...string) { - var policies []v1alpha1.HTTPRoutePolicy - for _, key := range ctxKeys { - policies = append(policies, tctx.HTTPRoutePolicies[key]...) - } - +func (t *Translator) fillHTTPRoutePolicies(routes []*adctypes.Route, policies []v1alpha1.HTTPRoutePolicy) { for _, policy := range policies { for _, route := range routes { route.Priority = policy.Spec.Priority diff --git a/internal/provider/provider.go b/internal/provider/provider.go index cc0a362ff..b359c31d9 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -38,7 +38,7 @@ type TranslateContext struct { BackendTrafficPolicies map[types.NamespacedName]*v1alpha1.BackendTrafficPolicy GatewayProxies map[ResourceKind]v1alpha1.GatewayProxy ResourceParentRefs map[ResourceKind][]ResourceKind - HTTPRoutePolicies map[string][]v1alpha1.HTTPRoutePolicy + HTTPRoutePolicies []v1alpha1.HTTPRoutePolicy StatusUpdaters []client.Object } @@ -53,6 +53,5 @@ func NewDefaultTranslateContext(ctx context.Context) *TranslateContext { BackendTrafficPolicies: make(map[types.NamespacedName]*v1alpha1.BackendTrafficPolicy), GatewayProxies: make(map[ResourceKind]v1alpha1.GatewayProxy), ResourceParentRefs: make(map[ResourceKind][]ResourceKind), - HTTPRoutePolicies: make(map[string][]v1alpha1.HTTPRoutePolicy), } } diff --git a/test/e2e/gatewayapi/httproute.go b/test/e2e/gatewayapi/httproute.go index 5838be81b..32afedfed 100644 --- a/test/e2e/gatewayapi/httproute.go +++ b/test/e2e/gatewayapi/httproute.go @@ -477,6 +477,7 @@ spec: Status(200) }) }) + Context("HTTPRoute Rule Match", func() { var exactRouteByGet = ` apiVersion: gateway.networking.k8s.io/v1 @@ -842,13 +843,19 @@ spec: }).WithTimeout(8 * time.Second).ProbeEvery(time.Second).Should(Equal(http.StatusOK)) }) - PIt("HTTPRoutePolicy status changes on HTTPRoute deleting", func() { + It("HTTPRoutePolicy status changes on HTTPRoute deleting", func() { By("create HTTPRoute") ResourceApplied("HTTPRoute", "httpbin", varsRoute, 1) By("create HTTPRoutePolicy") ResourceApplied("HTTPRoutePolicy", "http-route-policy-0", httpRoutePolicy, 1) + Eventually(func() string { + spec, err := s.GetResourceYaml("HTTPRoutePolicy", "http-route-policy-0") + Expect(err).NotTo(HaveOccurred(), "getting HTTPRoutePolicy") + return spec + }).WithTimeout(8 * time.Second).ProbeEvery(time.Second).Should(ContainSubstring("type: Accepted")) + By("access dataplane to check the HTTPRoutePolicy") s.NewAPISIXClient(). GET("/get"). diff --git a/test/e2e/ingress/ingress.go b/test/e2e/ingress/ingress.go index 0e810b4da..335944774 100644 --- a/test/e2e/ingress/ingress.go +++ b/test/e2e/ingress/ingress.go @@ -637,5 +637,46 @@ spec: }). WithTimeout(8 * time.Second).ProbeEvery(time.Second).Should(Equal(http.StatusOK)) }) + + It("HTTPRoutePolicy status changes on Ingress deleting", func() { + By("create Ingress") + err := s.CreateResourceFromString(ingressSpec) + Expect(err).NotTo(HaveOccurred(), "creating Ingress") + + By("create HTTPRoutePolicy") + err = s.CreateResourceFromString(httpRoutePolicySpec0) + Expect(err).NotTo(HaveOccurred(), "creating HTTPRoutePolicy") + Eventually(func() string { + spec, err := s.GetResourceYaml("HTTPRoutePolicy", "http-route-policy-0") + Expect(err).NotTo(HaveOccurred(), "HTTPRoutePolicy status should be True") + return spec + }). + WithTimeout(8 * time.Second).ProbeEvery(time.Second).Should(ContainSubstring(`status: "True"`)) + + By("request the route without vars should be Not Found") + Eventually(func() int { + return s.NewAPISIXClient().GET("/get").WithHost("example.com").Expect().Raw().StatusCode + }). + WithTimeout(8 * time.Second).ProbeEvery(time.Second).Should(Equal(http.StatusNotFound)) + + By("request the route with the correct vars should be OK") + s.NewAPISIXClient().GET("/get").WithHost("example.com"). + WithHeader("X-HRP-Name", "http-route-policy-0").Expect().Status(http.StatusOK) + + By("delete ingress") + err = s.DeleteResource("Ingress", "default") + Expect(err).NotTo(HaveOccurred(), "delete Ingress") + Eventually(func() int { + return s.NewAPISIXClient().GET("/get").WithHost("example.com"). + WithHeader("X-HRP-Name", "http-route-policy-0").Expect().Raw().StatusCode + }). + WithTimeout(8 * time.Second).ProbeEvery(time.Second).Should(Equal(http.StatusNotFound)) + + Eventually(func() string { + spec, err := s.GetResourceYaml("HTTPRoutePolicy", "http-route-policy-0") + Expect(err).NotTo(HaveOccurred(), "getting HTTPRoutePolicy") + return spec + }).WithTimeout(8 * time.Second).ProbeEvery(time.Second).ShouldNot(ContainSubstring("ancestorRef:")) + }) }) })