Repository: envoyproxy/gateway
Pull request #3537 (2024-06-04 22:45:19)

feat: support custom names for generated k8s resources
Relates to https://github.com/envoyproxy/gateway/pull/3527

codecov[bot]: ## [Codecov](https://app.codecov.io/gh/envoyproxy/gateway/pull/3537?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 68.16%. Comparing base [(`607d8bc`)](https://app.codecov.io/gh/envoyproxy/gateway/commit/607d8bcd9a833841eee057b263c0bdc06de0fbea?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy) to head [(`8a5705a`)](https://app.codecov.io/gh/envoyproxy/gateway/commit/8a5705a09613138937c7d2e1736f5a127dcd43b8?dropdown=coverage&el=desc&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             @@
##             main    #3537      +/-   ##
==========================================
- Coverage   68.16%   68.16%   -0.01%     
==========================================
  Files         167      167              
  Lines       20370    20379       +9     
==========================================
+ Hits        13885    13891       +6     
- Misses       5485     5487       +2     
- Partials     1000     1001       +1     
```



</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/envoyproxy/gateway/pull/3537?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).

arkodg: hey @cnvergence can you elaborate why thats needed, the above diff is changing the value right before setting the resource name ?

Patch:
diff --git a/go.mod b/go.mod
index 6eefe7df5..24338a4d8 100644
--- a/go.mod
+++ b/go.mod
@@ -1,6 +1,6 @@
 module github.com/envoyproxy/gateway
 
-go 1.22.3
+go 1.22.4
 
 require (
 	fortio.org/fortio v1.63.9
diff --git a/internal/gatewayapi/conformance/features.go b/internal/gatewayapi/conformance/suite.go
similarity index 100%
rename from internal/gatewayapi/conformance/features.go
rename to internal/gatewayapi/conformance/suite.go
diff --git a/internal/gatewayapi/conformance/support_level.go b/internal/gatewayapi/conformance/support_level.go
new file mode 100644
index 000000000..938b90dcf
--- /dev/null
+++ b/internal/gatewayapi/conformance/support_level.go
@@ -0,0 +1,55 @@
+// Copyright Envoy Gateway Authors
+// SPDX-License-Identifier: Apache-2.0
+// The full text of the Apache license is available in the LICENSE file at
+// the root of the repo.
+
+package conformance
+
+import (
+	"k8s.io/apimachinery/pkg/util/sets"
+	"sigs.k8s.io/gateway-api/conformance/utils/suite"
+	"sigs.k8s.io/gateway-api/pkg/features"
+)
+
+// SupportLevel represents the level of support for a feature.
+// See https://gateway-api.sigs.k8s.io/concepts/conformance/#2-support-levels.
+type SupportLevel string
+
+const (
+	// Core features are portable and expected to be supported by every implementation of Gateway-API.
+	Core SupportLevel = "core"
+
+	// Extended features are those that are portable but not universally supported across implementations.
+	// Those implementations that support the feature will have the same behavior and semantics.
+	// It is expected that some number of roadmap features will eventually migrate into the Core.
+	Extended SupportLevel = "extended"
+)
+
+// ExtendedFeatures is a list of supported Gateway-API features that are considered Extended.
+var ExtendedFeatures = sets.New[features.SupportedFeature]().
+	Insert(features.GatewayExtendedFeatures.UnsortedList()...).
+	Insert(features.HTTPRouteExtendedFeatures.UnsortedList()...).
+	Insert(features.MeshExtendedFeatures.UnsortedList()...)
+
+// GetTestSupportLevel returns the SupportLevel for a conformance test.
+// The support level is determined by the highest support level of the features.
+func GetTestSupportLevel(test suite.ConformanceTest) SupportLevel {
+	supportLevel := Core
+
+	if ExtendedFeatures.HasAny(test.Features...) {
+		supportLevel = Extended
+	}
+
+	return supportLevel
+}
+
+// GetFeatureSupportLevel returns the SupportLevel for a feature.
+func GetFeatureSupportLevel(feature features.SupportedFeature) SupportLevel {
+	supportLevel := Core
+
+	if ExtendedFeatures.Has(feature) {
+		supportLevel = Extended
+	}
+
+	return supportLevel
+}
diff --git a/internal/gatewayapi/helpers.go b/internal/gatewayapi/helpers.go
index c763d8068..e2fba7153 100644
--- a/internal/gatewayapi/helpers.go
+++ b/internal/gatewayapi/helpers.go
@@ -228,6 +228,15 @@ func GatewayClassOwnerLabel(name string) map[string]string {
 	return map[string]string{OwningGatewayClassLabel: name}
 }
 
+// OwnerLabels returns the owner labels based on the mergeGateways setting
+func OwnerLabels(gateway *gwapiv1.Gateway, mergeGateways bool) map[string]string {
+	if mergeGateways {
+		return GatewayClassOwnerLabel(string(gateway.Spec.GatewayClassName))
+	}
+
+	return GatewayOwnerLabels(gateway.Namespace, gateway.Name)
+}
+
 // servicePortToContainerPort translates a service port into an ephemeral
 // container port.
 func servicePortToContainerPort(servicePort int32, envoyProxy *egv1a1.EnvoyProxy) int32 {
diff --git a/internal/gatewayapi/status/gatewayclass.go b/internal/gatewayapi/status/gatewayclass.go
index 9bcc76f3a..ad8a032a2 100644
--- a/internal/gatewayapi/status/gatewayclass.go
+++ b/internal/gatewayapi/status/gatewayclass.go
@@ -20,6 +20,7 @@ import (
 	"k8s.io/apimachinery/pkg/util/sets"
 	gwapiv1 "sigs.k8s.io/gateway-api/apis/v1"
 	"sigs.k8s.io/gateway-api/conformance/utils/suite"
+	"sigs.k8s.io/gateway-api/pkg/features"
 
 	"github.com/envoyproxy/gateway/internal/gatewayapi/conformance"
 )
@@ -73,13 +74,8 @@ var GatewaySupportedFeatures = getSupportedFeatures(conformance.EnvoyGatewaySuit
 
 func getSupportedFeatures(gatewaySuite suite.ConformanceOptions, skippedTests []suite.ConformanceTest) []gwapiv1.SupportedFeature {
 	supportedFeatures := gatewaySuite.SupportedFeatures.Clone()
-	supportedFeatures.Delete(gatewaySuite.ExemptFeatures.UnsortedList()...)
-
-	for _, skippedTest := range skippedTests {
-		for _, feature := range skippedTest.Features {
-			supportedFeatures.Delete(feature)
-		}
-	}
+	unsupportedFeatures := getUnsupportedFeatures(gatewaySuite, skippedTests)
+	supportedFeatures.Delete(unsupportedFeatures...)
 
 	ret := sets.New[gwapiv1.SupportedFeature]()
 	for _, feature := range supportedFeatures.UnsortedList() {
@@ -87,3 +83,22 @@ func getSupportedFeatures(gatewaySuite suite.ConformanceOptions, skippedTests []
 	}
 	return sets.List(ret)
 }
+
+func getUnsupportedFeatures(gatewaySuite suite.ConformanceOptions, skippedTests []suite.ConformanceTest) []features.SupportedFeature {
+	unsupportedFeatures := gatewaySuite.ExemptFeatures.UnsortedList()
+
+	for _, skippedTest := range skippedTests {
+		switch conformance.GetTestSupportLevel(skippedTest) {
+		case conformance.Core:
+			unsupportedFeatures = append(unsupportedFeatures, skippedTest.Features...)
+		case conformance.Extended:
+			for _, feature := range skippedTest.Features {
+				if conformance.GetFeatureSupportLevel(feature) == conformance.Extended {
+					unsupportedFeatures = append(unsupportedFeatures, feature)
+				}
+			}
+		}
+	}
+
+	return unsupportedFeatures
+}
diff --git a/internal/infrastructure/kubernetes/proxy/resource_provider.go b/internal/infrastructure/kubernetes/proxy/resource_provider.go
index 502620c1c..36bdf3e0c 100644
--- a/internal/infrastructure/kubernetes/proxy/resource_provider.go
+++ b/internal/infrastructure/kubernetes/proxy/resource_provider.go
@@ -143,13 +143,19 @@ func (r *ResourceRender) Service() (*corev1.Service, error) {
 		},
 		ObjectMeta: metav1.ObjectMeta{
 			Namespace:   r.Namespace,
-			Name:        r.Name(),
 			Labels:      labels,
 			Annotations: annotations,
 		},
 		Spec: serviceSpec,
 	}
 
+	// set name
+	if envoyServiceConfig.Name != nil {
+		svc.ObjectMeta.Name = *envoyServiceConfig.Name
+	} else {
+		svc.ObjectMeta.Name = r.Name()
+	}
+
 	// apply merge patch to service
 	var err error
 	if svc, err = envoyServiceConfig.ApplyMergePatch(svc); err != nil {
@@ -225,7 +231,6 @@ func (r *ResourceRender) Deployment() (*appsv1.Deployment, error) {
 		},
 		ObjectMeta: metav1.ObjectMeta{
 			Namespace:   r.Namespace,
-			Name:        r.Name(),
 			Labels:      dpLabels,
 			Annotations: dpAnnotations,
 		},
@@ -261,6 +266,13 @@ func (r *ResourceRender) Deployment() (*appsv1.Deployment, error) {
 		},
 	}
 
+	// set name
+	if deploymentConfig.Name != nil {
+		deployment.ObjectMeta.Name = *deploymentConfig.Name
+	} else {
+		deployment.ObjectMeta.Name = r.Name()
+	}
+
 	// omit the deployment replicas if HPA is being set
 	if provider.GetEnvoyProxyKubeProvider().EnvoyHpa != nil {
 		deployment.Spec.Replicas = nil
@@ -314,7 +326,6 @@ func (r *ResourceRender) DaemonSet() (*appsv1.DaemonSet, error) {
 		},
 		ObjectMeta: metav1.ObjectMeta{
 			Namespace:   r.Namespace,
-			Name:        r.Name(),
 			Labels:      dsLabels,
 			Annotations: dsAnnotations,
 		},
@@ -331,6 +342,13 @@ func (r *ResourceRender) DaemonSet() (*appsv1.DaemonSet, error) {
 		},
 	}
 
+	// set name
+	if daemonSetConfig.Name != nil {
+		daemonSet.ObjectMeta.Name = *daemonSetConfig.Name
+	} else {
+		daemonSet.ObjectMeta.Name = r.Name()
+	}
+
 	// apply merge patch to daemonset
 	if daemonSet, err = daemonSetConfig.ApplyMergePatch(daemonSet); err != nil {
 		return nil, err
@@ -365,7 +383,6 @@ func (r *ResourceRender) HorizontalPodAutoscaler() (*autoscalingv2.HorizontalPod
 			ScaleTargetRef: autoscalingv2.CrossVersionObjectReference{
 				APIVersion: "apps/v1",
 				Kind:       "Deployment",
-				Name:       r.Name(),
 			},
 			MinReplicas: hpaConfig.MinReplicas,
 			MaxReplicas: ptr.Deref(hpaConfig.MaxReplicas, 1),
@@ -374,6 +391,14 @@ func (r *ResourceRender) HorizontalPodAutoscaler() (*autoscalingv2.HorizontalPod
 		},
 	}
 
+	// set deployment target ref name
+	deploymentConfig := provider.GetEnvoyProxyKubeProvider().EnvoyDeployment
+	if deploymentConfig.Name != nil {
+		hpa.Spec.ScaleTargetRef.Name = *deploymentConfig.Name
+	} else {
+		hpa.Spec.ScaleTargetRef.Name = r.Name()
+	}
+
 	return hpa, nil
 }
 
diff --git a/internal/provider/kubernetes/controller.go b/internal/provider/kubernetes/controller.go
index 71f3f2f70..ec51d0018 100644
--- a/internal/provider/kubernetes/controller.go
+++ b/internal/provider/kubernetes/controller.go
@@ -1578,14 +1578,14 @@ func (r *gatewayAPIReconciler) processParamsRef(ctx context.Context, gc *gwapiv1
 	}
 
 	epList := new(egv1a1.EnvoyProxyList)
+	gcParametersRefNamespace := string(*gc.Spec.ParametersRef.Namespace)
 
-	// The EnvoyProxy must be in the same namespace as EG.
-	if err := r.client.List(ctx, epList, &client.ListOptions{Namespace: r.namespace}); err != nil {
-		return fmt.Errorf("failed to list envoyproxies in namespace %s: %w", r.namespace, err)
+	if err := r.client.List(ctx, epList, &client.ListOptions{Namespace: gcParametersRefNamespace}); err != nil {
+		return fmt.Errorf("failed to list envoyproxies in namespace %s: %w", gcParametersRefNamespace, err)
 	}
 
 	if len(epList.Items) == 0 {
-		r.log.Info("no envoyproxies exist in", "namespace", r.namespace)
+		r.log.Info("no envoyproxies exist in", "namespace", gcParametersRefNamespace)
 		return nil
 	}
 
diff --git a/internal/provider/kubernetes/helpers.go b/internal/provider/kubernetes/helpers.go
index a59b7604f..bc765b226 100644
--- a/internal/provider/kubernetes/helpers.go
+++ b/internal/provider/kubernetes/helpers.go
@@ -18,7 +18,6 @@ import (
 
 	egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1"
 	"github.com/envoyproxy/gateway/internal/gatewayapi"
-	"github.com/envoyproxy/gateway/internal/infrastructure/kubernetes/proxy"
 )
 
 const (
@@ -145,17 +144,6 @@ func refsSecret(ref *gwapiv1.SecretObjectReference) bool {
 		(ref.Kind == nil || *ref.Kind == gatewayapi.KindSecret)
 }
 
-// infraName returns expected name for the EnvoyProxy infra resources.
-// By default it returns hashed string from {GatewayNamespace}/{GatewayName},
-// but if mergeGateways is set, it will return hashed string of {GatewayClassName}.
-func infraName(gateway *gwapiv1.Gateway, merged bool) string {
-	if merged {
-		return proxy.ExpectedResourceHashedName(string(gateway.Spec.GatewayClassName))
-	}
-	infraName := fmt.Sprintf("%s/%s", gateway.Namespace, gateway.Name)
-	return proxy.ExpectedResourceHashedName(infraName)
-}
-
 // validateBackendRef validates that ref is a reference to a local Service.
 // TODO: Add support for:
 //   - Validating weights.
diff --git a/internal/provider/kubernetes/predicates.go b/internal/provider/kubernetes/predicates.go
index eb4c35eff..320093980 100644
--- a/internal/provider/kubernetes/predicates.go
+++ b/internal/provider/kubernetes/predicates.go
@@ -464,34 +464,40 @@ func (r *gatewayAPIReconciler) validateDeploymentForReconcile(obj client.Object)
 
 // envoyDeploymentForGateway returns the Envoy Deployment, returning nil if the Deployment doesn't exist.
 func (r *gatewayAPIReconciler) envoyDeploymentForGateway(ctx context.Context, gateway *gwapiv1.Gateway) (*appsv1.Deployment, error) {
-	key := types.NamespacedName{
-		Namespace: r.namespace,
-		Name:      infraName(gateway, r.mergeGateways.Has(string(gateway.Spec.GatewayClassName))),
-	}
-	deployment := new(appsv1.Deployment)
-	if err := r.client.Get(ctx, key, deployment); err != nil {
+	var deployments appsv1.DeploymentList
+	labelSelector := labels.SelectorFromSet(labels.Set(gatewayapi.OwnerLabels(gateway, r.mergeGateways.Has(string(gateway.Spec.GatewayClassName)))))
+	if err := r.client.List(ctx, &deployments, &client.ListOptions{
+		LabelSelector: labelSelector,
+		Namespace:     r.namespace,
+	}); err != nil {
 		if kerrors.IsNotFound(err) {
 			return nil, nil
 		}
 		return nil, err
 	}
-	return deployment, nil
+	if len(deployments.Items) == 0 {
+		return nil, nil
+	}
+	return &deployments.Items[0], nil
 }
 
 // envoyServiceForGateway returns the Envoy service, returning nil if the service doesn't exist.
 func (r *gatewayAPIReconciler) envoyServiceForGateway(ctx context.Context, gateway *gwapiv1.Gateway) (*corev1.Service, error) {
-	key := types.NamespacedName{
-		Namespace: r.namespace,
-		Name:      infraName(gateway, r.mergeGateways.Has(string(gateway.Spec.GatewayClassName))),
-	}
-	svc := new(corev1.Service)
-	if err := r.client.Get(ctx, key, svc); err != nil {
+	var services corev1.ServiceList
+	labelSelector := labels.SelectorFromSet(labels.Set(gatewayapi.OwnerLabels(gateway, r.mergeGateways.Has(string(gateway.Spec.GatewayClassName)))))
+	if err := r.client.List(ctx, &services, &client.ListOptions{
+		LabelSelector: labelSelector,
+		Namespace:     r.namespace,
+	}); err != nil {
 		if kerrors.IsNotFound(err) {
 			return nil, nil
 		}
 		return nil, err
 	}
-	return svc, nil
+	if len(services.Items) == 0 {
+		return nil, nil
+	}
+	return &services.Items[0], nil
 }
 
 // findOwningGateway attempts finds a Gateway using "labels".
diff --git a/internal/xds/translator/route.go b/internal/xds/translator/route.go
index 55e6c258e..1765d2252 100644
--- a/internal/xds/translator/route.go
+++ b/internal/xds/translator/route.go
@@ -386,7 +386,7 @@ func buildXdsURLRewriteAction(destName string, urlRewrite *ir.URLRewrite, pathMa
 		if urlRewrite.Path.FullReplace != nil {
 			routeAction.RegexRewrite = &matcherv3.RegexMatchAndSubstitute{
 				Pattern: &matcherv3.RegexMatcher{
-					Regex: "/.+",
+					Regex: "^/.*$",
 				},
 				Substitution: *urlRewrite.Path.FullReplace,
 			}
diff --git a/site/content/en/v0.6.0/user/grafana-integration.md b/site/content/en/v0.6.0/user/grafana-integration.md
index d8acf06f6..ec2d9ce5c 100644
--- a/site/content/en/v0.6.0/user/grafana-integration.md
+++ b/site/content/en/v0.6.0/user/grafana-integration.md
@@ -50,15 +50,15 @@ To log in to Grafana, use the credentials `admin:admin`.
 
 Envoy Gateway has examples of dashboard for you to get started:
 
-### [Envoy Global](https://raw.githubusercontent.com/envoyproxy/gateway/main/examples/grafana/dashboards/envoy-global.json)
+### [Envoy Global](https://raw.githubusercontent.com/envoyproxy/gateway/main/charts/gateway-addons-helm/dashboards/envoy-global.json)
 
 ![Envoy Global](/img/envoy-global-dashboard.png)
 
-### [Envoy Clusters](https://raw.githubusercontent.com/envoyproxy/gateway/main/examples/grafana/dashboards/envoy-clusters.json)
+### [Envoy Clusters](https://raw.githubusercontent.com/envoyproxy/gateway/main/charts/gateway-addons-helm/dashboards/envoy-clusters.json)
 
 ![Envoy Clusters](/img/envoy-clusters-dashboard.png)
 
-### [Envoy Pod Resources](https://raw.githubusercontent.com/envoyproxy/gateway/main/examples/grafana/dashboards/envoy-pod-resource.json)
+### [Envoy Pod Resources](https://raw.githubusercontent.com/envoyproxy/gateway/main/charts/gateway-addons-helm/dashboards/envoy-pod-resource.json)
 
 ![Envoy Pod Resources](/img/envoy-pod-resources-dashboard.png)
 
diff --git a/site/content/en/v1.0.1/tasks/observability/grafana-integration.md b/site/content/en/v1.0.1/tasks/observability/grafana-integration.md
index ddf54f9d5..e2da53b30 100644
--- a/site/content/en/v1.0.1/tasks/observability/grafana-integration.md
+++ b/site/content/en/v1.0.1/tasks/observability/grafana-integration.md
@@ -50,15 +50,15 @@ To log in to Grafana, use the credentials `admin:admin`.
 
 Envoy Gateway has examples of dashboard for you to get started:
 
-### [Envoy Global](https://raw.githubusercontent.com/envoyproxy/gateway/main/examples/grafana/dashboards/envoy-global.json)
+### [Envoy Global](https://raw.githubusercontent.com/envoyproxy/gateway/main/charts/gateway-addons-helm/dashboards/envoy-global.json)
 
 ![Envoy Global](/img/envoy-global-dashboard.png)
 
-### [Envoy Clusters](https://raw.githubusercontent.com/envoyproxy/gateway/main/examples/grafana/dashboards/envoy-clusters.json)
+### [Envoy Clusters](https://raw.githubusercontent.com/envoyproxy/gateway/main/charts/gateway-addons-helm/dashboards/envoy-clusters.json)
 
 ![Envoy Clusters](/img/envoy-clusters-dashboard.png)
 
-### [Envoy Pod Resources](https://raw.githubusercontent.com/envoyproxy/gateway/main/examples/grafana/dashboards/envoy-pod-resource.json)
+### [Envoy Pod Resources](https://raw.githubusercontent.com/envoyproxy/gateway/main/charts/gateway-addons-helm/dashboards/envoy-pod-resource.json)
 
 ![Envoy Pod Resources](/img/envoy-pod-resources-dashboard.png)
 
diff --git a/site/go.mod b/site/go.mod
index 2e17a4c7d..6b54e56af 100644
--- a/site/go.mod
+++ b/site/go.mod
@@ -1,6 +1,6 @@
 module github.com/google/docsy-example
 
-go 1.22.3
+go 1.22.4
 
 require (
 	github.com/FortAwesome/Font-Awesome v0.0.0-20230327165841-0698449d50f2 // indirect
diff --git a/tools/src/buf/go.mod b/tools/src/buf/go.mod
index 8239e824e..3a4cad22d 100644
--- a/tools/src/buf/go.mod
+++ b/tools/src/buf/go.mod
@@ -1,6 +1,6 @@
 module local
 
-go 1.22.3
+go 1.22.4
 
 require github.com/bufbuild/buf v1.32.2
 
diff --git a/tools/src/controller-gen/go.mod b/tools/src/controller-gen/go.mod
index 28478b149..f5ffd934f 100644
--- a/tools/src/controller-gen/go.mod
+++ b/tools/src/controller-gen/go.mod
@@ -1,6 +1,6 @@
 module local
 
-go 1.22.3
+go 1.22.4
 
 require sigs.k8s.io/controller-tools v0.15.0
 
diff --git a/tools/src/crd-ref-docs/go.mod b/tools/src/crd-ref-docs/go.mod
index 6106a07e2..96f1eefd1 100644
--- a/tools/src/crd-ref-docs/go.mod
+++ b/tools/src/crd-ref-docs/go.mod
@@ -1,6 +1,6 @@
 module local
 
-go 1.22.3
+go 1.22.4
 
 require github.com/elastic/crd-ref-docs v0.0.13-0.20240413123740-ea9fcaa0230f
 
diff --git a/tools/src/golangci-lint/go.mod b/tools/src/golangci-lint/go.mod
index 1ced182b8..bb2a90d2f 100644
--- a/tools/src/golangci-lint/go.mod
+++ b/tools/src/golangci-lint/go.mod
@@ -1,6 +1,6 @@
 module local
 
-go 1.22.3
+go 1.22.4
 
 require github.com/golangci/golangci-lint v1.59.0
 
diff --git a/tools/src/helm-docs/go.mod b/tools/src/helm-docs/go.mod
index fde387c3c..dcbfce9db 100644
--- a/tools/src/helm-docs/go.mod
+++ b/tools/src/helm-docs/go.mod
@@ -1,6 +1,6 @@
 module github.com/envoyproxy/gateway/tools/src/helm-docs
 
-go 1.22.3
+go 1.22.4
 
 require github.com/norwoodj/helm-docs v1.13.0
 
diff --git a/tools/src/kind/go.mod b/tools/src/kind/go.mod
index a4cc3c462..6be0851d9 100644
--- a/tools/src/kind/go.mod
+++ b/tools/src/kind/go.mod
@@ -1,6 +1,6 @@
 module github.com/envoyproxy/gateway/tools/src/kind
 
-go 1.22.3
+go 1.22.4
 
 require sigs.k8s.io/kind v0.23.0
 
diff --git a/tools/src/protoc-gen-go-grpc/go.mod b/tools/src/protoc-gen-go-grpc/go.mod
index 1529cee12..750c1b0f2 100644
--- a/tools/src/protoc-gen-go-grpc/go.mod
+++ b/tools/src/protoc-gen-go-grpc/go.mod
@@ -1,6 +1,6 @@
 module github.com/envoyproxy/gateway/tools/src/protoc-gen-go-grpc
 
-go 1.22.3
+go 1.22.4
 
 require google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0
 
diff --git a/tools/src/protoc-gen-go/go.mod b/tools/src/protoc-gen-go/go.mod
index 21244e773..de3711fcd 100644
--- a/tools/src/protoc-gen-go/go.mod
+++ b/tools/src/protoc-gen-go/go.mod
@@ -1,5 +1,5 @@
 module github.com/envoyproxy/gateway/tools/src/protoc-gen-go
 
-go 1.22.3
+go 1.22.4
 
 require google.golang.org/protobuf v1.33.0


Test patch:
diff --git a/.github/workflows/build_and_test.yaml b/.github/workflows/build_and_test.yaml
index 2f570c2d4..ee41a92c2 100644
--- a/.github/workflows/build_and_test.yaml
+++ b/.github/workflows/build_and_test.yaml
@@ -179,4 +179,4 @@ jobs:
       if: github.event_name == 'push' && github.ref == 'refs/heads/main'
       # use `0.0.0` as the default latest version.
       # use `Always` image pull policy for latest version.
-      run: IMAGE_PULL_POLICY=Always OCI_REGISTRY=oci://docker.io/envoyproxy CHART_VERSION=v0.0.0-latest TAG=latest make helm-package helm-push
+      run: IMAGE_PULL_POLICY=Always OCI_REGISTRY=oci://docker.io/envoyproxy CHART_VERSION=v0.0.0-latest TAG=latest make helm-push
diff --git a/internal/cmd/egctl/testdata/translate/out/default-resources.all.yaml b/internal/cmd/egctl/testdata/translate/out/default-resources.all.yaml
index 3954e3e41..1e85fb5ff 100644
--- a/internal/cmd/egctl/testdata/translate/out/default-resources.all.yaml
+++ b/internal/cmd/egctl/testdata/translate/out/default-resources.all.yaml
@@ -160,7 +160,9 @@ gatewayClass:
       type: Accepted
     supportedFeatures:
     - GRPCRoute
+    - Gateway
     - GatewayPort8080
+    - HTTPRoute
     - HTTPRouteBackendProtocolH2C
     - HTTPRouteBackendProtocolWebSocket
     - HTTPRouteBackendTimeout
diff --git a/internal/cmd/egctl/testdata/translate/out/echo-gateway-api.cluster.yaml b/internal/cmd/egctl/testdata/translate/out/echo-gateway-api.cluster.yaml
index 6afabda49..85b5c588e 100644
--- a/internal/cmd/egctl/testdata/translate/out/echo-gateway-api.cluster.yaml
+++ b/internal/cmd/egctl/testdata/translate/out/echo-gateway-api.cluster.yaml
@@ -14,7 +14,9 @@ gatewayClass:
       type: Accepted
     supportedFeatures:
     - GRPCRoute
+    - Gateway
     - GatewayPort8080
+    - HTTPRoute
     - HTTPRouteBackendProtocolH2C
     - HTTPRouteBackendProtocolWebSocket
     - HTTPRouteBackendTimeout
diff --git a/internal/cmd/egctl/testdata/translate/out/echo-gateway-api.route.json b/internal/cmd/egctl/testdata/translate/out/echo-gateway-api.route.json
index 472c02fcf..663ce5404 100644
--- a/internal/cmd/egctl/testdata/translate/out/echo-gateway-api.route.json
+++ b/internal/cmd/egctl/testdata/translate/out/echo-gateway-api.route.json
@@ -20,7 +20,9 @@
       ],
       "supportedFeatures": [
         "GRPCRoute",
+        "Gateway",
         "GatewayPort8080",
+        "HTTPRoute",
         "HTTPRouteBackendProtocolH2C",
         "HTTPRouteBackendProtocolWebSocket",
         "HTTPRouteBackendTimeout",
diff --git a/internal/cmd/egctl/testdata/translate/out/invalid-envoyproxy.all.yaml b/internal/cmd/egctl/testdata/translate/out/invalid-envoyproxy.all.yaml
index a15d2481e..41be265b3 100644
--- a/internal/cmd/egctl/testdata/translate/out/invalid-envoyproxy.all.yaml
+++ b/internal/cmd/egctl/testdata/translate/out/invalid-envoyproxy.all.yaml
@@ -40,7 +40,9 @@ gatewayClass:
       type: Accepted
     supportedFeatures:
     - GRPCRoute
+    - Gateway
     - GatewayPort8080
+    - HTTPRoute
     - HTTPRouteBackendProtocolH2C
     - HTTPRouteBackendProtocolWebSocket
     - HTTPRouteBackendTimeout
diff --git a/internal/cmd/egctl/testdata/translate/out/rejected-http-route.route.yaml b/internal/cmd/egctl/testdata/translate/out/rejected-http-route.route.yaml
index f45a99fa5..1dd8cc46a 100644
--- a/internal/cmd/egctl/testdata/translate/out/rejected-http-route.route.yaml
+++ b/internal/cmd/egctl/testdata/translate/out/rejected-http-route.route.yaml
@@ -14,7 +14,9 @@ gatewayClass:
       type: Accepted
     supportedFeatures:
     - GRPCRoute
+    - Gateway
     - GatewayPort8080
+    - HTTPRoute
     - HTTPRouteBackendProtocolH2C
     - HTTPRouteBackendProtocolWebSocket
     - HTTPRouteBackendTimeout
diff --git a/internal/cmd/egctl/testdata/translate/out/valid-envoyproxy.all.yaml b/internal/cmd/egctl/testdata/translate/out/valid-envoyproxy.all.yaml
index feef2037c..53dcd5748 100644
--- a/internal/cmd/egctl/testdata/translate/out/valid-envoyproxy.all.yaml
+++ b/internal/cmd/egctl/testdata/translate/out/valid-envoyproxy.all.yaml
@@ -33,7 +33,9 @@ gatewayClass:
       type: Accepted
     supportedFeatures:
     - GRPCRoute
+    - Gateway
     - GatewayPort8080
+    - HTTPRoute
     - HTTPRouteBackendProtocolH2C
     - HTTPRouteBackendProtocolWebSocket
     - HTTPRouteBackendTimeout
diff --git a/internal/gatewayapi/status/gatewayclass_test.go b/internal/gatewayapi/status/gatewayclass_test.go
index 8e66d166f..f2a9dfa42 100644
--- a/internal/gatewayapi/status/gatewayclass_test.go
+++ b/internal/gatewayapi/status/gatewayclass_test.go
@@ -114,6 +114,30 @@ func TestGetSupportedFeatures(t *testing.T) {
 			},
 			expectedResult: []gwapiv1.SupportedFeature{"Gateway"},
 		},
+		{
+			name: "Core features remain supported with skipped extended tests",
+			gatewaySuite: suite.ConformanceOptions{
+				SupportedFeatures: sets.New[features.SupportedFeature]("Gateway", "HTTPRoute", "GatewayHTTPListenerIsolation"),
+			},
+			skippedTests: []suite.ConformanceTest{
+				{
+					Features: []features.SupportedFeature{"Gateway", "GatewayHTTPListenerIsolation", "HTTPRoute"},
+				},
+			},
+			expectedResult: []gwapiv1.SupportedFeature{"Gateway", "HTTPRoute"},
+		},
+		{
+			name: "Core feature removed when skipping core test",
+			gatewaySuite: suite.ConformanceOptions{
+				SupportedFeatures: sets.New[features.SupportedFeature]("Gateway", "HTTPRoute"),
+			},
+			skippedTests: []suite.ConformanceTest{
+				{
+					Features: []features.SupportedFeature{"HTTPRoute"},
+				},
+			},
+			expectedResult: []gwapiv1.SupportedFeature{"Gateway"},
+		},
 	}
 
 	for _, tc := range testCases {
diff --git a/internal/infrastructure/kubernetes/proxy/resource_provider_test.go b/internal/infrastructure/kubernetes/proxy/resource_provider_test.go
index e32d4953f..36862d4c5 100644
--- a/internal/infrastructure/kubernetes/proxy/resource_provider_test.go
+++ b/internal/infrastructure/kubernetes/proxy/resource_provider_test.go
@@ -511,6 +511,13 @@ func TestDeployment(t *testing.T) {
 				},
 			},
 		},
+		{
+			caseName: "with-name",
+			infra:    newTestInfra(),
+			deploy: &egv1a1.KubernetesDeploymentSpec{
+				Name: ptr.To("custom-deployment-name"),
+			},
+		},
 	}
 	for _, tc := range cases {
 		t.Run(tc.caseName, func(t *testing.T) {
@@ -933,6 +940,13 @@ func TestDaemonSet(t *testing.T) {
 			infra:     newTestInfra(),
 			extraArgs: []string{"--key1 val1", "--key2 val2"},
 		},
+		{
+			caseName: "with-name",
+			infra:    newTestInfra(),
+			daemonset: &egv1a1.KubernetesDaemonSetSpec{
+				Name: ptr.To("custom-daemonset-name"),
+			},
+		},
 	}
 	for _, tc := range cases {
 		t.Run(tc.caseName, func(t *testing.T) {
@@ -1083,6 +1097,13 @@ func TestService(t *testing.T) {
 				},
 			},
 		},
+		{
+			caseName: "with-name",
+			infra:    newTestInfra(),
+			service: &egv1a1.KubernetesServiceSpec{
+				Name: ptr.To("custom-service-name"),
+			},
+		},
 	}
 	for _, tc := range cases {
 		t.Run(tc.caseName, func(t *testing.T) {
@@ -1207,6 +1228,7 @@ func TestHorizontalPodAutoscaler(t *testing.T) {
 		caseName string
 		infra    *ir.Infra
 		hpa      *egv1a1.KubernetesHorizontalPodAutoscalerSpec
+		deploy   *egv1a1.KubernetesDeploymentSpec
 	}{
 		{
 			caseName: "default",
@@ -1245,6 +1267,17 @@ func TestHorizontalPodAutoscaler(t *testing.T) {
 				},
 			},
 		},
+		{
+			caseName: "with-deployment-name",
+			infra:    newTestInfra(),
+			hpa: &egv1a1.KubernetesHorizontalPodAutoscalerSpec{
+				MinReplicas: ptr.To[int32](5),
+				MaxReplicas: ptr.To[int32](10),
+			},
+			deploy: &egv1a1.KubernetesDeploymentSpec{
+				Name: ptr.To("custom-deployment-name"),
+			},
+		},
 	}
 
 	for _, tc := range cases {
@@ -1255,7 +1288,9 @@ func TestHorizontalPodAutoscaler(t *testing.T) {
 			if tc.hpa != nil {
 				provider.Kubernetes.EnvoyHpa = tc.hpa
 			}
-
+			if tc.deploy != nil {
+				provider.Kubernetes.EnvoyDeployment = tc.deploy
+			}
 			provider.GetEnvoyProxyKubeProvider()
 
 			r := NewResourceRender(cfg.Namespace, tc.infra.GetProxyInfra(), cfg.EnvoyGateway)
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-name.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-name.yaml
new file mode 100644
index 000000000..3820ca17e
--- /dev/null
+++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-name.yaml
@@ -0,0 +1,302 @@
+apiVersion: apps/v1
+kind: DaemonSet
+metadata:
+  creationTimestamp: null
+  labels:
+    app.kubernetes.io/component: proxy
+    app.kubernetes.io/managed-by: envoy-gateway
+    app.kubernetes.io/name: envoy
+    gateway.envoyproxy.io/owning-gateway-name: default
+    gateway.envoyproxy.io/owning-gateway-namespace: default
+  name: custom-daemonset-name
+  namespace: envoy-gateway-system
+spec:
+  selector:
+    matchLabels:
+      app.kubernetes.io/component: proxy
+      app.kubernetes.io/managed-by: envoy-gateway
+      app.kubernetes.io/name: envoy
+      gateway.envoyproxy.io/owning-gateway-name: default
+      gateway.envoyproxy.io/owning-gateway-namespace: default
+  template:
+    metadata:
+      annotations:
+        prometheus.io/path: /stats/prometheus
+        prometheus.io/port: "19001"
+        prometheus.io/scrape: "true"
+      creationTimestamp: null
+      labels:
+        app.kubernetes.io/component: proxy
+        app.kubernetes.io/managed-by: envoy-gateway
+        app.kubernetes.io/name: envoy
+        gateway.envoyproxy.io/owning-gateway-name: default
+        gateway.envoyproxy.io/owning-gateway-namespace: default
+    spec:
+      automountServiceAccountToken: false
+      containers:
+      - args:
+        - --service-cluster default
+        - --service-node $(ENVOY_POD_NAME)
+        - |
+          --config-yaml admin:
+            access_log:
+            - name: envoy.access_loggers.file
+              typed_config:
+                "@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog
+                path: /dev/null
+            address:
+              socket_address:
+                address: 127.0.0.1
+                port_value: 19000
+          layered_runtime:
+            layers:
+            - name: global_config
+              static_layer:
+                envoy.restart_features.use_eds_cache_for_ads: true
+                re2.max_program_size.error_level: 4294967295
+                re2.max_program_size.warn_level: 1000
+          dynamic_resources:
+            ads_config:
+              api_type: DELTA_GRPC
+              transport_api_version: V3
+              grpc_services:
+              - envoy_grpc:
+                  cluster_name: xds_cluster
+              set_node_on_first_message_only: true
+            lds_config:
+              ads: {}
+              resource_api_version: V3
+            cds_config:
+              ads: {}
+              resource_api_version: V3
+          static_resources:
+            listeners:
+            - name: envoy-gateway-proxy-ready-0.0.0.0-19001
+              address:
+                socket_address:
+                  address: 0.0.0.0
+                  port_value: 19001
+                  protocol: TCP
+              filter_chains:
+              - filters:
+                - name: envoy.filters.network.http_connection_manager
+                  typed_config:
+                    "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
+                    stat_prefix: eg-ready-http
+                    route_config:
+                      name: local_route
+                      virtual_hosts:
+                      - name: prometheus_stats
+                        domains:
+                        - "*"
+                        routes:
+                        - match:
+                            prefix: /stats/prometheus
+                          route:
+                            cluster: prometheus_stats
+                    http_filters:
+                    - name: envoy.filters.http.health_check
+                      typed_config:
+                        "@type": type.googleapis.com/envoy.extensions.filters.http.health_check.v3.HealthCheck
+                        pass_through_mode: false
+                        headers:
+                        - name: ":path"
+                          string_match:
+                            exact: /ready
+                    - name: envoy.filters.http.router
+                      typed_config:
+                        "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
+            clusters:
+            - name: prometheus_stats
+              connect_timeout: 0.250s
+              type: STATIC
+              lb_policy: ROUND_ROBIN
+              load_assignment:
+                cluster_name: prometheus_stats
+                endpoints:
+                - lb_endpoints:
+                  - endpoint:
+                      address:
+                        socket_address:
+                          address: 127.0.0.1
+                          port_value: 19000
+            - connect_timeout: 10s
+              load_assignment:
+                cluster_name: xds_cluster
+                endpoints:
+                - load_balancing_weight: 1
+                  lb_endpoints:
+                  - load_balancing_weight: 1
+                    endpoint:
+                      address:
+                        socket_address:
+                          address: envoy-gateway
+                          port_value: 18000
+              typed_extension_protocol_options:
+                envoy.extensions.upstreams.http.v3.HttpProtocolOptions:
+                  "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions"
+                  explicit_http_config:
+                    http2_protocol_options:
+                      connection_keepalive:
+                        interval: 30s
+                        timeout: 5s
+              name: xds_cluster
+              type: STRICT_DNS
+              transport_socket:
+                name: envoy.transport_sockets.tls
+                typed_config:
+                  "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
+                  common_tls_context:
+                    tls_params:
+                      tls_maximum_protocol_version: TLSv1_3
+                    tls_certificate_sds_secret_configs:
+                    - name: xds_certificate
+                      sds_config:
+                        path_config_source:
+                          path: "/sds/xds-certificate.json"
+                        resource_api_version: V3
+                    validation_context_sds_secret_config:
+                      name: xds_trusted_ca
+                      sds_config:
+                        path_config_source:
+                          path: "/sds/xds-trusted-ca.json"
+                        resource_api_version: V3
+          overload_manager:
+            refresh_interval: 0.25s
+            resource_monitors:
+            - name: "envoy.resource_monitors.global_downstream_max_connections"
+              typed_config:
+                "@type": type.googleapis.com/envoy.extensions.resource_monitors.downstream_connections.v3.DownstreamConnectionsConfig
+                max_active_downstream_connections: 50000
+        - --log-level warn
+        - --cpuset-threads
+        command:
+        - envoy
+        env:
+        - name: ENVOY_GATEWAY_NAMESPACE
+          valueFrom:
+            fieldRef:
+              apiVersion: v1
+              fieldPath: metadata.namespace
+        - name: ENVOY_POD_NAME
+          valueFrom:
+            fieldRef:
+              apiVersion: v1
+              fieldPath: metadata.name
+        image: envoyproxy/envoy:distroless-dev
+        imagePullPolicy: IfNotPresent
+        lifecycle:
+          preStop:
+            httpGet:
+              path: /shutdown/ready
+              port: 19002
+              scheme: HTTP
+        name: envoy
+        ports:
+        - containerPort: 8080
+          name: EnvoyHTTPPort
+          protocol: TCP
+        - containerPort: 8443
+          name: EnvoyHTTPSPort
+          protocol: TCP
+        - containerPort: 19001
+          name: metrics
+          protocol: TCP
+        readinessProbe:
+          failureThreshold: 3
+          httpGet:
+            path: /ready
+            port: 19001
+            scheme: HTTP
+          periodSeconds: 10
+          successThreshold: 1
+          timeoutSeconds: 1
+        resources:
+          requests:
+            cpu: 100m
+            memory: 512Mi
+        terminationMessagePath: /dev/termination-log
+        terminationMessagePolicy: File
+        volumeMounts:
+        - mountPath: /certs
+          name: certs
+          readOnly: true
+        - mountPath: /sds
+          name: sds
+      - args:
+        - envoy
+        - shutdown-manager
+        command:
+        - envoy-gateway
+        env:
+        - name: ENVOY_GATEWAY_NAMESPACE
+          valueFrom:
+            fieldRef:
+              apiVersion: v1
+              fieldPath: metadata.namespace
+        - name: ENVOY_POD_NAME
+          valueFrom:
+            fieldRef:
+              apiVersion: v1
+              fieldPath: metadata.name
+        image: envoyproxy/gateway-dev:latest
+        imagePullPolicy: IfNotPresent
+        lifecycle:
+          preStop:
+            exec:
+              command:
+              - envoy-gateway
+              - envoy
+              - shutdown
+        livenessProbe:
+          failureThreshold: 3
+          httpGet:
+            path: /healthz
+            port: 19002
+            scheme: HTTP
+          periodSeconds: 10
+          successThreshold: 1
+          timeoutSeconds: 1
+        name: shutdown-manager
+        readinessProbe:
+          failureThreshold: 3
+          httpGet:
+            path: /healthz
+            port: 19002
+            scheme: HTTP
+          periodSeconds: 10
+          successThreshold: 1
+          timeoutSeconds: 1
+        resources:
+          requests:
+            cpu: 10m
+            memory: 32Mi
+        terminationMessagePath: /dev/termination-log
+        terminationMessagePolicy: File
+      dnsPolicy: ClusterFirst
+      restartPolicy: Always
+      schedulerName: default-scheduler
+      serviceAccountName: envoy-default-37a8eec1
+      terminationGracePeriodSeconds: 900
+      volumes:
+      - name: certs
+        secret:
+          defaultMode: 420
+          secretName: envoy
+      - configMap:
+          defaultMode: 420
+          items:
+          - key: xds-trusted-ca.json
+            path: xds-trusted-ca.json
+          - key: xds-certificate.json
+            path: xds-certificate.json
+          name: envoy-default-37a8eec1
+          optional: false
+        name: sds
+  updateStrategy:
+    type: RollingUpdate
+status:
+  currentNumberScheduled: 0
+  desiredNumberScheduled: 0
+  numberMisscheduled: 0
+  numberReady: 0
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-name.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-name.yaml
new file mode 100644
index 000000000..91b38ecbd
--- /dev/null
+++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-name.yaml
@@ -0,0 +1,300 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  creationTimestamp: null
+  labels:
+    app.kubernetes.io/component: proxy
+    app.kubernetes.io/managed-by: envoy-gateway
+    app.kubernetes.io/name: envoy
+    gateway.envoyproxy.io/owning-gateway-name: default
+    gateway.envoyproxy.io/owning-gateway-namespace: default
+  name: custom-deployment-name
+  namespace: envoy-gateway-system
+spec:
+  progressDeadlineSeconds: 600
+  revisionHistoryLimit: 10
+  selector:
+    matchLabels:
+      app.kubernetes.io/component: proxy
+      app.kubernetes.io/managed-by: envoy-gateway
+      app.kubernetes.io/name: envoy
+      gateway.envoyproxy.io/owning-gateway-name: default
+      gateway.envoyproxy.io/owning-gateway-namespace: default
+  strategy:
+    type: RollingUpdate
+  template:
+    metadata:
+      annotations:
+        prometheus.io/path: /stats/prometheus
+        prometheus.io/port: "19001"
+        prometheus.io/scrape: "true"
+      creationTimestamp: null
+      labels:
+        app.kubernetes.io/component: proxy
+        app.kubernetes.io/managed-by: envoy-gateway
+        app.kubernetes.io/name: envoy
+        gateway.envoyproxy.io/owning-gateway-name: default
+        gateway.envoyproxy.io/owning-gateway-namespace: default
+    spec:
+      automountServiceAccountToken: false
+      containers:
+      - args:
+        - --service-cluster default
+        - --service-node $(ENVOY_POD_NAME)
+        - |
+          --config-yaml admin:
+            access_log:
+            - name: envoy.access_loggers.file
+              typed_config:
+                "@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog
+                path: /dev/null
+            address:
+              socket_address:
+                address: 127.0.0.1
+                port_value: 19000
+          layered_runtime:
+            layers:
+            - name: global_config
+              static_layer:
+                envoy.restart_features.use_eds_cache_for_ads: true
+                re2.max_program_size.error_level: 4294967295
+                re2.max_program_size.warn_level: 1000
+          dynamic_resources:
+            ads_config:
+              api_type: DELTA_GRPC
+              transport_api_version: V3
+              grpc_services:
+              - envoy_grpc:
+                  cluster_name: xds_cluster
+              set_node_on_first_message_only: true
+            lds_config:
+              ads: {}
+              resource_api_version: V3
+            cds_config:
+              ads: {}
+              resource_api_version: V3
+          static_resources:
+            listeners:
+            - name: envoy-gateway-proxy-ready-0.0.0.0-19001
+              address:
+                socket_address:
+                  address: 0.0.0.0
+                  port_value: 19001
+                  protocol: TCP
+              filter_chains:
+              - filters:
+                - name: envoy.filters.network.http_connection_manager
+                  typed_config:
+                    "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
+                    stat_prefix: eg-ready-http
+                    route_config:
+                      name: local_route
+                      virtual_hosts:
+                      - name: prometheus_stats
+                        domains:
+                        - "*"
+                        routes:
+                        - match:
+                            prefix: /stats/prometheus
+                          route:
+                            cluster: prometheus_stats
+                    http_filters:
+                    - name: envoy.filters.http.health_check
+                      typed_config:
+                        "@type": type.googleapis.com/envoy.extensions.filters.http.health_check.v3.HealthCheck
+                        pass_through_mode: false
+                        headers:
+                        - name: ":path"
+                          string_match:
+                            exact: /ready
+                    - name: envoy.filters.http.router
+                      typed_config:
+                        "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
+            clusters:
+            - name: prometheus_stats
+              connect_timeout: 0.250s
+              type: STATIC
+              lb_policy: ROUND_ROBIN
+              load_assignment:
+                cluster_name: prometheus_stats
+                endpoints:
+                - lb_endpoints:
+                  - endpoint:
+                      address:
+                        socket_address:
+                          address: 127.0.0.1
+                          port_value: 19000
+            - connect_timeout: 10s
+              load_assignment:
+                cluster_name: xds_cluster
+                endpoints:
+                - load_balancing_weight: 1
+                  lb_endpoints:
+                  - load_balancing_weight: 1
+                    endpoint:
+                      address:
+                        socket_address:
+                          address: envoy-gateway
+                          port_value: 18000
+              typed_extension_protocol_options:
+                envoy.extensions.upstreams.http.v3.HttpProtocolOptions:
+                  "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions"
+                  explicit_http_config:
+                    http2_protocol_options:
+                      connection_keepalive:
+                        interval: 30s
+                        timeout: 5s
+              name: xds_cluster
+              type: STRICT_DNS
+              transport_socket:
+                name: envoy.transport_sockets.tls
+                typed_config:
+                  "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
+                  common_tls_context:
+                    tls_params:
+                      tls_maximum_protocol_version: TLSv1_3
+                    tls_certificate_sds_secret_configs:
+                    - name: xds_certificate
+                      sds_config:
+                        path_config_source:
+                          path: "/sds/xds-certificate.json"
+                        resource_api_version: V3
+                    validation_context_sds_secret_config:
+                      name: xds_trusted_ca
+                      sds_config:
+                        path_config_source:
+                          path: "/sds/xds-trusted-ca.json"
+                        resource_api_version: V3
+          overload_manager:
+            refresh_interval: 0.25s
+            resource_monitors:
+            - name: "envoy.resource_monitors.global_downstream_max_connections"
+              typed_config:
+                "@type": type.googleapis.com/envoy.extensions.resource_monitors.downstream_connections.v3.DownstreamConnectionsConfig
+                max_active_downstream_connections: 50000
+        - --log-level warn
+        - --cpuset-threads
+        command:
+        - envoy
+        env:
+        - name: ENVOY_GATEWAY_NAMESPACE
+          valueFrom:
+            fieldRef:
+              apiVersion: v1
+              fieldPath: metadata.namespace
+        - name: ENVOY_POD_NAME
+          valueFrom:
+            fieldRef:
+              apiVersion: v1
+              fieldPath: metadata.name
+        image: envoyproxy/envoy:distroless-dev
+        imagePullPolicy: IfNotPresent
+        lifecycle:
+          preStop:
+            httpGet:
+              path: /shutdown/ready
+              port: 19002
+              scheme: HTTP
+        name: envoy
+        ports:
+        - containerPort: 8080
+          name: EnvoyHTTPPort
+          protocol: TCP
+        - containerPort: 8443
+          name: EnvoyHTTPSPort
+          protocol: TCP
+        - containerPort: 19001
+          name: metrics
+          protocol: TCP
+        readinessProbe:
+          failureThreshold: 3
+          httpGet:
+            path: /ready
+            port: 19001
+            scheme: HTTP
+          periodSeconds: 10
+          successThreshold: 1
+          timeoutSeconds: 1
+        resources:
+          requests:
+            cpu: 100m
+            memory: 512Mi
+        terminationMessagePath: /dev/termination-log
+        terminationMessagePolicy: File
+        volumeMounts:
+        - mountPath: /certs
+          name: certs
+          readOnly: true
+        - mountPath: /sds
+          name: sds
+      - args:
+        - envoy
+        - shutdown-manager
+        command:
+        - envoy-gateway
+        env:
+        - name: ENVOY_GATEWAY_NAMESPACE
+          valueFrom:
+            fieldRef:
+              apiVersion: v1
+              fieldPath: metadata.namespace
+        - name: ENVOY_POD_NAME
+          valueFrom:
+            fieldRef:
+              apiVersion: v1
+              fieldPath: metadata.name
+        image: envoyproxy/gateway-dev:latest
+        imagePullPolicy: IfNotPresent
+        lifecycle:
+          preStop:
+            exec:
+              command:
+              - envoy-gateway
+              - envoy
+              - shutdown
+        livenessProbe:
+          failureThreshold: 3
+          httpGet:
+            path: /healthz
+            port: 19002
+            scheme: HTTP
+          periodSeconds: 10
+          successThreshold: 1
+          timeoutSeconds: 1
+        name: shutdown-manager
+        readinessProbe:
+          failureThreshold: 3
+          httpGet:
+            path: /healthz
+            port: 19002
+            scheme: HTTP
+          periodSeconds: 10
+          successThreshold: 1
+          timeoutSeconds: 1
+        resources:
+          requests:
+            cpu: 10m
+            memory: 32Mi
+        terminationMessagePath: /dev/termination-log
+        terminationMessagePolicy: File
+      dnsPolicy: ClusterFirst
+      restartPolicy: Always
+      schedulerName: default-scheduler
+      serviceAccountName: envoy-default-37a8eec1
+      terminationGracePeriodSeconds: 900
+      volumes:
+      - name: certs
+        secret:
+          defaultMode: 420
+          secretName: envoy
+      - configMap:
+          defaultMode: 420
+          items:
+          - key: xds-trusted-ca.json
+            path: xds-trusted-ca.json
+          - key: xds-certificate.json
+            path: xds-certificate.json
+          name: envoy-default-37a8eec1
+          optional: false
+        name: sds
+status: {}
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/hpa/with-deployment-name.yaml b/internal/infrastructure/kubernetes/proxy/testdata/hpa/with-deployment-name.yaml
new file mode 100644
index 000000000..b421873f6
--- /dev/null
+++ b/internal/infrastructure/kubernetes/proxy/testdata/hpa/with-deployment-name.yaml
@@ -0,0 +1,22 @@
+apiVersion: autoscaling/v2
+kind: HorizontalPodAutoscaler
+metadata:
+  labels:
+    gateway.envoyproxy.io/owning-gateway-name: default
+    gateway.envoyproxy.io/owning-gateway-namespace: default
+  name: envoy-default-37a8eec1
+  namespace: envoy-gateway-system
+spec:
+  metrics:
+  - resource:
+      name: cpu
+      target:
+        averageUtilization: 80
+        type: Utilization
+    type: Resource
+  minReplicas: 5
+  maxReplicas: 10
+  scaleTargetRef:
+    apiVersion: apps/v1
+    kind: Deployment
+    name: custom-deployment-name
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/services/with-name.yaml b/internal/infrastructure/kubernetes/proxy/testdata/services/with-name.yaml
new file mode 100644
index 000000000..150fd62b5
--- /dev/null
+++ b/internal/infrastructure/kubernetes/proxy/testdata/services/with-name.yaml
@@ -0,0 +1,30 @@
+apiVersion: v1
+kind: Service
+metadata:
+  labels:
+    app.kubernetes.io/name: envoy
+    app.kubernetes.io/component: proxy
+    app.kubernetes.io/managed-by: envoy-gateway
+    gateway.envoyproxy.io/owning-gateway-name: default
+    gateway.envoyproxy.io/owning-gateway-namespace: default
+  name: custom-service-name
+  namespace: envoy-gateway-system
+spec:
+  externalTrafficPolicy: Local
+  ports:
+    - name: EnvoyHTTPPort
+      port: 0
+      protocol: TCP
+      targetPort: 8080
+    - name: EnvoyHTTPSPort
+      port: 0
+      protocol: TCP
+      targetPort: 8443
+  selector:
+    app.kubernetes.io/name: envoy
+    app.kubernetes.io/component: proxy
+    app.kubernetes.io/managed-by: envoy-gateway
+    gateway.envoyproxy.io/owning-gateway-name: default
+    gateway.envoyproxy.io/owning-gateway-namespace: default
+  sessionAffinity: None
+  type: LoadBalancer
diff --git a/internal/provider/kubernetes/predicates_test.go b/internal/provider/kubernetes/predicates_test.go
index 431d96382..c27caa97e 100644
--- a/internal/provider/kubernetes/predicates_test.go
+++ b/internal/provider/kubernetes/predicates_test.go
@@ -24,6 +24,7 @@ import (
 	"github.com/envoyproxy/gateway/api/v1alpha1"
 	"github.com/envoyproxy/gateway/internal/envoygateway"
 	"github.com/envoyproxy/gateway/internal/gatewayapi"
+	"github.com/envoyproxy/gateway/internal/infrastructure/kubernetes/proxy"
 	"github.com/envoyproxy/gateway/internal/logging"
 	"github.com/envoyproxy/gateway/internal/provider/kubernetes/test"
 )
@@ -498,7 +499,7 @@ func TestValidateServiceForReconcile(t *testing.T) {
 			configs: []client.Object{
 				test.GetGatewayClass("test-gc", v1alpha1.GatewayControllerName, nil),
 				sampleGateway,
-				test.GetGatewayDeployment(types.NamespacedName{Name: infraName(sampleGateway, false)}, nil),
+				test.GetGatewayDeployment(types.NamespacedName{Name: proxy.ExpectedResourceHashedName("default/scheduled-status-test")}, nil),
 			},
 			service: test.GetService(types.NamespacedName{Name: "service"}, map[string]string{
 				gatewayapi.OwningGatewayNameLabel:      "scheduled-status-test",
diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-rewrite-url-fullpath.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-rewrite-url-fullpath.routes.yaml
index f8b81712d..7c049365a 100644
--- a/internal/xds/translator/testdata/out/xds-ir/http-route-rewrite-url-fullpath.routes.yaml
+++ b/internal/xds/translator/testdata/out/xds-ir/http-route-rewrite-url-fullpath.routes.yaml
@@ -12,7 +12,7 @@
         cluster: rewrite-route
         regexRewrite:
           pattern:
-            regex: /.+
+            regex: ^/.*$
           substitution: /rewrite
         upgradeConfigs:
         - upgradeType: websocket
diff --git a/site/content/en/latest/tasks/observability/grafana-integration.md b/site/content/en/latest/tasks/observability/grafana-integration.md
index ef49d9ee5..42ab7d29c 100644
--- a/site/content/en/latest/tasks/observability/grafana-integration.md
+++ b/site/content/en/latest/tasks/observability/grafana-integration.md
@@ -52,25 +52,25 @@ To log in to Grafana, use the credentials `admin:admin`.
 Envoy Gateway has examples of dashboard for you to get started, you can load them in your Grafana to get started. 
 Please refer to Grafana docs for [importing dashboards](https://grafana.com/docs/grafana/latest/dashboards/manage-dashboards/#import-a-dashboard).
 
-### [Envoy Global](https://raw.githubusercontent.com/envoyproxy/gateway/main/examples/grafana/dashboards/envoy-global.json)
+### [Envoy Global](https://raw.githubusercontent.com/envoyproxy/gateway/main/charts/gateway-addons-helm/dashboards/envoy-global.json)
 
 This dashboard example shows the overall downstram and upstream stats for each Envoy Proxy instance.
 
 ![Envoy Global](/img/envoy-global-dashboard.png)
 
-### [Envoy Clusters](https://raw.githubusercontent.com/envoyproxy/gateway/main/examples/grafana/dashboards/envoy-clusters.json)
+### [Envoy Clusters](https://raw.githubusercontent.com/envoyproxy/gateway/main/charts/gateway-addons-helm/dashboards/envoy-clusters.json)
 
 This dashboard example shows the overall stats for each cluster from Envoy Proxy fleet.
 
 ![Envoy Clusters](/img/envoy-clusters-dashboard.png)
 
-### [Envoy Pod Resources](https://raw.githubusercontent.com/envoyproxy/gateway/main/examples/grafana/dashboards/envoy-pod-resource.json)
+### [Envoy Pod Resources](https://raw.githubusercontent.com/envoyproxy/gateway/main/charts/gateway-addons-helm/dashboards/envoy-pod-resource.json)
 
 This dashboard example shows the overall pod resources stats for each Envoy Proxy instance.
 
 ![Envoy Pod Resources](/img/envoy-pod-resources-dashboard.png)
 
-### [Envoy Gateway Global](https://raw.githubusercontent.com/envoyproxy/gateway/main/examples/grafana/dashboards/envoy-gateway-global.json)
+### [Envoy Gateway Global](https://raw.githubusercontent.com/envoyproxy/gateway/main/charts/gateway-addons-helm/dashboards/envoy-gateway-global.json)
 
 This dashboard example shows the overall stats exported by Envoy Gateway fleet.
 
diff --git a/site/content/en/latest/tasks/traffic/gatewayapi-support.md b/site/content/en/latest/tasks/traffic/gatewayapi-support.md
index 7ea0e91e5..779cce6fb 100644
--- a/site/content/en/latest/tasks/traffic/gatewayapi-support.md
+++ b/site/content/en/latest/tasks/traffic/gatewayapi-support.md
@@ -42,7 +42,7 @@ supported by Envoy Gateway:
 __Notes:__
 - The only [BackendRef][] kind supported by Envoy Gateway is a [Service][]. Routing traffic to other destinations such
   as arbitrary URLs is not possible.
-- The `filters` field within [HTTPBackendRef][] is not supported.
+- Only `requestHeaderModifier` and `responseHeaderModifier` filters are currently supported within [HTTPBackendRef][].
 
 ## TCPRoute
 
@@ -76,7 +76,7 @@ provide additional traffic processing:
 __Notes:__
 - The only [BackendRef][grpc-filter] kind supported by Envoy Gateway is a [Service][]. Routing traffic to other
   destinations such as arbitrary URLs is not currently possible.
-- The `filters` field within [HTTPBackendRef][] is not supported.
+- Only `requestHeaderModifier` and `responseHeaderModifier` filters are currently supported within [GRPCBackendRef][].
 
 ## TLSRoute
 
@@ -106,6 +106,7 @@ these types of cross-namespace references. Envoy Gateway supports the following
 [TCPRoute]: https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1alpha2.TCPRoute
 [UDPRoute]: https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1alpha2.UDPRoute
 [GRPCRoute]: https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1alpha2.GRPCRoute
+[GRPCBackendRef]: https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.GRPCBackendRef
 [gRPC]: https://grpc.io/
 [TLSRoute]: https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1alpha2.TLSRoute
 [ReferenceGrant]: https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1alpha2.ReferenceGrant
diff --git a/test/e2e/testdata/httproute-rewrite-full-path.yaml b/test/e2e/testdata/httproute-rewrite-full-path.yaml
new file mode 100644
index 000000000..7e8b11816
--- /dev/null
+++ b/test/e2e/testdata/httproute-rewrite-full-path.yaml
@@ -0,0 +1,22 @@
+apiVersion: gateway.networking.k8s.io/v1
+kind: HTTPRoute
+metadata:
+  name: rewrite-full-path
+  namespace: gateway-conformance-infra
+spec:
+  parentRefs:
+  - name: same-namespace
+  rules:
+  - matches:
+    - path:
+        type: PathPrefix
+        value: /
+    filters:
+    - type: URLRewrite
+      urlRewrite:
+        path:
+          type: ReplaceFullPath
+          replaceFullPath: /full-replace
+    backendRefs:
+    - name: infra-backend-v1
+      port: 8080
diff --git a/test/e2e/tests/httproute-rewrite-full-path.go b/test/e2e/tests/httproute-rewrite-full-path.go
new file mode 100644
index 000000000..dd043571c
--- /dev/null
+++ b/test/e2e/tests/httproute-rewrite-full-path.go
@@ -0,0 +1,59 @@
+// Copyright Envoy Gateway Authors
+// SPDX-License-Identifier: Apache-2.0
+// The full text of the Apache license is available in the LICENSE file at
+// the root of the repo.
+
+//go:build e2e
+// +build e2e
+
+package tests
+
+import (
+	"testing"
+
+	"k8s.io/apimachinery/pkg/types"
+	"sigs.k8s.io/gateway-api/conformance/utils/http"
+	"sigs.k8s.io/gateway-api/conformance/utils/kubernetes"
+	"sigs.k8s.io/gateway-api/conformance/utils/suite"
+)
+
+func init() {
+	ConformanceTests = append(ConformanceTests, HTTPRouteRewriteFullPath)
+}
+
+var HTTPRouteRewriteFullPath = suite.ConformanceTest{
+	ShortName:   "HTTPRouteRewriteFullPath",
+	Description: "An HTTPRoute with path rewrite filter to replace full path",
+	Manifests:   []string{"testdata/httproute-rewrite-full-path.yaml"},
+	Test: func(t *testing.T, suite *suite.ConformanceTestSuite) {
+		ns := "gateway-conformance-infra"
+		routeNN := types.NamespacedName{Name: "rewrite-full-path", Namespace: ns}
+		gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns}
+		gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN)
+		kubernetes.HTTPRouteMustHaveResolvedRefsConditionsTrue(t, suite.Client, suite.TimeoutConfig, routeNN, gwNN)
+
+		testCases := []http.ExpectedResponse{
+			{
+				Request: http.Request{
+					Path: "/",
+				},
+				ExpectedRequest: &http.ExpectedRequest{
+					Request: http.Request{
+						Path: "/full-replace",
+					},
+				},
+				Backend:   "infra-backend-v1",
+				Namespace: ns,
+			},
+		}
+		for i := range testCases {
+			// Declare tc here to avoid loop variable
+			// reuse issues across parallel tests.
+			tc := testCases[i]
+			t.Run(tc.GetTestCaseName(i), func(t *testing.T) {
+				t.Parallel()
+				http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, tc)
+			})
+		}
+	},
+}
diff --git a/tools/src/setup-envtest/go.mod b/tools/src/setup-envtest/go.mod
index 2d1c09adc..532d7b491 100644
--- a/tools/src/setup-envtest/go.mod
+++ b/tools/src/setup-envtest/go.mod
@@ -1,6 +1,6 @@
 module local
 
-go 1.22.3
+go 1.22.4
 
 require sigs.k8s.io/controller-runtime/tools/setup-envtest v0.0.0-20240423173400-ed81fa696dea