Skip to content

Commit e1186f1

Browse files
committed
enhance policy handling
1 parent bd32c55 commit e1186f1

File tree

7 files changed

+258
-19
lines changed

7 files changed

+258
-19
lines changed

charts/values.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ nameOverride: ""
22
labelsOverride: {}
33
annotations: {}
44
podAnnotations: {}
5-
controllerName: gateway.api7.io/api7-ingress-controller
5+
controllerName: gateway.apisix.io/api7-ingress-controller
66
replicas: 1
77
admin:
88
key: '' # Pass the admin key generated for the ingress gateway group

config/samples/config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
log_level: "info" # The log level of the API7 Ingress Controller.
22
# the default value is "info".
33

4-
controller_name: gateway.api7.io/api7-ingress-controller # The controller name of the API7 Ingress Controller,
4+
controller_name: gateway.apisix.io/api7-ingress-controller # The controller name of the API7 Ingress Controller,
55
# which is used to identify the controller in the GatewayClass.
66
# The default value is "gateway.api7.io/api7-ingress-controller".
77
leader_election_id: "api7-ingress-controller-leader" # The leader election ID for the API7 Ingress Controller.

docs/configure.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ The API7 Ingress Controller is a Kubernetes Ingress Controller that implements t
88
log_level: "info" # The log level of the API7 Ingress Controller.
99
# the default value is "info".
1010

11-
controller_name: gateway.api7.io/api7-ingress-controller # The controller name of the API7 Ingress Controller,
11+
controller_name: gateway.apisix.io/api7-ingress-controller # The controller name of the API7 Ingress Controller,
1212
# which is used to identify the controller in the GatewayClass.
1313
# The default value is "gateway.api7.io/api7-ingress-controller".
1414

internal/controller/httproutepolicy.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,24 @@ func (r *HTTPRouteReconciler) processHTTPRoutePolicies(tctx *provider.TranslateC
5252
}
5353
}
5454

