This is an automated email from the ASF dual-hosted git repository.

alinsran pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/apisix-ingress-controller.git


The following commit(s) were added to refs/heads/master by this push:
     new f536c26c chore: refactor e2e-test (#2467)
f536c26c is described below

commit f536c26c918e42b4de416eda1c4ffa95e9937a55
Author: AlinsRan <[email protected]>
AuthorDate: Thu Jul 17 09:00:11 2025 +0800

    chore: refactor e2e-test (#2467)
---
 Makefile                                  |   10 +
 go.mod                                    |   76 +-
 go.sum                                    |  157 +++-
 test/e2e/apisix/e2e_test.go               |    4 +-
 test/e2e/apisix/status.go                 |  161 ++---
 test/e2e/crds/backendtrafficpolicy.go     |  110 +--
 test/e2e/crds/consumer.go                 |  357 ++++++----
 test/e2e/framework/manifests/apisix.yaml  |    7 +
 test/e2e/framework/manifests/ingress.yaml |   21 +-
 test/e2e/gatewayapi/gatewayproxy.go       |   93 +--
 test/e2e/gatewayapi/httproute.go          | 1106 ++++++++++++++++-------------
 test/e2e/ingress/ingress.go               |    8 +-
 test/e2e/scaffold/apisix_deployer.go      |   12 +-
 test/e2e/scaffold/assertion.go            |  252 +++++++
 test/e2e/scaffold/k8s.go                  |   18 +-
 15 files changed, 1447 insertions(+), 945 deletions(-)

diff --git a/Makefile b/Makefile
index 15b7ecf1..35c593d1 100644
--- a/Makefile
+++ b/Makefile
@@ -30,8 +30,10 @@ KIND_NAME ?= apisix-ingress-cluster
 GATEAY_API_VERSION ?= v1.2.0
 ADC_VERSION ?= 0.20.0
 
+GINKGO_VERSION ?= 2.20.0
 TEST_TIMEOUT ?= 80m
 TEST_DIR ?= ./test/e2e/apisix/
+E2E_NODES ?= 2
 
 # CRD Reference Documentation
 CRD_REF_DOCS_VERSION ?= v0.1.0
@@ -127,6 +129,14 @@ kind-e2e-test: kind-up build-image kind-load-images 
e2e-test
 e2e-test:
        go test $(TEST_DIR) -test.timeout=$(TEST_TIMEOUT) -v -ginkgo.v 
-ginkgo.focus="$(TEST_FOCUS)" -ginkgo.label-filter="$(TEST_LABEL)"
 
+.PHONY: ginkgo-e2e-test
+ginkgo-e2e-test:
+       @ginkgo -cover -coverprofile=coverage.txt -r --randomize-all 
--randomize-suites --trace --focus=$(E2E_FOCUS) --nodes=$(E2E_NODES) $(TEST_DIR)
+
+.PHONY: install-ginkgo
+install-ginkgo:
+       @go install github.com/onsi/ginkgo/v2/ginkgo@v$(GINKGO_VERSION)
+
 .PHONY: conformance-test
 conformance-test:
        go test -v ./test/conformance -tags=conformance -timeout 60m
diff --git a/go.mod b/go.mod
index 068e83a9..3e5cf556 100644
--- a/go.mod
+++ b/go.mod
@@ -11,7 +11,7 @@ require (
        github.com/go-logr/logr v1.4.2
        github.com/go-logr/zapr v1.3.0
        github.com/google/uuid v1.6.0
-       github.com/gruntwork-io/terratest v0.47.0
+       github.com/gruntwork-io/terratest v0.50.0
        github.com/hashicorp/go-memdb v1.3.4
        github.com/incubator4/go-resty-expr v0.1.1
        github.com/onsi/ginkgo/v2 v2.20.0
@@ -19,7 +19,7 @@ require (
        github.com/pkg/errors v0.9.1
        github.com/samber/lo v1.47.0
        github.com/spf13/cobra v1.8.1
-       github.com/stretchr/testify v1.9.0
+       github.com/stretchr/testify v1.10.0
        go.uber.org/zap v1.27.0
        golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56
        gopkg.in/yaml.v3 v3.0.1
@@ -35,6 +35,7 @@ require (
 )
 
 require (
+       filippo.io/edwards25519 v1.1.0 // indirect
        github.com/Masterminds/goutils v1.1.1 // indirect
        github.com/Masterminds/semver/v3 v3.2.1 // indirect
        github.com/TylerBrock/colorjson v0.0.0-20200706003622-8a50f05110d2 // 
indirect
@@ -42,13 +43,48 @@ require (
        github.com/andybalholm/brotli v1.0.4 // indirect
        github.com/antlr4-go/antlr/v4 v4.13.0 // indirect
        github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // 
indirect
-       github.com/aws/aws-sdk-go v1.44.245 // indirect
+       github.com/aws/aws-sdk-go-v2 v1.32.5 // indirect
+       github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.7 // indirect
+       github.com/aws/aws-sdk-go-v2/config v1.28.5 // indirect
+       github.com/aws/aws-sdk-go-v2/credentials v1.17.46 // indirect
+       github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.20 // indirect
+       github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.41 // indirect
+       github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.24 // indirect
+       github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.24 // indirect
+       github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 // indirect
+       github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.24 // indirect
+       github.com/aws/aws-sdk-go-v2/service/acm v1.30.6 // indirect
+       github.com/aws/aws-sdk-go-v2/service/autoscaling v1.51.0 // indirect
+       github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.44.0 // indirect
+       github.com/aws/aws-sdk-go-v2/service/dynamodb v1.37.1 // indirect
+       github.com/aws/aws-sdk-go-v2/service/ec2 v1.193.0 // indirect
+       github.com/aws/aws-sdk-go-v2/service/ecr v1.36.6 // indirect
+       github.com/aws/aws-sdk-go-v2/service/ecs v1.52.0 // indirect
+       github.com/aws/aws-sdk-go-v2/service/iam v1.38.1 // indirect
+       github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1 
// indirect
+       github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.4.5 // 
indirect
+       github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery 
v1.10.5 // indirect
+       github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.5 // 
indirect
+       github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.5 // 
indirect
+       github.com/aws/aws-sdk-go-v2/service/kms v1.37.6 // indirect
+       github.com/aws/aws-sdk-go-v2/service/lambda v1.69.0 // indirect
+       github.com/aws/aws-sdk-go-v2/service/rds v1.91.0 // indirect
+       github.com/aws/aws-sdk-go-v2/service/route53 v1.46.2 // indirect
+       github.com/aws/aws-sdk-go-v2/service/s3 v1.69.0 // indirect
+       github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.34.6 // indirect
+       github.com/aws/aws-sdk-go-v2/service/sns v1.33.6 // indirect
+       github.com/aws/aws-sdk-go-v2/service/sqs v1.37.1 // indirect
+       github.com/aws/aws-sdk-go-v2/service/ssm v1.56.0 // indirect
+       github.com/aws/aws-sdk-go-v2/service/sso v1.24.6 // indirect
+       github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.5 // indirect
+       github.com/aws/aws-sdk-go-v2/service/sts v1.33.1 // indirect
+       github.com/aws/smithy-go v1.22.1 // indirect
        github.com/beorn7/perks v1.0.1 // indirect
        github.com/blang/semver/v4 v4.0.0 // indirect
        github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // 
indirect
        github.com/cenkalti/backoff/v4 v4.3.0 // indirect
        github.com/cespare/xxhash/v2 v2.3.0 // indirect
-       github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect
+       github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect
        github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // 
indirect
        github.com/emicklei/go-restful/v3 v3.12.0 // indirect
        github.com/evanphx/json-patch v5.9.0+incompatible // indirect
@@ -63,7 +99,7 @@ require (
        github.com/go-openapi/jsonpointer v0.21.0 // indirect
        github.com/go-openapi/jsonreference v0.21.0 // indirect
        github.com/go-openapi/swag v0.23.0 // indirect
-       github.com/go-sql-driver/mysql v1.7.1 // indirect
+       github.com/go-sql-driver/mysql v1.8.1 // indirect
        github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
        github.com/gobwas/glob v0.2.3 // indirect
        github.com/gogo/protobuf v1.3.2 // indirect
@@ -88,6 +124,10 @@ require (
        github.com/imdario/mergo v0.3.16 // indirect
        github.com/imkira/go-interpol v1.1.0 // indirect
        github.com/inconshreveable/mousetrap v1.1.0 // indirect
+       github.com/jackc/pgpassfile v1.0.0 // indirect
+       github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // 
indirect
+       github.com/jackc/pgx/v5 v5.7.1 // indirect
+       github.com/jackc/puddle/v2 v2.2.2 // indirect
        github.com/jmespath/go-jmespath v0.4.0 // indirect
        github.com/josharian/intern v1.0.0 // indirect
        github.com/json-iterator/go v1.1.12 // indirect
@@ -107,7 +147,7 @@ require (
        github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // 
indirect
        github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // 
indirect
        github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // 
indirect
-       github.com/pquerna/otp v1.2.0 // indirect
+       github.com/pquerna/otp v1.4.0 // indirect
        github.com/prometheus/client_golang v1.19.1 // indirect
        github.com/prometheus/client_model v0.6.1 // indirect
        github.com/prometheus/common v0.55.0 // indirect
@@ -119,7 +159,7 @@ require (
        github.com/spf13/cast v1.6.0 // indirect
        github.com/spf13/pflag v1.0.5 // indirect
        github.com/stoewer/go-strcase v1.2.0 // indirect
-       github.com/urfave/cli v1.22.14 // indirect
+       github.com/urfave/cli v1.22.16 // indirect
        github.com/valyala/bytebufferpool v1.0.0 // indirect
        github.com/valyala/fasthttp v1.34.0 // indirect
        github.com/x448/float16 v0.8.4 // indirect
@@ -129,31 +169,31 @@ require (
        github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 // indirect
        github.com/yudai/gojsondiff v1.0.0 // indirect
        github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 // indirect
-       go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 
// indirect
-       go.opentelemetry.io/otel v1.28.0 // indirect
+       go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 
// indirect
+       go.opentelemetry.io/otel v1.29.0 // indirect
        go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 // indirect
        go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0 
// indirect
-       go.opentelemetry.io/otel/metric v1.28.0 // indirect
-       go.opentelemetry.io/otel/sdk v1.28.0 // indirect
-       go.opentelemetry.io/otel/trace v1.28.0 // indirect
+       go.opentelemetry.io/otel/metric v1.29.0 // indirect
+       go.opentelemetry.io/otel/sdk v1.29.0 // indirect
+       go.opentelemetry.io/otel/trace v1.29.0 // indirect
        go.opentelemetry.io/proto/otlp v1.3.1 // indirect
        go.uber.org/multierr v1.11.0 // indirect
        golang.org/x/arch v0.6.0 // indirect
        golang.org/x/crypto v0.36.0 // indirect
        golang.org/x/mod v0.20.0 // indirect
        golang.org/x/net v0.38.0 // indirect
-       golang.org/x/oauth2 v0.21.0 // indirect
+       golang.org/x/oauth2 v0.24.0 // indirect
        golang.org/x/sync v0.12.0 // indirect
        golang.org/x/sys v0.31.0 // indirect
        golang.org/x/term v0.30.0 // indirect
        golang.org/x/text v0.23.0 // indirect
-       golang.org/x/time v0.5.0 // indirect
+       golang.org/x/time v0.8.0 // indirect
        golang.org/x/tools v0.24.0 // indirect
        gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
-       google.golang.org/genproto/googleapis/api 
v0.0.0-20240604185151-ef581f913117 // indirect
-       google.golang.org/genproto/googleapis/rpc 
v0.0.0-20240701130421-f6361c86f094 // indirect
-       google.golang.org/grpc v1.66.2 // indirect
-       google.golang.org/protobuf v1.34.2 // indirect
+       google.golang.org/genproto/googleapis/api 
v0.0.0-20241104194629-dd2ea8efbc28 // indirect
+       google.golang.org/genproto/googleapis/rpc 
v0.0.0-20241104194629-dd2ea8efbc28 // indirect
+       google.golang.org/grpc v1.67.1 // indirect
+       google.golang.org/protobuf v1.35.1 // indirect
        gopkg.in/fsnotify.v1 v1.4.7 // indirect
        gopkg.in/inf.v0 v0.9.1 // indirect
        gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
diff --git a/go.sum b/go.sum
index 2be83ffa..9ba03274 100644
--- a/go.sum
+++ b/go.sum
@@ -1,5 +1,7 @@
+filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
+filippo.io/edwards25519 v1.1.0/go.mod 
h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
 github.com/BurntSushi/toml v0.3.1/go.mod 
h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
-github.com/BurntSushi/toml v1.3.2/go.mod 
h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
+github.com/BurntSushi/toml v1.4.0/go.mod 
h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
 github.com/Masterminds/goutils v1.1.1 
h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
 github.com/Masterminds/goutils v1.1.1/go.mod 
h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
 github.com/Masterminds/semver/v3 v3.2.0/go.mod 
h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ=
@@ -22,8 +24,78 @@ github.com/armon/go-socks5 
v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPd
 github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod 
h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
 github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 
h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
 github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod 
h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
-github.com/aws/aws-sdk-go v1.44.245 
h1:KtY2s4q31/kn33AdV63R5t77mdxsI7rq3YT7Mgo805M=
-github.com/aws/aws-sdk-go v1.44.245/go.mod 
h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
+github.com/aws/aws-sdk-go-v2 v1.32.5 
h1:U8vdWJuY7ruAkzaOdD7guwJjD06YSKmnKCJs7s3IkIo=
+github.com/aws/aws-sdk-go-v2 v1.32.5/go.mod 
h1:P5WJBrYqqbWVaOxgH0X/FYYD47/nooaPOZPlQdmiN2U=
+github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.7 
h1:lL7IfaFzngfx0ZwUGOZdsFFnQ5uLvR0hWqqhyE7Q9M8=
+github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.7/go.mod 
h1:QraP0UcVlQJsmHfioCrveWOC1nbiWUl3ej08h4mXWoc=
+github.com/aws/aws-sdk-go-v2/config v1.28.5 
h1:Za41twdCXbuyyWv9LndXxZZv3QhTG1DinqlFsSuvtI0=
+github.com/aws/aws-sdk-go-v2/config v1.28.5/go.mod 
h1:4VsPbHP8JdcdUDmbTVgNL/8w9SqOkM5jyY8ljIxLO3o=
+github.com/aws/aws-sdk-go-v2/credentials v1.17.46 
h1:AU7RcriIo2lXjUfHFnFKYsLCwgbz1E7Mm95ieIRDNUg=
+github.com/aws/aws-sdk-go-v2/credentials v1.17.46/go.mod 
h1:1FmYyLGL08KQXQ6mcTlifyFXfJVCNJTVGuQP4m0d/UA=
+github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.20 
h1:sDSXIrlsFSFJtWKLQS4PUWRvrT580rrnuLydJrCQ/yA=
+github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.20/go.mod 
h1:WZ/c+w0ofps+/OUqMwWgnfrgzZH1DZO1RIkktICsqnY=
+github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.41 
h1:hqcxMc2g/MwwnRMod9n6Bd+t+9Nf7d5qRg7RaXKPd6o=
+github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.41/go.mod 
h1:d1eH0VrttvPmrCraU68LOyNdu26zFxQFjrVSb5vdhog=
+github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.24 
h1:4usbeaes3yJnCFC7kfeyhkdkPtoRYPa/hTmCqMpKpLI=
+github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.24/go.mod 
h1:5CI1JemjVwde8m2WG3cz23qHKPOxbpkq0HaoreEgLIY=
+github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.24 
h1:N1zsICrQglfzaBnrfM0Ys00860C+QFwu6u/5+LomP+o=
+github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.24/go.mod 
h1:dCn9HbJ8+K31i8IQ8EWmWj0EiIk0+vKiHNMxTTYveAg=
+github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 
h1:VaRN3TlFdd6KxX1x3ILT5ynH6HvKgqdiXoTxAF4HQcQ=
+github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1/go.mod 
h1:FbtygfRFze9usAadmnGJNc8KsP346kEe+y2/oyhGAGc=
+github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.24 
h1:JX70yGKLj25+lMC5Yyh8wBtvB01GDilyRuJvXJ4piD0=
+github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.24/go.mod 
h1:+Ln60j9SUTD0LEwnhEB0Xhg61DHqplBrbZpLgyjoEHg=
+github.com/aws/aws-sdk-go-v2/service/acm v1.30.6 
h1:fDg0RlN30Xf/yYzEUL/WXqhmgFsjVb/I3230oCfyI5w=
+github.com/aws/aws-sdk-go-v2/service/acm v1.30.6/go.mod 
h1:zRR6jE3v/TcbfO8C2P+H0Z+kShiKKVaVyoIl8NQRjyg=
+github.com/aws/aws-sdk-go-v2/service/autoscaling v1.51.0 
h1:1KzQVZi7OTixxaVJ8fWaJAUBjme+iQ3zBOCZhE4RgxQ=
+github.com/aws/aws-sdk-go-v2/service/autoscaling v1.51.0/go.mod 
h1:I1+/2m+IhnK5qEbhS3CrzjeiVloo9sItE/2K+so0fkU=
+github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.44.0 
h1:OREVd94+oXW5a+3SSUAo4K0L5ci8cucCLu+PSiek8OU=
+github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.44.0/go.mod 
h1:Qbr4yfpNqVNl69l/GEDK+8wxLf/vHi0ChoiSDzD7thU=
+github.com/aws/aws-sdk-go-v2/service/dynamodb v1.37.1 
h1:vucMirlM6D+RDU8ncKaSZ/5dGrXNajozVwpmWNPn2gQ=
+github.com/aws/aws-sdk-go-v2/service/dynamodb v1.37.1/go.mod 
h1:fceORfs010mNxZbQhfqUjUeHlTwANmIT4mvHamuUaUg=
+github.com/aws/aws-sdk-go-v2/service/ec2 v1.193.0 
h1:RhSoBFT5/8tTmIseJUXM6INTXTQDF8+0oyxWBnozIms=
+github.com/aws/aws-sdk-go-v2/service/ec2 v1.193.0/go.mod 
h1:mzj8EEjIHSN2oZRXiw1Dd+uB4HZTl7hC8nBzX9IZMWw=
+github.com/aws/aws-sdk-go-v2/service/ecr v1.36.6 
h1:zg+3FGHA0PBs0KM25qE/rOf2o5zsjNa1g/Qq83+SDI0=
+github.com/aws/aws-sdk-go-v2/service/ecr v1.36.6/go.mod 
h1:ZSq54Z9SIsOTf1Efwgw1msilSs4XVEfVQiP9nYVnKpM=
+github.com/aws/aws-sdk-go-v2/service/ecs v1.52.0 
h1:7/vgFWplkusJN/m+3QOa+W9FNRqa8ujMPNmdufRaJpg=
+github.com/aws/aws-sdk-go-v2/service/ecs v1.52.0/go.mod 
h1:dPTOvmjJQ1T7Q+2+Xs2KSPrMvx+p0rpyV+HsQVnUK4o=
+github.com/aws/aws-sdk-go-v2/service/iam v1.38.1 
h1:hfkzDZHBp9jAT4zcd5mtqckpU4E3Ax0LQaEWWk1VgN8=
+github.com/aws/aws-sdk-go-v2/service/iam v1.38.1/go.mod 
h1:u36ahDtZcQHGmVm/r+0L1sfKX4fzLEMdCqiKRKkUMVM=
+github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1 
h1:iXtILhvDxB6kPvEXgsDhGaZCSC6LQET5ZHSdJozeI0Y=
+github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1/go.mod 
h1:9nu0fVANtYiAePIBh2/pFUSwtJ402hLnp854CNoDOeE=
+github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.4.5 
h1:gvZOjQKPxFXy1ft3QnEyXmT+IqneM9QAUWlM3r0mfqw=
+github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.4.5/go.mod 
h1:DLWnfvIcm9IET/mmjdxeXbBKmTCm0ZB8p1za9BVteM8=
+github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.10.5 
h1:3Y457U2eGukmjYjeHG6kanZpDzJADa2m0ADqnuePYVQ=
+github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery 
v1.10.5/go.mod h1:CfwEHGkTjYZpkQ/5PvcbEtT7AJlG68KkEvmtwU8z3/U=
+github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.5 
h1:wtpJ4zcwrSbwhECWQoI/g6WM9zqCcSpHDJIWSbMLOu4=
+github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.5/go.mod 
h1:qu/W9HXQbbQ4+1+JcZp0ZNPV31ym537ZJN+fiS7Ti8E=
+github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.5 
h1:P1doBzv5VEg1ONxnJss1Kh5ZG/ewoIE4MQtKKc6Crgg=
+github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.5/go.mod 
h1:NOP+euMW7W3Ukt28tAxPuoWao4rhhqJD3QEBk7oCg7w=
+github.com/aws/aws-sdk-go-v2/service/kms v1.37.6 
h1:CZImQdb1QbU9sGgJ9IswhVkxAcjkkD1eQTMA1KHWk+E=
+github.com/aws/aws-sdk-go-v2/service/kms v1.37.6/go.mod 
h1:YJDdlK0zsyxVBxGU48AR/Mi8DMrGdc1E3Yij4fNrONA=
+github.com/aws/aws-sdk-go-v2/service/lambda v1.69.0 
h1:BXt75frE/FYtAmEDBJRBa2HexOw+oAZWZl6QknZEFgg=
+github.com/aws/aws-sdk-go-v2/service/lambda v1.69.0/go.mod 
h1:guz2K3x4FKSdDaoeB+TPVgJNU9oj2gftbp5cR8ela1A=
+github.com/aws/aws-sdk-go-v2/service/rds v1.91.0 
h1:eqHz3Uih+gb0vLE5Cc4Xf733vOxsxDp6GFUUVQU4d7w=
+github.com/aws/aws-sdk-go-v2/service/rds v1.91.0/go.mod 
h1:h2jc7IleH3xHY7y+h8FH7WAZcz3IVLOB6/jXotIQ/qU=
+github.com/aws/aws-sdk-go-v2/service/route53 v1.46.2 
h1:wmt05tPp/CaRZpPV5B4SaJ5TwkHKom07/BzHoLdkY1o=
+github.com/aws/aws-sdk-go-v2/service/route53 v1.46.2/go.mod 
h1:d+K9HESMpGb1EU9/UmmpInbGIUcAkwmcY6ZO/A3zZsw=
+github.com/aws/aws-sdk-go-v2/service/s3 v1.69.0 
h1:Q2ax8S21clKOnHhhr933xm3JxdJebql+R7aNo7p7GBQ=
+github.com/aws/aws-sdk-go-v2/service/s3 v1.69.0/go.mod 
h1:ralv4XawHjEMaHOWnTFushl0WRqim/gQWesAMF6hTow=
+github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.34.6 
h1:1KDMKvOKNrpD667ORbZ/+4OgvUoaok1gg/MLzrHF9fw=
+github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.34.6/go.mod 
h1:DmtyfCfONhOyVAJ6ZMTrDSFIeyCBlEO93Qkfhxwbxu0=
+github.com/aws/aws-sdk-go-v2/service/sns v1.33.6 
h1:lEUtRHICiXsd7VRwRjXaY7MApT2X4Ue0Mrwe6XbyBro=
+github.com/aws/aws-sdk-go-v2/service/sns v1.33.6/go.mod 
h1:SODr0Lu3lFdT0SGsGX1TzFTapwveBrT5wztVoYtppm8=
+github.com/aws/aws-sdk-go-v2/service/sqs v1.37.1 
h1:39WvSrVq9DD6UHkD+fx5x19P5KpRQfNdtgReDVNbelc=
+github.com/aws/aws-sdk-go-v2/service/sqs v1.37.1/go.mod 
h1:3gwPzC9LER/BTQdQZ3r6dUktb1rSjABF1D3Sr6nS7VU=
+github.com/aws/aws-sdk-go-v2/service/ssm v1.56.0 
h1:mADKqoZaodipGgiZfuAjtlcr4IVBtXPZKVjkzUZCCYM=
+github.com/aws/aws-sdk-go-v2/service/ssm v1.56.0/go.mod 
h1:l9qF25TzH95FhcIak6e4vt79KE4I7M2Nf59eMUVjj6c=
+github.com/aws/aws-sdk-go-v2/service/sso v1.24.6 
h1:3zu537oLmsPfDMyjnUS2g+F2vITgy5pB74tHI+JBNoM=
+github.com/aws/aws-sdk-go-v2/service/sso v1.24.6/go.mod 
h1:WJSZH2ZvepM6t6jwu4w/Z45Eoi75lPN7DcydSRtJg6Y=
+github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.5 
h1:K0OQAsDywb0ltlFrZm0JHPY3yZp/S9OaoLU33S7vPS8=
+github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.5/go.mod 
h1:ORITg+fyuMoeiQFiVGoqB3OydVTLkClw/ljbblMq6Cc=
+github.com/aws/aws-sdk-go-v2/service/sts v1.33.1 
h1:6SZUVRQNvExYlMLbHdlKB48x0fLbc2iVROyaNEwBHbU=
+github.com/aws/aws-sdk-go-v2/service/sts v1.33.1/go.mod 
h1:GqWyYCwLXnlUB1lOAXQyNSPqPLQJvmo8J0DWBzp9mtg=
+github.com/aws/smithy-go v1.22.1 
h1:/HPHZQ0g7f4eUeK6HKglFz8uwVfZKgoI25rb/J+dnro=
+github.com/aws/smithy-go v1.22.1/go.mod 
h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg=
 github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
 github.com/beorn7/perks v1.0.1/go.mod 
h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
 github.com/bgentry/speakeasy v0.1.0/go.mod 
h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
@@ -38,9 +110,9 @@ github.com/cenkalti/backoff/v4 v4.3.0/go.mod 
h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyY
 github.com/cespare/xxhash/v2 v2.3.0 
h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
 github.com/cespare/xxhash/v2 v2.3.0/go.mod 
h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
 github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod 
h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
-github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod 
h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
-github.com/cpuguy83/go-md2man/v2 v2.0.4 
h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4=
 github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod 
h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
+github.com/cpuguy83/go-md2man/v2 v2.0.5 
h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc=
+github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod 
h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
 github.com/creack/pty v1.1.9/go.mod 
h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
 github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod 
h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.0/go.mod 
h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -90,8 +162,8 @@ github.com/go-playground/assert/v2 v2.0.1/go.mod 
h1:VDjEfimB/XKnb+ZQfWdccd7VUvSc
 github.com/go-playground/locales v0.14.0/go.mod 
h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
 github.com/go-playground/universal-translator v0.18.0/go.mod 
h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
 github.com/go-playground/validator/v10 v10.10.0/go.mod 
h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos=
-github.com/go-sql-driver/mysql v1.7.1 
h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI=
-github.com/go-sql-driver/mysql v1.7.1/go.mod 
h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
+github.com/go-sql-driver/mysql v1.8.1 
h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
+github.com/go-sql-driver/mysql v1.8.1/go.mod 
h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
 github.com/go-task/slim-sprig/v3 v3.0.0 
h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
 github.com/go-task/slim-sprig/v3 v3.0.0/go.mod 
h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
 github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
@@ -130,8 +202,8 @@ github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 
h1:bkypFPDjIYGfCYD5mRBvpqxfYX1
 github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod 
h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k=
 github.com/gruntwork-io/go-commons v0.8.0 
h1:k/yypwrPqSeYHevLlEDmvmgQzcyTwrlZGRaxEM6G0ro=
 github.com/gruntwork-io/go-commons v0.8.0/go.mod 
h1:gtp0yTtIBExIZp7vyIV9I0XQkVwiQZze678hvDXof78=
-github.com/gruntwork-io/terratest v0.47.0 
h1:xIy1pT7NbGVlMLDZEHl3+3iSnvffh8tN2pL6idn448c=
-github.com/gruntwork-io/terratest v0.47.0/go.mod 
h1:oywHw1cFKXSYvKPm27U7quZVzDUlA22H2xUrKCe26xM=
+github.com/gruntwork-io/terratest v0.50.0 
h1:AbBJ7IRCpLZ9H4HBrjeoWESITv8nLjN6/f1riMNcAsw=
+github.com/gruntwork-io/terratest v0.50.0/go.mod 
h1:see0lbKvAqz6rvzvN2wyfuFQQG4PWcAb2yHulF6B2q4=
 github.com/hashicorp/errwrap v1.0.0/go.mod 
h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
 github.com/hashicorp/errwrap v1.1.0 
h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
 github.com/hashicorp/errwrap v1.1.0/go.mod 
h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
@@ -165,6 +237,14 @@ github.com/inconshreveable/mousetrap v1.1.0 
h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2
 github.com/inconshreveable/mousetrap v1.1.0/go.mod 
h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
 github.com/incubator4/go-resty-expr v0.1.1 
h1:9ur1M+p0wDzL1bprdGzHugGkfK0Yd3Ba/ijcgvL+a1k=
 github.com/incubator4/go-resty-expr v0.1.1/go.mod 
h1:w9YQkQLUs1cArOb4O7SGJwJL/L8kuAo6y5CVS2o9eag=
+github.com/jackc/pgpassfile v1.0.0 
h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
+github.com/jackc/pgpassfile v1.0.0/go.mod 
h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
+github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 
h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
+github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod 
h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
+github.com/jackc/pgx/v5 v5.7.1 h1:x7SYsPBYDkHDksogeSmZZ5xzThcTgRz++I5E+ePFUcs=
+github.com/jackc/pgx/v5 v5.7.1/go.mod 
h1:e7O26IywZZ+naJtWWos6i6fvWK+29etgITqrqHLfoZA=
+github.com/jackc/puddle/v2 v2.2.2 
h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo=
+github.com/jackc/puddle/v2 v2.2.2/go.mod 
h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
 github.com/jmespath/go-jmespath v0.4.0 
h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
 github.com/jmespath/go-jmespath v0.4.0/go.mod 
h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
 github.com/jmespath/go-jmespath/internal/testify v1.5.1 
h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
@@ -243,8 +323,8 @@ github.com/pmezard/go-difflib 
v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77
 github.com/pmezard/go-difflib v1.0.0/go.mod 
h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 
h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
 github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod 
h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
-github.com/pquerna/otp v1.2.0 h1:/A3+Jn+cagqayeR3iHs/L62m5ue7710D35zl1zJ1kok=
-github.com/pquerna/otp v1.2.0/go.mod 
h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg=
+github.com/pquerna/otp v1.4.0 h1:wZvl1TIVxKRThZIBiwOOHOGP/1+nZyWBil9Y2XNEDzg=
+github.com/pquerna/otp v1.4.0/go.mod 
h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg=
 github.com/prometheus/client_golang v1.19.1 
h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE=
 github.com/prometheus/client_golang v1.19.1/go.mod 
h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho=
 github.com/prometheus/client_model v0.6.1 
h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
@@ -288,6 +368,7 @@ github.com/stretchr/objx v0.1.0/go.mod 
h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
 github.com/stretchr/objx v0.1.1/go.mod 
h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/objx v0.4.0/go.mod 
h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
 github.com/stretchr/objx v0.5.0/go.mod 
h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
+github.com/stretchr/objx v0.5.2/go.mod 
h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
 github.com/stretchr/testify v0.0.0-20161117074351-18a02ba4a312/go.mod 
h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
 github.com/stretchr/testify v1.2.2/go.mod 
h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
 github.com/stretchr/testify v1.3.0/go.mod 
h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
@@ -298,14 +379,15 @@ github.com/stretchr/testify v1.7.0/go.mod 
h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
 github.com/stretchr/testify v1.7.1/go.mod 
h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/stretchr/testify v1.8.0/go.mod 
h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
 github.com/stretchr/testify v1.8.4/go.mod 
h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
-github.com/stretchr/testify v1.9.0 
h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
 github.com/stretchr/testify v1.9.0/go.mod 
h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
+github.com/stretchr/testify v1.10.0 
h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
+github.com/stretchr/testify v1.10.0/go.mod 
h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
 github.com/tailscale/depaware v0.0.0-20210622194025-720c4b409502/go.mod 
h1:p9lPsd+cx33L3H9nNoecRRxPssFKUwwI50I3pZ0yT+8=
 github.com/ugorji/go v1.2.7/go.mod 
h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M=
 github.com/ugorji/go/codec v1.2.7/go.mod 
h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY=
 github.com/urfave/cli v1.22.2/go.mod 
h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
-github.com/urfave/cli v1.22.14 h1:ebbhrRiGK2i4naQJr+1Xj92HXZCrK7MsyTS/ob3HnAk=
-github.com/urfave/cli v1.22.14/go.mod 
h1:X0eDS6pD6Exaclxm99NJ3FiCDRED7vIHpx2mDOHLvkA=
+github.com/urfave/cli v1.22.16 h1:MH0k6uJxdwdeWQTwhSO42Pwr4YLrNLwBtg1MRgTqPdQ=
+github.com/urfave/cli v1.22.16/go.mod 
h1:EeJR6BKodywf4zciqrdw6hpCPk68JO9z5LazXZMn5Po=
 github.com/valyala/bytebufferpool v1.0.0 
h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
 github.com/valyala/bytebufferpool v1.0.0/go.mod 
h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
 github.com/valyala/fasthttp v1.34.0 
h1:d3AAQJ2DRcxJYHm7OXNXtXt2as1vMDfxeIcFvhmGGm4=
@@ -331,20 +413,20 @@ github.com/yudai/pp v2.0.1+incompatible/go.mod 
h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZ
 github.com/yuin/goldmark v1.1.27/go.mod 
h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.2.1/go.mod 
h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.4.13/go.mod 
h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
-go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 
h1:4K4tsIXefpVJtvA/8srF4V4y0akAoPHkIslgAkjixJA=
-go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0/go.mod 
h1:jjdQuTGVsXV4vSs+CJ2qYDeDPf9yIJV23qlIzBm73Vg=
-go.opentelemetry.io/otel v1.28.0 
h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo=
-go.opentelemetry.io/otel v1.28.0/go.mod 
h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4=
+go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 
h1:TT4fX+nBOA/+LUkobKGW1ydGcn+G3vRw9+g5HwCphpk=
+go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0/go.mod 
h1:L7UH0GbB0p47T4Rri3uHjbpCFYrVrwc1I25QhNPiGK8=
+go.opentelemetry.io/otel v1.29.0 
h1:PdomN/Al4q/lN6iBJEN3AwPvUiHPMlt93c8bqTG5Llw=
+go.opentelemetry.io/otel v1.29.0/go.mod 
h1:N/WtXPs1CNCUEx+Agz5uouwCba+i+bJGFicT8SR4NP8=
 go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 
h1:3Q/xZUyC1BBkualc9ROb4G8qkH90LXEIICcs5zv1OYY=
 go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0/go.mod 
h1:s75jGIWA9OfCMzF0xr+ZgfrB5FEbbV7UuYo32ahUiFI=
 go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0 
h1:qFffATk0X+HD+f1Z8lswGiOQYKHRlzfmdJm0wEaVrFA=
 go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0/go.mod 
h1:MOiCmryaYtc+V0Ei+Tx9o5S1ZjA7kzLucuVuyzBZloQ=
-go.opentelemetry.io/otel/metric v1.28.0 
h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q=
-go.opentelemetry.io/otel/metric v1.28.0/go.mod 
h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s=
-go.opentelemetry.io/otel/sdk v1.28.0 
h1:b9d7hIry8yZsgtbmM0DKyPWMMUMlK9NEKuIG4aBqWyE=
-go.opentelemetry.io/otel/sdk v1.28.0/go.mod 
h1:oYj7ClPUA7Iw3m+r7GeEjz0qckQRJK2B8zjcZEfu7Pg=
-go.opentelemetry.io/otel/trace v1.28.0 
h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g=
-go.opentelemetry.io/otel/trace v1.28.0/go.mod 
h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI=
+go.opentelemetry.io/otel/metric v1.29.0 
h1:vPf/HFWTNkPu1aYeIsc98l4ktOQaL6LeSoeV2g+8YLc=
+go.opentelemetry.io/otel/metric v1.29.0/go.mod 
h1:auu/QWieFVWx+DmQOUMgj0F8LHWdgalxXqvp7BII/W8=
+go.opentelemetry.io/otel/sdk v1.29.0 
h1:vkqKjk7gwhS8VaWb0POZKmIEDimRCMsopNYnriHyryo=
+go.opentelemetry.io/otel/sdk v1.29.0/go.mod 
h1:pM8Dx5WKnvxLCb+8lG1PRNIDxu9g9b9g59Qr7hfAAok=
+go.opentelemetry.io/otel/trace v1.29.0 
h1:J/8ZNK4XgR7a21DZUAsbF8pZ5Jcw1VhACmnYt39JTi4=
+go.opentelemetry.io/otel/trace v1.29.0/go.mod 
h1:eHl3w0sp3paPkYstJOmAimxhiFXPg+MMTlEh3nsQgWQ=
 go.opentelemetry.io/proto/otlp v1.3.1 
h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0=
 go.opentelemetry.io/proto/otlp v1.3.1/go.mod 
h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8=
 go.uber.org/atomic v1.7.0/go.mod 
h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
@@ -385,12 +467,11 @@ golang.org/x/net 
v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
 golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod 
h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod 
h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
 golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod 
h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
-golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
 golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
 golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
 golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
-golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs=
-golang.org/x/oauth2 v0.21.0/go.mod 
h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
+golang.org/x/oauth2 v0.24.0 h1:KTBBxWqUa0ykRPLtV69rRto9TLXcqYkeswu48x/gvNE=
+golang.org/x/oauth2 v0.24.0/go.mod 
h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
 golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod 
h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod 
h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod 
h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -413,14 +494,12 @@ golang.org/x/sys 
v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBc
 golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod 
h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod 
h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod 
h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
 golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod 
h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod 
h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
-golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
 golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
 golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y=
 golang.org/x/term v0.30.0/go.mod 
h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g=
@@ -431,8 +510,8 @@ golang.org/x/text v0.3.7/go.mod 
h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
 golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
 golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
 golang.org/x/text v0.23.0/go.mod 
h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
-golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
-golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
+golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg=
+golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod 
h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod 
h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
 golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod 
h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
@@ -448,16 +527,16 @@ golang.org/x/xerrors 
v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T
 golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod 
h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 gomodules.xyz/jsonpatch/v2 v2.4.0 
h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw=
 gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod 
h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY=
-google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 
h1:+rdxYoE3E5htTEWIe15GlN6IfvbURM//Jt0mmkmm6ZU=
-google.golang.org/genproto/googleapis/api 
v0.0.0-20240604185151-ef581f913117/go.mod 
h1:OimBR/bc1wPO9iV4NC2bpyjy3VnAwZh5EBPQdtaE5oo=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 
h1:BwIjyKYGsK9dMCBOorzRri8MQwmi7mT9rGHsCEinZkA=
-google.golang.org/genproto/googleapis/rpc 
v0.0.0-20240701130421-f6361c86f094/go.mod 
h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY=
-google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo=
-google.golang.org/grpc v1.66.2/go.mod 
h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y=
+google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28 
h1:M0KvPgPmDZHPlbRbaNU1APr28TvwvvdUPlSv7PUvy8g=
+google.golang.org/genproto/googleapis/api 
v0.0.0-20241104194629-dd2ea8efbc28/go.mod 
h1:dguCy7UOdZhTvLzDyt15+rOrawrpM4q7DD9dQ1P11P4=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 
h1:XVhgTWWV3kGQlwJHR3upFWZeTsei6Oks1apkZSeonIE=
+google.golang.org/genproto/googleapis/rpc 
v0.0.0-20241104194629-dd2ea8efbc28/go.mod 
h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI=
+google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E=
+google.golang.org/grpc v1.67.1/go.mod 
h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA=
 google.golang.org/protobuf v1.26.0-rc.1/go.mod 
h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
 google.golang.org/protobuf v1.28.0/go.mod 
h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
-google.golang.org/protobuf v1.34.2 
h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
-google.golang.org/protobuf v1.34.2/go.mod 
h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
+google.golang.org/protobuf v1.35.1 
h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA=
+google.golang.org/protobuf v1.35.1/go.mod 
h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod 
h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod 
h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod 
h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
diff --git a/test/e2e/apisix/e2e_test.go b/test/e2e/apisix/e2e_test.go
index da357c5d..ea814157 100644
--- a/test/e2e/apisix/e2e_test.go
+++ b/test/e2e/apisix/e2e_test.go
@@ -38,9 +38,7 @@ func TestAPISIXE2E(t *testing.T) {
        _ = framework.NewFramework()
 
        // init newDeployer function
-       scaffold.NewDeployer = func(s *scaffold.Scaffold) scaffold.Deployer {
-               return scaffold.NewAPISIXDeployer(s)
-       }
+       scaffold.NewDeployer = scaffold.NewAPISIXDeployer
 
        _, _ = fmt.Fprintf(GinkgoWriter, "Starting APISIX standalone e2e 
suite\n")
        RunSpecs(t, "apisix standalone e2e suite")
diff --git a/test/e2e/apisix/status.go b/test/e2e/apisix/status.go
index 1c72e412..7bc0b6a5 100644
--- a/test/e2e/apisix/status.go
+++ b/test/e2e/apisix/status.go
@@ -39,10 +39,6 @@ var _ = Describe("Test CRD Status", 
Label("apisix.apache.org", "v2", "apisixrout
                applier = framework.NewApplier(s.GinkgoT, s.K8sClient, 
s.CreateResourceFromString)
        )
 
-       assertion := func(actualOrCtx any, args ...any) AsyncAssertion {
-               return 
Eventually(actualOrCtx).WithArguments(args...).WithTimeout(30 * 
time.Second).ProbeEvery(time.Second)
-       }
-
        Context("Test ApisixRoute Sync Status", func() {
                BeforeEach(func() {
                        By("create GatewayProxy")
@@ -95,22 +91,16 @@ spec:
     - name: non-existent-plugin
       enable: true
 `
-
-               getRequest := func(path string) func() int {
-                       return func() int {
-                               return 
s.NewAPISIXClient().GET(path).WithHost("httpbin").Expect().Raw().StatusCode
-                       }
-               }
-
                It("unknown plugin", func() {
                        if os.Getenv("PROVIDER_TYPE") == "apisix-standalone" {
                                Skip("apisix standalone does not validate 
unknown plugins")
                        }
                        By("apply ApisixRoute with valid plugin")
-                       applier.MustApplyAPIv2(types.NamespacedName{Namespace: 
s.Namespace(), Name: "default"}, &apiv2.ApisixRoute{}, arWithInvalidPlugin)
+                       err := s.CreateResourceFromString(arWithInvalidPlugin)
+                       Expect(err).NotTo(HaveOccurred(), "creating ApisixRoute 
with valid plugin")
 
                        By("check ApisixRoute status")
-                       assertion(func() string {
+                       s.RetryAssertion(func() string {
                                output, _ := s.GetOutputFromString("ar", 
"default", "-o", "yaml")
                                return output
                        }).Should(
@@ -124,67 +114,62 @@ spec:
                        By("Update ApisixRoute")
                        applier.MustApplyAPIv2(types.NamespacedName{Namespace: 
s.Namespace(), Name: "default"}, &apiv2.ApisixRoute{}, ar)
 
-                       By("check ApisixRoute status")
-                       assertion(func() string {
-                               output, _ := s.GetOutputFromString("ar", 
"default", "-o", "yaml")
-                               return output
-                       }).Should(
-                               And(
-                                       ContainSubstring(`status: "True"`),
-                                       ContainSubstring(`reason: Accepted`),
-                               ),
-                       )
-
                        By("check route in APISIX")
-                       assertion(getRequest("/get")).Should(Equal(200), 
"should be able to access the route")
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/get",
+                               Host:   "httpbin",
+                               Check:  scaffold.WithExpectedStatus(200),
+                       })
                })
 
                It("dataplane unavailable", func() {
                        By("apply ApisixRoute")
                        applier.MustApplyAPIv2(types.NamespacedName{Namespace: 
s.Namespace(), Name: "default"}, &apiv2.ApisixRoute{}, ar)
 
-                       By("check ApisixRoute status")
-                       assertion(func() string {
-                               output, _ := s.GetOutputFromString("ar", 
"default", "-o", "yaml")
-                               return output
-                       }).Should(
-                               And(
-                                       ContainSubstring(`status: "True"`),
-                                       ContainSubstring(`reason: Accepted`),
-                               ),
-                       )
-
                        By("check route in APISIX")
-                       assertion(getRequest("/get")).Should(Equal(200), 
"should be able to access the route")
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method:  "GET",
+                               Path:    "/get",
+                               Headers: map[string]string{"Host": "httpbin"},
+                               Check:   scaffold.WithExpectedStatus(200),
+                       })
 
                        s.Deployer.ScaleDataplane(0)
 
                        By("check ApisixRoute status")
-                       assertion(func() string {
+                       s.RetryAssertion(func() string {
                                output, _ := s.GetOutputFromString("ar", 
"default", "-o", "yaml")
                                return output
-                       }).Should(
-                               And(
-                                       ContainSubstring(`status: "False"`),
-                                       ContainSubstring(`reason: SyncFailed`),
-                               ),
-                       )
+                       }).WithTimeout(80 * time.Second).
+                               Should(
+                                       And(
+                                               ContainSubstring(`status: 
"False"`),
+                                               ContainSubstring(`reason: 
SyncFailed`),
+                                       ),
+                               )
 
                        s.Deployer.ScaleDataplane(1)
 
                        By("check ApisixRoute status after scaling up")
-                       assertion(func() string {
+                       s.RetryAssertion(func() string {
                                output, _ := s.GetOutputFromString("ar", 
"default", "-o", "yaml")
                                return output
-                       }).Should(
-                               And(
-                                       ContainSubstring(`status: "True"`),
-                                       ContainSubstring(`reason: Accepted`),
-                               ),
-                       )
+                       }).WithTimeout(80 * time.Second).
+                               Should(
+                                       And(
+                                               ContainSubstring(`status: 
"True"`),
+                                               ContainSubstring(`reason: 
Accepted`),
+                                       ),
+                               )
 
                        By("check route in APISIX")
-                       assertion(getRequest("/get")).Should(Equal(200), 
"should be able to access the route")
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/get",
+                               Host:   "httpbin",
+                               Check:  scaffold.WithExpectedStatus(200),
+                       })
                })
        })
 
@@ -276,67 +261,55 @@ spec:
                AfterEach(func() {
                        _ = s.DeleteResource("Gateway", "apisix")
                })
-               getRequest := func(path string) func() int {
-                       return func() int {
-                               return 
s.NewAPISIXClient().GET(path).WithHost("httpbin").Expect().Raw().StatusCode
-                       }
-               }
-               var resourceApplied = func(resourType, resourceName, 
resourceRaw string, observedGeneration int) {
-                       Expect(s.CreateResourceFromString(resourceRaw)).
-                               NotTo(HaveOccurred(), fmt.Sprintf("creating 
%s", resourType))
-
-                       Eventually(func() string {
-                               hryaml, err := s.GetResourceYaml(resourType, 
resourceName)
-                               Expect(err).NotTo(HaveOccurred(), 
fmt.Sprintf("getting %s yaml", resourType))
-                               return hryaml
-                       }, "8s", "2s").
-                               Should(
-                                       SatisfyAll(
-                                               ContainSubstring(`status: 
"True"`),
-                                               
ContainSubstring(fmt.Sprintf("observedGeneration: %d", observedGeneration)),
-                                       ),
-                                       fmt.Sprintf("checking %s condition 
status", resourType),
-                               )
-                       time.Sleep(5 * time.Second)
-               }
 
                It("dataplane unavailable", func() {
                        By("Create HTTPRoute")
-                       resourceApplied("HTTPRoute", "httpbin", httproute, 1)
+                       err := s.CreateResourceFromString(httproute)
+                       Expect(err).NotTo(HaveOccurred(), "creating HTTPRoute")
 
                        By("check route in APISIX")
-                       assertion(getRequest("/get")).Should(Equal(200), 
"should be able to access the route")
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/get",
+                               Host:   "httpbin",
+                               Check:  scaffold.WithExpectedStatus(200),
+                       })
 
                        s.Deployer.ScaleDataplane(0)
-                       time.Sleep(10 * time.Second)
 
                        By("check ApisixRoute status")
-                       assertion(func() string {
+                       s.RetryAssertion(func() string {
                                output, _ := s.GetOutputFromString("httproute", 
"httpbin", "-o", "yaml")
                                return output
-                       }).Should(
-                               And(
-                                       ContainSubstring(`status: "False"`),
-                                       ContainSubstring(`reason: SyncFailed`),
-                               ),
-                       )
+                       }).WithTimeout(80 * time.Second).
+                               Should(
+                                       And(
+                                               ContainSubstring(`status: 
"False"`),
+                                               ContainSubstring(`reason: 
SyncFailed`),
+                                       ),
+                               )
 
                        s.Deployer.ScaleDataplane(1)
-                       time.Sleep(10 * time.Second)
 
                        By("check ApisixRoute status after scaling up")
-                       assertion(func() string {
+                       s.RetryAssertion(func() string {
                                output, _ := s.GetOutputFromString("httproute", 
"httpbin", "-o", "yaml")
                                return output
-                       }).Should(
-                               And(
-                                       ContainSubstring(`status: "True"`),
-                                       ContainSubstring(`reason: Accepted`),
-                               ),
-                       )
+                       }).WithTimeout(80 * time.Second).
+                               Should(
+                                       And(
+                                               ContainSubstring(`status: 
"True"`),
+                                               ContainSubstring(`reason: 
Accepted`),
+                                       ),
+                               )
 
                        By("check route in APISIX")
-                       assertion(getRequest("/get")).Should(Equal(200), 
"should be able to access the route")
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/get",
+                               Host:   "httpbin",
+                               Check:  scaffold.WithExpectedStatus(200),
+                       })
                })
        })
 })
diff --git a/test/e2e/crds/backendtrafficpolicy.go 
b/test/e2e/crds/backendtrafficpolicy.go
index 4dc2ca92..82b88a20 100644
--- a/test/e2e/crds/backendtrafficpolicy.go
+++ b/test/e2e/crds/backendtrafficpolicy.go
@@ -19,7 +19,6 @@ package gatewayapi
 
 import (
        "fmt"
-       "time"
 
        . "github.com/onsi/ginkgo/v2"
        . "github.com/onsi/gomega"
@@ -130,33 +129,55 @@ spec:
                })
                It("should rewrite upstream host", func() {
                        s.ResourceApplied("BackendTrafficPolicy", "httpbin", 
createUpstreamHost, 1)
-                       s.NewAPISIXClient().
-                               GET("/headers").
-                               WithHost("httpbin.org").
-                               Expect().
-                               Status(200).
-                               Body().Contains("httpbin.example.com")
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/headers",
+                               Host:   "httpbin.org",
+                               Headers: map[string]string{
+                                       "Host": "httpbin.org",
+                               },
+                               Checks: []scaffold.ResponseCheckFunc{
+                                       scaffold.WithExpectedStatus(200),
+                                       scaffold.WithExpectedBodyContains(
+                                               "httpbin.example.com",
+                                       ),
+                               },
+                       })
 
                        s.ResourceApplied("BackendTrafficPolicy", "httpbin", 
updateUpstreamHost, 2)
-                       s.NewAPISIXClient().
-                               GET("/headers").
-                               WithHost("httpbin.org").
-                               Expect().
-                               Status(200).
-                               Body().Contains("httpbin.update.example.com")
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/headers",
+                               Host:   "httpbin.org",
+                               Headers: map[string]string{
+                                       "Host": "httpbin.org",
+                               },
+                               Checks: []scaffold.ResponseCheckFunc{
+                                       scaffold.WithExpectedStatus(200),
+                                       scaffold.WithExpectedBodyContains(
+                                               "httpbin.update.example.com",
+                                       ),
+                               },
+                       })
 
                        err := s.DeleteResourceFromString(createUpstreamHost)
                        Expect(err).NotTo(HaveOccurred(), "deleting 
BackendTrafficPolicy")
-                       time.Sleep(5 * time.Second)
 
-                       s.NewAPISIXClient().
-                               GET("/headers").
-                               WithHost("httpbin.org").
-                               Expect().
-                               Status(200).
-                               Body().
-                               NotContains("httpbin.update.example.com").
-                               NotContains("httpbin.example.com")
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/headers",
+                               Host:   "httpbin.org",
+                               Headers: map[string]string{
+                                       "Host": "httpbin.org",
+                               },
+                               Checks: []scaffold.ResponseCheckFunc{
+                                       scaffold.WithExpectedStatus(200),
+                                       scaffold.WithExpectedBodyNotContains(
+                                               "httpbin.update.example.com",
+                                               "httpbin.example.com",
+                                       ),
+                               },
+                       })
                })
        })
 })
@@ -231,7 +252,6 @@ spec:
                By("create Ingress with GatewayProxy IngressClass")
                err = s.CreateResourceFromString(defaultIngress)
                Expect(err).NotTo(HaveOccurred(), "creating Ingress with 
GatewayProxy IngressClass")
-               time.Sleep(5 * time.Second)
        }
 
        Context("Rewrite Upstream Host", func() {
@@ -265,34 +285,36 @@ spec:
 
                BeforeEach(beforeEach)
                It("should rewrite upstream host", func() {
+                       reqAssert := &scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/headers",
+                               Host:   "httpbin.org",
+                               Headers: map[string]string{
+                                       "Host": "httpbin.org",
+                               },
+                       }
                        s.ResourceApplied("BackendTrafficPolicy", "httpbin", 
createUpstreamHost, 1)
-                       s.NewAPISIXClient().
-                               GET("/headers").
-                               WithHost("httpbin.org").
-                               Expect().
-                               Status(200).
-                               Body().Contains("httpbin.example.com")
+                       s.RequestAssert(reqAssert.SetChecks(
+                               scaffold.WithExpectedStatus(200),
+                               
scaffold.WithExpectedBodyContains("httpbin.example.com"),
+                       ))
 
                        s.ResourceApplied("BackendTrafficPolicy", "httpbin", 
updateUpstreamHost, 2)
-                       s.NewAPISIXClient().
-                               GET("/headers").
-                               WithHost("httpbin.org").
-                               Expect().
-                               Status(200).
-                               Body().Contains("httpbin.update.example.com")
+                       s.RequestAssert(reqAssert.SetChecks(
+                               scaffold.WithExpectedStatus(200),
+                               
scaffold.WithExpectedBodyContains("httpbin.update.example.com"),
+                       ))
 
                        err := s.DeleteResourceFromString(createUpstreamHost)
                        Expect(err).NotTo(HaveOccurred(), "deleting 
BackendTrafficPolicy")
-                       time.Sleep(5 * time.Second)
 
-                       s.NewAPISIXClient().
-                               GET("/headers").
-                               WithHost("httpbin.org").
-                               Expect().
-                               Status(200).
-                               Body().
-                               NotContains("httpbin.update.example.com").
-                               NotContains("httpbin.example.com")
+                       s.RequestAssert(reqAssert.SetChecks(
+                               scaffold.WithExpectedStatus(200),
+                               scaffold.WithExpectedBodyNotContains(
+                                       "httpbin.update.example.com",
+                                       "httpbin.example.com",
+                               ),
+                       ))
                })
        })
 })
diff --git a/test/e2e/crds/consumer.go b/test/e2e/crds/consumer.go
index 879d6048..26b8554f 100644
--- a/test/e2e/crds/consumer.go
+++ b/test/e2e/crds/consumer.go
@@ -19,8 +19,6 @@ package gatewayapi
 
 import (
        "fmt"
-       "net/http"
-       "time"
 
        . "github.com/onsi/ginkgo/v2"
        . "github.com/onsi/gomega"
@@ -161,35 +159,47 @@ spec:
                        s.ResourceApplied("Consumer", "consumer-sample", 
limitCountConsumer, 1)
                        s.ResourceApplied("Consumer", "consumer-sample2", 
unlimitConsumer, 1)
 
-                       s.NewAPISIXClient().
-                               GET("/get").
-                               WithHeader("apikey", "sample-key").
-                               WithHost("httpbin.org").
-                               Expect().
-                               Status(200)
-
-                       s.NewAPISIXClient().
-                               GET("/get").
-                               WithHeader("apikey", "sample-key").
-                               WithHost("httpbin.org").
-                               Expect().
-                               Status(200)
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/get",
+                               Host:   "httpbin.org",
+                               Headers: map[string]string{
+                                       "apikey": "sample-key",
+                               },
+                               Check: scaffold.WithExpectedStatus(200),
+                       })
+
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/get",
+                               Host:   "httpbin.org",
+                               Headers: map[string]string{
+                                       "apikey": "sample-key",
+                               },
+                               Check: scaffold.WithExpectedStatus(200),
+                       })
 
                        By("trigger limit-count")
-                       s.NewAPISIXClient().
-                               GET("/get").
-                               WithHeader("apikey", "sample-key").
-                               WithHost("httpbin.org").
-                               Expect().
-                               Status(503)
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/get",
+                               Host:   "httpbin.org",
+                               Headers: map[string]string{
+                                       "apikey": "sample-key",
+                               },
+                               Check: scaffold.WithExpectedStatus(503),
+                       })
 
                        for i := 0; i < 10; i++ {
-                               s.NewAPISIXClient().
-                                       GET("/get").
-                                       WithHeader("apikey", "sample-key2").
-                                       WithHost("httpbin.org").
-                                       Expect().
-                                       Status(200)
+                               s.RequestAssert(&scaffold.RequestAssert{
+                                       Method: "GET",
+                                       Path:   "/get",
+                                       Host:   "httpbin.org",
+                                       Headers: map[string]string{
+                                               "apikey": "sample-key2",
+                                       },
+                                       Check: scaffold.WithExpectedStatus(200),
+                               })
                        }
                })
        })
@@ -244,72 +254,98 @@ spec:
                It("Create/Update/Delete", func() {
                        s.ResourceApplied("Consumer", "consumer-sample", 
defaultCredential, 1)
 
-                       s.NewAPISIXClient().
-                               GET("/get").
-                               WithHeader("apikey", "sample-key").
-                               WithHost("httpbin.org").
-                               Expect().
-                               Status(200)
-
-                       s.NewAPISIXClient().
-                               GET("/get").
-                               WithHeader("apikey", "sample-key2").
-                               WithHost("httpbin.org").
-                               Expect().
-                               Status(200)
-
-                       s.NewAPISIXClient().
-                               GET("/get").
-                               WithBasicAuth("sample-user", "sample-password").
-                               WithHost("httpbin.org").
-                               Expect().
-                               Status(200)
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/get",
+                               Host:   "httpbin.org",
+                               Headers: map[string]string{
+                                       "apikey": "sample-key",
+                               },
+                               Check: scaffold.WithExpectedStatus(200),
+                       })
+
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/get",
+                               Host:   "httpbin.org",
+                               Headers: map[string]string{
+                                       "apikey": "sample-key2",
+                               },
+                               Check: scaffold.WithExpectedStatus(200),
+                       })
+
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/get",
+                               Host:   "httpbin.org",
+                               BasicAuth: &scaffold.BasicAuth{
+                                       Username: "sample-user",
+                                       Password: "sample-password",
+                               },
+                               Check: scaffold.WithExpectedStatus(200),
+                       })
 
                        By("update Consumer")
                        s.ResourceApplied("Consumer", "consumer-sample", 
updateCredential, 2)
 
-                       s.NewAPISIXClient().
-                               GET("/get").
-                               WithHeader("apikey", "sample-key").
-                               WithHost("httpbin.org").
-                               Expect().
-                               Status(401)
-
-                       s.NewAPISIXClient().
-                               GET("/get").
-                               WithHeader("apikey", "sample-key2").
-                               WithHost("httpbin.org").
-                               Expect().
-                               Status(401)
-
-                       s.NewAPISIXClient().
-                               GET("/get").
-                               WithHeader("apikey", "consumer-key").
-                               WithHost("httpbin.org").
-                               Expect().
-                               Status(200)
-
-                       s.NewAPISIXClient().
-                               GET("/get").
-                               WithBasicAuth("sample-user", "sample-password").
-                               WithHost("httpbin.org").
-                               Expect().
-                               Status(200)
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/get",
+                               Host:   "httpbin.org",
+                               Headers: map[string]string{
+                                       "apikey": "sample-key",
+                               },
+                               Check: scaffold.WithExpectedStatus(401),
+                       })
+
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/get",
+                               Host:   "httpbin.org",
+                               Headers: map[string]string{
+                                       "apikey": "sample-key2",
+                               },
+                               Check: scaffold.WithExpectedStatus(401),
+                       })
+
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/get",
+                               Host:   "httpbin.org",
+                               Headers: map[string]string{
+                                       "apikey": "consumer-key",
+                               },
+                               Check: scaffold.WithExpectedStatus(200),
+                       })
+
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/get",
+                               Host:   "httpbin.org",
+                               BasicAuth: &scaffold.BasicAuth{
+                                       Username: "sample-user",
+                                       Password: "sample-password",
+                               },
+                               Check: scaffold.WithExpectedStatus(200),
+                       })
 
                        By("delete Consumer")
                        err := s.DeleteResourceFromString(updateCredential)
                        Expect(err).NotTo(HaveOccurred(), "deleting Consumer")
-                       time.Sleep(5 * time.Second)
-
-                       s.NewAPISIXClient().
-                               GET("/get").
-                               WithBasicAuth("sample-user", "sample-password").
-                               WithHost("httpbin.org").
-                               Expect().
-                               Status(401)
+
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/get",
+                               Host:   "httpbin.org",
+                               BasicAuth: &scaffold.BasicAuth{
+                                       Username: "sample-user",
+                                       Password: "sample-password",
+                               },
+                               Check: scaffold.WithExpectedStatus(401),
+                       })
                })
-       })
 
+       })
        Context("SecretRef", func() {
                var keyAuthSecret = `
 apiVersion: v1
@@ -370,61 +406,79 @@ spec:
                        Expect(err).NotTo(HaveOccurred(), "creating basic-auth 
secret")
                        s.ResourceApplied("Consumer", "consumer-sample", 
defaultConsumer, 1)
 
-                       s.NewAPISIXClient().
-                               GET("/get").
-                               WithHeader("apikey", "sample-key").
-                               WithHost("httpbin.org").
-                               Expect().
-                               Status(200)
-
-                       s.NewAPISIXClient().
-                               GET("/get").
-                               WithBasicAuth("sample-user", "sample-password").
-                               WithHost("httpbin.org").
-                               Expect().
-                               Status(200)
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/get",
+                               Host:   "httpbin.org",
+                               Headers: map[string]string{
+                                       "apikey": "sample-key",
+                               },
+                               Check: scaffold.WithExpectedStatus(200),
+                       })
+
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/get",
+                               Host:   "httpbin.org",
+                               BasicAuth: &scaffold.BasicAuth{
+                                       Username: "sample-user",
+                                       Password: "sample-password",
+                               },
+                               Check: scaffold.WithExpectedStatus(200),
+                       })
 
                        // update basic-auth password
                        err = s.CreateResourceFromString(basicAuthSecret2)
                        Expect(err).NotTo(HaveOccurred(), "creating basic-auth 
secret")
 
                        // use the old password will get 401
-                       Eventually(func() int {
-                               return s.NewAPISIXClient().
-                                       GET("/get").
-                                       WithBasicAuth("sample-user", 
"sample-password").
-                                       WithHost("httpbin.org").
-                                       Expect().
-                                       Raw().StatusCode
-                       }).WithTimeout(8 * time.Second).ProbeEvery(time.Second).
-                               Should(Equal(http.StatusUnauthorized))
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/get",
+                               Host:   "httpbin.org",
+                               BasicAuth: &scaffold.BasicAuth{
+                                       Username: "sample-user",
+                                       Password: "sample-password",
+                               },
+                               Check: scaffold.WithExpectedStatus(401),
+                       })
 
                        // use the new password will get 200
-                       s.NewAPISIXClient().
-                               GET("/get").
-                               WithBasicAuth("sample-user", 
"sample-password-new").
-                               WithHost("httpbin.org").
-                               Expect().
-                               Status(http.StatusOK)
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/get",
+                               Host:   "httpbin.org",
+                               BasicAuth: &scaffold.BasicAuth{
+                                       Username: "sample-user",
+                                       Password: "sample-password-new",
+                               },
+                               Check: scaffold.WithExpectedStatus(200),
+                       })
 
                        By("delete consumer")
                        err = s.DeleteResourceFromString(defaultConsumer)
                        Expect(err).NotTo(HaveOccurred(), "deleting consumer")
-                       time.Sleep(5 * time.Second)
-
-                       s.NewAPISIXClient().
-                               GET("/get").
-                               WithHeader("apikey", "sample-key").
-                               WithHost("httpbin.org").
-                               Expect().
-                               Status(401)
-
-                       s.NewAPISIXClient().
-                               GET("/get").
-                               WithBasicAuth("sample-user", "sample-password").
-                               WithHost("httpbin.org").
-                               Expect().
-                               Status(401)
+
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/get",
+                               Host:   "httpbin.org",
+                               Headers: map[string]string{
+                                       "apikey": "sample-key",
+                               },
+                               Check: scaffold.WithExpectedStatus(401),
+                       })
+
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/get",
+                               Host:   "httpbin.org",
+                               BasicAuth: &scaffold.BasicAuth{
+                                       Username: "sample-user",
+                                       Password: "sample-password",
+                               },
+                               Check: scaffold.WithExpectedStatus(401),
+                       })
                })
        })
 
@@ -471,12 +525,16 @@ spec:
                        s.ResourceApplied("Consumer", "consumer-sample", 
defaultCredential, 1)
 
                        // verify basic-auth works
-                       s.NewAPISIXClient().
-                               GET("/get").
-                               WithBasicAuth("sample-user", "sample-password").
-                               WithHost("httpbin.org").
-                               Expect().
-                               Status(200)
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/get",
+                               Host:   "httpbin.org",
+                               BasicAuth: &scaffold.BasicAuth{
+                                       Username: "sample-user",
+                                       Password: "sample-password",
+                               },
+                               Check: scaffold.WithExpectedStatus(200),
+                       })
 
                        By("create additional gateway group to get new admin 
key")
                        var err error
@@ -490,26 +548,35 @@ spec:
                        Expect(err).NotTo(HaveOccurred(), "creating APISIX 
client for additional gateway group")
 
                        By("Consumer not found for additional gateway group")
-                       client.
-                               GET("/get").
-                               WithBasicAuth("sample-user", "sample-password").
-                               WithHost("httpbin.org").
-                               Expect().
-                               Status(404)
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Client: client,
+                               Method: "GET",
+                               Path:   "/get",
+                               Host:   "httpbin.org",
+                               BasicAuth: &scaffold.BasicAuth{
+                                       Username: "sample-user",
+                                       Password: "sample-password",
+                               },
+                               Check: scaffold.WithExpectedStatus(404),
+                       })
 
                        By("update GatewayProxy with new admin key")
                        updatedProxy := fmt.Sprintf(updatedGatewayProxy, 
s.Deployer.GetAdminEndpoint(resources.DataplaneService), resources.AdminAPIKey)
                        err = s.CreateResourceFromString(updatedProxy)
                        Expect(err).NotTo(HaveOccurred(), "updating 
GatewayProxy")
-                       time.Sleep(5 * time.Second)
 
                        By("verify Consumer works for additional gateway group")
-                       client.
-                               GET("/get").
-                               WithBasicAuth("sample-user", "sample-password").
-                               WithHost("httpbin.org").
-                               Expect().
-                               Status(200)
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Client: client,
+                               Method: "GET",
+                               Path:   "/get",
+                               Host:   "httpbin.org",
+                               BasicAuth: &scaffold.BasicAuth{
+                                       Username: "sample-user",
+                                       Password: "sample-password",
+                               },
+                               Check: scaffold.WithExpectedStatus(200),
+                       })
                })
        })
 })
