11package conformance
22
33import (
4+ "context"
45 "fmt"
56 "os"
67 "testing"
8+ "time"
79
810 "github.com/api7/api7-ingress-controller/test/e2e/framework"
911 "github.com/gruntwork-io/terratest/modules/k8s"
12+ "github.com/gruntwork-io/terratest/modules/retry"
13+ "sigs.k8s.io/controller-runtime/pkg/client"
1014
1115 . "github.com/onsi/ginkgo/v2"
1216 . "github.com/onsi/gomega"
17+ gatewayv1 "sigs.k8s.io/gateway-api/apis/v1"
1318)
1419
1520var gatewayClassName = "api7"
@@ -24,15 +29,89 @@ spec:
2429 controllerName: %s
2530` , gatewayClassName , controllerName )
2631
32+ var gatewayProxyYaml = `
33+ apiVersion: gateway.apisix.io/v1alpha1
34+ kind: GatewayProxy
35+ metadata:
36+ name: conformance-gateway-proxy
37+ namespace: %s
38+ spec:
39+ statusAddress:
40+ - %s
41+ provider:
42+ type: ControlPlane
43+ controlPlane:
44+ endpoints:
45+ - %s
46+ auth:
47+ type: AdminKey
48+ adminKey:
49+ value: %s
50+ `
51+
52+ type GatewayProxyOpts struct {
53+ StatusAddress string
54+ AdminKey string
55+ AdminEndpoint string
56+ }
57+
58+ var defaultGatewayProxyOpts GatewayProxyOpts
59+
60+ func deleteNamespace (kubectl * k8s.KubectlOptions ) {
61+ // gateway api conformance test namespaces
62+ namespacesToDelete := []string {
63+ "gateway-conformance-infra" ,
64+ "gateway-conformance-web-backend" ,
65+ "gateway-conformance-app-backend" ,
66+ }
67+
68+ for _ , ns := range namespacesToDelete {
69+ _ , err := k8s .GetNamespaceE (GinkgoT (), kubectl , ns )
70+ if err == nil {
71+ // Namespace exists, delete it
72+ GinkgoT ().Logf ("Deleting existing namespace: %s" , ns )
73+ err := k8s .DeleteNamespaceE (GinkgoT (), kubectl , ns )
74+ if err != nil {
75+ GinkgoT ().Logf ("Error deleting namespace %s: %v" , ns , err )
76+ continue
77+ }
78+
79+ // Wait for deletion to complete by checking until GetNamespaceE returns an error
80+ _ , err = retry .DoWithRetryE (
81+ GinkgoT (),
82+ fmt .Sprintf ("Waiting for namespace %s to be deleted" , ns ),
83+ 30 ,
84+ 5 * time .Second ,
85+ func () (string , error ) {
86+ _ , err := k8s .GetNamespaceE (GinkgoT (), kubectl , ns )
87+ if err != nil {
88+ // Namespace is gone, which is what we want
89+ return "Namespace deleted" , nil
90+ }
91+ return "" , fmt .Errorf ("namespace %s still exists" , ns )
92+ },
93+ )
94+
95+ if err != nil {
96+ GinkgoT ().Logf ("Error waiting for namespace %s to be deleted: %v" , ns , err )
97+ }
98+ } else {
99+ GinkgoT ().Logf ("Namespace %s does not exist or cannot be accessed" , ns )
100+ }
101+ }
102+ }
103+
27104func TestMain (m * testing.M ) {
28105 RegisterFailHandler (Fail )
29106 f := framework .NewFramework ()
30107
31108 f .BeforeSuite ()
32109
33- namespace := "api7ee-conformance-test"
34-
110+ // Check and delete specific namespaces if they exist
35111 kubectl := k8s .NewKubectlOptions ("" , "" , "default" )
112+ deleteNamespace (kubectl )
113+
114+ namespace := "api7ee-conformance-test"
36115
37116 k8s .KubectlApplyFromString (GinkgoT (), kubectl , gatewayClass )
38117 defer k8s .KubectlDeleteFromString (GinkgoT (), kubectl , gatewayClass )
@@ -71,9 +150,94 @@ func TestMain(m *testing.M) {
71150 StatusAddress : address ,
72151 })
73152
153+ defaultGatewayProxyOpts = GatewayProxyOpts {
154+ StatusAddress : address ,
155+ AdminKey : adminKey ,
156+ AdminEndpoint : framework .DashboardTLSEndpoint ,
157+ }
158+
159+ patchGatewaysForConformanceTest (context .Background (), f .K8sClient )
160+
74161 code := m .Run ()
75162
76163 f .AfterSuite ()
77164
78165 os .Exit (code )
79166}
167+
168+ func patchGatewaysForConformanceTest (ctx context.Context , k8sClient client.Client ) {
169+ var gatewayProxyMap = make (map [string ]bool )
170+
171+ // list all gateways and patch them
172+ patchGateway := func (ctx context.Context , k8sClient client.Client ) bool {
173+ gatewayList := & gatewayv1.GatewayList {}
174+ if err := k8sClient .List (ctx , gatewayList ); err != nil {
175+ return false
176+ }
177+
178+ patched := false
179+ for i := range gatewayList .Items {
180+ gateway := & gatewayList .Items [i ]
181+
182+ // check if the gateway already has infrastructure.parametersRef
183+ if gateway .Spec .Infrastructure != nil &&
184+ gateway .Spec .Infrastructure .ParametersRef != nil {
185+ continue
186+ }
187+
188+ GinkgoT ().Logf ("Patching Gateway %s" , gateway .Name )
189+ // check if the gateway proxy has been created, if not, create it
190+ if ! gatewayProxyMap [gateway .Namespace ] {
191+ gatewayProxy := fmt .Sprintf (gatewayProxyYaml ,
192+ gateway .Namespace ,
193+ defaultGatewayProxyOpts .StatusAddress ,
194+ defaultGatewayProxyOpts .AdminEndpoint ,
195+ defaultGatewayProxyOpts .AdminKey )
196+ kubectl := k8s .NewKubectlOptions ("" , "" , gateway .Namespace )
197+ k8s .KubectlApplyFromString (GinkgoT (), kubectl , gatewayProxy )
198+
199+ // Mark this namespace as having a GatewayProxy
200+ gatewayProxyMap [gateway .Namespace ] = true
201+ }
202+
203+ // add infrastructure.parametersRef
204+ gateway .Spec .Infrastructure = & gatewayv1.GatewayInfrastructure {
205+ ParametersRef : & gatewayv1.LocalParametersReference {
206+ Group : "gateway.apisix.io" ,
207+ Kind : "GatewayProxy" ,
208+ Name : "conformance-gateway-proxy" ,
209+ },
210+ }
211+
212+ if err := k8sClient .Update (ctx , gateway ); err != nil {
213+ GinkgoT ().Logf ("Failed to patch Gateway %s: %v" , gateway .Name , err )
214+ continue
215+ }
216+
217+ patched = true
218+ GinkgoT ().Logf ("Successfully patched Gateway %s with GatewayProxy reference" , gateway .Name )
219+ }
220+
221+ return patched
222+ }
223+
224+ // continuously monitor and patch gateway resources
225+ go func () {
226+ ticker := time .NewTicker (2 * time .Second )
227+ defer ticker .Stop ()
228+
229+ for {
230+ select {
231+ case <- ctx .Done ():
232+ // clean up the gateway proxy
233+ for namespace := range gatewayProxyMap {
234+ kubectl := k8s .NewKubectlOptions ("" , "" , namespace )
235+ _ = k8s .RunKubectlE (GinkgoT (), kubectl , "delete" , "gatewayproxy" , "conformance-gateway-proxy" )
236+ }
237+ return
238+ case <- ticker .C :
239+ patchGateway (ctx , k8sClient )
240+ }
241+ }
242+ }()
243+ }
0 commit comments