55+
// todo: unreachable
56+
// if the HTTPRoute is deleted, clear tctx.HTTPRoutePolicies and delete Ancestors from HTTPRoutePolicies status
57+
// if !httpRoute.GetDeletionTimestamp().IsZero() {
58+
// for _, policies := range checker.policies {
59+
// for i := range policies {
60+
// policy := policies[i]
61+
// _ = DeleteAncestors(&policy.Status, httpRoute.Spec.ParentRefs)
62+
// data, _ := json.Marshal(policy.Status)
63+
// r.Log.Info("policy status after delete ancestor", "data", string(data))
64+
// if err := r.Status().Update(context.Background(), &policy); err != nil {
65+
// r.Log.Error(err, "failed to Update policy status")
66+
// }
67+
// // tctx.StatusUpdaters = append(tctx.StatusUpdaters, &policy)
68+
// }
69+
// }
70+
// return nil
71+
// }
72+
5573
var (
5674
status = true
5775
reason = string(v1alpha2.PolicyReasonAccepted)

internal/controller/policies.go

Lines changed: 35 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,23 @@ package controller
22

33
import (
44
"fmt"
5+
"slices"
56

7+
"k8s.io/apimachinery/pkg/api/meta"
8+
"k8s.io/utils/ptr"
69
gatewayv1 "sigs.k8s.io/gateway-api/apis/v1"
710
gatewayv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2"
811

9-
"github.com/api7/api7-ingress-controller/api/v1alpha1"
10-
"github.com/api7/api7-ingress-controller/internal/controller/config"
11-
"github.com/api7/api7-ingress-controller/internal/controller/indexer"
12-
"github.com/api7/api7-ingress-controller/internal/provider"
1312
"github.com/go-logr/logr"
1413
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1514
"k8s.io/apimachinery/pkg/runtime/schema"
1615
"k8s.io/apimachinery/pkg/types"
1716
"sigs.k8s.io/controller-runtime/pkg/client"
17+
18+
"github.com/api7/api7-ingress-controller/api/v1alpha1"
19+
"github.com/api7/api7-ingress-controller/internal/controller/config"
20+
"github.com/api7/api7-ingress-controller/internal/controller/indexer"
21+
"github.com/api7/api7-ingress-controller/internal/provider"
1822
)
1923

2024
type PolicyTargetKey struct {
@@ -115,19 +119,37 @@ func SetAncestors(status *v1alpha1.PolicyStatus, parentRefs []gatewayv1.ParentRe
115119
}
116120

117121
func SetAncestorStatus(status *v1alpha1.PolicyStatus, ancestorStatus gatewayv1alpha2.PolicyAncestorStatus) bool {
122+
if len(ancestorStatus.Conditions) == 0 {
123+
return false
124+
}
125+
condition := ancestorStatus.Conditions[0]
118126
for _, c := range status.Ancestors {
119-
if c.AncestorRef == ancestorStatus.AncestorRef {
120-
if len(c.Conditions) == 0 || len(ancestorStatus.Conditions) == 0 {
121-
c.Conditions = ancestorStatus.Conditions
122-
return true
127+
if parentRefValueEqual(c.AncestorRef, ancestorStatus.AncestorRef) &&
128+
c.ControllerName == ancestorStatus.ControllerName {
129+
if !VerifyConditions(&c.Conditions, condition) {
130+
return false
123131
}
124-
if c.Conditions[0].ObservedGeneration < ancestorStatus.Conditions[0].ObservedGeneration {
125-
c.Conditions = ancestorStatus.Conditions
126-
return true
127-
}
128-
return false
132+
meta.SetStatusCondition(&c.Conditions, condition)
133+
return true
129134
}
130135
}
131136
status.Ancestors = append(status.Ancestors, ancestorStatus)
132137
return true
133138
}
139+
140+
func DeleteAncestors(status *v1alpha1.PolicyStatus, parentRefs []gatewayv1.ParentReference) bool {
141+
var length = len(status.Ancestors)
142+
for _, parentRef := range parentRefs {
143+
status.Ancestors = slices.DeleteFunc(status.Ancestors, func(status gatewayv1alpha2.PolicyAncestorStatus) bool {
144+
return parentRefValueEqual(parentRef, status.AncestorRef)
145+
})
146+
}
147+
return length != len(status.Ancestors)
148+
}
149+
150+
func parentRefValueEqual(a, b gatewayv1.ParentReference) bool {
151+
return ptr.Equal(a.Group, b.Group) &&
152+
ptr.Equal(a.Kind, b.Kind) &&
153+
ptr.Equal(a.Namespace, b.Namespace) &&
154+
a.Name == b.Name
155+
}

test/e2e/crds/consumer.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ spec:
6767
filters:
6868
- type: ExtensionRef
6969
extensionRef:
70-
group: gateway.api7.io
70+
group: gateway.apisix.io
7171
kind: PluginConfig
7272
name: auth-plugin-config
7373
backendRefs:

test/e2e/gatewayapi/httproute.go

Lines changed: 201 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@ import (
66
"strings"
77
"time"
88

9+
"github.com/gruntwork-io/terratest/modules/retry"
910
. "github.com/onsi/ginkgo/v2"
1011
. "github.com/onsi/gomega"
12+
"github.com/pkg/errors"
1113

1214
"github.com/api7/api7-ingress-controller/test/e2e/framework"
1315
"github.com/api7/api7-ingress-controller/test/e2e/scaffold"
@@ -290,7 +292,7 @@ spec:
290292
- name: httpbin-service-e2e-test
291293
port: 80
292294
`
293-
var httpRoutePolicy = `
295+
const httpRoutePolicy = `
294296
apiVersion: gateway.apisix.io/v1alpha1
295297
kind: HTTPRoutePolicy
296298
metadata:
@@ -438,6 +440,18 @@ spec:
438440
WithHeader("X-Route-Name", "httpbin").
439441
Expect().
440442
Status(http.StatusOK)
443+
})
444+
445+
It("HTTPRoutePolicy in effect", func() {
446+
By("create HTTPRoute")
447+
ResourceApplied("HTTPRoute", "httpbin", varsRoute, 1)
448+
449+
s.NewAPISIXClient().
450+
GET("/get").
451+
WithHost("httpbin.example").
452+
WithHeader("X-Route-Name", "httpbin").
453+
Expect().
454+
Status(http.StatusOK)
441455

442456
By("create HTTPRoutePolicy")
443457
ResourceApplied("HTTPRoutePolicy", "http-route-policy-0", httpRoutePolicy, 1)
@@ -458,6 +472,191 @@ spec:
458472
WithQuery("hrp_name", "http-route-policy-0").
459473
Expect().
460474
Status(http.StatusOK)
475+
476+
By("update HTTPRoutePolicy")
477+
const changedHTTPRoutePolicy = `
478+
apiVersion: gateway.apisix.io/v1alpha1
479+
kind: HTTPRoutePolicy
480+
metadata:
481+
name: http-route-policy-0
482+
spec:
483+
targetRefs:
484+
- group: gateway.networking.k8s.io
485+
kind: HTTPRoute
486+
name: httpbin
487+
# sectionName: get
488+
priority: 10
489+
vars:
490+
- - http_x_hrp_name
491+
- ==
492+
- new-hrp-name
493+
`
494+
ResourceApplied("HTTPRoutePolicy", "http-route-policy-0", changedHTTPRoutePolicy, 1)
495+
// use the old vars cannot match any route
496+
s.NewAPISIXClient().
497+
GET("/get").
498+
WithHost("httpbin.example").
499+
WithHeader("X-Route-Name", "httpbin").
500+
WithHeader("X-HRP-Name", "http-route-policy-0").
501+
WithQuery("hrp_name", "http-route-policy-0").
502+
Expect().
503+
Status(http.StatusNotFound)
504+
// use the new vars can match the route
505+
s.NewAPISIXClient().
506+
GET("/get").
507+
WithHost("httpbin.example").
508+
WithHeader("X-Route-Name", "httpbin").
509+
WithHeader("X-HRP-Name", "new-hrp-name").
510+
Expect().
511+
Status(http.StatusOK)
512+
513+
By("delete the HTTPRoutePolicy")
514+
err := s.DeleteResource("HTTPRoutePolicy", "http-route-policy-0")
515+
Expect(err).NotTo(HaveOccurred(), "deleting HTTPRoutePolicy")
516+
Eventually(func() string {
517+
_, err := s.GetResourceYaml("HTTPRoutePolicy", "http-route-policy-0")
518+
return err.Error()
519+
}).WithTimeout(8 * time.Second).ProbeEvery(time.Second).Should(ContainSubstring(`httproutepolicies.gateway.apisix.io "http-route-policy-0" not found`))
520+
// access the route without additional vars should be OK
521+
message := retry.DoWithRetry(s.GinkgoT, "", 10, time.Second, func() (string, error) {
522+
statusCode := s.NewAPISIXClient().
523+
GET("/get").
524+
WithHost("httpbin.example").
525+
WithHeader("X-Route-Name", "httpbin").
526+
Expect().Raw().StatusCode
527+
if statusCode != http.StatusOK {
528+
return "", errors.Errorf("unexpected status code: %v", statusCode)
529+
}
530+
return "request OK", nil
531+
})
532+
s.Logf(message)
533+
})
534+
535+
It("HTTPRoutePolicy conflicts", func() {
536+
const httpRoutePolicy0 = `
537+
apiVersion: gateway.apisix.io/v1alpha1
538+
kind: HTTPRoutePolicy
539+
metadata:
540+
name: http-route-policy-0
541+
spec:
542+
targetRefs:
543+
- group: gateway.networking.k8s.io
544+
kind: HTTPRoute
545+
name: httpbin
546+
priority: 10
547+
vars:
548+
- - http_x_hrp_name
549+
- ==
550+
- http-route-policy-0
551+
`
552+
const httpRoutePolicy1 = `
553+
apiVersion: gateway.apisix.io/v1alpha1
554+
kind: HTTPRoutePolicy
555+
metadata:
556+
name: http-route-policy-1
557+
spec:
558+
targetRefs:
559+
- group: gateway.networking.k8s.io
560+
kind: HTTPRoute
561+
name: httpbin
562+
priority: 20
563+
vars:
564+
- - http_x_hrp_name
565+
- ==
566+
- http-route-policy-0
567+
`
568+
const httpRoutePolicy2 = `
569+
apiVersion: gateway.apisix.io/v1alpha1
570+
kind: HTTPRoutePolicy
571+
metadata:
572+
name: http-route-policy-2
573+
spec:
574+
targetRefs:
575+
- group: gateway.networking.k8s.io
576+
kind: HTTPRoute
577+
name: httpbin
578+
- group: gateway.networking.k8s.io
579+
kind: HTTPRoute
580+
name: httpbin-1
581+
priority: 30
582+
vars:
583+
- - http_x_hrp_name
584+
- ==
585+
- http-route-policy-0
586+
`
587+
By("create HTTPRoute")
588+
ResourceApplied("HTTPRoute", "httpbin", varsRoute, 1)
589+
590+
By("create HTTPRoutePolices")
591+
for _, spec := range []string{httpRoutePolicy0, httpRoutePolicy1, httpRoutePolicy2} {
592+
err := s.CreateResourceFromString(spec)
593+
Expect(err).NotTo(HaveOccurred(), "creating HTTPRoutePolicy")
594+
}
595+
for _, name := range []string{"http-route-policy-0", "http-route-policy-1", "http-route-policy-2"} {
596+
Eventually(func() string {
597+
spec, err := s.GetResourceYaml("HTTPRoutePolicy", name)
598+
Expect(err).NotTo(HaveOccurred(), "getting HTTPRoutePolicy yaml")
599+
return spec
600+
}).WithTimeout(8 * time.Second).ProbeEvery(time.Second).
601+
Should(ContainSubstring("reason: Conflicted"))
602+
}
603+
604+
// assert that conflict policies are not in effect
605+
s.NewAPISIXClient().
606+
GET("/get").
607+
WithHost("httpbin.example").
608+
WithHeader("X-Route-Name", "httpbin").
609+
Expect().
610+
Status(http.StatusOK)
611+
})
612+
613+
PIt("HTTPRoutePolicy status changes on HTTPRoute deleting", func() {
614+
By("create HTTPRoute")
615+
ResourceApplied("HTTPRoute", "httpbin", varsRoute, 1)
616+
617+
By("create HTTPRoutePolicy")
618+
ResourceApplied("HTTPRoutePolicy", "http-route-policy-0", httpRoutePolicy, 1)
619+
620+
By("access dataplane to check the HTTPRoutePolicy")
621+
s.NewAPISIXClient().
622+
GET("/get").
623+
WithHost("httpbin.example").
624+
WithHeader("X-Route-Name", "httpbin").
625+
Expect().
626+
Status(http.StatusNotFound)
627+
628+
s.NewAPISIXClient().
629+
GET("/get").
630+
WithHost("httpbin.example").
631+
WithHeader("X-Route-Name", "httpbin").
632+
WithHeader("X-HRP-Name", "http-route-policy-0").
633+
WithQuery("hrp_name", "http-route-policy-0").
634+
Expect().
635+
Status(http.StatusOK)
636+
637+
By("delete the HTTPRoute, assert the HTTPRoutePolicy's status will be changed")
638+
err := s.DeleteResource("HTTPRoute", "httpbin")
639+
Expect(err).NotTo(HaveOccurred(), "deleting HTTPRoute")
640+
message := retry.DoWithRetry(s.GinkgoT, "request the deleted route", 10, time.Second, func() (string, error) {
641+
statusCode := s.NewAPISIXClient().
642+
GET("/get").
643+
WithHost("httpbin.example").
644+
WithHeader("X-Route-Name", "httpbin").
645+
WithHeader("X-HRP-Name", "http-route-policy-0").
646+
WithQuery("hrp_name", "http-route-policy-0").
647+
Expect().Raw().StatusCode
648+
if statusCode != http.StatusNotFound {
649+
return "", errors.Errorf("unexpected status code: %v", statusCode)
650+
}
651+
return "the route is deleted", nil
652+
})
653+
s.Logf(message)
654+
655+
Eventually(func() string {
656+
spec, err := s.GetResourceYaml("HTTPRoutePolicy", "http-route-policy-0")
657+
Expect(err).NotTo(HaveOccurred(), "getting HTTPRoutePolicy")
658+
return spec
659+
}).WithTimeout(8 * time.Second).ProbeEvery(time.Second).ShouldNot(ContainSubstring("ancestorRef:"))
461660
})
462661
})
463662

@@ -661,7 +860,7 @@ spec:
661860
filters:
662861
- type: ExtensionRef
663862
extensionRef:
664-
group: gateway.api7.io
863+
group: gateway.apisix.io
665864
kind: PluginConfig
666865
name: example-plugin-config
667866
backendRefs:

0 commit comments

Comments
 (0)