diff --git a/test/e2e/framework/manifests/apisix.yaml 
b/test/e2e/framework/manifests/apisix.yaml
index affa4bfb..6b4adbbc 100644
--- a/test/e2e/framework/manifests/apisix.yaml
+++ b/test/e2e/framework/manifests/apisix.yaml
@@ -93,6 +93,13 @@ spec:
           volumeMounts:
             - name: config-writable
               mountPath: /usr/local/apisix/conf
+          readinessProbe:
+            failureThreshold: 6
+            initialDelaySeconds: 10
+            periodSeconds: 10
+            successThreshold: 1
+            tcpSocket:
+              port: 9080
       volumes:
         - name: config-source
           configMap:
diff --git a/test/e2e/framework/manifests/ingress.yaml 
b/test/e2e/framework/manifests/ingress.yaml
index c4bb1014..addb9552 100644
--- a/test/e2e/framework/manifests/ingress.yaml
+++ b/test/e2e/framework/manifests/ingress.yaml
@@ -68,7 +68,7 @@ rules:
 apiVersion: rbac.authorization.k8s.io/v1
 kind: ClusterRole
 metadata:
-  name: apisix-ingress-manager-role
+  name: {{ .Namespace }}-apisix-ingress-manager-role
 rules:
 - apiGroups:
   - ""
