Repository: knative/operator (go)

Issue:
`spec.deployments.replicas` does not take care about HorizontalPodAutoscaler
We can overrides `spec.deployments.replicas` as:

```
apiVersion: operator.knative.dev/v1alpha1
kind: KnativeServing
metadata:
  name: ks
  namespace: knative-serving
spec:
  deployments:
  - name: webhook
    replicas: 3
```

But it does not change the values in `HorizontalPodAutoscaler`:

https://github.com/knative/operator/blob/f4ce4ff51a7fe3f6941073c7733a2e83f8b7faf1/pkg/reconciler/common/deployments_override.go#L86-L90


Some deployments (e.g. webhook, activator) deploys HPA so we need to change the values.

https://github.com/knative/operator/blob/f4ce4ff51a7fe3f6941073c7733a2e83f8b7faf1/cmd/operator/kodata/knative-serving/0.25.1/2-serving-core.yaml#L5435

Pull request:
set HPA replica values when workload overrides are set
Fixes #762

## Proposed Changes
* Set HPA `minReplicas` and `maxReplicas` when `workloads.replicas` overrides are present for an object with HPA
* Uses the same behaviour as for the `high-availability` field
* Moved HPA transformation logic to a common file
* Add Eventing HPAs to `hasHorizontalPodAutoscaler`
* Add HPA name mapping for Eventing HPAs that are named different to their target: `getHPAName`

**Release Note**
```release-note
The operator now sets HorizontalPodAutoscaler replicas (on resources with HPAs) when workload overrides are defined.
```


Patch:
diff --git a/OWNERS_ALIASES b/OWNERS_ALIASES
index 6b7e972ec..386d7b4f1 100644
--- a/OWNERS_ALIASES
+++ b/OWNERS_ALIASES
@@ -36,6 +36,7 @@ aliases:
   - snneji
   eventing-reviewers:
   - aslom
+  - cali0707
   - creydr
   eventing-triage:
   - lberk
diff --git a/config/crd/bases/operator.knative.dev_knativeservings.yaml b/config/crd/bases/operator.knative.dev_knativeservings.yaml
index e59e59f14..db51f012a 100644
--- a/config/crd/bases/operator.knative.dev_knativeservings.yaml
+++ b/config/crd/bases/operator.knative.dev_knativeservings.yaml
@@ -2310,6 +2310,8 @@ spec:
                         type: boolean
                       service-type:
                         type: string
+                      service-load-balancer-ip:
+                        type: string
                       bootstrap-configmap:
                         type: string
                       http-port:
diff --git a/go.mod b/go.mod
index e4ae5674f..3d4de01f3 100644
--- a/go.mod
+++ b/go.mod
@@ -21,11 +21,11 @@ require (
 	k8s.io/client-go v0.26.5
 	k8s.io/code-generator v0.26.5
 	k8s.io/utils v0.0.0-20221108210102-8e77b1f39fe2
-	knative.dev/caching v0.0.0-20230906132213-a6afde1d97e9
-	knative.dev/eventing v0.38.1-0.20230906134312-a7b39bc87990
-	knative.dev/hack v0.0.0-20230906172513-760813ad2706
-	knative.dev/pkg v0.0.0-20230905144417-27252a376b30
-	knative.dev/serving v0.38.1-0.20230906132413-aeb4e94d5752
+	knative.dev/caching v0.0.0-20230911131321-f18279268e0e
+	knative.dev/eventing v0.38.1-0.20230911130820-74baa8fdca9d
+	knative.dev/hack v0.0.0-20230911131120-3af329f73ff3
+	knative.dev/pkg v0.0.0-20230911130819-09df2b681efd
+	knative.dev/serving v0.38.1-0.20230912012518-997d8ef27e0d
 	sigs.k8s.io/yaml v1.3.0
 )
 
