Skip to content

Commit ad69665

Browse files
authored
Fix some of the NFR tests to reduce error logs and pipeline failures (#3827)
Reduce NFR tests error logs and pipeline failures
1 parent b52a208 commit ad69665

File tree

8 files changed

+103
-64
lines changed

8 files changed

+103
-64
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ install-crds: ## Install CRDs
130130

131131
.PHONY: install-gateway-crds
132132
install-gateway-crds: ## Install Gateway API CRDs
133-
kubectl kustomize $(SELF_DIR)config/crd/gateway-api/$(if $(filter true,$(ENABLE_EXPERIMENTAL)),experimental,standard) | kubectl apply -f -
133+
kubectl kustomize $(SELF_DIR)config/crd/gateway-api/$(if $(filter true,$(ENABLE_EXPERIMENTAL)),experimental,standard) | kubectl apply --server-side -f -
134134

135135
.PHONY: uninstall-gateway-crds
136136
uninstall-gateway-crds: ## Uninstall Gateway API CRDs

tests/Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ stop-longevity-test: nfr-test ## Stop the longevity test and collects results
122122
.PHONY: .vm-nfr-test
123123
.vm-nfr-test: ## Runs the NFR tests on the GCP VM (called by `nfr-test`)
124124
CGO_ENABLED=1 go run github.com/onsi/ginkgo/v2/ginkgo --race --randomize-all --randomize-suites --keep-going --fail-on-pending \
125-
--trace -r -v --buildvcs --force-newlines $(GITHUB_OUTPUT) --flake-attempts=2 \
125+
--trace -r -v --buildvcs --force-newlines $(GITHUB_OUTPUT) --flake-attempts=1 --show-node-events --output-interceptor-mode=none \
126126
--label-filter "nfr" $(GINKGO_FLAGS) --timeout 5h ./suite -- --gateway-api-version=$(GW_API_VERSION) \
127127
--gateway-api-prev-version=$(GW_API_PREV_VERSION) --image-tag=$(TAG) --version-under-test=$(NGF_VERSION) \
128128
--ngf-image-repo=$(PREFIX) --nginx-image-repo=$(NGINX_PREFIX) --nginx-plus-image-repo=$(NGINX_PLUS_PREFIX) \
@@ -176,7 +176,7 @@ HELM_PARAMETERS += --set nginxGateway.name=nginx-gateway --set nginx.service.typ
176176
# it overrides the target in the main Makefile when the GW_API_VERSION is set to main
177177
ifeq ($(GW_API_VERSION),main)
178178
install-gateway-crds:
179-
kubectl kustomize "https://github.com/kubernetes-sigs/gateway-api/config/crd/$(if $(filter true,$(ENABLE_EXPERIMENTAL)),experimental,)?timeout=120&ref=main" | kubectl apply -f -
179+
kubectl kustomize "https://github.com/kubernetes-sigs/gateway-api/config/crd/$(if $(filter true,$(ENABLE_EXPERIMENTAL)),experimental,)?timeout=120&ref=main" | kubectl apply --server-side -f -
180180
endif
181181

182182
.PHONY: install-ngf-local-no-build

tests/framework/generate_manifests.go

Lines changed: 41 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -120,9 +120,14 @@ type route struct {
120120

121121
// ScaleObjects contains objects for scale testing.
122122
type ScaleObjects struct {
123-
// BaseObjects contains objects that are common to all scale iterations.
123+
// BaseObjects contains objects that should be created first:
124+
// secrets and other foundational resources.
124125
BaseObjects []client.Object
125-
// ScaleIterationGroups contains objects for each scale iteration.
126+
// GatewayAndServiceObjects contains backend services, deployments, and Gateway objects.
127+
// These are created after BaseObjects to ensure endpoints are ready before traffic.
128+
GatewayAndServiceObjects []client.Object
129+
// ScaleIterationGroups contains HTTPRoute objects for each scale iteration.
130+
// These are applied after GatewayAndServiceObjects to start traffic flow incrementally.
126131
ScaleIterationGroups [][]client.Object
127132
}
128133

@@ -150,12 +155,15 @@ func decodeObjects(reader io.Reader) ([]client.Object, error) {
150155
}
151156

152157
// GenerateScaleListenerObjects generates objects for a given number of listeners for the scale test.
158+
// Secrets are created first in BaseObjects, then backend services/deployments and Gateway in GatewayAndServiceObjects,
159+
// and finally HTTPRoutes in ScaleIterationGroups.
153160
func GenerateScaleListenerObjects(numListeners int, tls bool) (ScaleObjects, error) {
154161
var result ScaleObjects
155162

156163
listeners := make([]listener, 0)
157164
backends := make([]string, 0)
158165
secrets := make([]string, 0)
166+
routes := make([]route, 0)
159167

160168
for i := range numListeners {
161169
listenerName := fmt.Sprintf("listener-%d", i)
@@ -180,30 +188,34 @@ func GenerateScaleListenerObjects(numListeners int, tls bool) (ScaleObjects, err
180188
HostnamePrefix: hostnamePrefix,
181189
BackendName: backendName,
182190
}
191+
routes = append(routes, r)
183192

184193
backends = append(backends, backendName)
185-
186-
objects, err := generateManifests(listeners, []route{r})
187-
if err != nil {
188-
return ScaleObjects{}, err
189-
}
190-
191-
result.ScaleIterationGroups = append(result.ScaleIterationGroups, objects)
192194
}
193195

194196
secretObjects, err := generateSecrets(secrets)
195197
if err != nil {
196198
return ScaleObjects{}, err
197199
}
198-
199200
result.BaseObjects = append(result.BaseObjects, secretObjects...)
200201

201202
backendObjects, err := generateBackendAppObjects(backends)
202203
if err != nil {
203204
return ScaleObjects{}, err
204205
}
206+
result.GatewayAndServiceObjects = append(result.GatewayAndServiceObjects, backendObjects...)
205207

206-
result.BaseObjects = append(result.BaseObjects, backendObjects...)
208+
gatewayObjects, err := generateManifests(listeners, nil)
209+
if err != nil {
210+
return ScaleObjects{}, err
211+
}
212+
result.GatewayAndServiceObjects = append(result.GatewayAndServiceObjects, gatewayObjects...)
213+
214+
routeObjects, err := generateManifests(nil, routes)
215+
if err != nil {
216+
return ScaleObjects{}, err
217+
}
218+
result.ScaleIterationGroups = append(result.ScaleIterationGroups, routeObjects)
207219

208220
return result, nil
209221
}
@@ -240,6 +252,21 @@ func GenerateScaleHTTPRouteObjects(numRoutes int) (ScaleObjects, error) {
240252

241253
backendName := "backend"
242254

255+
// Generate backend objects and add to GatewayAndServiceObjects
256+
backendObjects, err := generateBackendAppObjects([]string{backendName})
257+
if err != nil {
258+
return ScaleObjects{}, err
259+
}
260+
result.GatewayAndServiceObjects = append(result.GatewayAndServiceObjects, backendObjects...)
261+
262+
// Generate Gateway object and add to GatewayAndServiceObjects
263+
gatewayObjects, err := generateManifests([]listener{l}, nil)
264+
if err != nil {
265+
return ScaleObjects{}, err
266+
}
267+
result.GatewayAndServiceObjects = append(result.GatewayAndServiceObjects, gatewayObjects...)
268+
269+
// Generate HTTPRoute objects for each iteration
243270
for i := range numRoutes {
244271
r := route{
245272
Name: fmt.Sprintf("route-%d", i),
@@ -248,27 +275,15 @@ func GenerateScaleHTTPRouteObjects(numRoutes int) (ScaleObjects, error) {
248275
BackendName: backendName,
249276
}
250277

251-
var listeners []listener
252-
if i == 0 {
253-
// only generate a Gateway on the first iteration
254-
listeners = []listener{l}
255-
}
256-
257-
objects, err := generateManifests(listeners, []route{r})
278+
// Generate only the HTTPRoute (no listeners/gateway)
279+
routeObjects, err := generateManifests(nil, []route{r})
258280
if err != nil {
259281
return ScaleObjects{}, err
260282
}
261283

262-
result.ScaleIterationGroups = append(result.ScaleIterationGroups, objects)
284+
result.ScaleIterationGroups = append(result.ScaleIterationGroups, routeObjects)
263285
}
264286

265-
backendObjects, err := generateBackendAppObjects([]string{backendName})
266-
if err != nil {
267-
return ScaleObjects{}, err
268-
}
269-
270-
result.BaseObjects = backendObjects
271-
272287
return result, nil
273288
}
274289

tests/framework/results.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,12 @@ func CreateResultsDir(testName, version string) (string, error) {
2121

2222
dirName := filepath.Join(filepath.Dir(pwd), "results", testName, version)
2323

24+
if _, err := os.Stat(dirName); err == nil {
25+
if err := os.RemoveAll(dirName); err != nil {
26+
return "", fmt.Errorf("failed to remove existing directory %s: %w", dirName, err)
27+
}
28+
}
29+
2430
return dirName, os.MkdirAll(dirName, 0o777)
2531
}
2632

tests/framework/timeout.go

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -38,22 +38,26 @@ type TimeoutConfig struct {
3838

3939
// KubernetesClientTimeout represents the maximum time for Kubernetes client operations.
4040
KubernetesClientTimeout time.Duration
41+
42+
// GatewayListenerUpdateTimeout represents the maximum time for Gateway Listener count to be updated.
43+
GatewayListenerUpdateTimeout time.Duration
4144
}
4245

4346
// DefaultTimeoutConfig populates a TimeoutConfig with the default values.
4447
func DefaultTimeoutConfig() TimeoutConfig {
4548
return TimeoutConfig{
46-
CreateTimeout: 60 * time.Second,
47-
UpdateTimeout: 60 * time.Second,
48-
DeleteTimeout: 10 * time.Second,
49-
DeleteNamespaceTimeout: 150 * time.Second,
50-
GetTimeout: 10 * time.Second,
51-
ManifestFetchTimeout: 10 * time.Second,
52-
RequestTimeout: 10 * time.Second,
53-
ContainerRestartTimeout: 10 * time.Second,
54-
GetLeaderLeaseTimeout: 60 * time.Second,
55-
GetStatusTimeout: 60 * time.Second,
56-
TestForTrafficTimeout: 60 * time.Second,
57-
KubernetesClientTimeout: 10 * time.Second,
49+
CreateTimeout: 60 * time.Second,
50+
UpdateTimeout: 60 * time.Second,
51+
DeleteTimeout: 10 * time.Second,
52+
DeleteNamespaceTimeout: 150 * time.Second,
53+
GetTimeout: 10 * time.Second,
54+
ManifestFetchTimeout: 10 * time.Second,
55+
RequestTimeout: 30 * time.Second,
56+
ContainerRestartTimeout: 10 * time.Second,
57+
GetLeaderLeaseTimeout: 60 * time.Second,
58+
GetStatusTimeout: 60 * time.Second,
59+
TestForTrafficTimeout: 60 * time.Second,
60+
KubernetesClientTimeout: 10 * time.Second,
61+
GatewayListenerUpdateTimeout: 60 * time.Second,
5862
}
5963
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
apiVersion: gateway.networking.k8s.io/v1
2+
kind: HTTPRoute
3+
metadata:
4+
name: route
5+
spec:
6+
parentRefs:
7+
- name: gateway
8+
sectionName: listener
9+
hostnames:
10+
- "*.example.com"
11+
rules:
12+
- matches:
13+
- path:
14+
type: PathPrefix
15+
value: /
16+
backendRefs:
17+
- name: backend
18+
port: 80

tests/suite/manifests/scale/upstreams.yaml

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,25 +13,6 @@ spec:
1313
port: 80
1414
protocol: HTTP
1515
---
16-
apiVersion: gateway.networking.k8s.io/v1
17-
kind: HTTPRoute
18-
metadata:
19-
name: route
20-
spec:
21-
parentRefs:
22-
- name: gateway
23-
sectionName: listener
24-
hostnames:
25-
- "*.example.com"
26-
rules:
27-
- matches:
28-
- path:
29-
type: PathPrefix
30-
value: /
31-
backendRefs:
32-
- name: backend
33-
port: 80
34-
---
3516
apiVersion: apps/v1
3617
kind: Deployment
3718
metadata:

tests/suite/scale_test.go

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ var _ = Describe("Scale test", Ordered, Label("nfr", "scale"), func() {
4040
"scale/upstreams.yaml",
4141
}
4242

43+
httpRouteManifests = []string{
44+
"scale/httproute.yaml",
45+
}
46+
4347
namespace = "scale"
4448

4549
scrapeInterval = 15 * time.Second
@@ -404,8 +408,12 @@ The logs are attached only if there are errors.
404408
Expect(err).ToNot(HaveOccurred())
405409
defer ttrCsvFile.Close()
406410

411+
// Apply BaseObjects first (secrets and other foundational resources)
407412
Expect(resourceManager.Apply(objects.BaseObjects)).To(Succeed())
408413

414+
// Apply GatewayAndServiceObjects next (backend services, deployments, and Gateway)
415+
Expect(resourceManager.Apply(objects.GatewayAndServiceObjects)).To(Succeed())
416+
409417
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
410418
defer cancel()
411419

@@ -468,6 +476,10 @@ The logs are attached only if there are errors.
468476
Expect(resourceManager.ApplyFromFiles(upstreamsManifests, namespace)).To(Succeed())
469477
Expect(resourceManager.WaitForAppsToBeReady(namespace)).To(Succeed())
470478

479+
// apply HTTPRoute after upstreams are ready
480+
Expect(resourceManager.ApplyFromFiles(httpRouteManifests, namespace)).To(Succeed())
481+
Expect(resourceManager.WaitForAppsToBeReady(namespace)).To(Succeed())
482+
471483
var nginxPodNames []string
472484
var err error
473485
Eventually(
@@ -512,6 +524,9 @@ The logs are attached only if there are errors.
512524
for _, obj := range objects.BaseObjects {
513525
obj.SetNamespace(namespace)
514526
}
527+
for _, obj := range objects.GatewayAndServiceObjects {
528+
obj.SetNamespace(namespace)
529+
}
515530
for _, objs := range objects.ScaleIterationGroups {
516531
for _, obj := range objs {
517532
obj.SetNamespace(namespace)
@@ -1012,13 +1027,13 @@ var _ = Describe("Zero downtime scale test", Ordered, Label("nfr", "zero-downtim
10121027
checkGatewayListeners := func(num int) {
10131028
Eventually(
10141029
func() error {
1015-
ctx, cancel := context.WithTimeout(context.Background(), timeoutConfig.GetTimeout)
1030+
ctx, cancel := context.WithTimeout(context.Background(), timeoutConfig.GetTimeout*2)
10161031
defer cancel()
10171032

10181033
var gw v1.Gateway
10191034
key := types.NamespacedName{Namespace: ns.Name, Name: "gateway"}
10201035
if err := resourceManager.K8sClient.Get(ctx, key, &gw); err != nil {
1021-
return err
1036+
return fmt.Errorf("failed to get gateway: %w", err)
10221037
}
10231038

10241039
if len(gw.Status.Listeners) != num {
@@ -1028,8 +1043,8 @@ var _ = Describe("Zero downtime scale test", Ordered, Label("nfr", "zero-downtim
10281043
return nil
10291044
},
10301045
).
1031-
WithTimeout(5 * time.Second).
1032-
WithPolling(100 * time.Millisecond).
1046+
WithTimeout(timeoutConfig.GatewayListenerUpdateTimeout).
1047+
WithPolling(1 * time.Second).
10331048
Should(Succeed())
10341049
}
10351050

0 commit comments

Comments
 (0)