@@ -244,7 +244,7 @@ rules:
 apiVersion: rbac.authorization.k8s.io/v1
 kind: ClusterRole
 metadata:
-  name: apisix-ingress-metrics-auth-role
+  name: {{ .Namespace }}-apisix-ingress-metrics-auth-role
 rules:
 - apiGroups:
   - authentication.k8s.io
@@ -262,7 +262,7 @@ rules:
 apiVersion: rbac.authorization.k8s.io/v1
 kind: ClusterRole
 metadata:
-  name: apisix-ingress-metrics-reader
+  name: {{ .Namespace }}-apisix-ingress-metrics-reader
 rules:
 - nonResourceURLs:
   - /metrics
@@ -280,7 +280,7 @@ metadata:
 roleRef:
   apiGroup: rbac.authorization.k8s.io
   kind: Role
-  name: apisix-ingress-leader-election-role
+  name: {{ .Namespace }}-apisix-ingress-leader-election-role
 subjects:
 - kind: ServiceAccount
   name: apisix-ingress-controller-manager
@@ -292,11 +292,11 @@ metadata:
   labels:
     app.kubernetes.io/managed-by: kustomize
     app.kubernetes.io/name: apisix-ingress
-  name: apisix-ingress-manager-rolebinding
+  name: {{ .Namespace }}-apisix-ingress-manager-rolebinding
 roleRef:
   apiGroup: rbac.authorization.k8s.io
   kind: ClusterRole
