Repository: envoyproxy/gateway
Pull request #4220 (2024-09-11 23:41:52)

[release/v1.1] cherry pick #4219
(cherry picked from commit 7cddd95dccd8b93408dc789fcdf916c482223dda)

**What type of PR is this?**
<!--
Your PR title should be descriptive, and generally start with type that contains a subsystem name with `()` if necessary 
and summary followed by a colon. format `chore/docs/api/feat/fix/refactor/style/test: summary`.
Examples:
* "docs: fix grammar error"
* "feat(translator): add new feature"
* "fix: fix xx bug"
* "chore: change ci & build tools etc"
* "api: add xxx fields in ClientTrafficPolicy"
-->

<!--
NOTE: If your PR contains any API changes (changes under `/api`), we recommend you to separate these API changes into
a new PR, and we will review the API part first. It will save you lots of implementation time if the API get accepted.
-->

**What this PR does / why we need it**:

**Which issue(s) this PR fixes**:
<!--
*Automatically closes linked issue when PR is merged.
Usage: `Fixes #<issue number>`, or `Fixes (paste link of issue)`.
-->
Fixes #


codecov[bot]: ## [Codecov](https://app.codecov.io/gh/envoyproxy/gateway/pull/4220?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy) Report
Attention: Patch coverage is `32.43243%` with `25 lines` in your changes missing coverage. Please review.
> Project coverage is 67.28%. Comparing base [(`7351b08`)](https://app.codecov.io/gh/envoyproxy/gateway/commit/7351b08150cc1b1be484291b91324c0888f2d553?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy) to head [(`92c9c39`)](https://app.codecov.io/gh/envoyproxy/gateway/commit/92c9c39b7a91258574a2f29b6b64831bf365fff5?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy).

| [Files with missing lines](https://app.codecov.io/gh/envoyproxy/gateway/pull/4220?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy) | Patch % | Lines |
|---|---|---|
| [internal/provider/kubernetes/status.go](https://app.codecov.io/gh/envoyproxy/gateway/pull/4220?src=pr&el=tree&filepath=internal%2Fprovider%2Fkubernetes%2Fstatus.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy#diff-aW50ZXJuYWwvcHJvdmlkZXIva3ViZXJuZXRlcy9zdGF0dXMuZ28=) | 18.18% | [17 Missing and 1 partial :warning: ](https://app.codecov.io/gh/envoyproxy/gateway/pull/4220?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy) |
| [internal/gatewayapi/runner/runner.go](https://app.codecov.io/gh/envoyproxy/gateway/pull/4220?src=pr&el=tree&filepath=internal%2Fgatewayapi%2Frunner%2Frunner.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy#diff-aW50ZXJuYWwvZ2F0ZXdheWFwaS9ydW5uZXIvcnVubmVyLmdv) | 61.53% | [5 Missing :warning: ](https://app.codecov.io/gh/envoyproxy/gateway/pull/4220?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy) |
| [internal/gatewayapi/status/backend.go](https://app.codecov.io/gh/envoyproxy/gateway/pull/4220?src=pr&el=tree&filepath=internal%2Fgatewayapi%2Fstatus%2Fbackend.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy#diff-aW50ZXJuYWwvZ2F0ZXdheWFwaS9zdGF0dXMvYmFja2VuZC5nbw==) | 0.00% | [2 Missing :warning: ](https://app.codecov.io/gh/envoyproxy/gateway/pull/4220?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy) |

<details><summary>Additional details and impacted files</summary>


```diff
@@               Coverage Diff                @@
##           release/v1.1    #4220      +/-   ##
================================================
- Coverage         67.33%   67.28%   -0.05%     
================================================
  Files               183      183              
  Lines             22480    22515      +35     
================================================
+ Hits              15137    15150      +13     
- Misses             6250     6272      +22     
  Partials           1093     1093              
```

</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/envoyproxy/gateway/pull/4220?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy).

guydc: /retest

Patch:
diff --git a/internal/gatewayapi/runner/runner.go b/internal/gatewayapi/runner/runner.go
index 8b9b57fc8..9762f06df 100644
--- a/internal/gatewayapi/runner/runner.go
+++ b/internal/gatewayapi/runner/runner.go
@@ -264,6 +264,13 @@ func (r *Runner) subscribeAndTranslate(ctx context.Context) {
 					}
 					delete(statusesToDelete.EnvoyExtensionPolicyStatusKeys, key)
 				}
+				for _, backend := range result.Backends {
+					key := utils.NamespacedName(backend)
+					if !(reflect.ValueOf(backend.Status).IsZero()) {
+						r.ProviderResources.BackendStatuses.Store(key, &backend.Status)
+					}
+					delete(statusesToDelete.BackendStatusKeys, key)
+				}
 				for _, extServerPolicy := range result.ExtensionServerPolicies {
 					extServerPolicy := extServerPolicy
 					key := message.NamespacedNameAndGVK{
@@ -325,6 +332,8 @@ type StatusesToDelete struct {
 	SecurityPolicyStatusKeys        map[types.NamespacedName]bool
 	EnvoyExtensionPolicyStatusKeys  map[types.NamespacedName]bool
 	ExtensionServerPolicyStatusKeys map[message.NamespacedNameAndGVK]bool
+
+	BackendStatusKeys map[types.NamespacedName]bool
 }
 
 func (r *Runner) getAllStatuses() *StatusesToDelete {
@@ -343,6 +352,8 @@ func (r *Runner) getAllStatuses() *StatusesToDelete {
 		BackendTLSPolicyStatusKeys:      make(map[types.NamespacedName]bool),
 		EnvoyExtensionPolicyStatusKeys:  make(map[types.NamespacedName]bool),
 		ExtensionServerPolicyStatusKeys: make(map[message.NamespacedNameAndGVK]bool),
+
+		BackendStatusKeys: make(map[types.NamespacedName]bool),
 	}
 
 	// Get current status keys
@@ -380,6 +391,9 @@ func (r *Runner) getAllStatuses() *StatusesToDelete {
 	for key := range r.ProviderResources.EnvoyExtensionPolicyStatuses.LoadAll() {
 		ds.EnvoyExtensionPolicyStatusKeys[key] = true
 	}
+	for key := range r.ProviderResources.BackendStatuses.LoadAll() {
+		ds.BackendStatusKeys[key] = true
+	}
 	return ds
 }
 
@@ -433,6 +447,10 @@ func (r *Runner) deleteStatusKeys(ds *StatusesToDelete) {
 		r.ProviderResources.ExtensionPolicyStatuses.Delete(key)
 		delete(ds.ExtensionServerPolicyStatusKeys, key)
 	}
+	for key := range ds.BackendStatusKeys {
+		r.ProviderResources.BackendStatuses.Delete(key)
+		delete(ds.BackendStatusKeys, key)
+	}
 }
 
 // deleteAllStatusKeys deletes all status keys stored by the subscriber.
@@ -476,6 +494,9 @@ func (r *Runner) deleteAllStatusKeys() {
 	for key := range r.ProviderResources.ExtensionPolicyStatuses.LoadAll() {
 		r.ProviderResources.ExtensionPolicyStatuses.Delete(key)
 	}
+	for key := range r.ProviderResources.BackendStatuses.LoadAll() {
+		r.ProviderResources.BackendStatuses.Delete(key)
+	}
 }
 
 // getIRKeysToDelete returns the list of IR keys to delete
diff --git a/internal/gatewayapi/status/backend.go b/internal/gatewayapi/status/backend.go
index 7b841baaa..16c0139ca 100644
--- a/internal/gatewayapi/status/backend.go
+++ b/internal/gatewayapi/status/backend.go
@@ -31,11 +31,11 @@ func UpdateBackendStatusAcceptedCondition(be *egv1a1.Backend, accepted bool, msg
 func computeBackendAcceptedCondition(be *egv1a1.Backend, accepted bool, msg string) metav1.Condition {
 	switch accepted {
 	case true:
-		return newCondition(string(egv1a1.BackendReasonInvalid), metav1.ConditionTrue,
+		return newCondition(string(egv1a1.BackendReasonAccepted), metav1.ConditionTrue,
 			string(egv1a1.BackendConditionAccepted),
 			"The Backend was accepted", time.Now(), be.Generation)
 	default:
-		return newCondition(string(egv1a1.BackendReasonAccepted), metav1.ConditionFalse,
+		return newCondition(string(egv1a1.BackendReasonInvalid), metav1.ConditionFalse,
 			string(egv1a1.BackendConditionAccepted),
 			msg, time.Now(), be.Generation)
 	}
diff --git a/internal/message/types.go b/internal/message/types.go
index fb82aa140..6a39685a8 100644
--- a/internal/message/types.go
+++ b/internal/message/types.go
@@ -12,6 +12,7 @@ import (
 	gwapiv1 "sigs.k8s.io/gateway-api/apis/v1"
 	gwapiv1a2 "sigs.k8s.io/gateway-api/apis/v1alpha2"
 
+	egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1"
 	"github.com/envoyproxy/gateway/internal/gatewayapi"
 	"github.com/envoyproxy/gateway/internal/ir"
 	xdstypes "github.com/envoyproxy/gateway/internal/xds/types"
@@ -29,6 +30,9 @@ type ProviderResources struct {
 
 	// PolicyStatuses is a group of policy statuses maps.
 	PolicyStatuses
+
+	// ExtensionStatuses is a group of gw-api extension resource statuses map.
+	ExtensionStatuses
 }
 
 func (p *ProviderResources) GetResources() []*gatewayapi.Resources {
@@ -104,6 +108,11 @@ type PolicyStatuses struct {
 	ExtensionPolicyStatuses      watchable.Map[NamespacedNameAndGVK, *gwapiv1a2.PolicyStatus]
 }
 
+// ExtensionStatuses contains statuses related to gw-api extension resources
+type ExtensionStatuses struct {
+	BackendStatuses watchable.Map[types.NamespacedName, *egv1a1.BackendStatus]
+}
+
 func (p *PolicyStatuses) Close() {
 	p.ClientTrafficPolicyStatuses.Close()
 	p.SecurityPolicyStatuses.Close()
diff --git a/internal/provider/kubernetes/status.go b/internal/provider/kubernetes/status.go
index 85e9ff993..c94ad2bc5 100644
--- a/internal/provider/kubernetes/status.go
+++ b/internal/provider/kubernetes/status.go
@@ -399,6 +399,38 @@ func (r *gatewayAPIReconciler) subscribeAndUpdateStatus(ctx context.Context, ext
 		r.log.Info("envoyExtensionPolicy status subscriber shutting down")
 	}()
 
+	// Backend object status updater
+	go func() {
+		message.HandleSubscription(
+			message.Metadata{Runner: string(egv1a1.LogComponentProviderRunner), Message: "backend-status"},
+			r.resources.BackendStatuses.Subscribe(ctx),
+			func(update message.Update[types.NamespacedName, *egv1a1.BackendStatus], errChan chan error) {
+				// skip delete updates.
+				if update.Delete {
+					return
+				}
+				key := update.Key
+				val := update.Value
+				r.statusUpdater.Send(Update{
+					NamespacedName: key,
+					Resource:       new(egv1a1.Backend),
+					Mutator: MutatorFunc(func(obj client.Object) client.Object {
+						t, ok := obj.(*egv1a1.Backend)
+						if !ok {
+							err := fmt.Errorf("unsupported object type %T", obj)
+							errChan <- err
+							panic(err)
+						}
+						tCopy := t.DeepCopy()
+						tCopy.Status = *val
+						return tCopy
+					}),
+				})
+			},
+		)
+		r.log.Info("backend status subscriber shutting down")
+	}()
+
 	if extensionManagerEnabled {
 		// EnvoyExtensionPolicy object status updater
 		go func() {


Test patch:
diff --git a/internal/gatewayapi/runner/runner_test.go b/internal/gatewayapi/runner/runner_test.go
index 5f3bc2a65..41c82da61 100644
--- a/internal/gatewayapi/runner/runner_test.go
+++ b/internal/gatewayapi/runner/runner_test.go
@@ -165,6 +165,10 @@ func TestDeleteStatusKeys(t *testing.T) {
 			Name:      "test7",
 			Namespace: "test-namespace",
 		},
+		{
+			Name:      "test8",
+			Namespace: "test-namespace",
+		},
 	}
 
 	r.ProviderResources.GatewayStatuses.Store(keys[0], &gwapiv1.GatewayStatus{})
@@ -174,6 +178,7 @@ func TestDeleteStatusKeys(t *testing.T) {
 	r.ProviderResources.TCPRouteStatuses.Store(keys[4], &gwapiv1a2.TCPRouteStatus{})
 	r.ProviderResources.UDPRouteStatuses.Store(keys[5], &gwapiv1a2.UDPRouteStatus{})
 	r.ProviderResources.UDPRouteStatuses.Store(keys[6], &gwapiv1a2.UDPRouteStatus{})
+	r.ProviderResources.BackendStatuses.Store(keys[7], &egv1a1.BackendStatus{})
 
 	// Checks that the keys are successfully stored to DeletableStatus and watchable maps
 	ds := r.getAllStatuses()
@@ -185,6 +190,7 @@ func TestDeleteStatusKeys(t *testing.T) {
 	require.True(t, ds.TCPRouteStatusKeys[keys[4]])
 	require.True(t, ds.UDPRouteStatusKeys[keys[5]])
 	require.True(t, ds.UDPRouteStatusKeys[keys[6]])
+	require.True(t, ds.BackendStatusKeys[keys[7]])
 
 	require.Equal(t, 1, r.ProviderResources.GatewayStatuses.Len())
 	require.Equal(t, 1, r.ProviderResources.HTTPRouteStatuses.Len())
@@ -192,6 +198,7 @@ func TestDeleteStatusKeys(t *testing.T) {
 	require.Equal(t, 1, r.ProviderResources.TLSRouteStatuses.Len())
 	require.Equal(t, 1, r.ProviderResources.TCPRouteStatuses.Len())
 	require.Equal(t, 2, r.ProviderResources.UDPRouteStatuses.Len())
+	require.Equal(t, 1, r.ProviderResources.BackendStatuses.Len())
 
 	// Delete all keys except the last UDPRouteStatus key
 	delete(ds.UDPRouteStatusKeys, keys[6])
@@ -203,6 +210,7 @@ func TestDeleteStatusKeys(t *testing.T) {
 	require.Equal(t, 0, r.ProviderResources.TLSRouteStatuses.Len())
 	require.Equal(t, 0, r.ProviderResources.TCPRouteStatuses.Len())
 	require.Equal(t, 1, r.ProviderResources.UDPRouteStatuses.Len())
+	require.Equal(t, 0, r.ProviderResources.BackendStatuses.Len())
 }
 
 func TestDeleteAllStatusKeys(t *testing.T) {
@@ -254,6 +262,10 @@ func TestDeleteAllStatusKeys(t *testing.T) {
 			Name:      "test6",
 			Namespace: "test-namespace",
 		},
+		{
+			Name:      "test7",
+			Namespace: "test-namespace",
+		},
 	}
 
 	r.ProviderResources.GatewayStatuses.Store(keys[0], &gwapiv1.GatewayStatus{})
@@ -262,6 +274,7 @@ func TestDeleteAllStatusKeys(t *testing.T) {
 	r.ProviderResources.TLSRouteStatuses.Store(keys[3], &gwapiv1a2.TLSRouteStatus{})
 	r.ProviderResources.TCPRouteStatuses.Store(keys[4], &gwapiv1a2.TCPRouteStatus{})
 	r.ProviderResources.UDPRouteStatuses.Store(keys[5], &gwapiv1a2.UDPRouteStatus{})
+	r.ProviderResources.BackendStatuses.Store(keys[6], &egv1a1.BackendStatus{})
 
 	// Checks that the keys are successfully stored to DeletableStatus and watchable maps
 	ds := r.getAllStatuses()
@@ -272,6 +285,7 @@ func TestDeleteAllStatusKeys(t *testing.T) {
 	require.True(t, ds.TLSRouteStatusKeys[keys[3]])
 	require.True(t, ds.TCPRouteStatusKeys[keys[4]])
 	require.True(t, ds.UDPRouteStatusKeys[keys[5]])
+	require.True(t, ds.BackendStatusKeys[keys[6]])
 
 	require.Equal(t, 1, r.ProviderResources.GatewayStatuses.Len())
 	require.Equal(t, 1, r.ProviderResources.HTTPRouteStatuses.Len())
@@ -279,6 +293,7 @@ func TestDeleteAllStatusKeys(t *testing.T) {
 	require.Equal(t, 1, r.ProviderResources.TLSRouteStatuses.Len())
 	require.Equal(t, 1, r.ProviderResources.TCPRouteStatuses.Len())
 	require.Equal(t, 1, r.ProviderResources.UDPRouteStatuses.Len())
+	require.Equal(t, 1, r.ProviderResources.BackendStatuses.Len())
 
 	// Delete all keys
 	r.deleteAllStatusKeys()
@@ -288,4 +303,5 @@ func TestDeleteAllStatusKeys(t *testing.T) {
 	require.Equal(t, 0, r.ProviderResources.TLSRouteStatuses.Len())
 	require.Equal(t, 0, r.ProviderResources.TCPRouteStatuses.Len())
 	require.Equal(t, 0, r.ProviderResources.UDPRouteStatuses.Len())
+	require.Equal(t, 0, r.ProviderResources.BackendStatuses.Len())
 }
diff --git a/internal/gatewayapi/testdata/backend-invalid-feature-disabled.out.yaml b/internal/gatewayapi/testdata/backend-invalid-feature-disabled.out.yaml
index 643df0503..60489063c 100644
--- a/internal/gatewayapi/testdata/backend-invalid-feature-disabled.out.yaml
+++ b/internal/gatewayapi/testdata/backend-invalid-feature-disabled.out.yaml
@@ -17,7 +17,7 @@ backends:
         Gateway Config
       reason: Accepted
       status: "False"
-      type: Accepted
+      type: Invalid
 envoyExtensionPolicies:
 - apiVersion: gateway.envoyproxy.io/v1alpha1
   kind: EnvoyExtensionPolicy
diff --git a/internal/gatewayapi/testdata/backend-invalid-hostname-address.out.yaml b/internal/gatewayapi/testdata/backend-invalid-hostname-address.out.yaml
index e917d9cb2..0c022cc4c 100644
--- a/internal/gatewayapi/testdata/backend-invalid-hostname-address.out.yaml
+++ b/internal/gatewayapi/testdata/backend-invalid-hostname-address.out.yaml
@@ -16,7 +16,7 @@ backends:
       message: 'The Backend was not accepted: hostname *.foo.com is not a valid FQDN'
       reason: Accepted
       status: "False"
-      type: Accepted
+      type: Invalid
 - apiVersion: gateway.envoyproxy.io/v1alpha1
   kind: Backend
   metadata:
@@ -35,7 +35,7 @@ backends:
         with at least two segments separated by dots'
       reason: Accepted
       status: "False"
-      type: Accepted
+      type: Invalid
 - apiVersion: gateway.envoyproxy.io/v1alpha1
   kind: Backend
   metadata:
@@ -54,7 +54,7 @@ backends:
         range is not supported'
       reason: Accepted
       status: "False"
-      type: Accepted
+      type: Invalid
 - apiVersion: gateway.envoyproxy.io/v1alpha1
   kind: Backend
   metadata:
@@ -72,6 +72,6 @@ backends:
       message: 'The Backend was not accepted: IP address example.com is invalid'
       reason: Accepted
       status: "False"
-      type: Accepted
+      type: Invalid
 infraIR: {}
 xdsIR: {}
diff --git a/internal/gatewayapi/testdata/backendtlspolicy-default-ns-targetrefs.out.yaml b/internal/gatewayapi/testdata/backendtlspolicy-default-ns-targetrefs.out.yaml
index 6f82b206f..5791f6071 100644
--- a/internal/gatewayapi/testdata/backendtlspolicy-default-ns-targetrefs.out.yaml
+++ b/internal/gatewayapi/testdata/backendtlspolicy-default-ns-targetrefs.out.yaml
@@ -62,7 +62,7 @@ backends:
       message: The Backend was accepted
       reason: Accepted
       status: "True"
-      type: Invalid
+      type: Accepted
 gateways:
 - apiVersion: gateway.networking.k8s.io/v1
   kind: Gateway
diff --git a/internal/gatewayapi/testdata/backendtlspolicy-default-ns.out.yaml b/internal/gatewayapi/testdata/backendtlspolicy-default-ns.out.yaml
index cf416e972..66dfad1a1 100644
--- a/internal/gatewayapi/testdata/backendtlspolicy-default-ns.out.yaml
+++ b/internal/gatewayapi/testdata/backendtlspolicy-default-ns.out.yaml
@@ -78,7 +78,7 @@ backends:
       message: The Backend was accepted
       reason: Accepted
       status: "True"
-      type: Invalid
+      type: Accepted
 gateways:
 - apiVersion: gateway.networking.k8s.io/v1
   kind: Gateway
diff --git a/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-with-multiple-backendrefs.out.yaml b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-with-multiple-backendrefs.out.yaml
index fda8a8185..b8b810a3d 100644
--- a/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-with-multiple-backendrefs.out.yaml
+++ b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-with-multiple-backendrefs.out.yaml
@@ -80,7 +80,7 @@ backends:
       message: The Backend was accepted
       reason: Accepted
       status: "True"
-      type: Invalid
+      type: Accepted
 - apiVersion: gateway.envoyproxy.io/v1alpha1
   kind: Backend
   metadata:
@@ -98,7 +98,7 @@ backends:
       message: The Backend was accepted
       reason: Accepted
       status: "True"
-      type: Invalid
+      type: Accepted
 envoyExtensionPolicies:
 - apiVersion: gateway.envoyproxy.io/v1alpha1
   kind: EnvoyExtensionPolicy
diff --git a/internal/gatewayapi/testdata/grpcroute-with-backend.out.yaml b/internal/gatewayapi/testdata/grpcroute-with-backend.out.yaml
index 12bc6d3e1..ba9f13c31 100644
--- a/internal/gatewayapi/testdata/grpcroute-with-backend.out.yaml
+++ b/internal/gatewayapi/testdata/grpcroute-with-backend.out.yaml
@@ -16,7 +16,7 @@ backends:
       message: The Backend was accepted
       reason: Accepted
       status: "True"
-      type: Invalid
+      type: Accepted
 gateways:
 - apiVersion: gateway.networking.k8s.io/v1
   kind: Gateway
diff --git a/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-backend-and-core-backendrefs.out.yaml b/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-backend-and-core-backendrefs.out.yaml
index 735622c40..484fe1191 100644
--- a/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-backend-and-core-backendrefs.out.yaml
+++ b/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-backend-and-core-backendrefs.out.yaml
@@ -15,7 +15,7 @@ backends:
       message: The Backend was accepted
       reason: Accepted
       status: "True"
-      type: Invalid
+      type: Accepted
 - apiVersion: gateway.envoyproxy.io/v1alpha1
   kind: Backend
   metadata:
@@ -33,7 +33,7 @@ backends:
       message: The Backend was accepted
       reason: Accepted
       status: "True"
-      type: Invalid
+      type: Accepted
 - apiVersion: gateway.envoyproxy.io/v1alpha1
   kind: Backend
   metadata:
@@ -51,7 +51,7 @@ backends:
       message: The Backend was accepted
       reason: Accepted
       status: "True"
-      type: Invalid
+      type: Accepted
 gateways:
 - apiVersion: gateway.networking.k8s.io/v1
   kind: Gateway
diff --git a/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-backend-backendref-mixed-address-type.out.yaml b/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-backend-backendref-mixed-address-type.out.yaml
index c93f3cbe7..80b6f6627 100644
--- a/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-backend-backendref-mixed-address-type.out.yaml
+++ b/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-backend-backendref-mixed-address-type.out.yaml
@@ -18,7 +18,7 @@ backends:
       message: The Backend was accepted
       reason: Accepted
       status: "True"
-      type: Invalid
+      type: Accepted
 - apiVersion: gateway.envoyproxy.io/v1alpha1
   kind: Backend
   metadata:
@@ -38,7 +38,7 @@ backends:
       message: The Backend was accepted
       reason: Accepted
       status: "True"
-      type: Invalid
+      type: Accepted
 - apiVersion: gateway.envoyproxy.io/v1alpha1
   kind: Backend
   metadata:
@@ -59,7 +59,7 @@ backends:
       message: The Backend was accepted
       reason: Accepted
       status: "True"
-      type: Invalid
+      type: Accepted
 - apiVersion: gateway.envoyproxy.io/v1alpha1
   kind: Backend
   metadata:
@@ -80,7 +80,7 @@ backends:
       message: The Backend was accepted
       reason: Accepted
       status: "True"
-      type: Invalid
+      type: Accepted
 gateways:
 - apiVersion: gateway.networking.k8s.io/v1
   kind: Gateway
diff --git a/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-backend-backendref.out.yaml b/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-backend-backendref.out.yaml
index 25ee9e8ba..cdbbe7880 100644
--- a/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-backend-backendref.out.yaml
+++ b/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-backend-backendref.out.yaml
@@ -15,7 +15,7 @@ backends:
       message: The Backend was accepted
       reason: Accepted
       status: "True"
-      type: Invalid
+      type: Accepted
 - apiVersion: gateway.envoyproxy.io/v1alpha1
   kind: Backend
   metadata:
@@ -33,7 +33,7 @@ backends:
       message: The Backend was accepted
       reason: Accepted
       status: "True"
-      type: Invalid
+      type: Accepted
 - apiVersion: gateway.envoyproxy.io/v1alpha1
   kind: Backend
   metadata:
@@ -51,7 +51,7 @@ backends:
       message: The Backend was accepted
       reason: Accepted
       status: "True"
-      type: Invalid
+      type: Accepted
 - apiVersion: gateway.envoyproxy.io/v1alpha1
   kind: Backend
   metadata:
@@ -70,7 +70,7 @@ backends:
         range is not supported'
       reason: Accepted
       status: "False"
-      type: Accepted
+      type: Invalid
 - apiVersion: gateway.envoyproxy.io/v1alpha1
   kind: Backend
   metadata:
@@ -89,7 +89,7 @@ backends:
         with at least two segments separated by dots'
       reason: Accepted
       status: "False"
-      type: Accepted
+      type: Invalid
 gateways:
 - apiVersion: gateway.networking.k8s.io/v1
   kind: Gateway
diff --git a/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-multiple-backend-backendrefs-diff-address-type.out.yaml b/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-multiple-backend-backendrefs-diff-address-type.out.yaml
index 68dd07112..3b5ddfa62 100644
--- a/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-multiple-backend-backendrefs-diff-address-type.out.yaml
+++ b/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-multiple-backend-backendrefs-diff-address-type.out.yaml
@@ -15,7 +15,7 @@ backends:
       message: The Backend was accepted
       reason: Accepted
       status: "True"
-      type: Invalid
+      type: Accepted
 - apiVersion: gateway.envoyproxy.io/v1alpha1
   kind: Backend
   metadata:
@@ -33,7 +33,7 @@ backends:
       message: The Backend was accepted
       reason: Accepted
       status: "True"
-      type: Invalid
+      type: Accepted
 - apiVersion: gateway.envoyproxy.io/v1alpha1
   kind: Backend
   metadata:
@@ -51,7 +51,7 @@ backends:
       message: The Backend was accepted
       reason: Accepted
       status: "True"
-      type: Invalid
+      type: Accepted
 gateways:
 - apiVersion: gateway.networking.k8s.io/v1
   kind: Gateway
diff --git a/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-multiple-backend-backendrefs-same-address-type.out.yaml b/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-multiple-backend-backendrefs-same-address-type.out.yaml
index 7f4812475..5a413ae46 100644
--- a/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-multiple-backend-backendrefs-same-address-type.out.yaml
+++ b/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-multiple-backend-backendrefs-same-address-type.out.yaml
@@ -15,7 +15,7 @@ backends:
       message: The Backend was accepted
       reason: Accepted
       status: "True"
-      type: Invalid
+      type: Accepted
 - apiVersion: gateway.envoyproxy.io/v1alpha1
   kind: Backend
   metadata:
@@ -33,7 +33,7 @@ backends:
       message: The Backend was accepted
       reason: Accepted
       status: "True"
-      type: Invalid
+      type: Accepted
 - apiVersion: gateway.envoyproxy.io/v1alpha1
   kind: Backend
   metadata:
@@ -51,7 +51,7 @@ backends:
       message: The Backend was accepted
       reason: Accepted
       status: "True"
-      type: Invalid
+      type: Accepted
 - apiVersion: gateway.envoyproxy.io/v1alpha1
   kind: Backend
   metadata:
@@ -68,7 +68,7 @@ backends:
       message: The Backend was accepted
       reason: Accepted
       status: "True"
-      type: Invalid
+      type: Accepted
 - apiVersion: gateway.envoyproxy.io/v1alpha1
   kind: Backend
   metadata:
@@ -86,7 +86,7 @@ backends:
       message: The Backend was accepted
       reason: Accepted
       status: "True"
-      type: Invalid
+      type: Accepted
 - apiVersion: gateway.envoyproxy.io/v1alpha1
   kind: Backend
   metadata:
@@ -104,7 +104,7 @@ backends:
       message: The Backend was accepted
       reason: Accepted
       status: "True"
-      type: Invalid
+      type: Accepted
 gateways:
 - apiVersion: gateway.networking.k8s.io/v1
   kind: Gateway
diff --git a/internal/gatewayapi/testdata/httproute-rule-with-non-service-backends-and-app-protocols.out.yaml b/internal/gatewayapi/testdata/httproute-rule-with-non-service-backends-and-app-protocols.out.yaml
index c02aa5200..4c5fcd5e8 100644
--- a/internal/gatewayapi/testdata/httproute-rule-with-non-service-backends-and-app-protocols.out.yaml
+++ b/internal/gatewayapi/testdata/httproute-rule-with-non-service-backends-and-app-protocols.out.yaml
@@ -18,7 +18,7 @@ backends:
       message: The Backend was accepted
       reason: Accepted
       status: "True"
-      type: Invalid
+      type: Accepted
 - apiVersion: gateway.envoyproxy.io/v1alpha1
   kind: Backend
   metadata:
@@ -38,7 +38,7 @@ backends:
       message: The Backend was accepted
       reason: Accepted
       status: "True"
-      type: Invalid
+      type: Accepted
 gateways:
 - apiVersion: gateway.networking.k8s.io/v1
   kind: Gateway
diff --git a/internal/gatewayapi/testdata/httproute-rule-with-non-service-backends-and-weights.out.yaml b/internal/gatewayapi/testdata/httproute-rule-with-non-service-backends-and-weights.out.yaml
index 195f13d09..d56407b0d 100644
--- a/internal/gatewayapi/testdata/httproute-rule-with-non-service-backends-and-weights.out.yaml
+++ b/internal/gatewayapi/testdata/httproute-rule-with-non-service-backends-and-weights.out.yaml
@@ -16,7 +16,7 @@ backends:
       message: The Backend was accepted
       reason: Accepted
       status: "True"
-      type: Invalid
+      type: Accepted
 - apiVersion: gateway.envoyproxy.io/v1alpha1
   kind: Backend
   metadata:
@@ -34,7 +34,7 @@ backends:
       message: The Backend was accepted
       reason: Accepted
       status: "True"
-      type: Invalid
+      type: Accepted
 gateways:
 - apiVersion: gateway.networking.k8s.io/v1
   kind: Gateway
diff --git a/internal/gatewayapi/testdata/tcproute-with-backend.out.yaml b/internal/gatewayapi/testdata/tcproute-with-backend.out.yaml
index c82e53e39..29a124844 100644
--- a/internal/gatewayapi/testdata/tcproute-with-backend.out.yaml
+++ b/internal/gatewayapi/testdata/tcproute-with-backend.out.yaml
@@ -16,7 +16,7 @@ backends:
       message: The Backend was accepted
       reason: Accepted
       status: "True"
-      type: Invalid
+      type: Accepted
 gateways:
 - apiVersion: gateway.networking.k8s.io/v1
   kind: Gateway
diff --git a/internal/gatewayapi/testdata/tlsroute-with-backend.out.yaml b/internal/gatewayapi/testdata/tlsroute-with-backend.out.yaml
index f5839c370..13c3ef41c 100644
--- a/internal/gatewayapi/testdata/tlsroute-with-backend.out.yaml
+++ b/internal/gatewayapi/testdata/tlsroute-with-backend.out.yaml
@@ -16,7 +16,7 @@ backends:
       message: The Backend was accepted
       reason: Accepted
       status: "True"
-      type: Invalid
+      type: Accepted
 gateways:
 - apiVersion: gateway.networking.k8s.io/v1
   kind: Gateway
diff --git a/test/e2e/tests/route_with_backend.go b/test/e2e/tests/route_with_backend.go
index fadb195c3..692764cca 100644
--- a/test/e2e/tests/route_with_backend.go
+++ b/test/e2e/tests/route_with_backend.go
@@ -36,6 +36,7 @@ var EnvoyGatewayBackendTest = suite.ConformanceTest{
 			routeNN := types.NamespacedName{Name: "httproute-to-backend-fqdn", Namespace: ns}
 			gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns}
 			gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN)
+			BackendMustBeAccepted(t, suite.Client, types.NamespacedName{Name: "backend-fqdn", Namespace: ns})
 
 			expectedResponse := http.ExpectedResponse{
 				Request: http.Request{
@@ -55,6 +56,7 @@ var EnvoyGatewayBackendTest = suite.ConformanceTest{
 			routeNN := types.NamespacedName{Name: "httproute-to-backend-ip", Namespace: ns}
 			gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns}
 			gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN)
+			BackendMustBeAccepted(t, suite.Client, types.NamespacedName{Name: "backend-ip", Namespace: ns})
 
 			expectedResponse := http.ExpectedResponse{
 				Request: http.Request{
@@ -74,6 +76,7 @@ var EnvoyGatewayBackendTest = suite.ConformanceTest{
 			routeNN := types.NamespacedName{Name: "httproute-to-backend-fqdn-http2", Namespace: ns}
 			gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns}
 			gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN)
+			BackendMustBeAccepted(t, suite.Client, types.NamespacedName{Name: "backend-fqdn-http2", Namespace: ns})
 
 			expectedResponse := http.ExpectedResponse{
 				Request: http.Request{
@@ -93,6 +96,7 @@ var EnvoyGatewayBackendTest = suite.ConformanceTest{
 			routeNN := types.NamespacedName{Name: "httproute-to-fqdn-backend-tls", Namespace: ns}
 			gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns}
 			gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN)
+			BackendMustBeAccepted(t, suite.Client, types.NamespacedName{Name: "backend-fqdn-tls", Namespace: ns})
 
 			expectedResponse := http.ExpectedResponse{
 				Request: http.Request{
diff --git a/test/e2e/tests/utils.go b/test/e2e/tests/utils.go
index c08b17685..c576dc704 100644
--- a/test/e2e/tests/utils.go
+++ b/test/e2e/tests/utils.go
@@ -311,6 +311,30 @@ func EnvoyExtensionPolicyMustBeAccepted(t *testing.T, client client.Client, poli
 	require.NoErrorf(t, waitErr, "error waiting for EnvoyExtensionPolicy to be accepted")
 }
 
+// BackendMustBeAccepted waits for the specified Backend to be accepted.
+func BackendMustBeAccepted(t *testing.T, client client.Client, backendName types.NamespacedName) {
+	t.Helper()
+
+	waitErr := wait.PollUntilContextTimeout(context.Background(), 1*time.Second, 60*time.Second, true, func(ctx context.Context) (bool, error) {
+		backend := &egv1a1.Backend{}
+		err := client.Get(ctx, backendName, backend)
+		if err != nil {
+			return false, fmt.Errorf("error fetching Backend: %w", err)
+		}
+
+		for _, condition := range backend.Status.Conditions {
+			if condition.Type == string(egv1a1.BackendConditionAccepted) && condition.Status == metav1.ConditionTrue {
+				return true, nil
+			}
+		}
+
+		tlog.Logf(t, "Backend not yet accepted: %v", backend)
+		return false, nil
+	})
+
+	require.NoErrorf(t, waitErr, "error waiting for Backend to be accepted")
+}
+
 func ScrapeMetrics(t *testing.T, c client.Client, nn types.NamespacedName, port int32, path string) error {
 	url, err := RetrieveURL(c, nn, port, path)
 	if err != nil {