fix: resolve readiness WaitReady blocking for 5 minutes on startup#407
fix: resolve readiness WaitReady blocking for 5 minutes on startup#407AlinsRan wants to merge 53 commits into
Conversation
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add ProviderTypeAPISIXStandalone skip guards to all ADC validation e2e tests so they are skipped on non-standalone backends that do not expose the /apisix/admin/configs/validate endpoint - Replace the 'duplicate credentials' consumer tests with invalid jwt-auth algorithm tests; APISIX validates plugin config schema in isolation and cannot detect cross-consumer key uniqueness, but it does reject unknown enum values (e.g. algorithm: INVALID_ALGO) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Revert CI/deployment changes that are not needed for the webhook ADC validation feature and work fine on master: - Revert docker login steps back to docker/login-action@v3 in all workflow files (apisix-conformance-test, apisix-e2e-test, conformance-test, e2e-test, e2e-test-k8s) - Revert e2e-test-k8s.yml kind cluster setup to original approach - Revert e2e-test-k8s.yml postgres image mirror preloading - Revert spell-checker.yml to use wget-based misspell install - Revert Makefile pull-infra-images to simple docker pull (keep jmalloc/echo-server removed since it is now built locally) - Revert Makefile ADC binary download to simple curl | tar Retained changes required for the feature: - build-e2e-echo-server-image target - kind-load-images dependency on build-e2e-echo-server-image Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The 'ApisixTls and Ingress with same certificate but different hosts' test was consistently failing due to two compounding issues: 1. Control-plane / data-plane propagation delay: the control plane confirms the api7.com SSL object, but APISIX data plane may not have loaded it yet when the HTTPS request is made. 2. Non-retryable Eventually block: NewAPISIXHttpsClient uses GinkgoT() as the httpexpect reporter. On TLS error, httpexpect calls GinkgoT().Fatalf() -> runtime.Goexit(), which exits the goroutine immediately. gomega's Eventually cannot retry because the goroutine is gone. Fix: replace the raw Eventually+httpexpect blocks with s.RequestAssert, which already exists in the scaffold and uses ErrorReporter (stores errors instead of calling FailNow). Transient TLS errors are now returned as retryable errors, letting Eventually poll until the data plane is fully ready. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
When ApisixTls references secrets that do not exist yet, the webhook should warn (not deny). The ADC validator calls PrepareApisixTlsForValidation which in turn calls validateSecret, which returns NotFound and causes admission denial - breaking the original warn-on-missing-secret behavior. Fix: skip ADC validation when collectWarnings already detected missing secrets. The translator cannot load cert/key material in that case, so ADC validation would always fail anyway. The existing warnings are sufficient to inform the user. Also fix initErr fail-open: a validator initialization failure should allow admission (return warnings, nil) rather than hard-deny every write. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- fail-open on ADC validator init error in ApisixRoute, ApisixConsumer, Consumer webhooks - redact TLS payload from logs in buildAPISIXValidateRequest (log bodyLen only) - set TLS MinVersion to 1.2 in newBackendHTTPClient - return JSON unmarshal error in extractCredentialKey instead of swallowing it - default supportsEndpointSlice to false in PrepareApisixRouteForValidation - rename waitExponentialBackoffWithTimeout to waitConstantIntervalWithTimeout (Factor=1 is constant, not exponential) - restore WaitPodsAvailable timeout to 2 minutes to match original behavior - add cache-propagation sleep after recreating TLS Secret in e2e test - tighten expectAdmissionDenied to assert NotFound error Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Returning the unmarshal error would deny Consumers with malformed inline credential config, and also deny new Consumers when any existing Consumer has a malformed credential (because we'd fail while reading the existing consumer's keys). Log at debug level and skip the credential from duplicate detection instead, preserving the original fail-open behaviour. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Restore original warn-on-missing-ref behavior for existing tests, and add update-path coverage for all four webhook resource types. Changes: - apisixconsumer_webhook.go: add missing 'if len(warnings) > 0' guard to skip ADC validation when references are missing (aligns with ApisixTls/ ApisixRoute pattern) - apisixconsumer.go: restore 'should warn on missing authentication secrets' (was incorrectly changed to deny) - apisixtls.go: restore 'should warn on missing TLS secrets' (was incorrectly changed to deny; webhook already admits when warnings exist) - apisixroute.go: add 'should reject route update that fails ADC validation' - apisixconsumer.go: add 'should reject consumer update that fails ADC validation' - apisixtls.go: add 'should reject TLS update with invalid certificate material' - consumer.go: add 'should reject consumer update that fails ADC validation' Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Remove unused messageSubstrings variadic parameter from expectAdmissionDenied - Add nolint:dupl to warn-on-missing It blocks (structurally similar but different YAML) - Fix gofmt trailing newline in consumer_webhook.go Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add expectUpdateDenied helper: UPDATE denials leave the resource intact so the resource-not-found check in expectAdmissionDenied is wrong for update scenarios - Use expectUpdateDenied in all four UPDATE It blocks - Redesign ApisixTls UPDATE test: change the secret reference in the spec instead of swapping secret content; spec must actually change to trigger the UPDATE admission webhook Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Both apisix and apisix-standalone backends now support /apisix/admin/configs/validate via ADC PR api7/adc#434. The CI uses apache/apisix:dev and ghcr.io/api7/adc:dev which include this support, so the skip guard is no longer needed. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Previously the apisix-standalone backend bypassed the ADC server and called APISIX's /apisix/admin/configs/validate directly. With api7/adc#440, the ADC server now exposes a /validate endpoint (same input format as /sync) that handles both apisix-standalone and apisix backends uniformly. Changes: - Remove apisix-standalone special-case in runHTTPValidateForSingleServer; all backends now call ADC server POST /validate - Fix ADCValidateResult.ErrorMessage JSON tag: errorMessage -> message to match the ADC server response format from api7/adc#440 - Remove buildAPISIXValidateRequest, apisixValidateRequest, newBackendHTTPClient, buildAPISIXValidatePayload and helpers - Update unit tests accordingly Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The ADC server registers PUT /validate (not POST), matching the same HTTP method used for PUT /sync. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
APISIX validates plugin schemas but not credential schemas via /validate. Switch the invalid Consumer config in e2e tests to use spec.plugins with jwt-auth algorithm: INVALID_ALGO, which triggers proper ADC validation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace hkccr.ccs.tencentyun.com/api7-dev/ with ghcr.io/api7/ across all workflow files, Makefile, and test framework configs. Update the private registry login step to use GHCR with GITHUB_TOKEN instead of Tencent Cloud credentials. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Remove leftover 'Login to Registry' steps from e2e-test.yml and conformance-test.yml - Add permissions (contents: read, packages: read) to all three workflow jobs to ensure GHCR pulls work under restricted token settings Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…sumer skip logic - Remove redundant failurePolicy=fail from all 4 webhook marker lines, keeping only failurePolicy=Ignore (kubebuilder uses the last occurrence, having both was ambiguous and wrong) - Fix ApisixConsumer ValidateCreate/ValidateUpdate: remove the unnecessary len(warnings) > 0 guard that skipped ADC validation when secrets were missing. Unlike ApisixTls, missing secretRef in ApisixConsumer merely skips that credential in translation; the consumer can still be validated by ADC. Only skip when initErr is non-nil (ADC client init failed). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
When auth secret references are missing, the ApisixConsumer translator cannot produce valid auth credentials — ADC validation would always fail in that state, causing admission denial instead of a warning. Restore the guard so that missing secrets produce a warning but still admit the resource. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…Consumer webhook Separate the initErr and warnings checks for better observability: log the init error explicitly when skipping ADC validation due to a failed ADC client initialization. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Backport fixes from upstream apache/apisix-ingress-controller#2663. Root cause: readiness.Start() is asynchronous. If a controller's reconcile loop calls Done() before Start() finishes registering resources, Done() finds no state entry and returns early. The resource is never removed from state, causing WaitReady to block until the 5-minute timeout. Changes: - Done() now waits for Start() to complete (<-r.started) before operating on state, eliminating the race condition - WaitReady() returns false on timeout instead of true (semantic fix: timed-out != ready) - Remove unnecessary mutex in registerState() since Done() is now guaranteed to run after Start() closes r.started - Add log statements for easier debugging of readiness lifecycle
|
Foo Bar seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account. You have signed the CLA already but the status is still pending? Let us recheck it. |
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (27)
📝 WalkthroughWalkthroughThis PR introduces ADC (Admission Control) validation for APISIX resources through webhooks, enabling validation-as-you-create for routes, consumers, and TLS configurations. Concurrently, it migrates container image registries from Tencent to GitHub Container Registry across CI/CD workflows and test infrastructure. ChangesADC Validation Feature
Docker Registry Migration
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Pull request overview
This PR addresses startup readiness deadlocks by synchronizing readiness state registration with reconcile completion signaling, and extends admission webhooks to perform ADC-backed validation (plus related e2e/CI updates).
Changes:
- Fix readiness startup race by gating
Done()onStart()completion and correctingWaitReady()timeout semantics. - Add ADC admission validation for multiple resources (Consumer/ApisixConsumer/ApisixRoute/ApisixTls), including new ADC
/validateclient path and error types. - Update e2e coverage and CI/manifests to use GHCR-hosted images and add webhook validation scenarios.
Reviewed changes
Copilot reviewed 27 out of 27 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
internal/manager/readiness/manager.go |
Gate Done() on started, adjust logging, and fix WaitReady() timeout return value. |
internal/webhook/v1/adc_validation.go |
Introduce shared ADC admission validator that translates resources and calls ADC validate. |
internal/webhook/v1/adc_validation_test.go |
Add test helpers for mocking ADC /validate endpoint and gatewayproxy/ingressclass wiring. |
internal/controller/webhook_validation.go |
Add controller helpers to prepare resources for translation/validation in admission context. |
internal/adc/client/executor.go |
Add HTTP executor support for /validate requests and response parsing. |
internal/adc/client/client.go |
Add Client.Validate() orchestration across configs with aggregated validation errors. |
internal/types/error.go |
Add ADCValidationErrors types for structured validation failures. |
internal/webhook/v1/apisixroute_webhook.go |
Wire ADC validation into ApisixRoute admission (fail-open on init errors). |
internal/webhook/v1/apisixroute_webhook_test.go |
Add unit tests for ADC validation deny + fail-open behavior for ApisixRoute. |
internal/webhook/v1/apisixconsumer_webhook.go |
Wire ADC validation into ApisixConsumer admission, skipping when warnings exist. |
internal/webhook/v1/apisixconsumer_webhook_test.go |
Add unit tests asserting ADC validation denial and validate-endpoint usage. |
internal/webhook/v1/apisixtls_webhook.go |
Wire ADC validation into ApisixTls admission, skipping when secret warnings exist. |
internal/webhook/v1/apisixtls_webhook_test.go |
Add unit test covering ADC validation denial for ApisixTls. |
internal/webhook/v1/consumer_webhook.go |
Add ADC validation + duplicate key-auth detection for v1alpha1 Consumer. |
internal/webhook/v1/consumer_webhook_test.go |
Add field-indexed fake client setup and duplicate key-auth denial test. |
test/e2e/webhook/helpers.go |
Add reusable helpers for asserting admission denial vs denied update. |
test/e2e/webhook/apisixroute.go |
Add e2e cases for ADC validation denial on create/update; simplify missing-service warning test. |
test/e2e/webhook/apisixconsumer.go |
Add e2e cases for ADC validation denial on create/update for ApisixConsumer. |
test/e2e/webhook/consumer.go |
Add e2e cases for ADC validation denial on create/update for v1alpha1 Consumer. |
test/e2e/webhook/apisixtls.go |
Add e2e cases for invalid TLS material denial on create/update; use generated certs. |
test/e2e/crds/v2/tls.go |
Use RequestAssert to retry transient TLS errors instead of immediate fatal failures. |
test/e2e/framework/manifests/dp.yaml |
Switch dataplane image reference to GHCR. |
test/e2e/framework/api7_dashboard.go |
Switch dashboard/dp-manager image repositories to GHCR. |
Makefile |
Update kind image load/pull targets to GHCR image locations. |
.github/workflows/e2e-test.yml |
Add GHCR login via GITHUB_TOKEN and required permissions. |
.github/workflows/e2e-test-k8s.yml |
Add GHCR login via GITHUB_TOKEN and required permissions. |
.github/workflows/conformance-test.yml |
Switch to GHCR login and add job permissions (but see review comment re: missing contents permission). |
Comments suppressed due to low confidence (1)
.github/workflows/conformance-test.yml:46
- Job-level
permissionsoverrides the defaults. This workflow grantspackages: readandpull-requests: writebut omitscontents: read, whichactions/checkouttypically requires. Addcontents: read(or broaden appropriately) to avoid checkout failures.
runs-on: ubuntu-latest
permissions:
packages: read
pull-requests: write
steps:
- name: Checkout
uses: actions/checkout@v4
with:
submodules: recursive
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| func (r *readinessManager) Start(ctx context.Context) error { | ||
| var err error | ||
| r.startOnce.Do(func() { | ||
| for _, cfg := range r.configs { | ||
| for _, gvk := range cfg.GVKs { | ||
| uList := &unstructured.UnstructuredList{} | ||
| uList.SetGroupVersionKind(gvk) | ||
| if listErr := r.client.List(ctx, uList); listErr != nil { | ||
| err = fmt.Errorf("list %s failed: %w", gvk.String(), listErr) | ||
| return | ||
| } | ||
| var expected []k8stypes.NamespacedName | ||
| for _, item := range uList.Items { | ||
| if cfg.Filter != nil && !cfg.Filter.Match(&item) { | ||
| continue | ||
| } | ||
| expected = append(expected, k8stypes.NamespacedName{ | ||
| Namespace: item.GetNamespace(), | ||
| Name: item.GetName(), | ||
| }) | ||
| } | ||
| if len(expected) > 0 { | ||
| r.log.V(1).Info("registering readiness state", "gvk", gvk, "expected", expected) | ||
| r.log.Info("registering readiness state", "gvk", gvk, "registered_count", len(expected)) | ||
| r.log.V(1).Info("registered resources for readiness", "gvk", gvk, "resources", expected) | ||
| r.registerState(gvk, expected) | ||
| } | ||
| } | ||
| } | ||
| close(r.started) | ||
| if len(r.state) == 0 && !r.isReady.Load() { | ||
| r.isReady.Store(true) | ||
| close(r.done) | ||
| } | ||
| r.log.Info("readiness manager started") | ||
| }) | ||
| return err | ||
| } |
| r.mu.Lock() | ||
| defer r.mu.Unlock() | ||
| gvk := types.GvkOf(obj) | ||
| r.log.Info("marking resource as done", "gvk", gvk, "name", nn, "state_count", len(r.state[gvk])) |
| // 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 v1 | ||
|
|
||
| import ( | ||
| "context" | ||
| "errors" | ||
|
|
||
| "github.com/go-logr/logr" | ||
| networkingv1 "k8s.io/api/networking/v1" | ||
| "sigs.k8s.io/controller-runtime/pkg/client" | ||
|
|
||
| adctypes "github.com/apache/apisix-ingress-controller/api/adc" | ||
| v1alpha1 "github.com/apache/apisix-ingress-controller/api/v1alpha1" | ||
| apiv2 "github.com/apache/apisix-ingress-controller/api/v2" | ||
| adcclient "github.com/apache/apisix-ingress-controller/internal/adc/client" | ||
| adctranslator "github.com/apache/apisix-ingress-controller/internal/adc/translator" | ||
| "github.com/apache/apisix-ingress-controller/internal/controller" | ||
| "github.com/apache/apisix-ingress-controller/internal/controller/config" | ||
| "github.com/apache/apisix-ingress-controller/internal/controller/label" | ||
| "github.com/apache/apisix-ingress-controller/internal/provider" | ||
| internaltypes "github.com/apache/apisix-ingress-controller/internal/types" | ||
| "github.com/apache/apisix-ingress-controller/internal/utils" | ||
| ) | ||
|
|
conformance test report - apisix-standalone modeapiVersion: gateway.networking.k8s.io/v1
date: "2026-05-08T03:43:57Z"
gatewayAPIChannel: experimental
gatewayAPIVersion: v1.3.0
implementation:
contact: null
organization: APISIX
project: apisix-ingress-controller
url: https://github.com/apache/apisix-ingress-controller.git
version: v2.0.0
kind: ConformanceReport
mode: default
profiles:
- core:
result: success
statistics:
Failed: 0
Passed: 12
Skipped: 0
name: GATEWAY-GRPC
summary: Core tests succeeded.
- core:
result: partial
skippedTests:
- HTTPRouteHTTPSListener
statistics:
Failed: 0
Passed: 32
Skipped: 1
extended:
result: partial
skippedTests:
- HTTPRouteRedirectPortAndScheme
statistics:
Failed: 0
Passed: 11
Skipped: 1
supportedFeatures:
- GatewayAddressEmpty
- GatewayPort8080
- HTTPRouteBackendProtocolWebSocket
- HTTPRouteDestinationPortMatching
- HTTPRouteHostRewrite
- HTTPRouteMethodMatching
- HTTPRoutePathRewrite
- HTTPRoutePortRedirect
- HTTPRouteQueryParamMatching
- HTTPRouteRequestMirror
- HTTPRouteResponseHeaderModification
- HTTPRouteSchemeRedirect
unsupportedFeatures:
- GatewayHTTPListenerIsolation
- GatewayInfrastructurePropagation
- GatewayStaticAddresses
- HTTPRouteBackendProtocolH2C
- HTTPRouteBackendRequestHeaderModification
- HTTPRouteBackendTimeout
- HTTPRouteParentRefPort
- HTTPRoutePathRedirect
- HTTPRouteRequestMultipleMirrors
- HTTPRouteRequestPercentageMirror
- HTTPRouteRequestTimeout
name: GATEWAY-HTTP
summary: Core tests partially succeeded with 1 test skips. Extended tests partially
succeeded with 1 test skips.
- core:
result: partial
skippedTests:
- TLSRouteSimpleSameNamespace
statistics:
Failed: 0
Passed: 10
Skipped: 1
name: GATEWAY-TLS
summary: Core tests partially succeeded with 1 test skips. |
conformance test report - apisix modeapiVersion: gateway.networking.k8s.io/v1
date: "2026-05-08T03:44:00Z"
gatewayAPIChannel: experimental
gatewayAPIVersion: v1.3.0
implementation:
contact: null
organization: APISIX
project: apisix-ingress-controller
url: https://github.com/apache/apisix-ingress-controller.git
version: v2.0.0
kind: ConformanceReport
mode: default
profiles:
- core:
result: partial
skippedTests:
- TLSRouteSimpleSameNamespace
statistics:
Failed: 0
Passed: 10
Skipped: 1
name: GATEWAY-TLS
summary: Core tests partially succeeded with 1 test skips.
- core:
result: success
statistics:
Failed: 0
Passed: 12
Skipped: 0
name: GATEWAY-GRPC
summary: Core tests succeeded.
- core:
failedTests:
- HTTPRouteInvalidBackendRefUnknownKind
result: failure
skippedTests:
- HTTPRouteHTTPSListener
statistics:
Failed: 1
Passed: 31
Skipped: 1
extended:
result: partial
skippedTests:
- HTTPRouteRedirectPortAndScheme
statistics:
Failed: 0
Passed: 11
Skipped: 1
supportedFeatures:
- GatewayAddressEmpty
- GatewayPort8080
- HTTPRouteBackendProtocolWebSocket
- HTTPRouteDestinationPortMatching
- HTTPRouteHostRewrite
- HTTPRouteMethodMatching
- HTTPRoutePathRewrite
- HTTPRoutePortRedirect
- HTTPRouteQueryParamMatching
- HTTPRouteRequestMirror
- HTTPRouteResponseHeaderModification
- HTTPRouteSchemeRedirect
unsupportedFeatures:
- GatewayHTTPListenerIsolation
- GatewayInfrastructurePropagation
- GatewayStaticAddresses
- HTTPRouteBackendProtocolH2C
- HTTPRouteBackendRequestHeaderModification
- HTTPRouteBackendTimeout
- HTTPRouteParentRefPort
- HTTPRoutePathRedirect
- HTTPRouteRequestMultipleMirrors
- HTTPRouteRequestPercentageMirror
- HTTPRouteRequestTimeout
name: GATEWAY-HTTP
summary: Core tests failed with 1 test failures. Extended tests partially succeeded
with 1 test skips. |
conformance test reportapiVersion: gateway.networking.k8s.io/v1
date: "2026-05-08T04:04:48Z"
gatewayAPIChannel: experimental
gatewayAPIVersion: v1.3.0
implementation:
contact: null
organization: APISIX
project: apisix-ingress-controller
url: https://github.com/apache/apisix-ingress-controller.git
version: v2.0.0
kind: ConformanceReport
mode: default
profiles:
- core:
failedTests:
- GRPCExactMethodMatching
- GRPCRouteHeaderMatching
- GRPCRouteListenerHostnameMatching
- GatewayModifyListeners
result: failure
statistics:
Failed: 4
Passed: 8
Skipped: 0
name: GATEWAY-GRPC
summary: Core tests failed with 4 test failures.
- core:
failedTests:
- GatewayModifyListeners
result: failure
skippedTests:
- HTTPRouteHTTPSListener
statistics:
Failed: 1
Passed: 31
Skipped: 1
extended:
failedTests:
- HTTPRouteBackendProtocolWebSocket
result: failure
skippedTests:
- HTTPRouteRedirectPortAndScheme
statistics:
Failed: 1
Passed: 10
Skipped: 1
supportedFeatures:
- GatewayAddressEmpty
- GatewayPort8080
- HTTPRouteBackendProtocolWebSocket
- HTTPRouteDestinationPortMatching
- HTTPRouteHostRewrite
- HTTPRouteMethodMatching
- HTTPRoutePathRewrite
- HTTPRoutePortRedirect
- HTTPRouteQueryParamMatching
- HTTPRouteRequestMirror
- HTTPRouteResponseHeaderModification
- HTTPRouteSchemeRedirect
unsupportedFeatures:
- GatewayHTTPListenerIsolation
- GatewayInfrastructurePropagation
- GatewayStaticAddresses
- HTTPRouteBackendProtocolH2C
- HTTPRouteBackendRequestHeaderModification
- HTTPRouteBackendTimeout
- HTTPRouteParentRefPort
- HTTPRoutePathRedirect
- HTTPRouteRequestMultipleMirrors
- HTTPRouteRequestPercentageMirror
- HTTPRouteRequestTimeout
name: GATEWAY-HTTP
summary: Core tests failed with 1 test failures. Extended tests failed with 1 test
failures.
- core:
failedTests:
- GatewayModifyListeners
- TLSRouteSimpleSameNamespace
result: failure
statistics:
Failed: 2
Passed: 9
Skipped: 0
name: GATEWAY-TLS
summary: Core tests failed with 2 test failures. |
Root Cause
readiness.Start()is asynchronous. A controller's reconcile loop can callDone()beforeStart()finishes registering resources intor.state. When this happens:Done()checksr.state[gvk]— entry doesn't exist yet (race condition)Done()returns early without doing anythingStart()later registers the resource intor.stateDone()again for that resourceWaitReadyblocks until the full 5-minute timeoutChanges
Done()now blocks on<-r.startedbefore touchingr.state, ensuringStart()has finished registering all resources before anyDone()call can proceedWaitReady()returnsfalseon timeout instead oftrue— timed out ≠ readyregisterState()— safe becauseDone()is now guaranteed to run afterStart()closesr.started, soregisterState()is always called before any concurrentDone()accessTesting
go build ./...passesgo vet ./...passesSummary by CodeRabbit
Release Notes
New Features
Bug Fixes
Chores