-  name: apisix-ingress-manager-role
+  name: {{ .Namespace }}-apisix-ingress-manager-role
 subjects:
 - kind: ServiceAccount
   name: apisix-ingress-controller-manager
@@ -305,11 +305,11 @@ subjects:
 apiVersion: rbac.authorization.k8s.io/v1
 kind: ClusterRoleBinding
 metadata:
-  name: apisix-ingress-metrics-auth-rolebinding
+  name: {{ .Namespace }}-apisix-ingress-metrics-auth-rolebinding
 roleRef:
   apiGroup: rbac.authorization.k8s.io
   kind: ClusterRole
-  name: apisix-ingress-metrics-auth-role
+  name: {{ .Namespace }}-apisix-ingress-metrics-auth-role
 subjects:
 - kind: ServiceAccount
   name: apisix-ingress-controller-manager
@@ -320,14 +320,13 @@ apiVersion: v1
 kind: ConfigMap
 metadata:
   name: ingress-config
+  namespace: {{ .Namespace }}
 data:
   config.yaml: |
     log_level: "debug"
-
     controller_name: {{ .ControllerName | default 
"apisix.apache.org/apisix-ingress-controller" }}
-
     leader_election_id: "apisix-ingress-controller-leader"
-
+    exec_adc_timeout: 5s
     provider:
       type: {{ .ProviderType | default "apisix" }}
       sync_period: {{ .ProviderSyncPeriod | default "0s" }}
