Skip to content

Commit c67d0c2

Browse files
committed
fix: conformance test
Signed-off-by: ashing <[email protected]>
1 parent ba5c304 commit c67d0c2

File tree

3 files changed

+169
-2
lines changed

3 files changed

+169
-2
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,5 @@ api7-ingress-controller
3232
api7-ingress-controller-conformance-report.yaml
3333

3434
*.mdx
35+
.cursor/
36+

test/conformance/suite_test.go

Lines changed: 161 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,20 @@
11
package conformance
22

33
import (
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

1520
var gatewayClassName = "api7"
@@ -24,15 +29,84 @@ 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+
2760
func TestMain(m *testing.M) {
2861
RegisterFailHandler(Fail)
2962
f := framework.NewFramework()
3063

3164
f.BeforeSuite()
3265

33-
namespace := "api7ee-conformance-test"
34-
66+
// Check and delete specific namespaces if they exist
3567
kubectl := k8s.NewKubectlOptions("", "", "default")
68+
namespacesToDelete := []string{
69+
"gateway-conformance-infra",
70+
"gateway-conformance-web-backend",
71+
"gateway-conformance-app-backend",
72+
}
73+
74+
for _, ns := range namespacesToDelete {
75+
_, err := k8s.GetNamespaceE(GinkgoT(), kubectl, ns)
76+
if err == nil {
77+
// Namespace exists, delete it
78+
GinkgoT().Logf("Deleting existing namespace: %s", ns)
79+
err := k8s.DeleteNamespaceE(GinkgoT(), kubectl, ns)
80+
if err != nil {
81+
GinkgoT().Logf("Error deleting namespace %s: %v", ns, err)
82+
continue
83+
}
84+
85+
// Wait for deletion to complete by checking until GetNamespaceE returns an error
86+
_, err = retry.DoWithRetryE(
87+
GinkgoT(),
88+
fmt.Sprintf("Waiting for namespace %s to be deleted", ns),
89+
30,
90+
5*time.Second,
91+
func() (string, error) {
92+
_, err := k8s.GetNamespaceE(GinkgoT(), kubectl, ns)
93+
if err != nil {
94+
// Namespace is gone, which is what we want
95+
return "Namespace deleted", nil
96+
}
97+
return "", fmt.Errorf("namespace %s still exists", ns)
98+
},
99+
)
100+
101+
if err != nil {
102+
GinkgoT().Logf("Error waiting for namespace %s to be deleted: %v", ns, err)
103+
}
104+
} else {
105+
GinkgoT().Logf("Namespace %s does not exist or cannot be accessed", ns)
106+
}
107+
}
108+
109+
namespace := "api7ee-conformance-test"
36110

37111
k8s.KubectlApplyFromString(GinkgoT(), kubectl, gatewayClass)
38112
defer k8s.KubectlDeleteFromString(GinkgoT(), kubectl, gatewayClass)
@@ -71,9 +145,94 @@ func TestMain(m *testing.M) {
71145
StatusAddress: address,
72146
})
73147

148+
defaultGatewayProxyOpts = GatewayProxyOpts{
149+
StatusAddress: address,
150+
AdminKey: adminKey,
151+
AdminEndpoint: framework.DashboardTLSEndpoint,
152+
}
153+
154+
patchGatewaysForConformanceTest(context.Background(), f.K8sClient)
155+
74156
code := m.Run()
75157

76158
f.AfterSuite()
77159

78160
os.Exit(code)
79161
}
162+
163+
func patchGatewaysForConformanceTest(ctx context.Context, k8sClient client.Client) {
164+
var gatewayProxyMap = make(map[string]bool)
165+
166+
// list all gateways and patch them
167+
patchGateway := func(ctx context.Context, k8sClient client.Client) bool {
168+
gatewayList := &gatewayv1.GatewayList{}
169+
if err := k8sClient.List(ctx, gatewayList); err != nil {
170+
return false
171+
}
172+
173+
patched := false
174+
for i := range gatewayList.Items {
175+
gateway := &gatewayList.Items[i]
176+
GinkgoT().Logf("Patching Gateway %s", gateway.Name)
177+
178+
// check if the gateway already has infrastructure.parametersRef
179+
if gateway.Spec.Infrastructure != nil &&
180+
gateway.Spec.Infrastructure.ParametersRef != nil {
181+
continue
182+
}
183+
184+
// check if the gateway proxy has been created, if not, create it
185+
if !gatewayProxyMap[gateway.Namespace] {
186+
gatewayProxy := fmt.Sprintf(gatewayProxyYaml,
187+
gateway.Namespace,
188+
defaultGatewayProxyOpts.StatusAddress,
189+
defaultGatewayProxyOpts.AdminEndpoint,
190+
defaultGatewayProxyOpts.AdminKey)
191+
kubectl := k8s.NewKubectlOptions("", "", gateway.Namespace)
192+
k8s.KubectlApplyFromString(GinkgoT(), kubectl, gatewayProxy)
193+
194+
// Mark this namespace as having a GatewayProxy
195+
gatewayProxyMap[gateway.Namespace] = true
196+
}
197+
198+
// add infrastructure.parametersRef
199+
gateway.Spec.Infrastructure = &gatewayv1.GatewayInfrastructure{
200+
ParametersRef: &gatewayv1.LocalParametersReference{
201+
Group: "gateway.apisix.io",
202+
Kind: "GatewayProxy",
203+
Name: "conformance-gateway-proxy",
204+
},
205+
}
206+
207+
if err := k8sClient.Update(ctx, gateway); err != nil {
208+
GinkgoT().Logf("Failed to patch Gateway %s: %v", gateway.Name, err)
209+
continue
210+
}
211+
212+
patched = true
213+
GinkgoT().Logf("Successfully patched Gateway %s with GatewayProxy reference", gateway.Name)
214+
}
215+
216+
return patched
217+
}
218+
219+
// continuously monitor and patch gateway resources
220+
go func() {
221+
ticker := time.NewTicker(5 * time.Second)
222+
defer ticker.Stop()
223+
224+
for {
225+
select {
226+
case <-ctx.Done():
227+
// clean up the gateway proxy
228+
for namespace := range gatewayProxyMap {
229+
kubectl := k8s.NewKubectlOptions("", "", namespace)
230+
_ = k8s.RunKubectlE(GinkgoT(), kubectl, "delete", "gatewayproxy", "conformance-gateway-proxy")
231+
}
232+
return
233+
case <-ticker.C:
234+
patchGateway(ctx, k8sClient)
235+
}
236+
}
237+
}()
238+
}

test/e2e/framework/framework.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
k8serrors "k8s.io/apimachinery/pkg/api/errors"
1818
"k8s.io/client-go/kubernetes"
1919
"k8s.io/client-go/rest"
20+
"sigs.k8s.io/controller-runtime/pkg/client"
2021
)
2122

2223
var (
@@ -44,6 +45,7 @@ type Framework struct {
4445
kubectlOpts *k8s.KubectlOptions
4546
clientset *kubernetes.Clientset
4647
restConfig *rest.Config
48+
K8sClient client.Client
4749

4850
DB *gorm.DB
4951
RawETCD *clientv3.Client
@@ -83,6 +85,10 @@ func NewFramework() *Framework {
8385
f.GomegaT.Expect(err).ShouldNot(HaveOccurred(), "creating Kubernetes clientset")
8486
f.clientset = clientset
8587

88+
k8sClient, err := client.New(restCfg, client.Options{})
89+
f.GomegaT.Expect(err).ShouldNot(HaveOccurred(), "creating controller-runtime client")
90+
f.K8sClient = k8sClient
91+
8692
_framework = f
8793

8894
// BeforeSuite(f.BeforeSuite)

0 commit comments

Comments
 (0)