@@ -139,7 +139,7 @@ require (
 	k8s.io/gengo v0.0.0-20221011193443-fad74ee6edd9 // indirect
 	k8s.io/klog/v2 v2.80.2-0.20221028030830-9ae4992afb54 // indirect
 	k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 // indirect
-	knative.dev/networking v0.0.0-20230830115731-dfd6edf47b91 // indirect
+	knative.dev/networking v0.0.0-20230906132213-17b4f7b1ea4a // indirect
 	sigs.k8s.io/controller-runtime v0.7.2 // indirect
 	sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect
 	sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
diff --git a/go.sum b/go.sum
index 74095566e..504b095d3 100644
--- a/go.sum
+++ b/go.sum
@@ -1397,18 +1397,18 @@ k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a/go.mod h1:jPW/WVKK9YHAvNhRxK0md/
 k8s.io/utils v0.0.0-20210930125809-cb0fa318a74b/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
 k8s.io/utils v0.0.0-20221108210102-8e77b1f39fe2 h1:GfD9OzL11kvZN5iArC6oTS7RTj7oJOIfnislxYlqTj8=
 k8s.io/utils v0.0.0-20221108210102-8e77b1f39fe2/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
-knative.dev/caching v0.0.0-20230906132213-a6afde1d97e9 h1:jwVftPnlpNSGHi5MPQaIjkLwhQWEZrm3SqMashXcA9g=
-knative.dev/caching v0.0.0-20230906132213-a6afde1d97e9/go.mod h1:cupRWm54x4N6X691zx3SstFaC1R0hs7EzNtsIYiUk5M=
-knative.dev/eventing v0.38.1-0.20230906134312-a7b39bc87990 h1:YflLmrwRJPBbN7Ayfw63HC2kmt2wRzYLY0LBsh9OkiA=
-knative.dev/eventing v0.38.1-0.20230906134312-a7b39bc87990/go.mod h1:3iuqypXhO+GTuy4Bn/53aWFBOglcY+cOzx4UFBDqsTA=
-knative.dev/hack v0.0.0-20230906172513-760813ad2706 h1:5/b4gPIUUNqVFkDKO9AMnEkdUvZrFVqf+z3r5rJ9w/U=
-knative.dev/hack v0.0.0-20230906172513-760813ad2706/go.mod h1:dx0YG3YWqJu653e9tjcT0Q1ZdS9JJXLKbUhzr4EB0g8=
-knative.dev/networking v0.0.0-20230830115731-dfd6edf47b91 h1:D3Pca9E6Jk7w2QmDaXeSjSRL2apMMA57Dtjt8efgii8=
-knative.dev/networking v0.0.0-20230830115731-dfd6edf47b91/go.mod h1:1voQlQD0tuot6U3Kldw+uch33mK2LV85fi3MfbV0CP8=
-knative.dev/pkg v0.0.0-20230905144417-27252a376b30 h1:q8OCYCux80XnBIscEUTyK9kMAM5cYhPMXlU0b77maz0=
-knative.dev/pkg v0.0.0-20230905144417-27252a376b30/go.mod h1:KOCW7iby+PL0aSDG2Ta7Vf1kCn+VAqL7QaTyK0c4fuk=
-knative.dev/serving v0.38.1-0.20230906132413-aeb4e94d5752 h1:AoeSPwhpamWSF9hqK+PsmXqCGFpwhNEgOg9juW6qxww=
-knative.dev/serving v0.38.1-0.20230906132413-aeb4e94d5752/go.mod h1:n6R3LX2i+sIdOsSYlUN5W9HuSdG/3+QN13VwCSsmPMk=
+knative.dev/caching v0.0.0-20230911131321-f18279268e0e h1:OZ5V5zyUKOUUdabuQ6FO6Cxz400VgZ9D/0ORyucqm3c=
+knative.dev/caching v0.0.0-20230911131321-f18279268e0e/go.mod h1:zBNGNn1uvHCpDqOxJbqs2qyn+RUYikCXlQAegkGpjqk=
+knative.dev/eventing v0.38.1-0.20230911130820-74baa8fdca9d h1:JOWFfjNkEqxWtgvTyGGrXuuE1vK3+tOk9JpgbuHYX/0=
+knative.dev/eventing v0.38.1-0.20230911130820-74baa8fdca9d/go.mod h1:V81fCtozZsKFXTLix6y0BXEguzUo+FCcJGzNfjL7JHc=
+knative.dev/hack v0.0.0-20230911131120-3af329f73ff3 h1:3vOdwAi/IjOTQvL2nP3RDRgPuYIbSRqEgaIgAgDFC08=
+knative.dev/hack v0.0.0-20230911131120-3af329f73ff3/go.mod h1:dx0YG3YWqJu653e9tjcT0Q1ZdS9JJXLKbUhzr4EB0g8=
+knative.dev/networking v0.0.0-20230906132213-17b4f7b1ea4a h1:xiF0cQfHuo0qBoaSeXjyk+56Cu1gYv0ezu6qMx9E8us=
+knative.dev/networking v0.0.0-20230906132213-17b4f7b1ea4a/go.mod h1:nXiCx9KmJ5WgDofa8zOXA5poIQe8GeBL/neZtQyfobg=
+knative.dev/pkg v0.0.0-20230911130819-09df2b681efd h1:p73TV5lMulQpFpa7FBMSGORaL9MFzENu+IVhMv/ELMs=
+knative.dev/pkg v0.0.0-20230911130819-09df2b681efd/go.mod h1:KOCW7iby+PL0aSDG2Ta7Vf1kCn+VAqL7QaTyK0c4fuk=
+knative.dev/serving v0.38.1-0.20230912012518-997d8ef27e0d h1:QiE3llHJVKeUi/R79jfobuH5h4vNAzerW/u4s4XEq30=
+knative.dev/serving v0.38.1-0.20230912012518-997d8ef27e0d/go.mod h1:v3lJx+0X60fxa+0yu6DY94ez1qbf6bt1vp7iXglHipU=
 nhooyr.io/websocket v1.8.6/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0=
 pgregory.net/rapid v1.0.0 h1:iQaM2w5PZ6xvt6x7hbd7tiDS+nk7YPp5uCaEba+T/F4=
 rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
diff --git a/pkg/apis/operator/base/ingressconfiguration.go b/pkg/apis/operator/base/ingressconfiguration.go
index 7c98a8f39..9da7337dc 100644
--- a/pkg/apis/operator/base/ingressconfiguration.go
+++ b/pkg/apis/operator/base/ingressconfiguration.go
@@ -41,6 +41,9 @@ type KourierIngressConfiguration struct {
 	// ServiceType specifies the service type for kourier gateway.
 	ServiceType v1.ServiceType `json:"service-type,omitempty"`
 
+	// ServiceLoadBalancerIP specifies the service load balancer IP.
+	ServiceLoadBalancerIP string `json:"service-load-balancer-ip,omitempty"`
+
 	// HTTPPort specifies the port used in case of ServiceType = "NodePort" for http traffic
 	HTTPPort int32 `json:"http-port,omitempty"`
 
diff --git a/pkg/reconciler/common/ha.go b/pkg/reconciler/common/ha.go
index 3d1004e09..968608658 100644
--- a/pkg/reconciler/common/ha.go
+++ b/pkg/reconciler/common/ha.go
@@ -18,32 +18,21 @@ package common
 
 import (
 	mf "github.com/manifestival/manifestival"
-	"go.uber.org/zap"
 	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
 	"k8s.io/apimachinery/pkg/util/sets"
 
 	"knative.dev/operator/pkg/apis/operator/base"
 )
 
-func haUnSupported(obj base.KComponent) sets.String {
+func haUnSupported(name string) bool {
 	return sets.NewString(
 		"pingsource-mt-adapter",
-	)
-}
-
-// When Deployment has HPA, the replicas should be controlled by HPA's minReplicas instead of operator.
-// Hence, skip changing the spec.replicas in deployment directory for these Deployments.
-func hasHorizontalPodAutoscaler(obj base.KComponent) sets.String {
-	return sets.NewString(
-		"webhook",
-		"activator",
-		"3scale-kourier-gateway",
-	)
+	).Has(name)
 }
 
 // HighAvailabilityTransform mutates configmaps and replicacounts of certain
 // controllers when HA control plane is specified.
-func HighAvailabilityTransform(obj base.KComponent, log *zap.SugaredLogger) mf.Transformer {
+func HighAvailabilityTransform(obj base.KComponent) mf.Transformer {
 	return func(u *unstructured.Unstructured) error {
 		// Use spec.deployments.replicas for the deployment instead of spec.high-availability.
 		for _, override := range obj.GetSpec().GetWorkloadOverrides() {
@@ -61,39 +50,14 @@ func HighAvailabilityTransform(obj base.KComponent, log *zap.SugaredLogger) mf.T
 		replicas := int64(*ha.Replicas)
 
 		// Transform deployments that support HA.
-		if u.GetKind() == "Deployment" && !haUnSupported(obj).Has(u.GetName()) && !hasHorizontalPodAutoscaler(obj).Has(u.GetName()) {
+		if u.GetKind() == "Deployment" && !haUnSupported(u.GetName()) && !hasHorizontalPodAutoscaler(u.GetName()) {
 			if err := unstructured.SetNestedField(u.Object, replicas, "spec", "replicas"); err != nil {
 				return err
 			}
 		}
 
 		if u.GetKind() == "HorizontalPodAutoscaler" {
-			min, _, err := unstructured.NestedInt64(u.Object, "spec", "minReplicas")
-			if err != nil {
-				return err
-			}
-			// Do nothing if the HPA ships with even more replicas out of the box.
-			if min >= replicas {
-				return nil
-			}
-
-			if err := unstructured.SetNestedField(u.Object, replicas, "spec", "minReplicas"); err != nil {
-				return err
-			}
-
-			max, found, err := unstructured.NestedInt64(u.Object, "spec", "maxReplicas")
-			if err != nil {
-				return err
-			}
-
-			// Do nothing if maxReplicas is not defined.
-			if !found {
-				return nil
-			}
-
-			// Increase maxReplicas to the amount that we increased,
-			// because we need to avoid minReplicas > maxReplicas happenning.
-			if err := unstructured.SetNestedField(u.Object, max+(replicas-min), "spec", "maxReplicas"); err != nil {
+			if err := hpaTransform(u, replicas); err != nil {
 				return err
 			}
 		}
diff --git a/pkg/reconciler/common/hpa.go b/pkg/reconciler/common/hpa.go
new file mode 100644
index 000000000..fba4a35cd
--- /dev/null
+++ b/pkg/reconciler/common/hpa.go
@@ -0,0 +1,89 @@
+/*
+Copyright 2023 The Knative Authors
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package common
+
+import (
+	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
+	"k8s.io/apimachinery/pkg/util/sets"
+)
+
+// When a Podspecable has HPA, the replicas should be controlled by HPAs minReplicas instead of operator.
+// Hence, skip changing the spec.replicas for these Podspecables.
+func hasHorizontalPodAutoscaler(name string) bool {
+	return sets.NewString(
+		"webhook",
+		"activator",
+		"3scale-kourier-gateway",
+		"eventing-webhook",
+		"mt-broker-ingress",
+		"mt-broker-filter",
+	).Has(name)
+}
+
+// Maps a Podspecables name to the HPAs name.
+// Add overrides here, if your HPA is named differently to the workloads name,
+// if no override is defined, the name of the podspecable is used as HPA name.
+func getHPAName(podspecableName string) string {
+	overrides := map[string]string{
+		"mt-broker-ingress": "broker-ingress-hpa",
+		"mt-broker-filter":  "broker-filter-hpa",
+	}
+	if v, ok := overrides[podspecableName]; ok {
+		return v
+	} else {
+		return podspecableName
+	}
+}
+
+// hpaTransform sets the minReplicas and maxReplicas of an HPA based on a replica override value.
+// If minReplica needs to be increased, the maxReplica is increased by the same value.
+func hpaTransform(u *unstructured.Unstructured, replicas int64) error {
+	if u.GetKind() != "HorizontalPodAutoscaler" {
+		return nil
+	}
+
+	min, _, err := unstructured.NestedInt64(u.Object, "spec", "minReplicas")
+	if err != nil {
+		return err
+	}
+
+	// Do nothing if the HPA ships with even more replicas out of the box.
+	if min >= replicas {
+		return nil
+	}
+
+	if err := unstructured.SetNestedField(u.Object, replicas, "spec", "minReplicas"); err != nil {
+		return err
+	}
+
+	max, found, err := unstructured.NestedInt64(u.Object, "spec", "maxReplicas")
+	if err != nil {
+		return err
+	}
+
+	// Do nothing if maxReplicas is not defined.
+	if !found {
+		return nil
+	}
+
+	// Increase maxReplicas to the amount that we increased,
+	// because we need to avoid minReplicas > maxReplicas happening.
+	if err := unstructured.SetNestedField(u.Object, max+(replicas-min), "spec", "maxReplicas"); err != nil {
+		return err
+	}
+	return nil
+}
diff --git a/pkg/reconciler/common/transformers.go b/pkg/reconciler/common/transformers.go
index 8b8fcdc0d..34ec3a1d8 100644
--- a/pkg/reconciler/common/transformers.go
+++ b/pkg/reconciler/common/transformers.go
@@ -30,7 +30,7 @@ func transformers(ctx context.Context, obj base.KComponent) []mf.Transformer {
 	return []mf.Transformer{
 		injectOwner(obj),
 		mf.InjectNamespace(obj.GetNamespace()),
-		HighAvailabilityTransform(obj, logger),
+		HighAvailabilityTransform(obj),
 		ImageTransform(obj.GetSpec().GetRegistry(), logger),
 		JobTransform(obj),
 		ConfigMapTransform(obj.GetSpec().GetConfig(), logger),
diff --git a/pkg/reconciler/common/workload_override.go b/pkg/reconciler/common/workload_override.go
index 8f334f6a7..a979b57af 100644
--- a/pkg/reconciler/common/workload_override.go
+++ b/pkg/reconciler/common/workload_override.go
@@ -47,7 +47,9 @@ func OverridesTransform(overrides []base.WorkloadOverride, log *zap.SugaredLogge
 				}
 				obj = deployment
 				ps = &deployment.Spec.Template
-				if override.Replicas != nil {
+
+				// Do not set replicas, if this resource is controlled by a HPA
+				if override.Replicas != nil && !hasHorizontalPodAutoscaler(override.Name) {
 					deployment.Spec.Replicas = override.Replicas
 				}
 			}
@@ -58,7 +60,9 @@ func OverridesTransform(overrides []base.WorkloadOverride, log *zap.SugaredLogge
 				}
 				obj = ss
 				ps = &ss.Spec.Template
-				if override.Replicas != nil {
+
+				// Do not set replicas, if this resource is controlled by a HPA
+				if override.Replicas != nil && !hasHorizontalPodAutoscaler(override.Name) {
 					ss.Spec.Replicas = override.Replicas
 				}
 			}
@@ -71,6 +75,13 @@ func OverridesTransform(overrides []base.WorkloadOverride, log *zap.SugaredLogge
 				ps = &job.Spec.Template
 			}
 
+			if u.GetKind() == "HorizontalPodAutoscaler" && override.Replicas != nil && u.GetName() == getHPAName(override.Name) {
+				overrideReplicas := int64(*override.Replicas)
+				if err := hpaTransform(u, overrideReplicas); err != nil {
+					return err
+				}
+			}
+
 			if obj == nil {
 				continue
 			}
diff --git a/pkg/reconciler/knativeserving/ingress/kourier.go b/pkg/reconciler/knativeserving/ingress/kourier.go
index a76bee20e..ad95d9e20 100644
--- a/pkg/reconciler/knativeserving/ingress/kourier.go
+++ b/pkg/reconciler/knativeserving/ingress/kourier.go
@@ -40,15 +40,15 @@ var kourierControllerDeploymentNames = sets.NewString("3scale-kourier-control",
 
 func kourierTransformers(ctx context.Context, instance *v1beta1.KnativeServing) []mf.Transformer {
 	return []mf.Transformer{
-		replaceGWNamespace(),
-		configureGWServiceType(instance),
+		replaceGatewayNamespace(),
+		configureGatewayService(instance),
 		configureBootstrapConfigMap(instance),
 	}
 }
 
-// replaceGWNamespace replace the environment variable KOURIER_GATEWAY_NAMESPACE with the
+// replaceGatewayNamespace replace the environment variable KOURIER_GATEWAY_NAMESPACE with the
 // namespace of the deployment its set on.
-func replaceGWNamespace() mf.Transformer {
+func replaceGatewayNamespace() mf.Transformer {
 	return func(u *unstructured.Unstructured) error {
 		if u.GetKind() == "Deployment" && kourierControllerDeploymentNames.Has(u.GetName()) {
 			deployment := &appsv1.Deployment{}
@@ -74,39 +74,50 @@ func replaceGWNamespace() mf.Transformer {
 	}
 }
 
-// configureGWServiceType configures Kourier GW's service type such as ClusterIP, LoadBalancer and NodePort.
-func configureGWServiceType(instance *v1beta1.KnativeServing) mf.Transformer {
+func configureGatewayService(instance *v1beta1.KnativeServing) mf.Transformer {
 	return func(u *unstructured.Unstructured) error {
-		if u.GetKind() == "Service" && u.GetName() == kourierGatewayServiceName {
-			if instance.Spec.Ingress.Kourier.ServiceType == "" {
-				// Do nothing if ServiceType is not configured.
-				return nil
-			}
-			svc := &v1.Service{}
-			if err := scheme.Scheme.Convert(u, svc, nil); err != nil {
-				return err
-			}
+		if !(u.GetKind() == "Service" && u.GetName() == kourierGatewayServiceName) {
+			return nil
+		}
+
+		svc := &v1.Service{}
+		if err := scheme.Scheme.Convert(u, svc, nil); err != nil {
+			return err
+		}
 
+		// First configure the Service Type.
+		if instance.Spec.Ingress.Kourier.ServiceType != "" {
 			serviceType := instance.Spec.Ingress.Kourier.ServiceType
 			switch serviceType {
 			case v1.ServiceTypeClusterIP, v1.ServiceTypeLoadBalancer:
 				svc.Spec.Type = serviceType
 			case v1.ServiceTypeNodePort:
 				svc.Spec.Type = serviceType
-				if instance.Spec.Ingress.Kourier.HTTPPort > 0 || instance.Spec.Ingress.Kourier.HTTPSPort > 0 {
-					configureGWServiceTypeNodePort(instance, svc)
-				}
 			case v1.ServiceTypeExternalName:
 				return fmt.Errorf("unsupported service type %q", serviceType)
 			default:
 				return fmt.Errorf("unknown service type %q", serviceType)
 			}
+		}
 
-			if err := scheme.Scheme.Convert(svc, u, nil); err != nil {
-				return err
+		// Configure LoadBalancerIP if set.
+		if instance.Spec.Ingress.Kourier.ServiceLoadBalancerIP != "" {
+			if svc.Spec.Type != v1.ServiceTypeLoadBalancer {
+				return fmt.Errorf("cannot configure LoadBalancerIP for service type %q", svc.Spec.Type)
 			}
+			svc.Spec.LoadBalancerIP = instance.Spec.Ingress.Kourier.ServiceLoadBalancerIP
 		}
-		return nil
+
+		// Configure HTTPPort/HTTPSPort if set.
+		if instance.Spec.Ingress.Kourier.HTTPPort > 0 || instance.Spec.Ingress.Kourier.HTTPSPort > 0 {
+			if svc.Spec.Type != v1.ServiceTypeNodePort {
+				return fmt.Errorf("cannot configure HTTP(S)Port for service type %q", svc.Spec.Type)
+			}
+			configureGatewayServiceTypeNodePort(instance, svc)
+		}
+
+		// Return any conversion error or nil
+		return scheme.Scheme.Convert(svc, u, nil)
 	}
 }
 
@@ -144,7 +155,7 @@ func configureBootstrapConfigMap(instance *v1beta1.KnativeServing) mf.Transforme
 	}
 }
 
-func configureGWServiceTypeNodePort(instance *v1beta1.KnativeServing, svc *v1.Service) {
+func configureGatewayServiceTypeNodePort(instance *v1beta1.KnativeServing, svc *v1.Service) {
 	for i, v := range svc.Spec.Ports {
 		if v.Name != "https" && instance.Spec.Ingress.Kourier.HTTPPort > 0 {
 			v.NodePort = instance.Spec.Ingress.Kourier.HTTPPort
diff --git a/vendor/knative.dev/eventing/pkg/apis/eventing/v1/broker_lifecycle.go b/vendor/knative.dev/eventing/pkg/apis/eventing/v1/broker_lifecycle.go
index ebe569271..9bc846e89 100644
--- a/vendor/knative.dev/eventing/pkg/apis/eventing/v1/broker_lifecycle.go
+++ b/vendor/knative.dev/eventing/pkg/apis/eventing/v1/broker_lifecycle.go
@@ -74,16 +74,14 @@ func (bs *BrokerStatus) GetTopLevelCondition() *apis.Condition {
 
 // SetAddress makes this Broker addressable by setting the URI. It also
 // sets the BrokerConditionAddressable to true.
-func (bs *BrokerStatus) SetAddress(url *apis.URL) {
+func (bs *BrokerStatus) SetAddress(address *v1.Addressable) {
 	bs.AddressStatus = v1.AddressStatus{
-		Address: &v1.Addressable{
-			URL: url,
-		},
+		Address: address,
 	}
 
-	if url != nil {
+	if address != nil && address.URL != nil {
 		bs.GetConditionSet().Manage(bs).MarkTrue(BrokerConditionAddressable)
-		bs.AddressStatus.Address.Name = &url.Scheme
+		bs.AddressStatus.Address.Name = &address.URL.Scheme
 	} else {
 		bs.GetConditionSet().Manage(bs).MarkFalse(BrokerConditionAddressable, "nil URL", "URL is nil")
 	}
diff --git a/vendor/knative.dev/serving/AUTHORS b/vendor/knative.dev/serving/AUTHORS
deleted file mode 100644
index f42714c4e..000000000
--- a/vendor/knative.dev/serving/AUTHORS
+++ /dev/null
@@ -1,11 +0,0 @@
-# This is the list of Knative authors for copyright purposes.
-#
-# This does not necessarily list everyone who has contributed code, since in
-# some cases, their employer may be the copyright holder.  To see the full list
-# of contributors, see the revision history in source control.
-Google LLC
-Pivotal Software, Inc.
-IBM Corp
-Red Hat, Inc.
-Cisco Systems, Inc.
-VMware, Inc.
diff --git a/vendor/knative.dev/serving/pkg/apis/serving/v1/route_lifecycle.go b/vendor/knative.dev/serving/pkg/apis/serving/v1/route_lifecycle.go
index ba2908cd1..fe2a43223 100644
--- a/vendor/knative.dev/serving/pkg/apis/serving/v1/route_lifecycle.go
+++ b/vendor/knative.dev/serving/pkg/apis/serving/v1/route_lifecycle.go
@@ -193,7 +193,7 @@ const (
 	// AutoTLSNotEnabledMessage is the message which is set on the
 	// RouteConditionCertificateProvisioned condition when it is set to True
 	// because AutoTLS was not enabled.
-	AutoTLSNotEnabledMessage = "autoTLS is not enabled"
+	AutoTLSNotEnabledMessage = "auto-tls is not enabled"
 
 	// TLSNotEnabledForClusterLocalMessage is the message which is set on the
 	// RouteConditionCertificateProvisioned condition when it is set to True
@@ -202,7 +202,7 @@ const (
 )
 
 // MarkTLSNotEnabled sets RouteConditionCertificateProvisioned to true when
-// certificate config such as autoTLS is not enabled or private cluster-local service.
+// certificate config such as auto-tls is not enabled or private cluster-local service.
 func (rs *RouteStatus) MarkTLSNotEnabled(msg string) {
 	routeCondSet.Manage(rs).MarkTrueWithReason(RouteConditionCertificateProvisioned,
 		"TLSNotEnabled", msg)
diff --git a/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/domainmapping_lifecycle.go b/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/domainmapping_lifecycle.go
index 80fed9d33..830a65c96 100644
--- a/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/domainmapping_lifecycle.go
+++ b/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/domainmapping_lifecycle.go
@@ -62,7 +62,7 @@ const (
 	// AutoTLSNotEnabledMessage is the message which is set on the
 	// DomainMappingConditionCertificateProvisioned condition when it is set to True
 	// because AutoTLS was not enabled.
-	AutoTLSNotEnabledMessage = "autoTLS is not enabled"
+	AutoTLSNotEnabledMessage = "auto-tls is not enabled"
 	// TLSCertificateProvidedExternally indicates that a TLS secret won't be created or managed
 	// instead a reference to an existing TLS secret should have been provided in the DomainMapping spec
 	TLSCertificateProvidedExternally = "TLS certificate was provided externally"
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 49f201fcf..174b279be 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -1256,11 +1256,11 @@ k8s.io/utils/net
 k8s.io/utils/pointer
 k8s.io/utils/strings/slices
 k8s.io/utils/trace
-# knative.dev/caching v0.0.0-20230906132213-a6afde1d97e9
+# knative.dev/caching v0.0.0-20230911131321-f18279268e0e
 ## explicit; go 1.18
 knative.dev/caching/pkg/apis/caching
 knative.dev/caching/pkg/apis/caching/v1alpha1
-# knative.dev/eventing v0.38.1-0.20230906134312-a7b39bc87990
+# knative.dev/eventing v0.38.1-0.20230911130820-74baa8fdca9d
 ## explicit; go 1.19
 knative.dev/eventing/pkg/apis/config
 knative.dev/eventing/pkg/apis/duck
@@ -1349,11 +1349,11 @@ knative.dev/eventing/test/upgrade/prober/wathola/fetcher
 knative.dev/eventing/test/upgrade/prober/wathola/forwarder
 knative.dev/eventing/test/upgrade/prober/wathola/receiver
 knative.dev/eventing/test/upgrade/prober/wathola/sender
-# knative.dev/hack v0.0.0-20230906172513-760813ad2706
+# knative.dev/hack v0.0.0-20230911131120-3af329f73ff3
 ## explicit; go 1.18
 knative.dev/hack
 knative.dev/hack/shell
-# knative.dev/networking v0.0.0-20230830115731-dfd6edf47b91
+# knative.dev/networking v0.0.0-20230906132213-17b4f7b1ea4a
 ## explicit; go 1.18
 knative.dev/networking/pkg
 knative.dev/networking/pkg/apis/networking
@@ -1368,7 +1368,7 @@ knative.dev/networking/pkg/http/probe
 knative.dev/networking/pkg/http/proxy
 knative.dev/networking/pkg/http/stats
 knative.dev/networking/pkg/k8s
-# knative.dev/pkg v0.0.0-20230905144417-27252a376b30
+# knative.dev/pkg v0.0.0-20230911130819-09df2b681efd
 ## explicit; go 1.18
 knative.dev/pkg/apiextensions/storageversion
 knative.dev/pkg/apiextensions/storageversion/cmd/migrate
@@ -1448,7 +1448,7 @@ knative.dev/pkg/webhook
 knative.dev/pkg/webhook/certificates
 knative.dev/pkg/webhook/certificates/resources
 knative.dev/pkg/webhook/resourcesemantics/conversion
-# knative.dev/serving v0.38.1-0.20230906132413-aeb4e94d5752
+# knative.dev/serving v0.38.1-0.20230912012518-997d8ef27e0d
 ## explicit; go 1.18
 knative.dev/serving/pkg/apis/autoscaling
 knative.dev/serving/pkg/apis/autoscaling/v1alpha1


Test patch:
diff --git a/pkg/reconciler/common/ha_test.go b/pkg/reconciler/common/ha_test.go
index a3ef3ed3c..cb5b4a318 100644
--- a/pkg/reconciler/common/ha_test.go
+++ b/pkg/reconciler/common/ha_test.go
@@ -23,7 +23,6 @@ import (
 	"knative.dev/operator/pkg/apis/operator/v1beta1"
 
 	appsv1 "k8s.io/api/apps/v1"
-	autoscalingv2beta1 "k8s.io/api/autoscaling/v2beta1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
 	"k8s.io/client-go/kubernetes/scheme"
@@ -74,10 +73,10 @@ func TestHighAvailabilityTransform(t *testing.T) {
 		in:       makeUnstructuredHPA(t, "activator", 2, 5),
 		expected: makeUnstructuredHPA(t, "activator", 2, 5),
 	}, {
-		name:     "HA; adjust hpa when replicas is lerger than maxReplicas",
+		name:     "HA; adjust hpa when replicas is larger than maxReplicas",
 		config:   makeHa(6),
 		in:       makeUnstructuredHPA(t, "activator", 2, 5),
-		expected: makeUnstructuredHPA(t, "activator", 6, 9), // maxReplicas is increased by max+(replicas-min) to avoid minReplicas > maxReplicas happenning.
+		expected: makeUnstructuredHPA(t, "activator", 6, 9), // maxReplicas is increased by max+(replicas-min) to avoid minReplicas > maxReplicas happening.
 	}, {
 		name:     "HA; adjust hpa when minReplica is equal to maxReplicas",
 		config:   makeHa(3),
@@ -107,7 +106,7 @@ func TestHighAvailabilityTransform(t *testing.T) {
 					},
 				},
 			}
-			haTransform := HighAvailabilityTransform(instance, log)
+			haTransform := HighAvailabilityTransform(instance)
 			err := haTransform(tc.in)
 
 			util.AssertDeepEqual(t, err, tc.err)
@@ -143,23 +142,3 @@ func makeUnstructuredDeploymentReplicas(t *testing.T, name string, replicas int3
 
 	return result
 }
-
-func makeUnstructuredHPA(t *testing.T, name string, minReplicas, maxReplicas int32) *unstructured.Unstructured {
-	hpa := &autoscalingv2beta1.HorizontalPodAutoscaler{
-		ObjectMeta: metav1.ObjectMeta{
-			Name: name,
-		},
-		Spec: autoscalingv2beta1.HorizontalPodAutoscalerSpec{
-			MinReplicas: &minReplicas,
-			MaxReplicas: maxReplicas,
-		},
-	}
-
-	result := &unstructured.Unstructured{}
-	err := scheme.Scheme.Convert(hpa, result, nil)
-	if err != nil {
-		t.Fatalf("Could not create unstructured HPA: %v, err: %v", hpa, err)
-	}
-
-	return result
-}
diff --git a/pkg/reconciler/common/hpa_test.go b/pkg/reconciler/common/hpa_test.go
new file mode 100644
index 000000000..e3d0bf487
--- /dev/null
+++ b/pkg/reconciler/common/hpa_test.go
@@ -0,0 +1,90 @@
+/*
+Copyright 2023 The Knative Authors
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package common
+
+import (
+	"testing"
+
+	"k8s.io/api/autoscaling/v2beta1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
+	"k8s.io/client-go/kubernetes/scheme"
+	util "knative.dev/operator/pkg/reconciler/common/testing"
+)
+
+func TestHpaTransform(t *testing.T) {
+	cases := []struct {
+		name     string
+		in       *unstructured.Unstructured
+		replicas int64
+		expected *unstructured.Unstructured
+		err      error
+	}{{
+		name:     "Object is not a HPA",
+		in:       makeUnstructuredDeployment(t, "not-a-hpa"),
+		replicas: 5,
+		expected: makeUnstructuredDeployment(t, "not-a-hpa"),
+		err:      nil,
+	}, {
+		name:     "minReplicas same as override",
+		in:       makeUnstructuredHPA(t, "hpa", 1, 2),
+		replicas: 1,
+		expected: makeUnstructuredHPA(t, "hpa", 1, 2),
+		err:      nil,
+	}, {
+		name:     "minReplicas lower than override",
+		in:       makeUnstructuredHPA(t, "hpa", 1, 2),
+		replicas: 5,
+		expected: makeUnstructuredHPA(t, "hpa", 5, 6),
+		err:      nil,
+	}}
+
+	for _, tc := range cases {
+		t.Run(tc.name, func(t *testing.T) {
+
+			err := hpaTransform(tc.in, tc.replicas)
+
+			util.AssertDeepEqual(t, err, tc.err)
+			util.AssertDeepEqual(t, tc.in, tc.expected)
+		})
+	}
+}
+
+func TestGetHPAName(t *testing.T) {
+	util.AssertEqual(t, getHPAName("mt-broker-ingress"), "broker-ingress-hpa")
+	util.AssertEqual(t, getHPAName("activator"), "activator")
+}
+
+func makeUnstructuredHPA(t *testing.T, name string, minReplicas, maxReplicas int32) *unstructured.Unstructured {
+	hpa := &v2beta1.HorizontalPodAutoscaler{
+		ObjectMeta: metav1.ObjectMeta{
+			Name: name,
+		},
+		Spec: v2beta1.HorizontalPodAutoscalerSpec{
+			MinReplicas: &minReplicas,
+			MaxReplicas: maxReplicas,
+		},
+	}
+
+	result := &unstructured.Unstructured{}
+	err := scheme.Scheme.Convert(hpa, result, nil)
+	if err != nil {
+		t.Fatalf("Could not create unstructured HPA: %v, err: %v", hpa, err)
+	}
+
+	return result
+}
diff --git a/pkg/reconciler/common/workload_override_test.go b/pkg/reconciler/common/workload_override_test.go
index 91d9a75d4..356de1dba 100644
--- a/pkg/reconciler/common/workload_override_test.go
+++ b/pkg/reconciler/common/workload_override_test.go
@@ -24,6 +24,7 @@ import (
 	mf "github.com/manifestival/manifestival"
 	"google.golang.org/api/googleapi"
 	appsv1 "k8s.io/api/apps/v1"
+	"k8s.io/api/autoscaling/v2beta1"
 	batchv1 "k8s.io/api/batch/v1"
 	corev1 "k8s.io/api/core/v1"
 	v1 "k8s.io/api/core/v1"
@@ -56,6 +57,11 @@ type expDeployments struct {
 	expDNSPolicy                 *corev1.DNSPolicy
 }
 
+type expHorizontalPodAutoscalers struct {
+	expMinReplicas int32
+	expMaxReplicas int32
+}
+
 type expJobs struct {
 	expNodeSelector map[string]string
 	expTolerations  []corev1.Toleration
@@ -65,12 +71,13 @@ func TestComponentsTransform(t *testing.T) {
 	var four int32 = 4
 	var five int32 = 5
 	var defaultDnsPolicy = corev1.DNSPolicy("")
-	var dnsClusterFirstWithHostNet corev1.DNSPolicy = corev1.DNSClusterFirstWithHostNet
+	var dnsClusterFirstWithHostNet = corev1.DNSClusterFirstWithHostNet
 	tests := []struct {
-		name           string
-		override       []base.WorkloadOverride
-		globalReplicas int32
-		expDeployment  map[string]expDeployments
+		name                       string
+		override                   []base.WorkloadOverride
+		globalReplicas             int32
+		expDeployment              map[string]expDeployments
+		expHorizontalPodAutoscaler map[string]expHorizontalPodAutoscalers
 	}{{
 		name:     "no override",
 		override: nil,
@@ -147,7 +154,7 @@ func TestComponentsTransform(t *testing.T) {
 			expDNSPolicy:   nil,
 		}},
 	}, {
-		name: "no replicas in deploymentoverride, use global replicas",
+		name: "no replicas in workload override, use global replicas",
 		override: []base.WorkloadOverride{
 			{Name: "controller"},
 		},
@@ -544,7 +551,7 @@ func TestComponentsTransform(t *testing.T) {
 			},
 		}},
 	}, {
-		name: "neither replicas in deploymentoverride nor global replicas",
+		name: "neither replicas in workload override nor global replicas",
 		override: []base.WorkloadOverride{
 			{Name: "controller"},
 		},
@@ -672,7 +679,7 @@ func TestComponentsTransform(t *testing.T) {
 				expTemplateLabels:      map[string]string{"serving.knative.dev/release": "v0.13.0", "app": "webhook", "role": "webhook", "e": "f"},
 				expAnnotations:         map[string]string{"g": "h"},
 				expTemplateAnnotations: map[string]string{"cluster-autoscaler.kubernetes.io/safe-to-evict": "false", "g": "h"},
-				expReplicas:            4,
+				expReplicas:            0,
 				expNodeSelector:        map[string]string{"env": "prod"},
 				expTopologySpreadConstraints: []corev1.TopologySpreadConstraint{{
 					MaxSkew:           1,
@@ -705,6 +712,88 @@ func TestComponentsTransform(t *testing.T) {
 				expDNSPolicy:   &dnsClusterFirstWithHostNet,
 			},
 		},
+	}, {
+		name: "activator HPA no override",
+		expDeployment: map[string]expDeployments{
+			"activator": {
+				expLabels:              map[string]string{"serving.knative.dev/release": "v0.13.0"},
+				expTemplateLabels:      map[string]string{"serving.knative.dev/release": "v0.13.0", "app": "activator", "role": "activator"},
+				expAnnotations:         nil,
+				expTemplateAnnotations: map[string]string{"cluster-autoscaler.kubernetes.io/safe-to-evict": "false"},
+				expReplicas:            0, // if hpa is used, this should never be set
+			},
+		},
+		expHorizontalPodAutoscaler: map[string]expHorizontalPodAutoscalers{
+			"activator": {
+				expMinReplicas: 1,  // defined in manifest.yaml
+				expMaxReplicas: 20, // defined in manifest.yaml
+			},
+		},
+	}, {
+		name:           "activator HPA global replicas override",
+		globalReplicas: 10,
+		expDeployment: map[string]expDeployments{
+			"activator": {
+				expLabels:              map[string]string{"serving.knative.dev/release": "v0.13.0"},
+				expTemplateLabels:      map[string]string{"serving.knative.dev/release": "v0.13.0", "app": "activator", "role": "activator"},
+				expAnnotations:         nil,
+				expTemplateAnnotations: map[string]string{"cluster-autoscaler.kubernetes.io/safe-to-evict": "false"},
+				expReplicas:            0, // if hpa is used, this should never be set
+			},
+		},
+		expHorizontalPodAutoscaler: map[string]expHorizontalPodAutoscalers{
+			"activator": {
+				expMinReplicas: 10,
+				expMaxReplicas: 29, // in manifest.yaml maxReplicas=20 +9 (difference between existing min and overwritten min)
+			},
+		},
+	}, {
+		name: "activator HPA workload override",
+		override: []base.WorkloadOverride{
+			{
+				Name:     "activator",
+				Replicas: &four,
+			},
+		},
+		expDeployment: map[string]expDeployments{
+			"activator": {
+				expLabels:              map[string]string{"serving.knative.dev/release": "v0.13.0"},
+				expTemplateLabels:      map[string]string{"serving.knative.dev/release": "v0.13.0", "app": "activator", "role": "activator"},
+				expAnnotations:         nil,
+				expTemplateAnnotations: map[string]string{"cluster-autoscaler.kubernetes.io/safe-to-evict": "false"},
+				expReplicas:            0, // if hpa is used, this should never be set
+			},
+		},
+		expHorizontalPodAutoscaler: map[string]expHorizontalPodAutoscalers{
+			"activator": {
+				expMinReplicas: four,
+				expMaxReplicas: 23, // in manifest.yaml maxReplicas=20 +3 (difference between existing min and overwritten min)
+			},
+		},
+	}, {
+		name:           "activator HPA global and workload override",
+		globalReplicas: 10,
+		override: []base.WorkloadOverride{
+			{
+				Name:     "activator",
+				Replicas: &four,
+			},
+		},
+		expDeployment: map[string]expDeployments{
+			"activator": {
+				expLabels:              map[string]string{"serving.knative.dev/release": "v0.13.0"},
+				expTemplateLabels:      map[string]string{"serving.knative.dev/release": "v0.13.0", "app": "activator", "role": "activator"},
+				expAnnotations:         nil,
+				expTemplateAnnotations: map[string]string{"cluster-autoscaler.kubernetes.io/safe-to-evict": "false"},
+				expReplicas:            0, // if hpa is used, this should never be set
+			},
+		},
+		expHorizontalPodAutoscaler: map[string]expHorizontalPodAutoscalers{
+			"activator": {
+				expMinReplicas: four,
+				expMaxReplicas: 23, // in manifest.yaml maxReplicas=20 +3 (difference between existing min and overwritten min)
+			},
+		},
 	}}
 
 	for _, test := range tests {
@@ -739,8 +828,7 @@ func TestComponentsTransform(t *testing.T) {
 			for key, ks := range kss {
 				t.Run(key, func(t *testing.T) {
 
-					//manifest, err = manifest.Transform(OverridesTransform(ks, log), HighAvailabilityTransform(ks, log))
-					manifest, err = manifest.Transform(HighAvailabilityTransform(ks, log), OverridesTransform(ks.GetSpec().GetWorkloadOverrides(), log))
+					manifest, err = manifest.Transform(HighAvailabilityTransform(ks), OverridesTransform(ks.GetSpec().GetWorkloadOverrides(), log))
 					if err != nil {
 						t.Fatalf("Failed to transform manifest: %v", err)
 					}
@@ -797,12 +885,12 @@ func TestComponentsTransform(t *testing.T) {
 								}
 								r, l := getProbes(got.Spec.Template.Spec.Containers, expName)
 								if d.expReadinessProbe != nil {
-									if diff := cmp.Diff(*r, (*d.expReadinessProbe)); diff != "" {
+									if diff := cmp.Diff(*r, *d.expReadinessProbe); diff != "" {
 										t.Fatalf("Unexpected readiness probe in pod template: %v", diff)
 									}
 								}
 								if d.expLivenessProbe != nil {
-									if diff := cmp.Diff(*l, (*d.expLivenessProbe)); diff != "" {
+									if diff := cmp.Diff(*l, *d.expLivenessProbe); diff != "" {
 										t.Fatalf("Unexpected liveness probe in pod template: %v", diff)
 									}
 								}
@@ -823,6 +911,29 @@ func TestComponentsTransform(t *testing.T) {
 							}
 						}
 					}
+
+					for expName, d := range test.expHorizontalPodAutoscaler {
+						for _, u := range manifest.Resources() {
+							if u.GetKind() == "HorizontalPodAutoscaler" && u.GetName() == expName {
+								got := &v2beta1.HorizontalPodAutoscaler{}
+								if err := scheme.Scheme.Convert(&u, got, nil); err != nil {
+									t.Fatalf("Failed to convert unstructured to deployment: %v", err)
+								}
+
+								minReplicas := int32(0)
+								if got.Spec.MinReplicas != nil {
+									minReplicas = *got.Spec.MinReplicas
+								}
+								if diff := cmp.Diff(minReplicas, d.expMinReplicas); diff != "" {
+									t.Fatalf("Unexpected minReplicas: %v", diff)
+								}
+
+								if diff := cmp.Diff(got.Spec.MaxReplicas, d.expMaxReplicas); diff != "" {
+									t.Fatalf("Unexpected maxReplicas: %v", diff)
+								}
+							}
+						}
+					}
 				})
 			}
 		})
diff --git a/pkg/reconciler/knativeserving/ingress/kourier_test.go b/pkg/reconciler/knativeserving/ingress/kourier_test.go
index 9a38127a8..5dacfd406 100644
--- a/pkg/reconciler/knativeserving/ingress/kourier_test.go
+++ b/pkg/reconciler/knativeserving/ingress/kourier_test.go
@@ -34,7 +34,7 @@ import (
 
 const servingNamespace = "knative-serving"
 
-func servingInstance(ns string, serviceType v1.ServiceType, bootstrapConfigmapName string) *servingv1beta1.KnativeServing {
+func servingInstance(ns string, serviceType v1.ServiceType, bootstrapConfigmapName string, serviceLoadBalancerIP string) *servingv1beta1.KnativeServing {
 	return &servingv1beta1.KnativeServing{
 		ObjectMeta: metav1.ObjectMeta{
 			Name:      "test-instance",
@@ -45,6 +45,7 @@ func servingInstance(ns string, serviceType v1.ServiceType, bootstrapConfigmapNa
 				Kourier: base.KourierIngressConfiguration{
 					Enabled:                true,
 					ServiceType:            serviceType,
+					ServiceLoadBalancerIP:  serviceLoadBalancerIP,
 					BootstrapConfigmapName: bootstrapConfigmapName,
 				},
 			},
@@ -74,36 +75,46 @@ func servingInstanceNodePorts(ns string, bootstrapConfigmapName string, httpPort
 
 func TestTransformKourierManifest(t *testing.T) {
 	tests := []struct {
-		name              string
-		instance          *servingv1beta1.KnativeServing
-		expNamespace      string
-		expServiceType    string
-		expConfigMapName  string
-		expNodePortsHTTP  int32
-		expNodePortsHTTPS int32
-		expError          error
+		name                     string
+		instance                 *servingv1beta1.KnativeServing
+		expNamespace             string
+		expServiceType           string
+		expServiceLoadBalancerIP string
+		expConfigMapName         string
+		expNodePortsHTTP         int32
+		expNodePortsHTTPS        int32
+		expError                 error
 	}{{
 		name:             "Replaces Kourier Gateway Namespace, ServiceType and bootstrap cm",
-		instance:         servingInstance(servingNamespace, "ClusterIP", "my-bootstrap"),
+		instance:         servingInstance(servingNamespace, "ClusterIP", "my-bootstrap", ""),
 		expNamespace:     servingNamespace,
 		expConfigMapName: "my-bootstrap",
 		expServiceType:   "ClusterIP",
 	}, {
-		name:             "Use Kourier default service type",
-		instance:         servingInstance(servingNamespace, "" /* empty service type */, ""),
-		expNamespace:     servingNamespace,
-		expConfigMapName: kourierDefaultVolumeName,
-		expServiceType:   "LoadBalancer", // kourier GW default service type
+		name:                     "Use Kourier default service type",
+		instance:                 servingInstance(servingNamespace, "" /* empty service type */, "", ""),
+		expNamespace:             servingNamespace,
+		expConfigMapName:         kourierDefaultVolumeName,
+		expServiceType:           "LoadBalancer", // kourier GW default service type
+		expServiceLoadBalancerIP: "",
 	}, {
-		name:             "Use unsupported service type",
-		instance:         servingInstance(servingNamespace, "ExternalName", ""),
-		expNamespace:     servingNamespace,
-		expServiceType:   "ExternalName",
-		expConfigMapName: kourierDefaultVolumeName,
-		expError:         fmt.Errorf("unsupported service type \"ExternalName\""),
+		name:                     "Sets Kourier Gateway ServiceLoadBalancerIP",
+		instance:                 servingInstance(servingNamespace, "" /* empty service type */, "", "1.2.3.4"),
+		expNamespace:             servingNamespace,
+		expConfigMapName:         kourierDefaultVolumeName,
+		expServiceType:           "LoadBalancer",
+		expServiceLoadBalancerIP: "1.2.3.4",
+	}, {
+		name:                     "Use ServiceLoadBalancerIP with unsupported service type",
+		instance:                 servingInstance(servingNamespace, "ClusterIP", "", "1.2.3.4"),
+		expNamespace:             servingNamespace,
+		expConfigMapName:         kourierDefaultVolumeName,
+		expServiceType:           "ClusterIP",
+		expServiceLoadBalancerIP: "1.2.3.4",
+		expError:                 fmt.Errorf("cannot configure LoadBalancerIP for service type \"ClusterIP\""),
 	}, {
 		name:             "Use unknown service type",
-		instance:         servingInstance(servingNamespace, "Foo", ""),
+		instance:         servingInstance(servingNamespace, "Foo", "", ""),
 		expNamespace:     servingNamespace,
 		expServiceType:   "Foo",
 		expConfigMapName: kourierDefaultVolumeName,
@@ -142,12 +153,12 @@ func TestTransformKourierManifest(t *testing.T) {
 				t.Fatalf("Failed to read manifest: %v", err)
 			}
 
-			manifest, err = manifest.Transform(replaceGWNamespace())
+			manifest, err = manifest.Transform(replaceGatewayNamespace())
 			if err != nil {
 				t.Fatalf("Failed to transform manifest: %v", err)
 			}
 
-			manifest, err = manifest.Transform(configureGWServiceType(tt.instance))
+			manifest, err = manifest.Transform(configureGatewayService(tt.instance))
 			if err != nil {
 				util.AssertEqual(t, err.Error(), tt.expError.Error())
 			} else {
@@ -162,6 +173,7 @@ func TestTransformKourierManifest(t *testing.T) {
 			for _, u := range manifest.Resources() {
 				verifyControllerNamespace(t, &u, tt.expNamespace)
 				verifyGatewayServiceType(t, &u, tt.expServiceType)
+				verifyGatewayServiceLoadBalancerIP(t, &u, tt.expServiceLoadBalancerIP)
 				verifyGatewayServiceTypeNodePortHTTP(t, &u, tt.expNodePortsHTTP)
 				verifyGatewayServiceTypeNodePortHTTPS(t, &u, tt.expNodePortsHTTPS)
 				verifyBootstrapVolumeName(t, &u, tt.expConfigMapName)
@@ -238,6 +250,16 @@ func verifyGatewayServiceType(t *testing.T, u *unstructured.Unstructured, expSer
 	}
 }
 
+func verifyGatewayServiceLoadBalancerIP(t *testing.T, u *unstructured.Unstructured, expServiceLoadBalancerIP string) {
+	if u.GetKind() == "Service" && u.GetName() == kourierGatewayServiceName {
+		svc := &v1.Service{}
+		err := scheme.Scheme.Convert(u, svc, nil)
+		util.AssertEqual(t, err, nil)
+		svcLoadBalancerIP := svc.Spec.LoadBalancerIP
+		util.AssertDeepEqual(t, svcLoadBalancerIP, expServiceLoadBalancerIP)
+	}
+}
+
 // removeProviderLabels removes labels. This util is used for tests without provider label.
 func removeLabels() mf.Transformer {
 	return func(u *unstructured.Unstructured) error {
diff --git a/vendor/knative.dev/eventing/pkg/apis/eventing/v1/test_helper.go b/vendor/knative.dev/eventing/pkg/apis/eventing/v1/test_helper.go
index 80b251000..31c2c51c8 100644
--- a/vendor/knative.dev/eventing/pkg/apis/eventing/v1/test_helper.go
+++ b/vendor/knative.dev/eventing/pkg/apis/eventing/v1/test_helper.go
@@ -61,7 +61,9 @@ func (t testHelper) ReadyBrokerStatus() *BrokerStatus {
 	bs.PropagateIngressAvailability(t.AvailableEndpoints())
 	bs.PropagateTriggerChannelReadiness(t.ReadyChannelStatus())
 	bs.PropagateFilterAvailability(t.AvailableEndpoints())
-	bs.SetAddress(apis.HTTP("example.com"))
+	bs.SetAddress(&duckv1.Addressable{
+		URL: apis.HTTP("example.com"),
+	})
 	bs.MarkDeadLetterSinkResolvedSucceeded(eventingduckv1.DeliveryStatus{})
 	return bs
 }
@@ -71,7 +73,9 @@ func (t testHelper) ReadyBrokerStatusWithoutDLS() *BrokerStatus {
 	bs.PropagateIngressAvailability(t.AvailableEndpoints())
 	bs.PropagateTriggerChannelReadiness(t.ReadyChannelStatus())
 	bs.PropagateFilterAvailability(t.AvailableEndpoints())
-	bs.SetAddress(apis.HTTP("example.com"))
+	bs.SetAddress(&duckv1.Addressable{
+		URL: apis.HTTP("example.com"),
+	})
 	bs.MarkDeadLetterSinkNotConfigured()
 	return bs
 }
diff --git a/vendor/knative.dev/eventing/pkg/reconciler/testing/v1/broker.go b/vendor/knative.dev/eventing/pkg/reconciler/testing/v1/broker.go
index 970b9abbd..3ef470c25 100644
--- a/vendor/knative.dev/eventing/pkg/reconciler/testing/v1/broker.go
+++ b/vendor/knative.dev/eventing/pkg/reconciler/testing/v1/broker.go
@@ -88,19 +88,19 @@ func WithBrokerConfig(config *duckv1.KReference) BrokerOption {
 }
 
 // WithBrokerAddress sets the Broker's address.
-func WithBrokerAddress(address string) BrokerOption {
+func WithBrokerAddress(address *duckv1.Addressable) BrokerOption {
 	return func(b *v1.Broker) {
-		b.Status.SetAddress(&apis.URL{
-			Scheme: "http",
-			Host:   address,
-		})
+		b.Status.SetAddress(address)
 	}
 }
 
 // WithBrokerAddressURI sets the Broker's address as URI.
 func WithBrokerAddressURI(uri *apis.URL) BrokerOption {
 	return func(b *v1.Broker) {
-		b.Status.SetAddress(uri)
+		b.Status.SetAddress(&duckv1.Addressable{
+			Name: &uri.Scheme,
+			URL:  uri,
+		})
 	}
 }
 
diff --git a/vendor/knative.dev/serving/test/e2e-auto-tls-tests.sh b/vendor/knative.dev/serving/test/e2e-auto-tls-tests.sh
index c8f3f1c87..143976a80 100644
--- a/vendor/knative.dev/serving/test/e2e-auto-tls-tests.sh
+++ b/vendor/knative.dev/serving/test/e2e-auto-tls-tests.sh
@@ -67,15 +67,15 @@ function setup_auto_tls_common() {
 
   setup_custom_domain
 
-  toggle_feature autoTLS Enabled config-network
-  toggle_feature autocreateClusterDomainClaims true config-network
+  toggle_feature auto-tls Enabled config-network
+  toggle_feature autocreate-cluster-domain-claims true config-network
 }
 
 function cleanup_auto_tls_common() {
   cleanup_custom_domain
 
-  toggle_feature autoTLS Disabled config-network
-  toggle_feature autocreateClusterDomainClaims false config-network
+  toggle_feature auto-tls Disabled config-network
+  toggle_feature autocreate-cluster-domain-claims false config-network
   toggle_feature namespace-wildcard-cert-selector "" config-network
   kubectl delete kcert --all -n "${TLS_TEST_NAMESPACE}"
 }
diff --git a/vendor/knative.dev/serving/test/e2e-tests.sh b/vendor/knative.dev/serving/test/e2e-tests.sh
index 00bb9a045..9966af0c1 100644
--- a/vendor/knative.dev/serving/test/e2e-tests.sh
+++ b/vendor/knative.dev/serving/test/e2e-tests.sh
@@ -50,7 +50,7 @@ fi
 
 if (( HTTPS )); then
   E2E_TEST_FLAGS+=" -https"
-  toggle_feature autoTLS Enabled config-network
+  toggle_feature auto-tls Enabled config-network
   kubectl apply -f "${E2E_YAML_DIR}"/test/config/autotls/certmanager/caissuer/
   add_trap "kubectl delete -f ${E2E_YAML_DIR}/test/config/autotls/certmanager/caissuer/ --ignore-not-found" SIGKILL SIGTERM SIGQUIT
 fi
@@ -64,14 +64,14 @@ if (( SHORT )); then
 fi
 
 
-toggle_feature autocreateClusterDomainClaims true config-network || fail_test
+toggle_feature autocreate-cluster-domain-claims true config-network || fail_test
 go_test_e2e -timeout=30m \
   ${GO_TEST_FLAGS} \
   ./test/conformance/api/... \
   ./test/conformance/runtime/... \
   ./test/e2e \
   ${E2E_TEST_FLAGS} || failed=1
-toggle_feature autocreateClusterDomainClaims false config-network || fail_test
+toggle_feature autocreate-cluster-domain-claims false config-network || fail_test
 
 toggle_feature tag-header-based-routing Enabled
 go_test_e2e -timeout=2m ./test/e2e/tagheader ${E2E_TEST_FLAGS} || failed=1
@@ -81,9 +81,9 @@ toggle_feature allow-zero-initial-scale true config-autoscaler || fail_test
 go_test_e2e -timeout=2m ./test/e2e/initscale ${E2E_TEST_FLAGS} || failed=1
 toggle_feature allow-zero-initial-scale false config-autoscaler || fail_test
 
-toggle_feature autocreateClusterDomainClaims true config-network || fail_test
+toggle_feature autocreate-cluster-domain-claims true config-network || fail_test
 go_test_e2e -timeout=2m ./test/e2e/domainmapping ${E2E_TEST_FLAGS} || failed=1
-toggle_feature autocreateClusterDomainClaims false config-network || fail_test
+toggle_feature autocreate-cluster-domain-claims false config-network || fail_test
 
 kubectl get cm "config-gc" -n "${SYSTEM_NAMESPACE}" -o yaml > "${TMP_DIR}"/config-gc.yaml
 add_trap "kubectl replace cm 'config-gc' -n ${SYSTEM_NAMESPACE} -f ${TMP_DIR}/config-gc.yaml" SIGKILL SIGTERM SIGQUIT
@@ -123,17 +123,17 @@ toggle_feature secure-pod-defaults Disabled
 
 # Run HA tests separately as they're stopping core Knative Serving pods.
 # Define short -spoofinterval to ensure frequent probing while stopping pods.
-toggle_feature autocreateClusterDomainClaims true config-network || fail_test
+toggle_feature autocreate-cluster-domain-claims true config-network || fail_test
 go_test_e2e -timeout=25m -failfast -parallel=1 ./test/ha \
   ${E2E_TEST_FLAGS} \
   -replicas="${REPLICAS:-1}" \
   -buckets="${BUCKETS:-1}" \
   -spoofinterval="10ms" || failed=1
-toggle_feature autocreateClusterDomainClaims false config-network || fail_test
+toggle_feature autocreate-cluster-domain-claims false config-network || fail_test
 
 if (( HTTPS )); then
   kubectl delete -f ${E2E_YAML_DIR}/test/config/autotls/certmanager/caissuer/ --ignore-not-found
-  toggle_feature autoTLS Disabled config-network
+  toggle_feature auto-tls Disabled config-network
 fi
 
 (( failed )) && fail_test