diff --git a/test/e2e/gatewayapi/gatewayproxy.go 
b/test/e2e/gatewayapi/gatewayproxy.go
index dfcbba9b..f8fc56f7 100644
--- a/test/e2e/gatewayapi/gatewayproxy.go
+++ b/test/e2e/gatewayapi/gatewayproxy.go
@@ -123,25 +123,6 @@ spec:
       port: 80
 `
 
-       var resourceApplied = func(resourceType, resourceName, resourceRaw 
string, observedGeneration int) {
-               Expect(s.CreateResourceFromString(resourceRaw)).
-                       NotTo(HaveOccurred(), fmt.Sprintf("creating %s", 
resourceType))
-
-               Eventually(func() string {
-                       hryaml, err := s.GetResourceYaml(resourceType, 
resourceName)
-                       Expect(err).NotTo(HaveOccurred(), fmt.Sprintf("getting 
%s yaml", resourceType))
-                       return hryaml
-               }).WithTimeout(8*time.Second).ProbeEvery(2*time.Second).
-                       Should(
-                               SatisfyAll(
-                                       ContainSubstring(`status: "True"`),
-                                       
ContainSubstring(fmt.Sprintf("observedGeneration: %d", observedGeneration)),
-                               ),
-                               fmt.Sprintf("checking %s condition status", 
resourceType),
-                       )
-               time.Sleep(3 * time.Second)
-       }
-
        var (
                gatewayClassName string
        )
@@ -176,43 +157,40 @@ spec:
                Expect(gwyaml).To(ContainSubstring("message: the gateway has 
been accepted by the apisix-ingress-controller"), "checking Gateway condition 
message")
        })
 
-       AfterEach(func() {
-               By("Clean up resources")
-               _ = s.DeleteResourceFromString(fmt.Sprintf(httpRouteForTest, 
"apisix"))
-               _ = s.DeleteResourceFromString(fmt.Sprintf(gatewayWithProxy, 
gatewayClassName))
-               _ = 
s.DeleteResourceFromString(fmt.Sprintf(gatewayProxyWithEnabledPlugin, 
s.Deployer.GetAdminEndpoint(), s.AdminKey()))
-       })
-
        Context("Test Gateway with enabled GatewayProxy plugin", func() {
                It("Should apply plugin configuration when enabled", func() {
                        By("Create HTTPRoute for Gateway with GatewayProxy")
-                       resourceApplied("HTTPRoute", "test-route", 
fmt.Sprintf(httpRouteForTest, "apisix"), 1)
+                       s.ResourceApplied("HTTPRoute", "test-route", 
fmt.Sprintf(httpRouteForTest, "apisix"), 1)
 
                        By("Check if the plugin is applied")
-                       resp := s.NewAPISIXClient().
-                               GET("/get").
-                               WithHost("example.com").
-                               Expect().
-                               Status(200)
-
-                       resp.Header("X-Proxy-Test").IsEqual("enabled")
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/get",
+                               Host:   "example.com",
+                               Checks: []scaffold.ResponseCheckFunc{
+                                       scaffold.WithExpectedStatus(200),
+                                       
scaffold.WithExpectedHeader("X-Proxy-Test", "enabled"),
+                               },
+                       })
 
                        By("Update GatewayProxy with disabled plugin")
                        err := 
s.CreateResourceFromString(fmt.Sprintf(gatewayProxyWithDisabledPlugin, 
s.Deployer.GetAdminEndpoint(), s.AdminKey()))
                        Expect(err).NotTo(HaveOccurred(), "updating 
GatewayProxy with disabled plugin")
-                       time.Sleep(5 * time.Second)
 
                        By("Create HTTPRoute for Gateway with GatewayProxy")
-                       resourceApplied("HTTPRoute", "test-route", 
fmt.Sprintf(httpRouteForTest, "apisix"), 1)
+                       s.ResourceApplied("HTTPRoute", "test-route", 
fmt.Sprintf(httpRouteForTest, "apisix"), 1)
 
                        By("Check if the plugin is not applied")
-                       resp = s.NewAPISIXClient().
-                               GET("/get").
-                               WithHost("example.com").
-                               Expect().
-                               Status(200)
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/get",
+                               Host:   "example.com",
+                               Checks: []scaffold.ResponseCheckFunc{
+                                       scaffold.WithExpectedStatus(200),
+                                       
scaffold.WithExpectedHeader("X-Proxy-Test", ""),
+                               },
+                       })
 
-                       resp.Header("X-Proxy-Test").IsEmpty()
                })
        })
 
@@ -238,20 +216,19 @@ spec:
                        By("Update GatewayProxy with invalid endpoint")
                        err := 
s.CreateResourceFromString(fmt.Sprintf(gatewayProxyWithInvalidEndpoint, 
s.Deployer.GetAdminEndpoint(), s.AdminKey()))
                        Expect(err).NotTo(HaveOccurred(), "creating 
GatewayProxy with enabled plugin")
-                       time.Sleep(5 * time.Second)
 
                        By("Create HTTPRoute")
-                       resourceApplied("HTTPRoute", "test-route", 
fmt.Sprintf(httpRouteForTest, "apisix"), 1)
-
-                       expectRequest := func() bool {
-                               resp := s.NewAPISIXClient().
-                                       GET("/get").
-                                       WithHost("example.com").
-                                       Expect().Raw()
-                               return resp.StatusCode == 200 && 
resp.Header.Get("X-Proxy-Test") == ""
-                       }
-
-                       Eventually(expectRequest).WithTimeout(8 * 
time.Second).ProbeEvery(time.Second).Should(BeTrue())
+                       s.ResourceApplied("HTTPRoute", "test-route", 
fmt.Sprintf(httpRouteForTest, "apisix"), 1)
+
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/get",
+                               Host:   "example.com",
+                               Checks: []scaffold.ResponseCheckFunc{
+                                       scaffold.WithExpectedStatus(200),
+                                       
scaffold.WithExpectedHeader("X-Proxy-Test", ""),
+                               },
+                       })
                })
        })
 
@@ -311,12 +288,10 @@ spec:
                        err := 
s.CreateResourceFromString(gatewayProxyWithValidProvider)
                        Expect(err).NotTo(HaveOccurred(), "creating 
GatewayProxy with valid provider")
 
-                       Eventually(func() string {
-                               gpYaml, err := 
s.GetResourceYaml("GatewayProxy", "apisix-proxy-config")
-                               Expect(err).NotTo(HaveOccurred(), "getting 
GatewayProxy yaml")
+                       s.RetryAssertion(func() string {
+                               gpYaml, _ := s.GetResourceYaml("GatewayProxy", 
"apisix-proxy-config")
                                return gpYaml
-                       }).WithTimeout(8*time.Second).ProbeEvery(2*time.Second).
-                               
Should(ContainSubstring(`"type":"ControlPlane"`), "checking GatewayProxy is 
applied")
+                       }).Should(ContainSubstring(`"type":"ControlPlane"`), 
"checking GatewayProxy is applied")
                })
        })
 })
diff --git a/test/e2e/gatewayapi/httproute.go b/test/e2e/gatewayapi/httproute.go
index a634447e..daba664e 100644
--- a/test/e2e/gatewayapi/httproute.go
+++ b/test/e2e/gatewayapi/httproute.go
@@ -24,7 +24,6 @@ import (
        "strings"
        "time"
 
-       "github.com/gruntwork-io/terratest/modules/retry"
        . "github.com/onsi/ginkgo/v2"
        . "github.com/onsi/gomega"
        "github.com/pkg/errors"
@@ -112,86 +111,80 @@ spec:
       name: apisix-proxy-config
 `
 
-       var ResourceApplied = func(resourType, resourceName, resourceRaw 
string, observedGeneration int) {
-               Expect(s.CreateResourceFromString(resourceRaw)).
-                       NotTo(HaveOccurred(), fmt.Sprintf("creating %s", 
resourType))
-
-               Eventually(func() string {
-                       hryaml, err := s.GetResourceYaml(resourType, 
resourceName)
-                       Expect(err).NotTo(HaveOccurred(), fmt.Sprintf("getting 
%s yaml", resourType))
-                       return hryaml
-               }, "8s", "2s").
-                       Should(
-                               SatisfyAll(
-                                       ContainSubstring(`status: "True"`),
-                                       
ContainSubstring(fmt.Sprintf("observedGeneration: %d", observedGeneration)),
-                               ),
-                               fmt.Sprintf("checking %s condition status", 
resourType),
-                       )
-               time.Sleep(5 * time.Second)
-       }
-
        var beforeEachHTTP = func() {
-               By("create GatewayProxy")
-               err := s.CreateResourceFromString(getGatewayProxySpec())
-               Expect(err).NotTo(HaveOccurred(), "creating GatewayProxy")
-               time.Sleep(5 * time.Second)
-
-               By("create GatewayClass")
-               gatewayClassName := fmt.Sprintf("apisix-%d", time.Now().Unix())
-               err = 
s.CreateResourceFromStringWithNamespace(fmt.Sprintf(gatewayClassYaml, 
gatewayClassName, s.GetControllerName()), "")
-               Expect(err).NotTo(HaveOccurred(), "creating GatewayClass")
-               time.Sleep(5 * time.Second)
-
-               By("check GatewayClass condition")
-               gcyaml, err := s.GetResourceYaml("GatewayClass", 
gatewayClassName)
-               Expect(err).NotTo(HaveOccurred(), "getting GatewayClass yaml")
-               Expect(gcyaml).To(ContainSubstring(`status: "True"`), "checking 
GatewayClass condition status")
-               Expect(gcyaml).To(ContainSubstring("message: the gatewayclass 
has been accepted by the apisix-ingress-controller"), "checking GatewayClass 
condition message")
-
-               By("create Gateway")
-               err = 
s.CreateResourceFromStringWithNamespace(fmt.Sprintf(defaultGateway, 
gatewayClassName), s.Namespace())
-               Expect(err).NotTo(HaveOccurred(), "creating Gateway")
-               time.Sleep(5 * time.Second)
-
-               By("check Gateway condition")
-               gwyaml, err := s.GetResourceYaml("Gateway", "apisix")
-               Expect(err).NotTo(HaveOccurred(), "getting Gateway yaml")
-               Expect(gwyaml).To(ContainSubstring(`status: "True"`), "checking 
Gateway condition status")
-               Expect(gwyaml).To(ContainSubstring("message: the gateway has 
been accepted by the apisix-ingress-controller"), "checking Gateway condition 
message")
+               Expect(s.CreateResourceFromString(getGatewayProxySpec())).
+                       NotTo(HaveOccurred(), "creating GatewayProxy")
+
+               gatewayClassName := fmt.Sprintf("apisix-%d", 
time.Now().Nanosecond())
+               
Expect(s.CreateResourceFromStringWithNamespace(fmt.Sprintf(gatewayClassYaml, 
gatewayClassName, s.GetControllerName()), "")).
+                       NotTo(HaveOccurred(), "creating GatewayClass")
+
+               s.RetryAssertion(func() string {
+                       gcyaml, _ := s.GetResourceYaml("GatewayClass", 
gatewayClassName)
+                       return gcyaml
+               }).Should(
+                       And(
+                               ContainSubstring(`status: "True"`),
+                               ContainSubstring("message: the gatewayclass has 
been accepted by the apisix-ingress-controller"),
+                       ),
+                       "check GatewayClass condition",
+               )
+
+               
Expect(s.CreateResourceFromStringWithNamespace(fmt.Sprintf(defaultGateway, 
gatewayClassName), s.Namespace())).
+                       NotTo(HaveOccurred(), "creating Gateway")
+
+               s.RetryAssertion(func() string {
+                       gcyaml, _ := s.GetResourceYaml("Gateway", "apisix")
+                       return gcyaml
+               }).Should(
+                       And(
+                               ContainSubstring(`status: "True"`),
+                               ContainSubstring("message: the gateway has been 
accepted by the apisix-ingress-controlle"),
+                       ),
+                       "check Gateway condition status",
+               )
        }
 
        var beforeEachHTTPS = func() {
                By("create GatewayProxy")
                err := s.CreateResourceFromString(getGatewayProxySpec())
                Expect(err).NotTo(HaveOccurred(), "creating GatewayProxy")
-               time.Sleep(5 * time.Second)
 
                secretName := _secretName
                createSecret(s, secretName)
-               By("create GatewayClass")
-               gatewayClassName := fmt.Sprintf("apisix-%d", time.Now().Unix())
-               err = 
s.CreateResourceFromStringWithNamespace(fmt.Sprintf(gatewayClassYaml, 
gatewayClassName, s.GetControllerName()), "")
-               Expect(err).NotTo(HaveOccurred(), "creating GatewayClass")
-               time.Sleep(5 * time.Second)
 
-               By("check GatewayClass condition")
-               gcyaml, err := s.GetResourceYaml("GatewayClass", 
gatewayClassName)
-               Expect(err).NotTo(HaveOccurred(), "getting GatewayClass yaml")
-               Expect(gcyaml).To(ContainSubstring(`status: "True"`), "checking 
GatewayClass condition status")
-               Expect(gcyaml).To(ContainSubstring("message: the gatewayclass 
has been accepted by the apisix-ingress-controller"), "checking GatewayClass 
condition message")
+               By("create GatewayClass")
+               gatewayClassName := fmt.Sprintf("apisix-%d", 
time.Now().Nanosecond())
+               
Expect(s.CreateResourceFromStringWithNamespace(fmt.Sprintf(gatewayClassYaml, 
gatewayClassName, s.GetControllerName()), "")).
+                       NotTo(HaveOccurred(), "creating GatewayClass")
+
+               s.RetryAssertion(func() string {
+                       gcyaml, _ := s.GetResourceYaml("GatewayClass", 
gatewayClassName)
+                       return gcyaml
+               }).Should(
+                       And(
+                               ContainSubstring(`status: "True"`),
+                               ContainSubstring("message: the gatewayclass has 
been accepted by the apisix-ingress-controller"),
+                       ),
+                       "check GatewayClass condition",
+               )
 
                By("create Gateway")
                err = 
s.CreateResourceFromStringWithNamespace(fmt.Sprintf(defaultGatewayHTTPS, 
gatewayClassName), s.Namespace())
                Expect(err).NotTo(HaveOccurred(), "creating Gateway")
-               time.Sleep(5 * time.Second)
 
-               By("check Gateway condition")
-               gwyaml, err := s.GetResourceYaml("Gateway", "apisix")
-               Expect(err).NotTo(HaveOccurred(), "getting Gateway yaml")
-               Expect(gwyaml).To(ContainSubstring(`status: "True"`), "checking 
Gateway condition status")
-               Expect(gwyaml).To(ContainSubstring("message: the gateway has 
been accepted by the apisix-ingress-controller"), "checking Gateway condition 
message")
+               s.RetryAssertion(func() string {
+                       gcyaml, _ := s.GetResourceYaml("Gateway", "apisix")
+                       return gcyaml
+               }).Should(
+                       And(
+                               ContainSubstring(`status: "True"`),
+                               ContainSubstring("message: the gateway has been 
accepted by the apisix-ingress-controlle"),
+                       ),
+                       "check Gateway condition status",
+               )
        }
+
        Context("HTTPRoute with HTTPS Gateway", func() {
                var exactRouteByGet = `
 apiVersion: gateway.networking.k8s.io/v1
@@ -217,24 +210,26 @@ spec:
 
                It("Create/Updtea/Delete HTTPRoute", func() {
                        By("create HTTPRoute")
-                       ResourceApplied("HTTPRoute", "httpbin", 
exactRouteByGet, 1)
+                       s.ResourceApplied("HTTPRoute", "httpbin", 
exactRouteByGet, 1)
 
                        By("access dataplane to check the HTTPRoute")
-                       s.NewAPISIXHttpsClient("api6.com").
-                               GET("/get").
-                               WithHost("api6.com").
-                               Expect().
-                               Status(200)
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/get",
+                               Host:   "api6.com",
+                               Check:  scaffold.WithExpectedStatus(200),
+                       })
+
                        By("delete HTTPRoute")
                        err := s.DeleteResourceFromString(exactRouteByGet)
                        Expect(err).NotTo(HaveOccurred(), "deleting HTTPRoute")
-                       time.Sleep(5 * time.Second)
 
-                       s.NewAPISIXHttpsClient("api6.com").
-                               GET("/get").
-                               WithHost("api6.com").
-                               Expect().
-                               Status(404)
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/get",
+                               Host:   "api6.com",
+                               Check:  scaffold.WithExpectedStatus(404),
+                       })
                })
        })
 
@@ -323,12 +318,17 @@ spec:
                        additionalGatewayClassName = fmt.Sprintf("apisix-%d", 
time.Now().Unix())
                        err = 
s.CreateResourceFromStringWithNamespace(fmt.Sprintf(gatewayClassYaml, 
additionalGatewayClassName, s.GetControllerName()), "")
                        Expect(err).NotTo(HaveOccurred(), "creating additional 
GatewayClass")
-                       time.Sleep(5 * time.Second)
+
                        By("Check additional GatewayClass condition")
-                       gcyaml, err := s.GetResourceYaml("GatewayClass", 
additionalGatewayClassName)
-                       Expect(err).NotTo(HaveOccurred(), "getting additional 
GatewayClass yaml")
-                       Expect(gcyaml).To(ContainSubstring(`status: "True"`), 
"checking additional GatewayClass condition status")
-                       Expect(gcyaml).To(ContainSubstring("message: the 
gatewayclass has been accepted by the apisix-ingress-controller"), "checking 
additional GatewayClass condition message")
+                       s.RetryAssertion(func() string {
+                               gcyaml, _ := s.GetResourceYaml("GatewayClass", 
additionalGatewayClassName)
+                               return gcyaml
+                       }).Should(
+                               And(
+                                       ContainSubstring(`status: "True"`),
+                                       ContainSubstring("message: the 
gatewayclass has been accepted by the apisix-ingress-controller"),
+                               ),
+                       )
 
                        additionalGatewayProxy := 
fmt.Sprintf(additionalGatewayProxyYaml, 
s.Deployer.GetAdminEndpoint(resources.DataplaneService), resources.AdminAPIKey)
                        err = 
s.CreateResourceFromStringWithNamespace(additionalGatewayProxy, 
resources.DataplaneService.Namespace)
@@ -340,52 +340,56 @@ spec:
                                additionalSvc.Namespace,
                        )
                        Expect(err).NotTo(HaveOccurred(), "creating additional 
Gateway")
-                       time.Sleep(5 * time.Second)
                })
 
                It("HTTPRoute should be accessible through both gateways", 
func() {
                        By("Create HTTPRoute referencing both gateways")
                        multiGatewayRoute := fmt.Sprintf(multiGatewayHTTPRoute, 
s.Namespace(), additionalSvc.Namespace)
-                       ResourceApplied("HTTPRoute", "multi-gateway-route", 
multiGatewayRoute, 1)
+                       s.ResourceApplied("HTTPRoute", "multi-gateway-route", 
multiGatewayRoute, 1)
 
                        By("Access through default gateway")
-                       s.NewAPISIXClient().
-                               GET("/get").
-                               WithHost("httpbin.example").
-                               Expect().
-                               Status(http.StatusOK)
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/get",
+                               Host:   "httpbin.example",
+                               Check:  
scaffold.WithExpectedStatus(http.StatusOK),
+                       })
 
                        By("Access through additional gateway")
                        client, err := 
s.NewAPISIXClientForGateway(additionalGatewayGroupID)
                        Expect(err).NotTo(HaveOccurred(), "creating client for 
additional gateway")
 
-                       client.
-                               GET("/get").
-                               WithHost("httpbin-additional.example").
-                               Expect().
-                               Status(http.StatusOK)
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Client: client,
+                               Method: "GET",
+                               Path:   "/get",
+                               Host:   "httpbin-additional.example",
+                               Check:  
scaffold.WithExpectedStatus(http.StatusOK),
+                       })
 
                        By("Delete Additional Gateway")
                        err = 
s.DeleteResourceFromStringWithNamespace(fmt.Sprintf(additionalGateway, 
additionalGatewayClassName), additionalSvc.Namespace)
                        Expect(err).NotTo(HaveOccurred(), "deleting additional 
Gateway")
-                       time.Sleep(5 * time.Second)
 
                        By("HTTPRoute should still be accessible through 
default gateway")
-                       s.NewAPISIXClient().
-                               GET("/get").
-                               WithHost("httpbin.example").
-                               Expect().
-                               Status(http.StatusOK)
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/get",
+                               Host:   "httpbin.example",
+                               Check:  
scaffold.WithExpectedStatus(http.StatusOK),
+                       })
 
                        By("HTTPRoute should not be accessible through 
additional gateway")
                        client, err = 
s.NewAPISIXClientForGateway(additionalGatewayGroupID)
                        Expect(err).NotTo(HaveOccurred(), "creating client for 
additional gateway")
 
-                       client.
-                               GET("/get").
-                               WithHost("httpbin-additional.example").
-                               Expect().
-                               Status(http.StatusNotFound)
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Client: client,
+                               Method: "GET",
+                               Path:   "/get",
+                               Host:   "httpbin-additional.example",
+                               Check:  
scaffold.WithExpectedStatus(http.StatusNotFound),
+                       })
                })
        })
 
@@ -397,7 +401,7 @@ metadata:
   name: httpbin-external-domain
 spec:
   type: ExternalName
-  externalName: postman-echo.com
+  externalName: httpbin-service-e2e-test
 ---
 apiVersion: gateway.networking.k8s.io/v1
 kind: HTTPRoute
@@ -501,121 +505,136 @@ spec:
 
                It("Create/Update/Delete HTTPRoute", func() {
                        By("create HTTPRoute")
-                       ResourceApplied("HTTPRoute", "httpbin", 
exactRouteByGet, 1)
+                       s.ResourceApplied("HTTPRoute", "httpbin", 
exactRouteByGet, 1)
 
                        By("access dataplane to check the HTTPRoute")
-                       s.NewAPISIXClient().
-                               GET("/get").
-                               Expect().
-                               Status(404)
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/get",
+                               Check:  
scaffold.WithExpectedStatus(http.StatusNotFound),
+                       })
 
-                       s.NewAPISIXClient().
-                               GET("/get").
-                               WithHost("httpbin.example").
-                               Expect().
-                               Status(200)
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/get",
+                               Host:   "httpbin.example",
+                               Check:  
scaffold.WithExpectedStatus(http.StatusOK),
+                       })
 
-                       By("delete HTTPRoute")
-                       err := s.DeleteResourceFromString(exactRouteByGet)
-                       Expect(err).NotTo(HaveOccurred(), "deleting HTTPRoute")
-                       time.Sleep(5 * time.Second)
+                       Expect(s.DeleteResourceFromString(exactRouteByGet)).
+                               NotTo(HaveOccurred(), "deleting HTTPRoute")
 
-                       s.NewAPISIXClient().
-                               GET("/get").
-                               WithHost("httpbin.example").
-                               Expect().
-                               Status(404)
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/get",
+                               Host:   "httpbin.example",
+                               Check:  
scaffold.WithExpectedStatus(http.StatusNotFound),
+                       })
                })
 
                It("Delete Gateway after apply HTTPRoute", func() {
                        By("create HTTPRoute")
-                       ResourceApplied("HTTPRoute", "httpbin", 
exactRouteByGet, 1)
+                       s.ResourceApplied("HTTPRoute", "httpbin", 
exactRouteByGet, 1)
 
                        By("access dataplane to check the HTTPRoute")
-                       s.NewAPISIXClient().
-                               GET("/get").
-                               WithHost("httpbin.example").
-                               Expect().
-                               Status(200)
-
-                       By("delete Gateway")
-                       err := s.DeleteResource("Gateway", "apisix")
-                       Expect(err).NotTo(HaveOccurred(), "deleting Gateway")
-
-                       Eventually(func() int {
-                               return s.NewAPISIXClient().
-                                       GET("/get").
-                                       WithHost("httpbin.example").
-                                       Expect().
-                                       Raw().StatusCode
-                       }).WithTimeout(5 * 
time.Second).ProbeEvery(time.Second).Should(Equal(http.StatusNotFound))
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/get",
+                               Host:   "httpbin.example",
+                               Check:  
scaffold.WithExpectedStatus(http.StatusOK),
+                       })
+
+                       Expect(s.DeleteResource("Gateway", "apisix")).
+                               NotTo(HaveOccurred(), "deleting Gateway")
+
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/get",
+                               Host:   "httpbin.example",
+                               Check:  
scaffold.WithExpectedStatus(http.StatusNotFound),
+                       })
                })
 
                It("Proxy External Service", func() {
                        By("create HTTPRoute")
-                       ResourceApplied("HTTPRoute", "httpbin", 
httprouteWithExternalName, 1)
+                       s.ResourceApplied("HTTPRoute", "httpbin", 
httprouteWithExternalName, 1)
 
                        By("checking the external service response")
-                       s.NewAPISIXClient().
-                               GET("/get").
-                               WithHost("httpbin.external").
-                               Expect().
-                               Status(http.StatusMovedPermanently)
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/get",
+                               Host:   "httpbin.external",
+                               Check:  
scaffold.WithExpectedStatus(http.StatusOK),
+                       })
                })
 
                It("Match Port", func() {
                        By("create HTTPRoute")
-                       ResourceApplied("HTTPRoute", "httpbin", 
invalidBackendPort, 1)
+                       s.ResourceApplied("HTTPRoute", "httpbin", 
invalidBackendPort, 1)
 
-                       serviceResources, err := 
s.DefaultDataplaneResource().Service().List(context.Background())
-                       Expect(err).NotTo(HaveOccurred(), "listing services")
-                       Expect(serviceResources).To(HaveLen(1), "checking 
service length")
+                       s.RetryAssertion(func() error {
+                               serviceResources, err := 
s.DefaultDataplaneResource().Service().List(context.Background())
+                               if err != nil {
+                                       return errors.Wrap(err, "listing 
services")
+                               }
+                               if len(serviceResources) != 1 {
+                                       return fmt.Errorf("expected 1 service, 
got %d", len(serviceResources))
+                               }
 
-                       serviceResource := serviceResources[0]
-                       nodes := serviceResource.Upstream.Nodes
-                       Expect(nodes).To(HaveLen(1), "checking nodes length")
-                       Expect(nodes[0].Port).To(Equal(80))
+                               serviceResource := serviceResources[0]
+                               nodes := serviceResource.Upstream.Nodes
+                               if len(nodes) != 1 {
+                                       return fmt.Errorf("expected 1 node, got 
%d", len(nodes))
+                               }
+                               if nodes[0].Port != 80 {
+                                       return fmt.Errorf("expected node port 
80, got %d", nodes[0].Port)
+                               }
+                               return nil
+                       }).Should(Succeed(), "checking service port")
                })
 
                It("Delete HTTPRoute during restart", func() {
                        By("create HTTPRoute httpbin")
-                       ResourceApplied("HTTPRoute", "httpbin", 
exactRouteByGet, 1)
+                       s.ResourceApplied("HTTPRoute", "httpbin", 
exactRouteByGet, 1)
 
                        By("create HTTPRoute httpbin2")
-                       ResourceApplied("HTTPRoute", "httpbin2", 
exactRouteByGet2, 1)
+                       s.ResourceApplied("HTTPRoute", "httpbin2", 
exactRouteByGet2, 1)
 
-                       s.NewAPISIXClient().
-                               GET("/get").
-                               WithHost("httpbin.example").
-                               Expect().
-                               Status(200)
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/get",
+                               Host:   "httpbin.example",
+                               Check:  
scaffold.WithExpectedStatus(http.StatusOK),
+                       })
 
-                       s.NewAPISIXClient().
-                               GET("/get").
-                               WithHost("httpbin2.example").
-                               Expect().
-                               Status(200)
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/get",
+                               Host:   "httpbin2.example",
+                               Check:  
scaffold.WithExpectedStatus(http.StatusOK),
+                       })
 
                        s.Deployer.ScaleIngress(0)
 
-                       By("delete HTTPRoute httpbin2")
-                       err := s.DeleteResource("HTTPRoute", "httpbin2")
-                       Expect(err).NotTo(HaveOccurred(), "deleting HTTPRoute 
httpbin2")
+                       Expect(s.DeleteResource("HTTPRoute", "httpbin2")).
+                               NotTo(HaveOccurred(), "deleting HTTPRoute 
httpbin2")
 
                        s.Deployer.ScaleIngress(1)
-                       time.Sleep(1 * time.Minute)
-
-                       s.NewAPISIXClient().
-                               GET("/get").
-                               WithHost("httpbin.example").
-                               Expect().
-                               Status(200)
-
-                       s.NewAPISIXClient().
-                               GET("/get").
-                               WithHost("httpbin2.example").
-                               Expect().
-                               Status(404)
+
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method:  "GET",
+                               Path:    "/get",
+                               Host:    "httpbin.example",
+                               Timeout: 1 * time.Minute,
+                               Check:   
scaffold.WithExpectedStatus(http.StatusOK),
+                       })
+
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/get",
+                               Host:   "httpbin2.example",
+                               Check:  
scaffold.WithExpectedStatus(http.StatusNotFound),
+                       })
                })
        })
 
@@ -736,92 +755,106 @@ spec:
 
                It("HTTPRoute Exact Match", func() {
                        By("create HTTPRoute")
-                       ResourceApplied("HTTPRoute", "httpbin", 
exactRouteByGet, 1)
+                       s.ResourceApplied("HTTPRoute", "httpbin", 
exactRouteByGet, 1)
 
                        By("access daataplane to check the HTTPRoute")
-                       s.NewAPISIXClient().
-                               GET("/get").
-                               WithHost("httpbin.example").
-                               Expect().
-                               Status(200)
-
-                       s.NewAPISIXClient().
-                               GET("/get/xxx").
-                               WithHost("httpbin.example").
-                               Expect().
-                               Status(404)
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/get",
+                               Host:   "httpbin.example",
+                               Check:  
scaffold.WithExpectedStatus(http.StatusOK),
+                       })
+
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/get/xxx",
+                               Host:   "httpbin.example",
+                               Check:  
scaffold.WithExpectedStatus(http.StatusNotFound),
+                       })
                })
 
                It("HTTPRoute Prefix Match", func() {
                        By("create HTTPRoute")
-                       ResourceApplied("HTTPRoute", "httpbin", 
prefixRouteByStatus, 1)
+                       s.ResourceApplied("HTTPRoute", "httpbin", 
prefixRouteByStatus, 1)
 
                        By("access daataplane to check the HTTPRoute")
-                       s.NewAPISIXClient().
-                               GET("/status/200").
-                               WithHost("httpbin.example").
-                               Expect().
-                               Status(200)
-
-                       s.NewAPISIXClient().
-                               GET("/status/201").
-                               WithHost("httpbin.example").
-                               Expect().
-                               Status(201)
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/status/200",
+                               Host:   "httpbin.example",
+                               Check:  
scaffold.WithExpectedStatus(http.StatusOK),
+                       })
+
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/status/201",
+                               Host:   "httpbin.example",
+                               Check:  
scaffold.WithExpectedStatus(http.StatusCreated),
+                       })
                })
 
                It("HTTPRoute Method Match", func() {
                        By("create HTTPRoute")
-                       ResourceApplied("HTTPRoute", "httpbin", 
methodRouteGETAndDELETEByAnything, 1)
+                       s.ResourceApplied("HTTPRoute", "httpbin", 
methodRouteGETAndDELETEByAnything, 1)
 
                        By("access daataplane to check the HTTPRoute")
-                       s.NewAPISIXClient().
-                               GET("/anything").
-                               WithHost("httpbin.example").
-                               Expect().
-                               Status(200)
-
-                       s.NewAPISIXClient().
-                               DELETE("/anything").
-                               WithHost("httpbin.example").
-                               Expect().
-                               Status(200)
-
-                       s.NewAPISIXClient().
-                               POST("/anything").
-                               WithHost("httpbin.example").
-                               Expect().
-                               Status(404)
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/anything",
+                               Host:   "httpbin.example",
+                               Check:  
scaffold.WithExpectedStatus(http.StatusOK),
+                       })
+
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "DELETE",
+                               Path:   "/anything",
+                               Host:   "httpbin.example",
+                               Check:  
scaffold.WithExpectedStatus(http.StatusOK),
+                       })
+
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "POST",
+                               Path:   "/anything",
+                               Host:   "httpbin.example",
+                               Check:  
scaffold.WithExpectedStatus(http.StatusNotFound),
+                       })
                })
 
                It("HTTPRoute Vars Match", func() {
                        By("create HTTPRoute")
-                       ResourceApplied("HTTPRoute", "httpbin", varsRoute, 1)
+                       s.ResourceApplied("HTTPRoute", "httpbin", varsRoute, 1)
 
                        By("access dataplane to check the HTTPRoute")
-                       s.NewAPISIXClient().
-                               GET("/get").
-                               WithHost("httpbin.example").
-                               Expect().
-                               Status(http.StatusNotFound)
-
-                       s.NewAPISIXClient().
-                               GET("/get").
-                               WithHost("httpbin.example").
-                               WithHeader("X-Route-Name", "httpbin").
-                               Expect().
-                               Status(http.StatusOK)
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/get",
+                               Host:   "httpbin.example",
+                               Check:  
scaffold.WithExpectedStatus(http.StatusNotFound),
+                       })
+
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/get",
+                               Host:   "httpbin.example",
+                               Headers: map[string]string{
+                                       "X-Route-Name": "httpbin",
+                               },
+                               Check: 
scaffold.WithExpectedStatus(http.StatusOK),
+                       })
                })
 
                It("HTTPRoutePolicy in effect", func() {
                        By("create HTTPRoute")
                        s.ApplyHTTPRoute(types.NamespacedName{Namespace: 
s.Namespace(), Name: "httpbin"}, varsRoute)
-                       request := func() int {
-                               return s.NewAPISIXClient().GET("/get").
-                                       
WithHost("httpbin.example").WithHeader("X-Route-Name", "httpbin").
-                                       Expect().Raw().StatusCode
-                       }
-                       Eventually(request).WithTimeout(5 * 
time.Second).ProbeEvery(time.Second).Should(Equal(http.StatusOK))
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/get",
+                               Host:   "httpbin.example",
+                               Headers: map[string]string{
+                                       "X-Route-Name": "httpbin",
+                               },
+                               Check: 
scaffold.WithExpectedStatus(http.StatusOK),
+                       })
 
                        By("create HTTPRoutePolicy")
                        s.ApplyHTTPRoutePolicy(
@@ -831,16 +864,29 @@ spec:
                        )
 
                        By("access dataplane to check the HTTPRoutePolicy")
-                       Eventually(request).WithTimeout(5 * 
time.Second).ProbeEvery(time.Second).Should(Equal(http.StatusNotFound))
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/get",
+                               Host:   "httpbin.example",
+                               Headers: map[string]string{
+                                       "X-Route-Name": "httpbin",
+                               },
+                               Check: 
scaffold.WithExpectedStatus(http.StatusNotFound),
+                       })
 
-                       s.NewAPISIXClient().
-                               GET("/get").
-                               WithHost("httpbin.example").
-                               WithHeader("X-Route-Name", "httpbin").
-                               WithHeader("X-HRP-Name", "http-route-policy-0").
-                               WithQuery("hrp_name", "http-route-policy-0").
-                               Expect().
-                               Status(http.StatusOK)
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/get",
+                               Host:   "httpbin.example",
+                               Query: map[string]any{
+                                       "hrp_name": "http-route-policy-0",
+                               },
+                               Headers: map[string]string{
+                                       "X-Route-Name": "httpbin",
+                                       "X-HRP-Name":   "http-route-policy-0",
+                               },
+                               Check: 
scaffold.WithExpectedStatus(http.StatusOK),
+                       })
 
                        By("update HTTPRoutePolicy")
                        const changedHTTPRoutePolicy = `
@@ -867,24 +913,31 @@ spec:
                        )
 
                        // use the old vars cannot match any route
-                       Eventually(func() int {
-                               return s.NewAPISIXClient().
-                                       GET("/get").
-                                       WithHost("httpbin.example").
-                                       WithHeader("X-Route-Name", "httpbin").
-                                       WithHeader("X-HRP-Name", 
"http-route-policy-0").
-                                       WithQuery("hrp_name", 
"http-route-policy-0").
-                                       Expect().Raw().StatusCode
-                       }).WithTimeout(8 * 
time.Second).ProbeEvery(time.Second).Should(Equal(http.StatusNotFound))
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/get",
+                               Host:   "httpbin.example",
+                               Query: map[string]any{
+                                       "hrp_name": "http-route-policy-0",
+                               },
+                               Headers: map[string]string{
+                                       "X-Route-Name": "httpbin",
+                                       "X-HRP-Name":   "http-route-policy-0",
+                               },
+                               Check: 
scaffold.WithExpectedStatus(http.StatusNotFound),
+                       })
 
                        // use the new vars can match the route
-                       s.NewAPISIXClient().
-                               GET("/get").
-                               WithHost("httpbin.example").
-                               WithHeader("X-Route-Name", "httpbin").
-                               WithHeader("X-HRP-Name", "new-hrp-name").
-                               Expect().
-                               Status(http.StatusOK)
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/get",
+                               Host:   "httpbin.example",
+                               Headers: map[string]string{
+                                       "X-Route-Name": "httpbin",
+                                       "X-HRP-Name":   "new-hrp-name",
+                               },
+                               Check: 
scaffold.WithExpectedStatus(http.StatusOK),
+                       })
 
                        By("delete the HTTPRoutePolicy")
                        err := s.DeleteResource("HTTPRoutePolicy", 
"http-route-policy-0")
@@ -894,18 +947,15 @@ spec:
                                return err.Error()
                        }).WithTimeout(8 * 
time.Second).ProbeEvery(time.Second).Should(ContainSubstring(`httproutepolicies.apisix.apache.org
 "http-route-policy-0" not found`))
                        // access the route without additional vars should be OK
-                       message := retry.DoWithRetry(s.GinkgoT, "", 10, 
time.Second, func() (string, error) {
-                               statusCode := s.NewAPISIXClient().
-                                       GET("/get").
-                                       WithHost("httpbin.example").
-                                       WithHeader("X-Route-Name", "httpbin").
-                                       Expect().Raw().StatusCode
-                               if statusCode != http.StatusOK {
-                                       return "", errors.Errorf("unexpected 
status code: %v", statusCode)
-                               }
-                               return "request OK", nil
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/get",
+                               Host:   "httpbin.example",
+                               Headers: map[string]string{
+                                       "X-Route-Name": "httpbin",
+                               },
+                               Check: 
scaffold.WithExpectedStatus(http.StatusOK),
                        })
-                       s.Logf(message)
                })
 
                It("HTTPRoutePolicy conflicts", func() {
@@ -1007,13 +1057,15 @@ spec:
                        }
 
                        // assert that conflict policies are not in effect
-                       Eventually(func() int {
-                               return s.NewAPISIXClient().
-                                       GET("/get").
-                                       WithHost("httpbin.example").
-                                       WithHeader("X-Route-Name", "httpbin").
-                                       Expect().Raw().StatusCode
-                       }).WithTimeout(8 * 
time.Second).ProbeEvery(time.Second).Should(Equal(http.StatusOK))
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/get",
+                               Host:   "httpbin.example",
+                               Headers: map[string]string{
+                                       "X-Route-Name": "httpbin",
+                               },
+                               Check: 
scaffold.WithExpectedStatus(http.StatusOK),
+                       })
 
                        By("delete HTTPRoutePolicies")
                        err := s.DeleteResource("HTTPRoutePolicy", 
"http-route-policy-2")
@@ -1029,13 +1081,15 @@ spec:
                                        },
                                )
                        }
-                       Eventually(func() int {
-                               return s.NewAPISIXClient().
-                                       GET("/get").
-                                       WithHost("httpbin.example").
-                                       WithHeader("X-Route-Name", "httpbin").
-                                       Expect().Raw().StatusCode
-                       }).WithTimeout(8 * 
time.Second).ProbeEvery(time.Second).Should(Equal(http.StatusNotFound))
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/get",
+                               Host:   "httpbin.example",
+                               Headers: map[string]string{
+                                       "X-Route-Name": "httpbin",
+                               },
+                               Check: 
scaffold.WithExpectedStatus(http.StatusNotFound),
+                       })
 
                        By("update HTTPRoutePolicy")
                        err = 
s.CreateResourceFromString(httpRoutePolicy1Priority20)
@@ -1058,13 +1112,16 @@ spec:
                                        },
                                )
                        }
-                       Eventually(func() int {
-                               return s.NewAPISIXClient().
-                                       GET("/get").
-                                       WithHost("httpbin.example").
-                                       WithHeader("X-Route-Name", "httpbin").
-                                       Expect().Raw().StatusCode
-                       }).WithTimeout(8 * 
time.Second).ProbeEvery(time.Second).Should(Equal(http.StatusOK))
+
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/get",
+                               Host:   "httpbin.example",
+                               Headers: map[string]string{
+                                       "X-Route-Name": "httpbin",
+                               },
+                               Check: 
scaffold.WithExpectedStatus(http.StatusOK),
+                       })
                })
 
                It("HTTPRoutePolicy status changes on HTTPRoute deleting", 
func() {
@@ -1079,42 +1136,49 @@ spec:
                        )
 
                        By("access dataplane to check the HTTPRoutePolicy")
-                       Eventually(func() int {
-                               return s.NewAPISIXClient().
-                                       GET("/get").
-                                       WithHost("httpbin.example").
-                                       WithHeader("X-Route-Name", "httpbin").
-                                       Expect().Raw().StatusCode
-                       }).WithTimeout(8 * 
time.Second).ProbeEvery(time.Second).Should(Equal(http.StatusNotFound))
-
-                       s.NewAPISIXClient().
-                               GET("/get").
-                               WithHost("httpbin.example").
-                               WithHeader("X-Route-Name", "httpbin").
-                               WithHeader("X-HRP-Name", "http-route-policy-0").
-                               WithQuery("hrp_name", "http-route-policy-0").
-                               Expect().
-                               Status(http.StatusOK)
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/get",
+                               Host:   "httpbin.example",
+                               Headers: map[string]string{
+                                       "X-Route-Name": "httpbin",
+                               },
+                               Check: 
scaffold.WithExpectedStatus(http.StatusNotFound),
+                       })
+
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/get",
+                               Host:   "httpbin.example",
+                               Query: map[string]any{
+                                       "hrp_name": "http-route-policy-0",
+                               },
+                               Headers: map[string]string{
+                                       "X-Route-Name": "httpbin",
+                                       "X-HRP-Name":   "http-route-policy-0",
+                               },
+                               Check: 
scaffold.WithExpectedStatus(http.StatusOK),
+                       })
 
                        By("delete the HTTPRoute, assert the HTTPRoutePolicy's 
status will be changed")
-                       err := s.DeleteResource("HTTPRoute", "httpbin")
-                       Expect(err).NotTo(HaveOccurred(), "deleting HTTPRoute")
-                       message := retry.DoWithRetry(s.GinkgoT, "request the 
deleted route", 10, time.Second, func() (string, error) {
-                               statusCode := s.NewAPISIXClient().
-                                       GET("/get").
-                                       WithHost("httpbin.example").
-                                       WithHeader("X-Route-Name", "httpbin").
-                                       WithHeader("X-HRP-Name", 
"http-route-policy-0").
-                                       WithQuery("hrp_name", 
"http-route-policy-0").
-                                       Expect().Raw().StatusCode
-                               if statusCode != http.StatusNotFound {
-                                       return "", errors.Errorf("unexpected 
status code: %v", statusCode)
-                               }
-                               return "the route is deleted", nil
+                       Expect(s.DeleteResource("HTTPRoute", "httpbin")).
+                               NotTo(HaveOccurred(), "deleting HTTPRoute")
+
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/get",
+                               Host:   "httpbin.example",
+                               Query: map[string]any{
+                                       "hrp_name": "http-route-policy-0",
+                               },
+                               Headers: map[string]string{
+                                       "X-Route-Name": "httpbin",
+                                       "X-HRP-Name":   "http-route-policy-0",
+                               },
+                               Check: 
scaffold.WithExpectedStatus(http.StatusNotFound),
                        })
-                       s.Logf(message)
 
-                       err = 
framework.PollUntilHTTPRoutePolicyHaveStatus(s.K8sClient, 8*time.Second, 
types.NamespacedName{Namespace: s.Namespace(), Name: "http-route-policy-0"},
+                       err := 
framework.PollUntilHTTPRoutePolicyHaveStatus(s.K8sClient, 8*time.Second, 
types.NamespacedName{Namespace: s.Namespace(), Name: "http-route-policy-0"},
                                func(hrp *v1alpha1.HTTPRoutePolicy) bool {
                                        return len(hrp.Status.Ancestors) == 0
                                },
@@ -1335,63 +1399,73 @@ spec:
 
                It("HTTPRoute RequestHeaderModifier", func() {
                        By("create HTTPRoute")
-                       ResourceApplied("HTTPRoute", "httpbin", 
reqHeaderModifyByHeaders, 1)
+                       s.ResourceApplied("HTTPRoute", "httpbin", 
reqHeaderModifyByHeaders, 1)
 
                        By("access daataplane to check the HTTPRoute")
-                       respExp := s.NewAPISIXClient().
-                               GET("/headers").
-                               WithHost("httpbin.example").
-                               WithHeader("X-Req-Add", "test").
-                               WithHeader("X-Req-Removed", "test").
-                               WithHeader("X-Req-Set", "test").
-                               Expect()
-
-                       respExp.Status(200)
-                       respExp.Body().
-                               Contains(`"X-Req-Add": "test,add"`).
-                               Contains(`"X-Req-Set": "set"`).
-                               NotContains(`"X-Req-Removed": "remove"`)
-
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/headers",
+                               Host:   "httpbin.example",
+                               Headers: map[string]string{
+                                       "X-Req-Add":     "test",
+                                       "X-Req-Removed": "test",
+                                       "X-Req-Set":     "test",
+                               },
+                               Checks: []scaffold.ResponseCheckFunc{
+                                       
scaffold.WithExpectedStatus(http.StatusOK),
+                                       
scaffold.WithExpectedBodyContains(`"X-Req-Add": "test,add"`, `"X-Req-Set": 
"set"`),
+                                       
scaffold.WithExpectedBodyNotContains(`"X-Req-Removed": "remove"`),
+                               },
+                       })
                })
 
                It("HTTPRoute ResponseHeaderModifier", func() {
                        By("create HTTPRoute")
-                       ResourceApplied("HTTPRoute", "httpbin", 
respHeaderModifyByHeaders, 1)
+                       s.ResourceApplied("HTTPRoute", "httpbin", 
respHeaderModifyByHeaders, 1)
 
                        By("access daataplane to check the HTTPRoute")
-                       respExp := s.NewAPISIXClient().
-                               GET("/headers").
-                               WithHost("httpbin.example").
-                               Expect()
-
-                       respExp.Status(200)
-                       respExp.Header("X-Resp-Add").IsEqual("add")
-                       respExp.Header("X-Resp-Set").IsEqual("set")
-                       respExp.Header("Server").IsEmpty()
-                       respExp.Body().
-                               NotContains(`"X-Resp-Add": "add"`).
-                               NotContains(`"X-Resp-Set": "set"`).
-                               NotContains(`"Server"`)
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/headers",
+                               Host:   "httpbin.example",
+                               Checks: []scaffold.ResponseCheckFunc{
+                                       
scaffold.WithExpectedStatus(http.StatusOK),
+                                       
scaffold.WithExpectedHeaders(map[string]string{
+                                               "X-Resp-Add": "add",
+                                               "X-Resp-Set": "set",
+                                               "Server":     "",
+                                       }),
+                                       
scaffold.WithExpectedBodyNotContains(`"X-Resp-Add": "add"`, `"X-Resp-Set": 
"set"`, `"Server"`),
+                               },
+                       })
                })
 
                It("HTTPRoute RequestRedirect", func() {
                        By("create HTTPRoute")
-                       ResourceApplied("HTTPRoute", "httpbin", 
httpsRedirectByHeaders, 1)
-
-                       s.NewAPISIXClient().GET("/headers").
-                               WithHeader("Host", "httpbin.example").
-                               Expect().
-                               Status(http.StatusFound).
-                               
Header("Location").IsEqual("https://httpbin.example:9443/headers";)
+                       s.ResourceApplied("HTTPRoute", "httpbin", 
httpsRedirectByHeaders, 1)
+
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/headers",
+                               Host:   "httpbin.example",
+                               Checks: []scaffold.ResponseCheckFunc{
+                                       
scaffold.WithExpectedStatus(http.StatusFound),
+                                       scaffold.WithExpectedHeader("Location", 
"https://httpbin.example:9443/headers";),
+                               },
+                       })
 
                        By("update HTTPRoute")
-                       ResourceApplied("HTTPRoute", "httpbin", 
hostnameRedirectByHeaders, 2)
-
-                       s.NewAPISIXClient().GET("/headers").
-                               WithHeader("Host", "httpbin.example").
-                               Expect().
-                               Status(http.StatusMovedPermanently).
-                               
Header("Location").IsEqual("http://httpbin.org/headers";)
+                       s.ResourceApplied("HTTPRoute", "httpbin", 
hostnameRedirectByHeaders, 2)
+
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/headers",
+                               Host:   "httpbin.example",
+                               Checks: []scaffold.ResponseCheckFunc{
+                                       
scaffold.WithExpectedStatus(http.StatusMovedPermanently),
+                                       scaffold.WithExpectedHeader("Location", 
"http://httpbin.org/headers";),
+                               },
+                       })
                })
 
                It("HTTPRoute RequestMirror", func() {
@@ -1453,78 +1527,89 @@ spec:
     - name: httpbin-service-e2e-test
       port: 80
 `
-                       ResourceApplied("HTTPRoute", "httpbin", echoRoute, 1)
-
-                       time.Sleep(time.Second * 6)
-
-                       _ = s.NewAPISIXClient().GET("/headers").
-                               WithHeader("Host", "httpbin.example").
-                               Expect().
-                               Status(http.StatusOK)
+                       s.ResourceApplied("HTTPRoute", "httpbin", echoRoute, 1)
 
-                       echoLogs := s.GetDeploymentLogs("echo")
-                       Expect(echoLogs).To(ContainSubstring("GET /headers"))
+                       s.RetryAssertion(func() string {
+                               resp := 
s.NewAPISIXClient().GET("/headers").WithHost("httpbin.example").Expect().Raw()
+                               if resp.StatusCode != http.StatusOK {
+                                       return fmt.Sprintf("expected status OK, 
got %d", resp.StatusCode)
+                               }
+                               return s.GetDeploymentLogs("echo")
+                       }).WithTimeout(2 * 
time.Minute).Should(ContainSubstring("GET /headers"))
                })
 
                It("HTTPRoute URLRewrite with ReplaceFullPath And Hostname", 
func() {
                        By("create HTTPRoute")
-                       ResourceApplied("HTTPRoute", "httpbin", 
replaceFullPathAndHost, 1)
+                       s.ResourceApplied("HTTPRoute", "httpbin", 
replaceFullPathAndHost, 1)
 
                        By("/replace/201 should be rewritten to /headers")
-                       s.NewAPISIXClient().GET("/replace/201").
-                               WithHeader("Host", "httpbin.example").
-                               Expect().
-                               Status(http.StatusOK).
-                               Body().
-                               Contains("replace.example.org")
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/replace/201",
+                               Host:   "httpbin.example",
+                               Checks: []scaffold.ResponseCheckFunc{
+                                       
scaffold.WithExpectedStatus(http.StatusOK),
+                                       
scaffold.WithExpectedBodyContains("replace.example.org"),
+                               },
+                       })
 
                        By("/replace/500 should be rewritten to /headers")
-                       s.NewAPISIXClient().GET("/replace/500").
-                               WithHeader("Host", "httpbin.example").
-                               Expect().
-                               Status(http.StatusOK).
-                               Body().
-                               Contains("replace.example.org")
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/replace/500",
+                               Host:   "httpbin.example",
+                               Checks: []scaffold.ResponseCheckFunc{
+                                       
scaffold.WithExpectedStatus(http.StatusOK),
+                                       
scaffold.WithExpectedBodyContains("replace.example.org"),
+                               },
+                       })
                })
 
                It("HTTPRoute URLRewrite with ReplacePrefixMatch", func() {
                        By("create HTTPRoute")
-                       ResourceApplied("HTTPRoute", "httpbin", 
replacePrefixMatch, 1)
+                       s.ResourceApplied("HTTPRoute", "httpbin", 
replacePrefixMatch, 1)
 
                        By("/replace/201 should be rewritten to /status/201")
-                       s.NewAPISIXClient().GET("/replace/201").
-                               WithHeader("Host", "httpbin.example").
-                               Expect().
-                               Status(http.StatusCreated)
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/replace/201",
+                               Host:   "httpbin.example",
+                               Check:  
scaffold.WithExpectedStatus(http.StatusCreated),
+                       })
 
                        By("/replace/500 should be rewritten to /status/500")
-                       s.NewAPISIXClient().GET("/replace/500").
-                               WithHeader("Host", "httpbin.example").
-                               Expect().
-                               Status(http.StatusInternalServerError)
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/replace/500",
+                               Host:   "httpbin.example",
+                               Checks: []scaffold.ResponseCheckFunc{
+                                       
scaffold.WithExpectedStatus(http.StatusInternalServerError),
+                               },
+                       })
                })
 
                It("HTTPRoute ExtensionRef", func() {
                        By("create HTTPRoute")
-                       err := s.CreateResourceFromString(echoPlugin)
-                       Expect(err).NotTo(HaveOccurred(), "creating 
PluginConfig")
-                       ResourceApplied("HTTPRoute", "httpbin", 
extensionRefEchoPlugin, 1)
-
-                       s.NewAPISIXClient().GET("/get").
-                               WithHeader("Host", "httpbin.example").
-                               Expect().
-                               Body().
-                               Contains("Hello, World!!")
-
-                       err = s.CreateResourceFromString(echoPluginUpdated)
-                       Expect(err).NotTo(HaveOccurred(), "updating 
PluginConfig")
-                       time.Sleep(5 * time.Second)
+                       Expect(s.CreateResourceFromString(echoPlugin)).
+                               NotTo(HaveOccurred(), "creating PluginConfig")
+                       s.ResourceApplied("HTTPRoute", "httpbin", 
extensionRefEchoPlugin, 1)
+
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/get",
+                               Host:   "httpbin.example",
+                               Check:  
scaffold.WithExpectedBodyContains("Hello, World!!"),
+                       })
 
-                       s.NewAPISIXClient().GET("/get").
-                               WithHeader("Host", "httpbin.example").
-                               Expect().
-                               Body().
-                               Contains("Updated")
+                       Expect(s.CreateResourceFromString(echoPluginUpdated)).
+                               NotTo(HaveOccurred(), "updating PluginConfig")
+
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/get",
+                               Host:   "httpbin.example",
+                               Check:  
scaffold.WithExpectedBodyContains("Updated"),
+                       })
                })
        })
 
@@ -1583,45 +1668,58 @@ spec:
                        })
                })
                It("HTTPRoute Canary", func() {
-                       ResourceApplied("HTTPRoute", "httpbin", sameWeiht, 1)
+                       s.ResourceApplied("HTTPRoute", "httpbin", sameWeiht, 1)
+                       time.Sleep(5 * time.Second)
 
-                       var (
-                               hitNginxCnt   = 0
-                               hitHttpbinCnt = 0
-                       )
-                       for i := 0; i < 100; i++ {
-                               body := s.NewAPISIXClient().GET("/get").
-                                       WithHeader("Host", "httpbin.example").
-                                       Expect().
-                                       Status(http.StatusOK).
-                                       Body().Raw()
-
-                               if strings.Contains(body, "Hello") {
-                                       hitNginxCnt++
-                               } else {
-                                       hitHttpbinCnt++
+                       s.RetryAssertion(func() int {
+                               var (
+                                       hitNginxCnt   = 0
+                                       hitHttpbinCnt = 0
+                               )
+                               for i := 0; i < 20; i++ {
+                                       resp := s.NewAPISIXClient().GET("/get").
+                                               WithHeader("Host", 
"httpbin.example").
+                                               Expect()
+                                       body := resp.Body().Raw()
+                                       status := resp.Raw().StatusCode
+                                       if status != http.StatusOK {
+                                               return -100
+                                       }
+
+                                       if strings.Contains(body, "Hello") {
+                                               hitNginxCnt++
+                                       } else {
+                                               hitHttpbinCnt++
+                                       }
                                }
-                       }
-                       Expect(hitNginxCnt - 
hitHttpbinCnt).To(BeNumerically("~", 0, 2))
-
-                       ResourceApplied("HTTPRoute", "httpbin", oneWeiht, 2)
-
-                       hitNginxCnt = 0
-                       hitHttpbinCnt = 0
-                       for i := 0; i < 100; i++ {
-                               body := s.NewAPISIXClient().GET("/get").
-                                       WithHeader("Host", "httpbin.example").
-                                       Expect().
-                                       Status(http.StatusOK).
-                                       Body().Raw()
-
-                               if strings.Contains(body, "Hello") {
-                                       hitNginxCnt++
-                               } else {
-                                       hitHttpbinCnt++
+                               return hitNginxCnt - hitHttpbinCnt
+                       }).WithTimeout(2 * 
time.Minute).Should(BeNumerically("~", 0, 2))
+
+                       s.ResourceApplied("HTTPRoute", "httpbin", oneWeiht, 2)
+
+                       s.RetryAssertion(func() int {
+                               var (
+                                       hitNginxCnt   = 0
+                                       hitHttpbinCnt = 0
+                               )
+                               for i := 0; i < 20; i++ {
+                                       resp := s.NewAPISIXClient().GET("/get").
+                                               WithHeader("Host", 
"httpbin.example").
+                                               Expect()
+                                       body := resp.Body().Raw()
+                                       status := resp.Raw().StatusCode
+                                       if status != http.StatusOK {
+                                               return -100
+                                       }
+
+                                       if strings.Contains(body, "Hello") {
+                                               hitNginxCnt++
+                                       } else {
+                                               hitHttpbinCnt++
+                                       }
                                }
-                       }
-                       Expect(hitHttpbinCnt - hitNginxCnt).To(Equal(100))
+                               return hitHttpbinCnt - hitNginxCnt
+                       }).WithTimeout(2 * time.Minute).Should(Equal(20))
                })
        })
 
@@ -1669,14 +1767,15 @@ spec:
 
                It("Should sync HTTPRoute when GatewayProxy is updated", func() 
{
                        By("create HTTPRoute")
-                       ResourceApplied("HTTPRoute", "httpbin", 
exactRouteByGet, 1)
+                       s.ResourceApplied("HTTPRoute", "httpbin", 
exactRouteByGet, 1)
 
                        By("verify HTTPRoute works")
-                       s.NewAPISIXClient().
-                               GET("/get").
-                               WithHost("httpbin.example").
-                               Expect().
-                               Status(200)
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Method: "GET",
+                               Path:   "/get",
+                               Host:   "httpbin.example",
+                               Check:  
scaffold.WithExpectedStatus(http.StatusOK),
+                       })
 
                        By("create additional gateway group to get new admin 
key")
                        var err error
@@ -1690,24 +1789,27 @@ spec:
                        Expect(err).NotTo(HaveOccurred(), "creating APISIX 
client for additional gateway group")
 
                        By("HTTPRoute not found for additional gateway group")
-                       client.
-                               GET("/get").
-                               WithHost("httpbin.example").
-                               Expect().
-                               Status(404)
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Client: client,
+                               Method: "GET",
+                               Path:   "/get",
+                               Host:   "httpbin.example",
+                               Check:  
scaffold.WithExpectedStatus(http.StatusNotFound),
+                       })
 
                        By("update GatewayProxy with new admin key")
                        updatedProxy := fmt.Sprintf(updatedGatewayProxy, 
s.Deployer.GetAdminEndpoint(resources.DataplaneService), resources.AdminAPIKey)
                        err = s.CreateResourceFromString(updatedProxy)
                        Expect(err).NotTo(HaveOccurred(), "updating 
GatewayProxy")
-                       time.Sleep(5 * time.Second)
 
                        By("verify HTTPRoute works for additional gateway 
group")
-                       client.
-                               GET("/get").
-                               WithHost("httpbin.example").
-                               Expect().
-                               Status(200)
+                       s.RequestAssert(&scaffold.RequestAssert{
+                               Client: client,
+                               Method: "GET",
+                               Path:   "/get",
+                               Host:   "httpbin.example",
+                               Check:  
scaffold.WithExpectedStatus(http.StatusOK),
+                       })
                })
        })
 
@@ -1721,7 +1823,7 @@ metadata:
   name: httpbin-external-domain
 spec:
   type: ExternalName
-  externalName: httpbin.org
+  externalName: httpbin-service-e2e-test
 ---
 apiVersion: v1
 kind: Service
@@ -1744,7 +1846,7 @@ spec:
     kind: Service
     group: ""
   passHost: node
-  scheme: https
+  scheme: http
 ---
 apiVersion: gateway.networking.k8s.io/v1
 kind: HTTPRoute
@@ -1760,10 +1862,10 @@ spec:
         value: /headers
     backendRefs:
     - name: httpbin-external-domain
-      port: 443
+      port: 80
       weight: 1
     - name: mockapi7-external-domain
-      port: 443
+      port: 80
       weight: 1
 `
 
@@ -1778,22 +1880,14 @@ spec:
                        totalRequests := 20
 
                        for i := 0; i < totalRequests; i++ {
-                               resp := 
s.NewAPISIXClient().GET("/headers").Expect().Status(http.StatusOK)
-
-                               // Parse JSON response to get the Host header
-                               var responseBody map[string]any
-                               resp.JSON().Decode(&responseBody)
-
-                               if headers, ok := 
responseBody["headers"].(map[string]any); ok {
-                                       var host string
-                                       if host, ok = headers["Host"].(string); 
!ok {
-                                               host, ok = 
headers["host"].(string)
-                                       }
-                                       if ok && host != "" {
-                                               upstreamHosts[host]++
-                                       }
-                                       Expect(ok).To(BeTrue(), "Host header 
should be present")
-                                       
Expect(host).Should(Or(Equal("httpbin.org"), Equal("mock.api7.ai")))
+                               statusCode := 
s.NewAPISIXClient().GET("/headers").Expect().Raw().StatusCode
+                               Expect(statusCode).To(Or(Equal(http.StatusOK), 
Equal(http.StatusMovedPermanently)))
+
+                               switch statusCode {
+                               case http.StatusOK:
+                                       
upstreamHosts["httpbin-service-e2e-test"]++
+                               case http.StatusMovedPermanently:
+                                       upstreamHosts["mock.api7.ai"]++
                                }
                                time.Sleep(100 * time.Millisecond) // Small 
delay between requests
                        }
@@ -1806,16 +1900,4 @@ spec:
                        }
                })
        })
-
-       /*
-               Context("HTTPRoute Status Updated", func() {
-               })
-
-               Context("HTTPRoute ParentRefs With Multiple Gateway", func() {
-               })
-
-
-               Context("HTTPRoute BackendRefs Discovery", func() {
-               })
-       */
 })
diff --git a/test/e2e/ingress/ingress.go b/test/e2e/ingress/ingress.go
index 0c85c532..6b537b98 100644
--- a/test/e2e/ingress/ingress.go
+++ b/test/e2e/ingress/ingress.go
@@ -186,7 +186,7 @@ metadata:
   name: httpbin-external-domain
 spec:
   type: ExternalName
-  externalName: postman-echo.com
+  externalName: httpbin-service-e2e-test
 ---
 apiVersion: networking.k8s.io/v1
 kind: Ingress
@@ -253,7 +253,7 @@ spec:
                                GET("/get").
                                WithHost("httpbin.external").
                                Expect().
-                               Status(http.StatusMovedPermanently)
+                               Status(http.StatusOK)
                })
 
                It("Delete Ingress during restart", func() {
@@ -283,7 +283,7 @@ spec:
                                GET("/get").
                                WithHost("httpbin.external").
                                Expect().
-                               Status(http.StatusMovedPermanently)
+                               Status(http.StatusOK)
 
                        s.NewAPISIXClient().
                                GET("/get").
@@ -304,7 +304,7 @@ spec:
                                GET("/get").
                                WithHost("httpbin.external").
                                Expect().
-                               Status(http.StatusMovedPermanently)
+                               Status(http.StatusOK)
 
                        s.NewAPISIXClient().
                                GET("/get").
diff --git a/test/e2e/scaffold/apisix_deployer.go 
b/test/e2e/scaffold/apisix_deployer.go
index b6fe7feb..e3e8b90a 100644
--- a/test/e2e/scaffold/apisix_deployer.go
+++ b/test/e2e/scaffold/apisix_deployer.go
@@ -53,7 +53,7 @@ type APISIXDeployer struct {
        adminTunnel *k8s.Tunnel
 }
 
-func NewAPISIXDeployer(s *Scaffold) *APISIXDeployer {
+func NewAPISIXDeployer(s *Scaffold) Deployer {
        return &APISIXDeployer{
                Scaffold: s,
        }
@@ -66,7 +66,7 @@ func (s *APISIXDeployer) BeforeEach() {
                Namespace:  s.namespace,
        }
        if s.opts.ControllerName == "" {
-               s.opts.ControllerName = fmt.Sprintf("%s/%d", 
DefaultControllerName, time.Now().Nanosecond())
+               s.opts.ControllerName = fmt.Sprintf("%s/%s", 
DefaultControllerName, s.namespace)
        }
        s.finalizers = nil
        if s.label == nil {
@@ -130,14 +130,14 @@ func (s *APISIXDeployer) AfterEach() {
                Expect(err).NotTo(HaveOccurred(), "cleaning up additional 
gateway")
        }
 
-       // if the test case is successful, just delete namespace
-       err := k8s.DeleteNamespaceE(s.t, s.kubectlOptions, s.namespace)
-       Expect(err).NotTo(HaveOccurred(), "deleting namespace "+s.namespace)
-
        for i := len(s.finalizers) - 1; i >= 0; i-- {
                runWithRecover(s.finalizers[i])
        }
 
+       // if the test case is successful, just delete namespace
+       err := k8s.DeleteNamespaceE(s.t, s.kubectlOptions, s.namespace)
+       Expect(err).NotTo(HaveOccurred(), "deleting namespace "+s.namespace)
+
        // Wait for a while to prevent the worker node being overwhelming
        // (new cases will be run).
        time.Sleep(3 * time.Second)
diff --git a/test/e2e/scaffold/assertion.go b/test/e2e/scaffold/assertion.go
new file mode 100644
index 00000000..c8946f2f
--- /dev/null
+++ b/test/e2e/scaffold/assertion.go
@@ -0,0 +1,252 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package scaffold
+
+import (
+       "fmt"
+       "net/http"
+       "strings"
+       "time"
+
+       "github.com/gavv/httpexpect/v2"
+       . "github.com/onsi/gomega" //nolint:staticcheck
+       "github.com/onsi/gomega/types"
+)
+
+const (
+       DefaultTimeout  = 12 * time.Second
+       DefaultInterval = 1 * time.Second
+)
+
+type ResponseCheckFunc func(*HTTPResponse) error
+
+type HTTPResponse struct {
+       *http.Response
+
+       Body string
+}
+
+type BasicAuth struct {
+       Username string
+       Password string
+}
+
+type RequestAssert struct {
+       Client    *httpexpect.Expect
+       Method    string
+       Path      string
+       Host      string
+       Query     map[string]any
+       Headers   map[string]string
+       Body      []byte
+       BasicAuth *BasicAuth
+
+       Timeout  time.Duration
+       Interval time.Duration
+
+       Check  ResponseCheckFunc
+       Checks []ResponseCheckFunc
+}
+
+func (c *RequestAssert) request(method, path string, body []byte) 
*httpexpect.Request {
+       switch strings.ToUpper(method) {
+       case "GET":
+               return c.Client.GET(path)
+       case "POST":
+               return c.Client.POST(path).WithBytes(body)
+       case "PUT":
+               return c.Client.PUT(path).WithBytes(body)
+       case "DELETE":
+               return c.Client.DELETE(path)
+       case "PATCH":
+               return c.Client.PATCH(path).WithBytes(body)
+       default:
+               panic("unsupported method: " + method)
+       }
+}
+
+func (c *RequestAssert) WithCheck(check ResponseCheckFunc) *RequestAssert {
+       c.Checks = append(c.Checks, check)
+       return c
+}
+
+func (c *RequestAssert) WithChecks(checks ...ResponseCheckFunc) *RequestAssert 
{
+       c.Checks = append(c.Checks, checks...)
+       return c
+}
+
+func (c *RequestAssert) SetChecks(checks ...ResponseCheckFunc) *RequestAssert {
+       c.Checks = checks
+       return c
+}
+
+func WithExpectedStatus(status int) ResponseCheckFunc {
+       return func(resp *HTTPResponse) error {
+               if resp.StatusCode != status {
+                       return fmt.Errorf("expected %d, but got %d", status, 
resp.StatusCode)
+               }
+               return nil
+       }
+}
+
+func WithExpectedBodyContains(expectedBodyList ...string) ResponseCheckFunc {
+       return func(resp *HTTPResponse) error {
+               for _, body := range expectedBodyList {
+                       if !strings.Contains(resp.Body, body) {
+                               return fmt.Errorf("expected body to contain %q, 
but got %q", body, resp.Body)
+                       }
+               }
+               return nil
+       }
+}
+
+func WithExpectedBodyNotContains(unexpectedBodyList ...string) 
ResponseCheckFunc {
+       return func(resp *HTTPResponse) error {
+               for _, unexpectedBody := range unexpectedBodyList {
+                       if strings.Contains(resp.Body, unexpectedBody) {
+                               return fmt.Errorf("expected body not to contain 
%q, but got %q", unexpectedBody, resp.Body)
+                       }
+               }
+               return nil
+       }
+}
+
+func WithExpectedHeader(key, value string) ResponseCheckFunc {
+       return func(resp *HTTPResponse) error {
+               if resp.Header.Get(key) != value {
+                       return fmt.Errorf("expected header %q to be %q, but got 
%q",
+                               key, value, resp.Header.Get(key))
+               }
+               return nil
+       }
+}
+
+func WithExpectedHeaders(expectedHeaders map[string]string) ResponseCheckFunc {
+       return func(resp *HTTPResponse) error {
+               for key, expectedValue := range expectedHeaders {
+                       actualValue := resp.Header.Get(key)
+                       if actualValue != expectedValue {
+                               return fmt.Errorf("expected header %q to be %q, 
but got %q",
+                                       key, expectedValue, actualValue)
+                       }
+               }
+               return nil
+       }
+}
+
+func (s *Scaffold) RequestAssert(r *RequestAssert) bool {
+       if r.Client == nil {
+               r.Client = s.NewAPISIXClient()
+       }
+       if r.Method == "" {
+               if len(r.Body) > 0 {
+                       r.Method = "POST"
+               } else {
+                       r.Method = "GET"
+               }
+       }
+       if r.Timeout == 0 {
+               r.Timeout = DefaultTimeout
+       }
+       if r.Interval == 0 {
+               r.Interval = DefaultInterval
+       }
+       if r.Check == nil && len(r.Checks) == 0 {
+               r.Check = WithExpectedStatus(http.StatusOK)
+       } else if r.Check != nil {
+               r.Checks = append(r.Checks, r.Check)
+       }
+
+       return EventuallyWithOffset(1, func() error {
+               req := r.request(r.Method, r.Path, r.Body)
+               if len(r.Headers) > 0 {
+                       req = req.WithHeaders(r.Headers)
+               }
+               if r.Host != "" {
+                       req = req.WithHost(r.Host)
+               }
+               if len(r.Query) > 0 {
+                       for key, value := range r.Query {
+                               req = req.WithQuery(key, value)
+                       }
+               }
+               if r.BasicAuth != nil {
+                       req = req.WithBasicAuth(r.BasicAuth.Username, 
r.BasicAuth.Password)
+               }
+               expResp := req.Expect()
+
+               resp := &HTTPResponse{
+                       Response: expResp.Raw(),
+                       Body:     expResp.Body().Raw(),
+               }
+
+               for _, check := range r.Checks {
+                       if err := check(resp); err != nil {
+                               return fmt.Errorf("response check failed: %w", 
err)
+                       }
+               }
+               return nil
+       }).WithTimeout(r.Timeout).ProbeEvery(r.Interval).Should(Succeed())
+}
+
+// RetryAssertion provides a reusable Eventually-based assertion
+type RetryAssertion struct {
+       timeout  time.Duration
+       interval time.Duration
+
+       args        []any
+       actualOrCtx any
+}
+
+// NewRetryAssertion creates a RetryAssertion with defaults
+func (s *Scaffold) RetryAssertion(actualOrCtx any, args ...any) 
*RetryAssertion {
+       return &RetryAssertion{
+               timeout:     DefaultTimeout,
+               interval:    DefaultInterval,
+               args:        args,
+               actualOrCtx: actualOrCtx,
+       }
+}
+
+// WithTimeout sets the timeout
+func (r *RetryAssertion) WithTimeout(timeout time.Duration) *RetryAssertion {
+       r.timeout = timeout
+       return r
+}
+
+// WithInterval sets the polling interval
+func (r *RetryAssertion) WithInterval(interval time.Duration) *RetryAssertion {
+       r.interval = interval
+       return r
+}
+
+// Should runs the Eventually assertion with the given matcher
+func (r *RetryAssertion) Should(matcher types.GomegaMatcher, 
optionalDescription ...any) bool {
+       return EventuallyWithOffset(1, r.actualOrCtx, r.args...).
+               WithTimeout(r.timeout).
+               ProbeEvery(r.interval).
+               Should(matcher, optionalDescription...)
+}
+
+// ShouldNot runs the Eventually assertion with the given matcher
+func (r *RetryAssertion) ShouldNot(matcher types.GomegaMatcher, 
optionalDescription ...any) bool {
+       return EventuallyWithOffset(1, r.actualOrCtx, r.args...).
+               WithTimeout(r.timeout).
+               ProbeEvery(r.interval).
+               ShouldNot(matcher, optionalDescription...)
+}
diff --git a/test/e2e/scaffold/k8s.go b/test/e2e/scaffold/k8s.go
index 890552c7..0612d4c0 100644
--- a/test/e2e/scaffold/k8s.go
+++ b/test/e2e/scaffold/k8s.go
@@ -184,19 +184,17 @@ func (s *Scaffold) ResourceApplied(resourType, 
resourceName, resourceRaw string,
        Expect(s.CreateResourceFromString(resourceRaw)).
                NotTo(HaveOccurred(), fmt.Sprintf("creating %s", resourType))
 
-       Eventually(func() string {
+       s.RetryAssertion(func() string {
                hryaml, err := s.GetResourceYaml(resourType, resourceName)
                Expect(err).NotTo(HaveOccurred(), fmt.Sprintf("getting %s 
yaml", resourType))
                return hryaml
-       }).WithTimeout(8*time.Second).ProbeEvery(2*time.Second).
-               Should(
-                       SatisfyAll(
-                               ContainSubstring(`status: "True"`),
-                               
ContainSubstring(fmt.Sprintf("observedGeneration: %d", observedGeneration)),
-                       ),
-                       fmt.Sprintf("checking %s condition status", resourType),
-               )
-       time.Sleep(3 * time.Second)
+       }).Should(
+               SatisfyAll(
+                       ContainSubstring(`status: "True"`),
+                       ContainSubstring(fmt.Sprintf("observedGeneration: %d", 
observedGeneration)),
+               ),
+               fmt.Sprintf("checking %s condition status", resourType),
+       )
 }
 
 func (s *Scaffold) ApplyDefaultGatewayResource(

Reply via email to