Repository: knative/serving
Pull request #10809 (2021-02-18 20:07:43)

bump k8s versions for kind e2e
Bump patches and introduce v1.20 - since we haven't been testing it

knative-prow-robot: [APPROVALNOTIFIER] This PR is **NOT APPROVED**

This pull-request has been approved by:
To complete the [pull request process](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process), please assign **dprotaso** after the PR has been reviewed.
You can assign the PR to them by writing `/assign @dprotaso` in a comment when ready.

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=knative%2Fserving).

<details open>
Needs approval from an approver in each of these files:

- **[OWNERS](https://github.com/knative/serving/blob/master/OWNERS)**

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":["dprotaso"]} -->
codecov[bot]: # [Codecov](https://codecov.io/gh/knative/serving/pull/10809?src=pr&el=h1) Report
> Merging [#10809](https://codecov.io/gh/knative/serving/pull/10809?src=pr&el=desc) (24eaf6f) into [master](https://codecov.io/gh/knative/serving/commit/130f8ace745397cbee16fb549664d91f08e8baa6?el=desc) (130f8ac) will **decrease** coverage by `0.05%`.
> The diff coverage is `n/a`.

[![Impacted file tree graph](https://codecov.io/gh/knative/serving/pull/10809/graphs/tree.svg?width=650&height=150&src=pr&token=MPpDfAj4Ui)](https://codecov.io/gh/knative/serving/pull/10809?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master   #10809      +/-   ##
==========================================
- Coverage   88.01%   87.95%   -0.06%     
==========================================
  Files         188      188              
  Lines        9043     9043              
==========================================
- Hits         7959     7954       -5     
- Misses        831      834       +3     
- Partials      253      255       +2     
```


| [Impacted Files](https://codecov.io/gh/knative/serving/pull/10809?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [pkg/autoscaler/statforwarder/forwarder.go](https://codecov.io/gh/knative/serving/pull/10809/diff?src=pr&el=tree#diff-cGtnL2F1dG9zY2FsZXIvc3RhdGZvcndhcmRlci9mb3J3YXJkZXIuZ28=) | `90.74% <0.00%> (-5.56%)` | :arrow_down: |
| [pkg/autoscaler/statforwarder/processor.go](https://codecov.io/gh/knative/serving/pull/10809/diff?src=pr&el=tree#diff-cGtnL2F1dG9zY2FsZXIvc3RhdGZvcndhcmRlci9wcm9jZXNzb3IuZ28=) | `88.88% <0.00%> (-5.56%)` | :arrow_down: |
| [pkg/activator/net/revision\_backends.go](https://codecov.io/gh/knative/serving/pull/10809/diff?src=pr&el=tree#diff-cGtnL2FjdGl2YXRvci9uZXQvcmV2aXNpb25fYmFja2VuZHMuZ28=) | `90.41% <0.00%> (-0.92%)` | :arrow_down: |
| [pkg/autoscaler/scaling/multiscaler.go](https://codecov.io/gh/knative/serving/pull/10809/diff?src=pr&el=tree#diff-cGtnL2F1dG9zY2FsZXIvc2NhbGluZy9tdWx0aXNjYWxlci5nbw==) | `89.38% <0.00%> (+1.76%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/knative/serving/pull/10809?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/knative/serving/pull/10809?src=pr&el=footer). Last update [130f8ac...a960eb4](https://codecov.io/gh/knative/serving/pull/10809?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

knative-prow-robot: @dprotaso: The following test **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-knative-serving-istio-stable-no-mesh-tls | a960eb443b320c90f72cf6e9358879ac7f1ad573 | [link](https://prow.knative.dev/view/gs/knative-prow/pr-logs/pull/knative_serving/10809/pull-knative-serving-istio-stable-no-mesh-tls/1362494038502019072) | `/test pull-knative-serving-istio-stable-no-mesh-tls`

[Full PR test history](https://gubernator.knative.dev/pr/knative_serving/10809). [Your PR dashboard](https://gubernator.knative.dev/pr/dprotaso).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
dprotaso: weird

`
Error from server (Forbidden): clusterrolebindings.rbac.authorization.k8s.io "cluster-admin-binding" is forbidden: user "prow-job@knative-tests.iam.gserviceaccount.com" (groups=["system:authenticated"]) is attempting to grant RBAC permissions not currently held:
`
dprotaso: /retest
knative-prow-robot: @dprotaso: The following test **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-knative-serving-istio-stable-no-mesh | a960eb443b320c90f72cf6e9358879ac7f1ad573 | [link](https://prow.knative.dev/view/gs/knative-prow/pr-logs/pull/knative_serving/10809/pull-knative-serving-istio-stable-no-mesh/1362494038472658944) | `/test pull-knative-serving-istio-stable-no-mesh`

[Full PR test history](https://gubernator.knative.dev/pr/knative_serving/10809). [Your PR dashboard](https://gubernator.knative.dev/pr/dprotaso).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
dprotaso: /retest

Patch:
diff --git a/cmd/activator/main.go b/cmd/activator/main.go
index 68e3ae46b..98d09740e 100644
--- a/cmd/activator/main.go
+++ b/cmd/activator/main.go
@@ -34,7 +34,6 @@ import (
 	kubeclient "knative.dev/pkg/client/injection/kube/client"
 	"knative.dev/pkg/injection"
 	"knative.dev/serving/pkg/activator"
-	revisioninformer "knative.dev/serving/pkg/client/injection/informers/serving/v1/revision"
 
 	"k8s.io/apimachinery/pkg/util/wait"
 
@@ -181,7 +180,7 @@ func main() {
 	ah = tracing.HTTPSpanMiddleware(ah)
 	ah = configStore.HTTPMiddleware(ah)
 	reqLogHandler, err := pkghttp.NewRequestLogHandler(ah, logging.NewSyncFileWriter(os.Stdout), "",
-		requestLogTemplateInputGetter(revisioninformer.Get(ctx).Lister()), false /*enableProbeRequestLog*/)
+		requestLogTemplateInputGetter, false /*enableProbeRequestLog*/)
 	if err != nil {
 		logger.Fatalw("Unable to create request log handler", zap.Error(err))
 	}
diff --git a/cmd/activator/request_log.go b/cmd/activator/request_log.go
index 3878f80d1..c800ed7c6 100644
--- a/cmd/activator/request_log.go
+++ b/cmd/activator/request_log.go
@@ -22,9 +22,8 @@ import (
 	"go.uber.org/zap"
 	corev1 "k8s.io/api/core/v1"
 	"knative.dev/pkg/metrics"
-	"knative.dev/serving/pkg/activator"
+	"knative.dev/serving/pkg/activator/handler"
 	"knative.dev/serving/pkg/apis/serving"
-	servinglisters "knative.dev/serving/pkg/client/listers/serving/v1"
 	pkghttp "knative.dev/serving/pkg/http"
 )
 
@@ -48,25 +47,25 @@ func updateRequestLogFromConfigMap(logger *zap.SugaredLogger, h *pkghttp.Request
 	}
 }
 
-func requestLogTemplateInputGetter(revisionLister servinglisters.RevisionLister) pkghttp.RequestLogTemplateInputGetter {
-	return func(req *http.Request, resp *pkghttp.RequestLogResponse) *pkghttp.RequestLogTemplateInput {
-		namespace := req.Header.Get(activator.RevisionHeaderNamespace)
-		name := req.Header.Get(activator.RevisionHeaderName)
-		revInfo := &pkghttp.RequestLogRevision{
-			Namespace: namespace,
-			Name:      name,
-		}
+// requestLogTemplateInputGetter gets the template input from the request.
+// It assumes the Revision has been set on the context such that
+// handler.FromRevision() returns a non-nil revision.
+func requestLogTemplateInputGetter(req *http.Request, resp *pkghttp.RequestLogResponse) *pkghttp.RequestLogTemplateInput {
+	revision := handler.RevisionFrom(req.Context())
 
-		revision, err := revisionLister.Revisions(namespace).Get(name)
-		if err == nil && revision.Labels != nil {
-			revInfo.Configuration = revision.Labels[serving.ConfigurationLabelKey]
-			revInfo.Service = revision.Labels[serving.ServiceLabelKey]
-		}
+	revInfo := &pkghttp.RequestLogRevision{
+		Namespace: revision.Namespace,
+		Name:      revision.Name,
+	}
 
-		return &pkghttp.RequestLogTemplateInput{
-			Request:  req,
-			Response: resp,
-			Revision: revInfo,
-		}
+	if revision.Labels != nil {
+		revInfo.Configuration = revision.Labels[serving.ConfigurationLabelKey]
+		revInfo.Service = revision.Labels[serving.ServiceLabelKey]
+	}
+
+	return &pkghttp.RequestLogTemplateInput{
+		Request:  req,
+		Response: resp,
+		Revision: revInfo,
 	}
 }
diff --git a/cmd/queue/main.go b/cmd/queue/main.go
index 582b75552..fbced2fe0 100644
--- a/cmd/queue/main.go
+++ b/cmd/queue/main.go
@@ -220,7 +220,7 @@ func main() {
 	}()
 
 	// Blocks until we actually receive a TERM signal or one of the servers
-	// exit unexpectedly. We fold both signals together because we only want
+	// exits unexpectedly. We fold both signals together because we only want
 	// to act on the first of those to reach here.
 	select {
 	case err := <-errCh:
@@ -291,7 +291,7 @@ func buildServer(ctx context.Context, env config, healthState *health.State, rp
 	}
 	composedHandler = queue.ProxyHandler(breaker, stats, tracingEnabled, composedHandler)
 	composedHandler = queue.ForwardedShimHandler(composedHandler)
-	composedHandler = handler.NewTimeToFirstByteTimeoutHandler(composedHandler, "request timeout", handler.StaticTimeoutFunc(timeout))
+	composedHandler = handler.NewTimeToFirstByteTimeoutHandler(composedHandler, "request timeout", timeout)
 
 	if metricsSupported {
 		composedHandler = requestMetricsHandler(logger, composedHandler, env)
diff --git a/pkg/activator/handler/concurrency_reporter.go b/pkg/activator/handler/concurrency_reporter.go
index d8da02d77..3fe7a3dc5 100644
--- a/pkg/activator/handler/concurrency_reporter.go
+++ b/pkg/activator/handler/concurrency_reporter.go
@@ -242,7 +242,7 @@ func (cr *ConcurrencyReporter) run(stopCh <-chan struct{}, reportCh <-chan time.
 // machinery.
 func (cr *ConcurrencyReporter) Handler(next http.Handler) http.HandlerFunc {
 	return func(w http.ResponseWriter, r *http.Request) {
-		revisionKey := revIDFrom(r.Context())
+		revisionKey := RevIDFrom(r.Context())
 
 		stat := cr.handleRequestIn(network.ReqEvent{Key: revisionKey, Type: network.ReqIn, Time: time.Now()})
 		defer func() {
diff --git a/pkg/activator/handler/context.go b/pkg/activator/handler/context.go
index 835a44b6a..6cee2d3b8 100644
--- a/pkg/activator/handler/context.go
+++ b/pkg/activator/handler/context.go
@@ -33,22 +33,22 @@ type (
 	revIDKey    struct{}
 )
 
-// withRevision attaches the Revision object to the context.
-func withRevision(ctx context.Context, rev *v1.Revision) context.Context {
+// WithRevision attaches the Revision object to the context.
+func WithRevision(ctx context.Context, rev *v1.Revision) context.Context {
 	return context.WithValue(ctx, revisionKey{}, rev)
 }
 
-// revisionFrom retrieves the Revision object from the context.
-func revisionFrom(ctx context.Context) *v1.Revision {
+// RevisionFrom retrieves the Revision object from the context.
+func RevisionFrom(ctx context.Context) *v1.Revision {
 	return ctx.Value(revisionKey{}).(*v1.Revision)
 }
 
-// withRevID attaches the the revisionID to the context.
-func withRevID(ctx context.Context, revID types.NamespacedName) context.Context {
+// WithRevID attaches the the revisionID to the context.
+func WithRevID(ctx context.Context, revID types.NamespacedName) context.Context {
 	return context.WithValue(ctx, revIDKey{}, revID)
 }
 
-// revIDFrom retrieves the the revisionID from the context.
-func revIDFrom(ctx context.Context) types.NamespacedName {
+// RevIDFrom retrieves the the revisionID from the context.
+func RevIDFrom(ctx context.Context) types.NamespacedName {
 	return ctx.Value(revIDKey{}).(types.NamespacedName)
 }
diff --git a/pkg/activator/handler/context_handler.go b/pkg/activator/handler/context_handler.go
index c255dbed6..e49676927 100644
--- a/pkg/activator/handler/context_handler.go
+++ b/pkg/activator/handler/context_handler.go
@@ -76,8 +76,8 @@ func (h *contextHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 
 	ctx := r.Context()
 	ctx = logging.WithLogger(ctx, logger)
-	ctx = withRevision(ctx, revision)
-	ctx = withRevID(ctx, revID)
+	ctx = WithRevision(ctx, revision)
+	ctx = WithRevID(ctx, revID)
 
 	h.nextHandler.ServeHTTP(w, r.WithContext(ctx))
 }
diff --git a/pkg/activator/handler/handler.go b/pkg/activator/handler/handler.go
index a291675b1..5cf085767 100644
--- a/pkg/activator/handler/handler.go
+++ b/pkg/activator/handler/handler.go
@@ -74,7 +74,7 @@ func (a *activationHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 		tryContext, trySpan = trace.StartSpan(r.Context(), "throttler_try")
 	}
 
-	if err := a.throttler.Try(tryContext, revIDFrom(r.Context()), func(dest string) error {
+	if err := a.throttler.Try(tryContext, RevIDFrom(r.Context()), func(dest string) error {
 		trySpan.End()
 
 		proxyCtx, proxySpan := r.Context(), (*trace.Span)(nil)
diff --git a/pkg/activator/handler/metric_handler.go b/pkg/activator/handler/metric_handler.go
index c2f4938cc..8c3b058f3 100644
--- a/pkg/activator/handler/metric_handler.go
+++ b/pkg/activator/handler/metric_handler.go
@@ -42,7 +42,7 @@ type MetricHandler struct {
 }
 
 func (h *MetricHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
-	rev := revisionFrom(r.Context())
+	rev := RevisionFrom(r.Context())
 	reporterCtx, _ := metrics.PodRevisionContext(h.podName, activator.Name,
 		rev.Namespace, rev.Labels[serving.ServiceLabelKey], rev.Labels[serving.ConfigurationLabelKey], rev.Name)
 
diff --git a/pkg/apis/serving/v1/configuration_validation.go b/pkg/apis/serving/v1/configuration_validation.go
index 01c0cefad..6b719ae6b 100644
--- a/pkg/apis/serving/v1/configuration_validation.go
+++ b/pkg/apis/serving/v1/configuration_validation.go
@@ -18,7 +18,6 @@ package v1
 
 import (
 	"context"
-	"strings"
 
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"knative.dev/pkg/apis"
@@ -63,19 +62,8 @@ func (cs *ConfigurationSpec) Validate(ctx context.Context) *apis.FieldError {
 
 // validateLabels function validates configuration labels
 func (c *Configuration) validateLabels() (errs *apis.FieldError) {
-	for key, val := range c.GetLabels() {
-		switch key {
-		case serving.RouteLabelKey,
-			serving.ConfigurationUIDLabelKey,
-			serving.ServiceUIDLabelKey:
-			// Known valid labels - so just skip them
-		case serving.ServiceLabelKey:
-			errs = errs.Also(verifyLabelOwnerRef(val, serving.ServiceLabelKey, "Service", c.GetOwnerReferences()))
-		default:
-			if strings.HasPrefix(key, serving.GroupNamePrefix) {
-				errs = errs.Also(apis.ErrInvalidKeyName(key, apis.CurrentField))
-			}
-		}
+	if val, ok := c.Labels[serving.ServiceLabelKey]; ok {
+		errs = errs.Also(verifyLabelOwnerRef(val, serving.ServiceLabelKey, "Service", c.GetOwnerReferences()))
 	}
 	return errs
 }
diff --git a/pkg/apis/serving/v1/revision_types.go b/pkg/apis/serving/v1/revision_types.go
index 32ac6180a..63ea4f6c3 100644
--- a/pkg/apis/serving/v1/revision_types.go
+++ b/pkg/apis/serving/v1/revision_types.go
@@ -82,9 +82,9 @@ type RevisionSpec struct {
 	// +optional
 	ContainerConcurrency *int64 `json:"containerConcurrency,omitempty"`
 
-	// TimeoutSeconds holds the max duration the instance is allowed for
-	// responding to a request.  If unspecified, a system default will
-	// be provided.
+	// TimeoutSeconds is the maximum duration in seconds that the request routing
+	// layer will wait for a request delivered to a container to begin replying
+	// (send network traffic). If unspecified, a system default will be provided.
 	// +optional
 	TimeoutSeconds *int64 `json:"timeoutSeconds,omitempty"`
 }
diff --git a/pkg/apis/serving/v1/revision_validation.go b/pkg/apis/serving/v1/revision_validation.go
index 02f50a196..e5c961bde 100644
--- a/pkg/apis/serving/v1/revision_validation.go
+++ b/pkg/apis/serving/v1/revision_validation.go
@@ -123,22 +123,8 @@ func (rs *RevisionStatus) Validate(_ context.Context) *apis.FieldError {
 
 // ValidateLabels function validates service labels
 func (r *Revision) ValidateLabels() (errs *apis.FieldError) {
-	for key, val := range r.GetLabels() {
-		switch key {
-		case serving.RoutingStateLabelKey,
-			serving.RouteLabelKey,
-			serving.ServiceLabelKey,
-			serving.ConfigurationUIDLabelKey,
-			serving.ServiceUIDLabelKey,
-			serving.ConfigurationGenerationLabelKey:
-			// Known valid labels.
-		case serving.ConfigurationLabelKey:
-			errs = errs.Also(verifyLabelOwnerRef(val, serving.ConfigurationLabelKey, "Configuration", r.GetOwnerReferences()))
-		default:
-			if strings.HasPrefix(key, serving.GroupNamePrefix) {
-				errs = errs.Also(apis.ErrInvalidKeyName(key, ""))
-			}
-		}
+	if val, ok := r.Labels[serving.ConfigurationLabelKey]; ok {
+		errs = errs.Also(verifyLabelOwnerRef(val, serving.ConfigurationLabelKey, "Configuration", r.GetOwnerReferences()))
 	}
 	return errs
 }
diff --git a/pkg/apis/serving/v1/route_validation.go b/pkg/apis/serving/v1/route_validation.go
index cbe667f7f..0a9a4c9d6 100644
--- a/pkg/apis/serving/v1/route_validation.go
+++ b/pkg/apis/serving/v1/route_validation.go
@@ -19,7 +19,6 @@ package v1
 import (
 	"context"
 	"fmt"
-	"strings"
 
 	"k8s.io/apimachinery/pkg/util/validation"
 	network "knative.dev/networking/pkg"
@@ -204,17 +203,13 @@ func validateClusterVisibilityLabel(label string) *apis.FieldError {
 
 // validateLabels function validates route labels.
 func (r *Route) validateLabels() (errs *apis.FieldError) {
-	for key, val := range r.GetLabels() {
-		switch key {
-		case network.VisibilityLabelKey:
-			errs = errs.Also(validateClusterVisibilityLabel(val))
-		case serving.ServiceLabelKey:
-			errs = errs.Also(verifyLabelOwnerRef(val, serving.ServiceLabelKey, "Service", r.GetOwnerReferences()))
-		default:
-			if strings.HasPrefix(key, serving.GroupNamePrefix) {
-				errs = errs.Also(apis.ErrInvalidKeyName(key, apis.CurrentField))
-			}
-		}
+	if val, ok := r.Labels[network.VisibilityLabelKey]; ok {
+		errs = errs.Also(validateClusterVisibilityLabel(val))
+	}
+
+	if val, ok := r.Labels[serving.ServiceLabelKey]; ok {
+		errs = errs.Also(verifyLabelOwnerRef(val, serving.ServiceLabelKey, "Service", r.GetOwnerReferences()))
 	}
+
 	return errs
 }
diff --git a/pkg/apis/serving/v1/service_validation.go b/pkg/apis/serving/v1/service_validation.go
index 7178bd7fe..eb1ecbf63 100644
--- a/pkg/apis/serving/v1/service_validation.go
+++ b/pkg/apis/serving/v1/service_validation.go
@@ -18,7 +18,6 @@ package v1
 
 import (
 	"context"
-	"strings"
 
 	network "knative.dev/networking/pkg"
 	"knative.dev/pkg/apis"
@@ -67,13 +66,8 @@ func (ss *ServiceSpec) Validate(ctx context.Context) *apis.FieldError {
 
 // validateLabels function validates service labels
 func (s *Service) validateLabels() (errs *apis.FieldError) {
-	for key, val := range s.GetLabels() {
-		switch {
-		case key == network.VisibilityLabelKey:
-			errs = errs.Also(validateClusterVisibilityLabel(val))
-		case strings.HasPrefix(key, serving.GroupNamePrefix):
-			errs = errs.Also(apis.ErrInvalidKeyName(key, apis.CurrentField))
-		}
+	if val, ok := s.Labels[network.VisibilityLabelKey]; ok {
+		errs = errs.Also(validateClusterVisibilityLabel(val))
 	}
 	return errs
 }
diff --git a/pkg/autoscaler/aggregation/bucketing.go b/pkg/autoscaler/aggregation/bucketing.go
index 48bb84461..ca61e4487 100644
--- a/pkg/autoscaler/aggregation/bucketing.go
+++ b/pkg/autoscaler/aggregation/bucketing.go
@@ -54,6 +54,12 @@ type TimedFloat64Buckets struct {
 	// invalid buckets, e.g. buckets written to before firstTime or after
 	// lastTime are included in this total.
 	windowTotal float64
+
+	// decayMultiplier contains the speed with which the importance
+	// of items in the past decays. The larger the faster weights decay.
+	// It is autocomputed from window size and weightPrecision constant
+	// and is bounded by minExponent below.
+	decayMultiplier float64
 }
 
 // String implements the Stringer interface.
@@ -61,16 +67,31 @@ func (t *TimedFloat64Buckets) String() string {
 	return spew.Sdump(t.buckets)
 }
 
+// computeDecayMultiplier computes the decay given number of buckets.
+// The function uses precision and min exponent value constants.
+func computeDecayMultiplier(nb float64) float64 {
+	return math.Max(
+		// Given number of buckets, infer the desired multiplier
+		// so that at least weightPrecision sum of buckets is met.
+		1-math.Pow(1-weightPrecision, 1/nb),
+		// If it's smaller than minExponent — then use minExponent,
+		// otherwise with extremely large windows we basically end up
+		// very close to the simple average.
+		minExponent,
+	)
+}
+
 // NewTimedFloat64Buckets generates a new TimedFloat64Buckets with the given
 // granularity.
 func NewTimedFloat64Buckets(window, granularity time.Duration) *TimedFloat64Buckets {
 	// Number of buckets is `window` divided by `granularity`, rounded up.
 	// e.g. 60s / 2s = 30.
-	nb := int(math.Ceil(float64(window) / float64(granularity)))
+	nb := math.Ceil(float64(window) / float64(granularity))
 	return &TimedFloat64Buckets{
-		buckets:     make([]float64, nb),
-		granularity: granularity,
-		window:      window,
+		buckets:         make([]float64, int(nb)),
+		granularity:     granularity,
+		window:          window,
+		decayMultiplier: computeDecayMultiplier(nb),
 	}
 }
 
@@ -79,6 +100,11 @@ func (t *TimedFloat64Buckets) IsEmpty(now time.Time) bool {
 	now = now.Truncate(t.granularity)
 	t.bucketsMutex.RLock()
 	defer t.bucketsMutex.RUnlock()
+	return t.isEmptyLocked(now)
+}
+
+// isEmptyLocked expects `now` to be truncated and at least Read Lock held.
+func (t *TimedFloat64Buckets) isEmptyLocked(now time.Time) bool {
 	return now.Sub(t.lastWrite) > t.window
 }
 
@@ -87,6 +113,56 @@ func roundToNDigits(n int, f float64) float64 {
 	return math.Floor(f*p) / p
 }
 
+const (
+	// minExponent is the minimal decay multiplier for the weighted average computations.
+	minExponent = 0.2
+	// The sum of weights for weighted average should be at least this much.
+	weightPrecision = 0.9999
+	precision       = 6
+)
+
+// WeightedAverage returns the exponential weighted average. This means
+// that more recent items have much greater impact on the average than
+// the older ones.
+// TODO(vagababov): optimize for O(1) computation, if possible.
+// E.g. with data  [10, 10, 5, 5] (newest last), then
+// the `WindowAverage` would return (10+10+5+5)/4 = 7.5
+// This with exponent of 0.6 would return 5*0.6+5*0.6*0.4+10*0.6*0.4^2+10*0.6*0.4^3 = 5.544
+// If we reverse the data to [5, 5, 10, 10] the simple average would remain the same,
+// but this one would change to 9.072.
+func (t *TimedFloat64Buckets) WeightedAverage(now time.Time) float64 {
+	now = now.Truncate(t.granularity)
+	t.bucketsMutex.RLock()
+	defer t.bucketsMutex.RUnlock()
+	if t.isEmptyLocked(now) {
+		return 0
+	}
+
+	totalB := len(t.buckets)
+	numB := len(t.buckets)
+
+	multiplier := t.decayMultiplier
+	// We start with 0es. But we know that we have _some_ data because
+	// IsEmpty returned false.
+	if now.After(t.lastWrite) {
+		numZ := now.Sub(t.lastWrite) / t.granularity
+		// Skip to this multiplier directly: m*(1-m)^(nz-1).
+		multiplier = multiplier * math.Pow(1-t.decayMultiplier, float64(numZ))
+		// Reduce effective number of buckets.
+		numB -= int(numZ)
+	}
+	startIdx := t.timeToIndex(t.lastWrite) + totalB // To ensure always positive % operation.
+	ret := 0.
+	for i := 0; i < numB; i++ {
+		effectiveIdx := (startIdx - i) % totalB
+		v := t.buckets[effectiveIdx] * multiplier
+		ret += v
+		multiplier *= (1 - t.decayMultiplier)
+		// TODO(vagababov): bail out if sm > weightPrecision?
+	}
+	return ret
+}
+
 // WindowAverage returns the average bucket value over the window.
 //
 // If the first write was less than the window length ago, an average is
@@ -104,7 +180,6 @@ func roundToNDigits(n int, f float64) float64 {
 // window length, the missing data is assumed to be 0 and the average is over
 // the whole window length inclusive of the missing data.
 func (t *TimedFloat64Buckets) WindowAverage(now time.Time) float64 {
-	const precision = 6
 	now = now.Truncate(t.granularity)
 	t.bucketsMutex.RLock()
 	defer t.bucketsMutex.RUnlock()
@@ -256,4 +331,5 @@ func (t *TimedFloat64Buckets) ResizeWindow(w time.Duration) {
 	t.window = w
 	t.buckets = newBuckets
 	t.windowTotal = newTotal
+	t.decayMultiplier = computeDecayMultiplier(float64(numBuckets))
 }
diff --git a/pkg/http/handler/timeout.go b/pkg/http/handler/timeout.go
index d8a667f2b..0e49c89df 100644
--- a/pkg/http/handler/timeout.go
+++ b/pkg/http/handler/timeout.go
@@ -28,25 +28,14 @@ import (
 	"knative.dev/pkg/websocket"
 )
 
-// TimeoutFunc returns the timeout duration to be used by the timeout handler.
-type TimeoutFunc func(req *http.Request) time.Duration
-
-// StaticTimeoutFunc returns a TimeoutFunc that always returns the same duration.
-func StaticTimeoutFunc(timeout time.Duration) TimeoutFunc {
-	return func(req *http.Request) time.Duration {
-		return timeout
-	}
-}
-
 type timeToFirstByteTimeoutHandler struct {
-	handler     http.Handler
-	timeoutFunc TimeoutFunc
-	body        string
+	handler http.Handler
+	timeout time.Duration
+	body    string
 }
 
 // NewTimeToFirstByteTimeoutHandler returns a Handler that runs `h` with the
-// given time limit from the timeout function in which the first byte of
-// the response must be written.
+// given timeout in which the first byte of the response must be written.
 //
 // The new Handler calls h.ServeHTTP to handle each request, but if a
 // call runs for longer than its time limit, the handler responds with
@@ -60,11 +49,11 @@ type timeToFirstByteTimeoutHandler struct {
 // https://golang.org/pkg/net/http/#Handler.
 //
 // The implementation is largely inspired by http.TimeoutHandler.
-func NewTimeToFirstByteTimeoutHandler(h http.Handler, msg string, timeoutFunc TimeoutFunc) http.Handler {
+func NewTimeToFirstByteTimeoutHandler(h http.Handler, msg string, timeout time.Duration) http.Handler {
 	return &timeToFirstByteTimeoutHandler{
-		handler:     h,
-		body:        msg,
-		timeoutFunc: timeoutFunc,
+		handler: h,
+		body:    msg,
+		timeout: timeout,
 	}
 }
 
@@ -86,7 +75,7 @@ func (h *timeToFirstByteTimeoutHandler) ServeHTTP(w http.ResponseWriter, r *http
 		h.handler.ServeHTTP(tw, r.WithContext(ctx))
 	}()
 
-	timeout := time.NewTimer(h.timeoutFunc(r))
+	timeout := time.NewTimer(h.timeout)
 	defer timeout.Stop()
 	for {
 		select {
@@ -164,8 +153,8 @@ func (tw *timeoutWriter) WriteHeader(code int) {
 	tw.w.WriteHeader(code)
 }
 
-// timeoutAndError writes an error to the response write if
-// nothing has been written on the writer before. Returns whether
+// timeoutAndWriteError writes an error to the responsewriter if
+// nothing has been written to the writer before. Returns whether
 // an error was written or not.
 //
 // If this writes an error, all subsequent calls to Write will
diff --git a/pkg/http/proxy.go b/pkg/http/proxy.go
index ff96d23a2..06085d782 100644
--- a/pkg/http/proxy.go
+++ b/pkg/http/proxy.go
@@ -19,6 +19,8 @@ package http
 import (
 	"net/http"
 	"net/http/httputil"
+
+	"knative.dev/pkg/network"
 )
 
 // NewHeaderPruningReverseProxy returns a httputil.ReverseProxy that proxies
@@ -30,9 +32,9 @@ func NewHeaderPruningReverseProxy(targetHost string, headersToRemove []string) *
 			req.URL.Host = targetHost
 
 			// Copied from httputil.NewSingleHostReverseProxy.
-			if _, ok := req.Header["User-Agent"]; !ok {
+			if _, ok := req.Header[network.UserAgentKey]; !ok {
 				// explicitly disable User-Agent so it's not set to default value
-				req.Header.Set("User-Agent", "")
+				req.Header.Set(network.UserAgentKey, "")
 			}
 
 			for _, h := range headersToRemove {
diff --git a/pkg/reconciler/autoscaling/hpa/resources/hpa.go b/pkg/reconciler/autoscaling/hpa/resources/hpa.go
index fb4833e2d..536191988 100644
--- a/pkg/reconciler/autoscaling/hpa/resources/hpa.go
+++ b/pkg/reconciler/autoscaling/hpa/resources/hpa.go
@@ -56,8 +56,7 @@ func MakeHPA(pa *v1alpha1.PodAutoscaler, config *autoscalerconfig.Config) *autos
 		hpa.Spec.MinReplicas = &min
 	}
 
-	switch pa.Metric() {
-	case autoscaling.CPU:
+	if pa.Metric() == autoscaling.CPU {
 		if target, ok := pa.Target(); ok {
 			hpa.Spec.Metrics = []autoscalingv2beta1.MetricSpec{{
 				Type: autoscalingv2beta1.ResourceMetricSourceType,
diff --git a/pkg/reconciler/domainmapping/resources/ingress.go b/pkg/reconciler/domainmapping/resources/ingress.go
index b739eb7c1..82841c138 100644
--- a/pkg/reconciler/domainmapping/resources/ingress.go
+++ b/pkg/reconciler/domainmapping/resources/ingress.go
@@ -56,20 +56,22 @@ func MakeIngress(dm *servingv1alpha1.DomainMapping, backendServiceName, hostName
 				Hosts:      []string{dm.Name},
 				Visibility: netv1alpha1.IngressVisibilityExternalIP,
 				HTTP: &netv1alpha1.HTTPIngressRuleValue{
-					Paths: append([]netv1alpha1.HTTPIngressPath{{
-						RewriteHost: hostName,
-						Splits: []netv1alpha1.IngressBackendSplit{{
-							Percent: 100,
-							AppendHeaders: map[string]string{
-								network.OriginalHostHeader: dm.Name,
-							},
-							IngressBackend: netv1alpha1.IngressBackend{
-								ServiceNamespace: dm.Namespace,
-								ServiceName:      backendServiceName,
-								ServicePort:      intstr.FromInt(80),
-							},
-						}},
-					}}, routeresources.MakeACMEIngressPaths(acmeChallenges, dm.GetName())...),
+					// The order of the paths is sensitive, always put tls challenge first
+					Paths: append(routeresources.MakeACMEIngressPaths(acmeChallenges, dm.GetName()),
+						[]netv1alpha1.HTTPIngressPath{{
+							RewriteHost: hostName,
+							Splits: []netv1alpha1.IngressBackendSplit{{
+								Percent: 100,
+								AppendHeaders: map[string]string{
+									network.OriginalHostHeader: dm.Name,
+								},
+								IngressBackend: netv1alpha1.IngressBackend{
+									ServiceNamespace: dm.Namespace,
+									ServiceName:      backendServiceName,
+									ServicePort:      intstr.FromInt(80),
+								},
+							}},
+						}}...),
 				},
 			}},
 		},
diff --git a/pkg/reconciler/route/controller.go b/pkg/reconciler/route/controller.go
index 721015cc7..fdcf50202 100644
--- a/pkg/reconciler/route/controller.go
+++ b/pkg/reconciler/route/controller.go
@@ -47,12 +47,12 @@ func NewController(
 	ctx context.Context,
 	cmw configmap.Watcher,
 ) *controller.Impl {
-	return newControllerWithClock(ctx, cmw, clock.RealClock{})
+	return newController(ctx, cmw, clock.RealClock{})
 }
 
 type reconcilerOption func(*Reconciler)
 
-func newControllerWithClock(
+func newController(
 	ctx context.Context,
 	cmw configmap.Watcher,
 	clock clock.Clock,
diff --git a/pkg/reconciler/route/reconcile_resources.go b/pkg/reconciler/route/reconcile_resources.go
index 552511bd5..cbd182132 100644
--- a/pkg/reconciler/route/reconcile_resources.go
+++ b/pkg/reconciler/route/reconcile_resources.go
@@ -120,11 +120,10 @@ func (c *Reconciler) reconcilePlaceholderServices(ctx context.Context, route *v1
 	logger := logging.FromContext(ctx)
 	recorder := controller.GetEventRecorder(ctx)
 
-	existingServices, err := c.getServices(route)
+	existingServiceNames, err := c.getPlaceholderServiceNames(route)
 	if err != nil {
 		return nil, fmt.Errorf("failed to fetch existing services: %w", err)
 	}
-	existingServiceNames := resources.GetNames(existingServices)
 
 	ns := route.Namespace
 	names := make(sets.String, len(targets))
@@ -134,6 +133,7 @@ func (c *Reconciler) reconcilePlaceholderServices(ctx context.Context, route *v1
 
 	services := make([]*corev1.Service, 0, names.Len())
 	createdServiceNames := make(sets.String, names.Len())
+	// NB: we don't need to sort here, but it makes table tests work...
 	for _, name := range names.List() {
 		desiredService, err := resources.MakeK8sPlaceholderService(ctx, route, name)
 		if err != nil {
@@ -267,7 +267,7 @@ func (c *Reconciler) reconcileRollout(
 	if nextStepTime > 0 {
 		nextStepTime -= now
 		c.enqueueAfter(r, time.Duration(nextStepTime))
-		logger.Debug("Re-enqueuing after", zap.Duration("duration", time.Duration(nextStepTime)))
+		logger.Debug("Re-enqueuing after", zap.Duration("nextStepTime", time.Duration(nextStepTime)))
 	}
 
 	// Comparing and diffing isn't cheap so do it only if we're going
diff --git a/pkg/reconciler/route/resources/service.go b/pkg/reconciler/route/resources/service.go
index 86e8adc0a..8d53a8d18 100644
--- a/pkg/reconciler/route/resources/service.go
+++ b/pkg/reconciler/route/resources/service.go
@@ -22,9 +22,7 @@ import (
 
 	corev1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-	"k8s.io/apimachinery/pkg/labels"
 	"k8s.io/apimachinery/pkg/util/intstr"
-	"k8s.io/apimachinery/pkg/util/sets"
 
 	network "knative.dev/networking/pkg"
 	"knative.dev/networking/pkg/apis/networking"
@@ -37,22 +35,6 @@ import (
 
 var errLoadBalancerNotFound = errors.New("failed to fetch loadbalancer domain/IP from ingress status")
 
-// GetNames returns a set of service names.
-func GetNames(services []*corev1.Service) sets.String {
-	names := make(sets.String, len(services))
-
-	for i := range services {
-		names.Insert(services[i].Name)
-	}
-
-	return names
-}
-
-// SelectorFromRoute creates a label selector given a specific route.
-func SelectorFromRoute(route *v1.Route) labels.Selector {
-	return labels.SelectorFromSet(labels.Set{serving.RouteLabelKey: route.Name})
-}
-
 // MakeK8sPlaceholderService creates a placeholder Service to prevent naming collisions. It's owned by the
 // provided v1.Route.
 func MakeK8sPlaceholderService(ctx context.Context, route *v1.Route, targetName string) (*corev1.Service, error) {
@@ -65,11 +47,7 @@ func MakeK8sPlaceholderService(ctx context.Context, route *v1.Route, targetName
 		return nil, err
 	}
 
-	service, err := makeK8sService(ctx, route, targetName)
-	if err != nil {
-		return nil, err
-	}
-	service.Spec = corev1.ServiceSpec{
+	return makeK8sService(ctx, route, &corev1.ServiceSpec{
 		Type:            corev1.ServiceTypeExternalName,
 		ExternalName:    fullName,
 		SessionAffinity: corev1.ServiceAffinityNone,
@@ -78,28 +56,23 @@ func MakeK8sPlaceholderService(ctx context.Context, route *v1.Route, targetName
 			Port:       int32(80),
 			TargetPort: intstr.FromInt(80),
 		}},
-	}
-
-	return service, nil
+	}, targetName)
 }
 
 // MakeK8sService creates a Service that redirect to the loadbalancer specified
 // in Ingress status. It's owned by the provided v1.Route.
-func MakeK8sService(ctx context.Context, route *v1.Route, targetName string, ingress *netv1alpha1.Ingress, isPrivate bool, clusterIP string) (*corev1.Service, error) {
+func MakeK8sService(ctx context.Context, route *v1.Route,
+	targetName string, ingress *netv1alpha1.Ingress, isPrivate bool, clusterIP string) (*corev1.Service, error) {
 	svcSpec, err := makeServiceSpec(ingress, isPrivate, clusterIP)
 	if err != nil {
 		return nil, err
 	}
 
-	service, err := makeK8sService(ctx, route, targetName)
-	if err != nil {
-		return nil, err
-	}
-	service.Spec = *svcSpec
-	return service, nil
+	return makeK8sService(ctx, route, svcSpec, targetName)
 }
 
-func makeK8sService(ctx context.Context, route *v1.Route, targetName string) (*corev1.Service, error) {
+func makeK8sService(ctx context.Context, route *v1.Route,
+	spec *corev1.ServiceSpec, targetName string) (*corev1.Service, error) {
 	hostname, err := domains.HostnameFromTemplate(ctx, route.Name, targetName)
 	if err != nil {
 		return nil, err
@@ -124,6 +97,7 @@ func makeK8sService(ctx context.Context, route *v1.Route, targetName string) (*c
 			}), svcLabels),
 			Annotations: route.GetAnnotations(),
 		},
+		Spec: *spec,
 	}, nil
 }
 
diff --git a/pkg/reconciler/route/route.go b/pkg/reconciler/route/route.go
index 02279d6ed..b0aefd33e 100644
--- a/pkg/reconciler/route/route.go
+++ b/pkg/reconciler/route/route.go
@@ -24,7 +24,6 @@ import (
 	"strings"
 	"time"
 
-	corev1 "k8s.io/api/core/v1"
 	kubelabels "k8s.io/apimachinery/pkg/labels"
 	"k8s.io/apimachinery/pkg/runtime/schema"
 	"k8s.io/apimachinery/pkg/util/clock"
@@ -42,6 +41,7 @@ import (
 	"knative.dev/pkg/logging"
 	pkgreconciler "knative.dev/pkg/reconciler"
 	"knative.dev/pkg/tracker"
+	"knative.dev/serving/pkg/apis/serving"
 	v1 "knative.dev/serving/pkg/apis/serving/v1"
 	clientset "knative.dev/serving/pkg/client/clientset/versioned"
 	routereconciler "knative.dev/serving/pkg/client/injection/reconciler/serving/v1/route"
@@ -92,18 +92,21 @@ func certClass(ctx context.Context, r *v1.Route) string {
 	return config.FromContext(ctx).Network.DefaultCertificateClass
 }
 
-func (c *Reconciler) getServices(route *v1.Route) ([]*corev1.Service, error) {
-	currentServices, err := c.serviceLister.Services(route.Namespace).List(resources.SelectorFromRoute(route))
+// getPlaceholderServiceNames returns the placeholder services names, or an error.
+func (c *Reconciler) getPlaceholderServiceNames(route *v1.Route) (sets.String, error) {
+	currentServices, err := c.serviceLister.Services(route.Namespace).List(
+		kubelabels.SelectorFromSet(kubelabels.Set{serving.RouteLabelKey: route.Name}),
+	)
 	if err != nil {
 		return nil, err
 	}
 
-	serviceCopy := make([]*corev1.Service, len(currentServices))
-	for i, svc := range currentServices {
-		serviceCopy[i] = svc.DeepCopy()
+	names := make(sets.String, len(currentServices))
+	for _, svc := range currentServices {
+		names.Insert(svc.Name)
 	}
 
-	return serviceCopy, nil
+	return names, nil
 }
 
 // ReconcileKind implements Interface.ReconcileKind.
@@ -155,11 +158,7 @@ func (c *Reconciler) ReconcileKind(ctx context.Context, r *v1.Route) pkgreconcil
 	roInProgress := !effectiveRO.Done()
 	if ingress.GetObjectMeta().GetGeneration() != ingress.Status.ObservedGeneration {
 		r.Status.MarkIngressNotConfigured()
-	} else if roInProgress {
-		logger.Info("Rollout is in progress")
-		// Rollout in progress, so mark the status as such.
-		r.Status.MarkIngressRolloutInProgress()
-	} else {
+	} else if !roInProgress {
 		r.Status.PropagateIngressStatus(ingress.Status)
 	}
 
@@ -171,8 +170,11 @@ func (c *Reconciler) ReconcileKind(ctx context.Context, r *v1.Route) pkgreconcil
 	// We do it here, rather than in the similar check above,
 	// since we might be inside a rollout and Ingress
 	// is not yet ready and that takes priority, so the `roInProgress` branch
-	// wil not be triggered.
+	// will not be triggered.
 	if roInProgress {
+		logger.Info("Rollout is in progress")
+		// Rollout in progress, so mark the status as such.
+		r.Status.MarkIngressRolloutInProgress()
 		// Update the route.Status.Traffic to contain correct traffic
 		// distribution based on rollout status.
 		r.Status.Traffic, err = traffic.GetRevisionTrafficTargets(ctx, r, effectiveRO)


Test patch:
diff --git a/.github/workflows/kind-e2e.yaml b/.github/workflows/kind-e2e.yaml
index 691550fff..aa4bea147 100644
--- a/.github/workflows/kind-e2e.yaml
+++ b/.github/workflows/kind-e2e.yaml
@@ -18,9 +18,10 @@ jobs:
       fail-fast: false # Keep running if one leg fails.
       matrix:
         k8s-version:
-        - v1.17.11
-        - v1.18.8
-        - v1.19.1
+        - v1.17.17
+        - v1.18.15
+        - v1.19.7
+        - v1.20.2
 
         test-suite:
         - ./test/conformance/runtime
@@ -32,19 +33,24 @@ jobs:
           # Map between K8s and KinD versions.
           # This is attempting to make it a bit clearer what's being tested.
           # See: https://github.com/kubernetes-sigs/kind/releases/tag/v0.9.0
-        - k8s-version: v1.17.11
-          kind-version: v0.9.0
-          kind-image-sha: sha256:5240a7a2c34bf241afb54ac05669f8a46661912eab05705d660971eeb12f6555
+        - k8s-version: v1.17.17
+          kind-version: v0.10.0
+          kind-image-sha: sha256:7b6369d27eee99c7a85c48ffd60e11412dc3f373658bc59b7f4d530b7056823e
           kingress: istio
           cluster-suffix: c${{ github.run_id }}.local
-        - k8s-version: v1.18.8
-          kind-version: v0.9.0
-          kind-image-sha: sha256:f4bcc97a0ad6e7abaf3f643d890add7efe6ee4ab90baeb374b4f41a4c95567eb
+        - k8s-version: v1.18.15
+          kind-version: v0.10.0
+          kind-image-sha: sha256:5c1b980c4d0e0e8e7eb9f36f7df525d079a96169c8a8f20d8bd108c0d0889cc4
           kingress: kourier
           cluster-suffix: c${{ github.run_id }}.local
-        - k8s-version: v1.19.1
-          kind-version: v0.9.0
-          kind-image-sha: sha256:98cf5288864662e37115e362b23e4369c8c4a408f99cbc06e58ac30ddc721600
+        - k8s-version: v1.19.7
+          kind-version: v0.10.0
+          kind-image-sha: sha256:a70639454e97a4b733f9d9b67e12c01f6b0297449d5b9cbbef87473458e26dca
+          kingress: contour
+          cluster-suffix: c${{ github.run_id }}.local
+        - k8s-version: v1.20.2
+          kind-version: v0.10.0
+          kind-image-sha: sha256:8f7ea6e7642c0da54f04a7ee10431549c0257315b3a634f6ef2fecaaedb19bab
           kingress: contour
           cluster-suffix: c${{ github.run_id }}.local
 
diff --git a/cmd/activator/request_log_test.go b/cmd/activator/request_log_test.go
index aa9762e40..e3dd0ecc5 100644
--- a/cmd/activator/request_log_test.go
+++ b/cmd/activator/request_log_test.go
@@ -23,20 +23,15 @@ import (
 	"testing"
 
 	"github.com/google/go-cmp/cmp"
-
 	corev1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/util/uuid"
-
 	ltesting "knative.dev/pkg/logging/testing"
 	"knative.dev/pkg/metrics"
-	rtesting "knative.dev/pkg/reconciler/testing"
 	"knative.dev/serving/pkg/activator"
+	activatorhandler "knative.dev/serving/pkg/activator/handler"
 	"knative.dev/serving/pkg/apis/serving"
 	v1 "knative.dev/serving/pkg/apis/serving/v1"
-	fakeservingclient "knative.dev/serving/pkg/client/injection/client/fake"
-	fakerevisioninformer "knative.dev/serving/pkg/client/injection/informers/serving/v1/revision/fake"
-	servinglisters "knative.dev/serving/pkg/client/listers/serving/v1"
 	pkghttp "knative.dev/serving/pkg/http"
 )
 
@@ -53,7 +48,7 @@ func TestUpdateRequestLogFromConfigMap(t *testing.T) {
 	})
 	buf := bytes.NewBufferString("")
 	handler, err := pkghttp.NewRequestLogHandler(baseHandler, buf, "",
-		requestLogTemplateInputGetter(revisionLister(t, true)), false /*enableProbeRequestLog*/)
+		requestLogTemplateInputGetter, false /*enableProbeRequestLog*/)
 	if err != nil {
 		t.Fatal("want: no error, got:", err)
 	}
@@ -131,11 +126,8 @@ func TestUpdateRequestLogFromConfigMap(t *testing.T) {
 			resp := httptest.NewRecorder()
 			rs := string(uuid.NewUUID())
 			req := httptest.NewRequest(http.MethodPost, test.url, bytes.NewBufferString(rs))
-			req.Header = map[string][]string{
-				activator.RevisionHeaderName:      {testRevisionName},
-				activator.RevisionHeaderNamespace: {testNamespaceName},
-			}
-			handler.ServeHTTP(resp, req)
+			ctx := activatorhandler.WithRevision(req.Context(), revision(true))
+			handler.ServeHTTP(resp, req.WithContext(ctx))
 
 			if got := buf.String(); got != test.want {
 				t.Errorf("got '%v', want '%v'", got, test.want)
@@ -147,13 +139,13 @@ func TestUpdateRequestLogFromConfigMap(t *testing.T) {
 func TestRequestLogTemplateInputGetter(t *testing.T) {
 	tests := []struct {
 		name     string
-		getter   pkghttp.RequestLogTemplateInputGetter
+		revision *v1.Revision
 		request  *http.Request
 		response *pkghttp.RequestLogResponse
 		want     pkghttp.RequestLogRevision
 	}{{
-		name:   "success",
-		getter: requestLogTemplateInputGetter(revisionLister(t, true)),
+		name:     "success",
+		revision: revision(true),
 		request: &http.Request{Header: map[string][]string{
 			activator.RevisionHeaderName:      {testRevisionName},
 			activator.RevisionHeaderNamespace: {testNamespaceName},
@@ -166,20 +158,8 @@ func TestRequestLogTemplateInputGetter(t *testing.T) {
 			Service:       testServiceName,
 		},
 	}, {
-		name:   "revision not found",
-		getter: requestLogTemplateInputGetter(revisionLister(t, true)),
-		request: &http.Request{Header: map[string][]string{
-			activator.RevisionHeaderName:      {"foo"},
-			activator.RevisionHeaderNamespace: {"bar"},
-		}},
-		response: &pkghttp.RequestLogResponse{Code: http.StatusAlreadyReported},
-		want: pkghttp.RequestLogRevision{
-			Name:      "foo",
-			Namespace: "bar",
-		},
-	}, {
-		name:   "labels not found",
-		getter: requestLogTemplateInputGetter(revisionLister(t, false)),
+		name:     "labels not found",
+		revision: revision(false),
 		request: &http.Request{Header: map[string][]string{
 			activator.RevisionHeaderName:      {testRevisionName},
 			activator.RevisionHeaderNamespace: {testNamespaceName},
@@ -193,12 +173,15 @@ func TestRequestLogTemplateInputGetter(t *testing.T) {
 
 	for _, test := range tests {
 		t.Run(test.name, func(t *testing.T) {
-			got := test.getter(test.request, test.response)
+			ctx := activatorhandler.WithRevision(test.request.Context(), test.revision)
+			request := test.request.WithContext(ctx)
+
+			got := requestLogTemplateInputGetter(request, test.response)
 			if !cmp.Equal(*got.Revision, test.want) {
 				t.Errorf("Got = %v, want: %v, diff:\n%s", got.Revision, test.want, cmp.Diff(got.Revision, test.want))
 			}
-			if got.Request != test.request {
-				t.Errorf("Got = %v, want: %v", got.Request, test.request)
+			if got.Request != request {
+				t.Errorf("Got = %v, want: %v", got.Request, request)
 			}
 			if got.Response != test.response {
 				t.Errorf("Got = %v, want: %v", got.Response, test.response)
@@ -207,13 +190,14 @@ func TestRequestLogTemplateInputGetter(t *testing.T) {
 	}
 }
 
-func revisionLister(t *testing.T, addLabels bool) servinglisters.RevisionLister {
+func revision(addLabels bool) *v1.Revision {
 	rev := &v1.Revision{
 		ObjectMeta: metav1.ObjectMeta{
 			Name:      testRevisionName,
 			Namespace: testNamespaceName,
 		},
 	}
+
 	if addLabels {
 		rev.Labels = map[string]string{
 			serving.ConfigurationLabelKey: testConfigName,
@@ -221,9 +205,5 @@ func revisionLister(t *testing.T, addLabels bool) servinglisters.RevisionLister
 		}
 	}
 
-	ctx, _ := rtesting.SetupFakeContext(t)
-	fakeservingclient.Get(ctx).ServingV1().Revisions(testNamespaceName).Create(ctx, rev, metav1.CreateOptions{})
-	ri := fakerevisioninformer.Get(ctx)
-	ri.Informer().GetIndexer().Add(rev)
-	return ri.Lister()
+	return rev
 }
diff --git a/pkg/activator/handler/concurrency_reporter_test.go b/pkg/activator/handler/concurrency_reporter_test.go
index e93f284c9..1db6d3f9f 100644
--- a/pkg/activator/handler/concurrency_reporter_test.go
+++ b/pkg/activator/handler/concurrency_reporter_test.go
@@ -437,7 +437,7 @@ func TestConcurrencyReporterHandler(t *testing.T) {
 
 	resp := httptest.NewRecorder()
 	req := httptest.NewRequest(http.MethodPost, "http://example.com", nil)
-	rCtx := withRevID(context.Background(), rev1)
+	rCtx := WithRevID(context.Background(), rev1)
 
 	// Send a few requests.
 	handler.ServeHTTP(resp, req.WithContext(rCtx))
@@ -644,7 +644,7 @@ func BenchmarkConcurrencyReporterHandler(b *testing.B) {
 			Name:      testRevName + strconv.Itoa(i),
 		}
 		req := httptest.NewRequest(http.MethodGet, "http://example.com", nil)
-		reqs = append(reqs, req.WithContext(withRevID(context.Background(), key)))
+		reqs = append(reqs, req.WithContext(WithRevID(context.Background(), key)))
 
 		// Create revisions in the fake clients to trigger report logic.
 		rev := revision(key.Namespace, key.Name)
diff --git a/pkg/activator/handler/context_handler_test.go b/pkg/activator/handler/context_handler_test.go
index 06c688ddb..c4cee0092 100644
--- a/pkg/activator/handler/context_handler_test.go
+++ b/pkg/activator/handler/context_handler_test.go
@@ -38,12 +38,12 @@ func TestContextHandler(t *testing.T) {
 	revisionInformer(ctx, revision)
 
 	baseHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-		if got := revisionFrom(r.Context()); got != revision {
+		if got := RevisionFrom(r.Context()); got != revision {
 			t.Errorf("revisionFrom() = %v, want %v", got, revision)
 		}
 
-		if got := revIDFrom(r.Context()); got != revID {
-			t.Errorf("revIDFrom() = %v, want %v", got, revID)
+		if got := RevIDFrom(r.Context()); got != revID {
+			t.Errorf("RevIDFrom() = %v, want %v", got, revID)
 		}
 	})
 
diff --git a/pkg/activator/handler/handler_test.go b/pkg/activator/handler/handler_test.go
index 273442ba5..a706b4b4e 100644
--- a/pkg/activator/handler/handler_test.go
+++ b/pkg/activator/handler/handler_test.go
@@ -134,7 +134,7 @@ func TestActivationHandler(t *testing.T) {
 			// Set up config store to populate context.
 			configStore := setupConfigStore(t, logging.FromContext(ctx))
 			ctx = configStore.ToContext(ctx)
-			ctx = withRevID(ctx, types.NamespacedName{Namespace: testNamespace, Name: testRevName})
+			ctx = WithRevID(ctx, types.NamespacedName{Namespace: testNamespace, Name: testRevName})
 
 			handler.ServeHTTP(resp, req.WithContext(ctx))
 
@@ -172,7 +172,7 @@ func TestActivationHandlerProxyHeader(t *testing.T) {
 	// Set up config store to populate context.
 	configStore := setupConfigStore(t, logging.FromContext(ctx))
 	ctx = configStore.ToContext(req.Context())
-	ctx = withRevID(ctx, types.NamespacedName{Namespace: testNamespace, Name: testRevName})
+	ctx = WithRevID(ctx, types.NamespacedName{Namespace: testNamespace, Name: testRevName})
 
 	handler.ServeHTTP(writer, req.WithContext(ctx))
 
@@ -267,7 +267,7 @@ func sendRequest(namespace, revName string, handler http.Handler, store *activat
 	resp := httptest.NewRecorder()
 	req := httptest.NewRequest(http.MethodPost, "http://example.com/", nil)
 	ctx := store.ToContext(req.Context())
-	ctx = withRevID(ctx, types.NamespacedName{Namespace: namespace, Name: revName})
+	ctx = WithRevID(ctx, types.NamespacedName{Namespace: namespace, Name: revName})
 	handler.ServeHTTP(resp, req.WithContext(ctx))
 	return resp
 }
@@ -318,7 +318,7 @@ func BenchmarkHandler(b *testing.B) {
 			req.Host = "test-host"
 
 			reqCtx := configStore.ToContext(context.Background())
-			reqCtx = withRevID(reqCtx, types.NamespacedName{Namespace: testNamespace, Name: testRevName})
+			reqCtx = WithRevID(reqCtx, types.NamespacedName{Namespace: testNamespace, Name: testRevName})
 			return req.WithContext(reqCtx)
 		}
 
diff --git a/pkg/activator/handler/healthz_handler_test.go b/pkg/activator/handler/healthz_handler_test.go
index 239923d28..74891206e 100644
--- a/pkg/activator/handler/healthz_handler_test.go
+++ b/pkg/activator/handler/healthz_handler_test.go
@@ -24,6 +24,7 @@ import (
 	"testing"
 
 	ktesting "knative.dev/pkg/logging/testing"
+	"knative.dev/pkg/network"
 )
 
 func TestHealthHandler(t *testing.T) {
@@ -36,19 +37,17 @@ func TestHealthHandler(t *testing.T) {
 		check          func() error
 	}{{
 		name:           "forward non-kubelet request",
-		headers:        mapToHeader(map[string]string{"User-Agent": "chromium/734.6.5"}),
+		headers:        http.Header{network.UserAgentKey: []string{"chromium/734.6.5"}},
 		passed:         true,
 		expectedStatus: http.StatusOK,
 	}, {
 		name:           "kubelet probe success",
-		headers:        mapToHeader(map[string]string{"User-Agent": "kube-probe/something"}),
-		passed:         false,
+		headers:        http.Header{network.UserAgentKey: []string{"kube-probe/something"}},
 		expectedStatus: http.StatusOK,
 		check:          func() error { return nil },
 	}, {
 		name:           "kubelet probe failure",
-		headers:        mapToHeader(map[string]string{"User-Agent": "kube-probe/something"}),
-		passed:         false,
+		headers:        http.Header{network.UserAgentKey: []string{"kube-probe/something"}},
 		expectedStatus: http.StatusInternalServerError,
 		check:          func() error { return errors.New("not ready") },
 	}}
@@ -77,7 +76,7 @@ func TestHealthHandler(t *testing.T) {
 			}
 
 			if resp.Code != e.expectedStatus {
-				t.Errorf("Unexpected response status. Want %d, got %d", e.expectedStatus, resp.Code)
+				t.Errorf("HTTP Status = %d, want: %d", resp.Code, e.expectedStatus)
 			}
 		})
 	}
@@ -90,15 +89,15 @@ func BenchmarkHealthHandler(b *testing.B) {
 		check   func() error
 	}{{
 		label:   "forward non-kubelet request",
-		headers: mapToHeader(map[string]string{"User-Agent": "chromium/734.6.5"}),
+		headers: http.Header{network.UserAgentKey: []string{"chromium/734.6.5"}},
 		check:   func() error { return nil },
 	}, {
 		label:   "kubelet probe success",
-		headers: mapToHeader(map[string]string{"User-Agent": "kube-probe/something"}),
+		headers: http.Header{network.UserAgentKey: []string{"kube-probe/something"}},
 		check:   func() error { return nil },
 	}, {
 		label:   "kubelet probe failure",
-		headers: mapToHeader(map[string]string{"User-Agent": "kube-probe/something"}),
+		headers: http.Header{network.UserAgentKey: []string{"kube-probe/something"}},
 		check:   func() error { return errors.New("not ready") },
 	}}
 
diff --git a/pkg/activator/handler/metric_handler_test.go b/pkg/activator/handler/metric_handler_test.go
index 154790684..0c6a4421c 100644
--- a/pkg/activator/handler/metric_handler_test.go
+++ b/pkg/activator/handler/metric_handler_test.go
@@ -114,8 +114,8 @@ func TestRequestMetricHandler(t *testing.T) {
 				metricstest.AssertMetricExists(t, responseTimeInMsecM.Name())
 			}()
 
-			reqCtx := withRevision(context.Background(), rev)
-			reqCtx = withRevID(reqCtx, types.NamespacedName{Namespace: testNamespace, Name: testRevName})
+			reqCtx := WithRevision(context.Background(), rev)
+			reqCtx = WithRevID(reqCtx, types.NamespacedName{Namespace: testNamespace, Name: testRevName})
 			handler.ServeHTTP(resp, req.WithContext(reqCtx))
 		})
 	}
@@ -128,7 +128,7 @@ func reset() {
 
 func BenchmarkMetricHandler(b *testing.B) {
 	baseHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})
-	reqCtx := withRevision(context.Background(), revision(testNamespace, testRevName))
+	reqCtx := WithRevision(context.Background(), revision(testNamespace, testRevName))
 
 	handler := NewMetricHandler("benchPod", baseHandler)
 
diff --git a/pkg/activator/handler/probe_handler_test.go b/pkg/activator/handler/probe_handler_test.go
index 630a188c3..3251f4b34 100644
--- a/pkg/activator/handler/probe_handler_test.go
+++ b/pkg/activator/handler/probe_handler_test.go
@@ -42,14 +42,12 @@ func TestProbeHandler(t *testing.T) {
 		method:         http.MethodPost,
 	}, {
 		label:          "filter a POST request containing probe header, even if probe is for a different target",
-		headers:        mapToHeader(map[string]string{network.ProbeHeaderName: queue.Name}),
-		passed:         false,
+		headers:        http.Header{network.ProbeHeaderName: []string{queue.Name}},
 		expectedStatus: http.StatusBadRequest,
 		method:         http.MethodPost,
 	}, {
 		label:          "filter a POST request containing probe header",
-		headers:        mapToHeader(map[string]string{network.ProbeHeaderName: activator.Name}),
-		passed:         false,
+		headers:        http.Header{network.ProbeHeaderName: []string{activator.Name}},
 		expectedStatus: http.StatusOK,
 		method:         http.MethodPost,
 	}, {
@@ -60,19 +58,18 @@ func TestProbeHandler(t *testing.T) {
 		method:         http.MethodGet,
 	}, {
 		label:          "filter a GET request containing probe header, with wrong target system",
-		headers:        mapToHeader(map[string]string{network.ProbeHeaderName: "not-empty"}),
-		passed:         false,
+		headers:        http.Header{network.ProbeHeaderName: []string{"not-empty"}},
 		expectedStatus: http.StatusBadRequest,
 		method:         http.MethodGet,
 	}, {
 		label:          "filter a GET request containing probe header",
-		headers:        mapToHeader(map[string]string{network.ProbeHeaderName: activator.Name}),
+		headers:        http.Header{network.ProbeHeaderName: []string{activator.Name}},
 		passed:         false,
 		expectedStatus: http.StatusOK,
 		method:         http.MethodGet,
 	}, {
 		label:          "forward a request containing empty retry header",
-		headers:        mapToHeader(map[string]string{network.ProbeHeaderName: ""}),
+		headers:        http.Header{network.ProbeHeaderName: []string{""}},
 		passed:         true,
 		expectedStatus: http.StatusOK,
 		method:         http.MethodPost,
@@ -108,24 +105,16 @@ func TestProbeHandler(t *testing.T) {
 	}
 }
 
-func mapToHeader(m map[string]string) http.Header {
-	h := http.Header{}
-	for k, v := range m {
-		h.Add(k, v)
-	}
-	return h
-}
-
 func BenchmarkProbeHandler(b *testing.B) {
 	tests := []struct {
 		label   string
 		headers http.Header
 	}{{
 		label:   "valid header name",
-		headers: mapToHeader(map[string]string{network.ProbeHeaderName: activator.Name}),
+		headers: http.Header{network.ProbeHeaderName: []string{activator.Name}},
 	}, {
 		label:   "invalid header name",
-		headers: mapToHeader(map[string]string{network.ProbeHeaderName: "not-empty"}),
+		headers: http.Header{network.ProbeHeaderName: []string{"some-other-cool-value"}},
 	}, {
 		label:   "empty header name",
 		headers: http.Header{},
diff --git a/pkg/apis/serving/v1/configuration_validation_test.go b/pkg/apis/serving/v1/configuration_validation_test.go
index 337bca88c..59c17e9f2 100644
--- a/pkg/apis/serving/v1/configuration_validation_test.go
+++ b/pkg/apis/serving/v1/configuration_validation_test.go
@@ -385,7 +385,9 @@ func TestConfigurationLabelValidation(t *testing.T) {
 		},
 		want: apis.ErrMissingField("metadata.labels.serving.knative.dev/service"),
 	}, {
-		name: "invalid knative label",
+		// We want to be able to introduce new labels with the serving prefix in the future
+		// and not break downgrading.
+		name: "allow unknown uses of knative.dev/serving prefix",
 		c: &Configuration{
 			ObjectMeta: metav1.ObjectMeta{
 				Name: "byo-name",
@@ -395,8 +397,9 @@ func TestConfigurationLabelValidation(t *testing.T) {
 			},
 			Spec: validConfigSpec,
 		},
-		want: apis.ErrInvalidKeyName("serving.knative.dev/testlabel", "metadata.labels"),
+		want: nil,
 	}}
+
 	for _, test := range tests {
 		t.Run(test.name, func(t *testing.T) {
 			got := test.c.Validate(context.Background())
diff --git a/pkg/apis/serving/v1/revision_validation_test.go b/pkg/apis/serving/v1/revision_validation_test.go
index 78e7c7bf1..9ffe1ff41 100644
--- a/pkg/apis/serving/v1/revision_validation_test.go
+++ b/pkg/apis/serving/v1/revision_validation_test.go
@@ -221,7 +221,9 @@ func TestRevisionLabelAnnotationValidation(t *testing.T) {
 		},
 		want: apis.ErrMissingField("metadata.labels.serving.knative.dev/configuration"),
 	}, {
-		name: "invalid knative label",
+		// We want to be able to introduce new labels with the serving prefix in the future
+		// and not break downgrading.
+		name: "allow unknown uses of knative.dev/serving prefix",
 		r: &Revision{
 			ObjectMeta: metav1.ObjectMeta{
 				Name: "byo-name",
@@ -231,7 +233,7 @@ func TestRevisionLabelAnnotationValidation(t *testing.T) {
 			},
 			Spec: validRevisionSpec,
 		},
-		want: apis.ErrInvalidKeyName("serving.knative.dev/testlabel", "metadata.labels"),
+		want: nil,
 	}}
 	for _, test := range tests {
 		t.Run(test.name, func(t *testing.T) {
diff --git a/pkg/apis/serving/v1/route_validation_test.go b/pkg/apis/serving/v1/route_validation_test.go
index 3aac8e96a..76678adfa 100644
--- a/pkg/apis/serving/v1/route_validation_test.go
+++ b/pkg/apis/serving/v1/route_validation_test.go
@@ -585,7 +585,9 @@ func TestRouteLabelValidation(t *testing.T) {
 			Spec: validRouteSpec,
 		},
 	}, {
-		name: "invalid knative label",
+		// We want to be able to introduce new labels with the serving prefix in the future
+		// and not break downgrading.
+		name: "allow unknown uses of knative.dev/serving prefix",
 		r: &Route{
 			ObjectMeta: metav1.ObjectMeta{
 				Name: "byo-name",
@@ -595,7 +597,7 @@ func TestRouteLabelValidation(t *testing.T) {
 			},
 			Spec: validRouteSpec,
 		},
-		want: apis.ErrInvalidKeyName("serving.knative.dev/testlabel", "metadata.labels"),
+		want: nil,
 	}}
 	for _, test := range tests {
 		t.Run(test.name, func(t *testing.T) {
diff --git a/pkg/apis/serving/v1/service_validation_test.go b/pkg/apis/serving/v1/service_validation_test.go
index 6710ecc1f..e5ac0e7ef 100644
--- a/pkg/apis/serving/v1/service_validation_test.go
+++ b/pkg/apis/serving/v1/service_validation_test.go
@@ -83,21 +83,6 @@ func TestServiceValidation(t *testing.T) {
 				RouteSpec:         goodRouteSpec,
 			},
 		},
-	}, {
-		name: "invalid knative label",
-		r: &Service{
-			ObjectMeta: metav1.ObjectMeta{
-				Name: "valid",
-				Labels: map[string]string{
-					"serving.knative.dev/name": "some-value",
-				},
-			},
-			Spec: ServiceSpec{
-				ConfigurationSpec: goodConfigSpec,
-				RouteSpec:         goodRouteSpec,
-			},
-		},
-		wantErr: apis.ErrInvalidKeyName("serving.knative.dev/name", "metadata.labels"),
 	}, {
 		name: "valid non knative label",
 		r: &Service{
@@ -259,27 +244,47 @@ func TestServiceValidation(t *testing.T) {
 					"autoscaling.knative.dev/foo": "bar",
 				},
 			},
-			Spec: ServiceSpec{
-				ConfigurationSpec: ConfigurationSpec{
-					Template: RevisionTemplateSpec{
-						Spec: RevisionSpec{
-							PodSpec: corev1.PodSpec{
-								Containers: []corev1.Container{{
-									Image: "hellworld",
-								}},
-							},
-						},
-					},
+			Spec: getServiceSpec("helloworld:foo"),
+		},
+		wantErr: apis.ErrInvalidKeyName("autoscaling.knative.dev/foo", "metadata.annotations", `autoscaling annotations must be put under "spec.template.metadata.annotations" to work`),
+	}, {
+		// We want to be able to introduce new labels with the serving prefix in the future
+		// and not break downgrading.
+		name: "allow unknown uses of knative.dev/serving prefix for labels",
+		r: &Service{
+			ObjectMeta: metav1.ObjectMeta{
+				Name: "byo-name",
+				Labels: map[string]string{
+					"serving.knative.dev/testlabel": "value",
 				},
-				RouteSpec: RouteSpec{
-					Traffic: []TrafficTarget{{
-						LatestRevision: ptr.Bool(true),
-						Percent:        ptr.Int64(100),
-					}},
+			},
+			Spec: getServiceSpec("helloworld:foo"),
+		},
+		wantErr: nil,
+	}, {
+		name: "invalid serving.knative.dev annotation",
+		r: &Service{
+			ObjectMeta: metav1.ObjectMeta{
+				Name: "serving-annotation",
+				Annotations: map[string]string{
+					"serving.knative.dev/foo": "bar",
 				},
 			},
+			Spec: getServiceSpec("helloworld:foo"),
+		},
+		wantErr: apis.ErrInvalidKeyName("serving.knative.dev/foo", "metadata.annotations"),
+	}, {
+		name: "invalid name",
+		r: &Service{
+			ObjectMeta: metav1.ObjectMeta{
+				Name: "",
+			},
+			Spec: getServiceSpec("helloworld:foo"),
+		},
+		wantErr: &apis.FieldError{
+			Message: "name or generateName is required",
+			Paths:   []string{"metadata.name"},
 		},
-		wantErr: apis.ErrInvalidKeyName("autoscaling.knative.dev/foo", "metadata.annotations", `autoscaling annotations must be put under "spec.template.metadata.annotations" to work`),
 	}}
 
 	// TODO(dangerd): PodSpec validation failures.
diff --git a/pkg/autoscaler/aggregation/bucketing_test.go b/pkg/autoscaler/aggregation/bucketing_test.go
index 2d454a083..0ed5d4ca7 100644
--- a/pkg/autoscaler/aggregation/bucketing_test.go
+++ b/pkg/autoscaler/aggregation/bucketing_test.go
@@ -18,6 +18,7 @@ package aggregation
 
 import (
 	"fmt"
+	"math"
 	"math/rand"
 	"testing"
 	"time"
@@ -25,9 +26,34 @@ import (
 	"github.com/google/go-cmp/cmp"
 )
 
-const (
-	granularity = time.Second
-)
+const granularity = time.Second
+
+func TestComputeDecayMultiplier(t *testing.T) {
+	tests := []struct {
+		numBuckets float64
+		want       float64
+	}{{
+		numBuckets: 100,
+		want:       minExponent,
+	}, {
+		numBuckets: 60,
+		want:       minExponent,
+	}, {
+		numBuckets: 40,
+		want:       0.20567,
+	}, {
+		numBuckets: 6,
+		want:       0.78456,
+	}}
+
+	for _, tc := range tests {
+		t.Run(fmt.Sprint("nb=", tc.numBuckets), func(t *testing.T) {
+			if got, want := computeDecayMultiplier(tc.numBuckets), tc.want; math.Abs(got-want) > weightPrecision {
+				t.Errorf("Decay multiplier = %v, want: %v", got, want)
+			}
+		})
+	}
+}
 
 func TestTimedFloat64BucketsSimple(t *testing.T) {
 	trunc1 := time.Now().Truncate(1 * time.Second)
@@ -173,6 +199,49 @@ func TestTimedFloat64BucketsManyRepsWithNonMonotonicalOrder(t *testing.T) {
 	}
 }
 
+func TestTimedFloat64BucketsWeightedAverage(t *testing.T) {
+	now := time.Now()
+	buckets := NewTimedFloat64Buckets(5*time.Second, granularity)
+
+	buckets.Record(now, 2)
+	want := 2 * buckets.decayMultiplier // 2*dm = dm.
+	if got, want := buckets.WeightedAverage(now), want; got != want {
+		t.Errorf("WeightedAverage = %v, want: %v", got, want)
+	}
+
+	// Let's read one second in future, but no writes.
+	want *= (1 - buckets.decayMultiplier)
+	if got, want := buckets.WeightedAverage(now.Add(time.Second)), want; got != want {
+		t.Errorf("WeightedAverage = %v, want: %v", got, want)
+	}
+	// Record some more data.
+	buckets.Record(now.Add(time.Second), 2)
+	want += 2 * buckets.decayMultiplier
+	if got, want := buckets.WeightedAverage(now.Add(time.Second)), want; got != want {
+		t.Errorf("WeightedAverage = %v, want: %v", got, want)
+	}
+
+	// Fill the whole window, with [2, 3, 4, 5, 6]
+	for i := 0; i < 5; i++ {
+		buckets.Record(now.Add(time.Duration(2+i)*time.Second), float64(i+2))
+	}
+	// Manually compute wanted average.
+	m := buckets.decayMultiplier
+	want = 6*m +
+		5*m*(1-m) +
+		4*m*(1-m)*(1-m) +
+		3*m*(1-m)*(1-m)*(1-m) +
+		2*m*(1-m)*(1-m)*(1-m)*(1-m)
+	if got, want := buckets.WeightedAverage(now.Add(6*time.Second)), want; got != want {
+		t.Errorf("WeightedAverage = %v, want: %v", got, want)
+	}
+
+	// Read from an empty window.
+	if got, want := buckets.WeightedAverage(now.Add(16*time.Second)), 0.; got != want {
+		t.Errorf("WeightedAverage = %v, want: %v", got, want)
+	}
+}
+
 func TestTimedFloat64BucketsWindowAverage(t *testing.T) {
 	now := time.Now()
 	buckets := NewTimedFloat64Buckets(5*time.Second, granularity)
@@ -306,10 +375,14 @@ func TestTimedFloat64BucketsHoles(t *testing.T) {
 	}
 }
 
-func TestTimedFloat64BucketsWindowUpdate(t *testing.T) {
+func TestTimedFloat64BucketsResizeWindow(t *testing.T) {
 	startTime := time.Now()
 	buckets := NewTimedFloat64Buckets(5*time.Second, granularity)
 
+	if got, want := buckets.decayMultiplier, computeDecayMultiplier(5); math.Abs(got-want) > weightPrecision {
+		t.Errorf("DecayMultipler = %v, want: %v", got, want)
+	}
+
 	// Fill the whole bucketing list with rollover.
 	buckets.Record(startTime, 1)
 	buckets.Record(startTime.Add(1*time.Second), 2)
@@ -339,6 +412,9 @@ func TestTimedFloat64BucketsWindowUpdate(t *testing.T) {
 	if got, want := buckets.window, 10*time.Second; got != want {
 		t.Fatalf("Resized bucket windows = %v, want: %v", got, want)
 	}
+	if got, want := buckets.decayMultiplier, computeDecayMultiplier(10); math.Abs(got-want) > weightPrecision {
+		t.Errorf("DecayMultipler = %v, want: %v", got, want)
+	}
 
 	// Verify values were properly copied.
 	sum = 0.
diff --git a/pkg/autoscaler/statserver/server_test.go b/pkg/autoscaler/statserver/server_test.go
index 1846c5d07..ed287798e 100644
--- a/pkg/autoscaler/statserver/server_test.go
+++ b/pkg/autoscaler/statserver/server_test.go
@@ -81,7 +81,7 @@ func TestProbe(t *testing.T) {
 	if err != nil {
 		t.Fatal("Error creating request:", err)
 	}
-	req.Header.Set("User-Agent", "kube-probe/1.15.i.wish")
+	req.Header.Set(network.UserAgentKey, network.KubeProbeUAPrefix+"1.15.i.wish")
 
 	resp, err := http.DefaultClient.Do(req)
 	if err != nil {
diff --git a/pkg/http/handler/timeout_test.go b/pkg/http/handler/timeout_test.go
index 1b9b25d55..88066022a 100644
--- a/pkg/http/handler/timeout_test.go
+++ b/pkg/http/handler/timeout_test.go
@@ -81,7 +81,7 @@ func TestTimeToFirstByteTimeoutHandler(t *testing.T) {
 
 	tests := []struct {
 		name           string
-		timeoutFunc    TimeoutFunc
+		timeout        time.Duration
 		handler        func(mux *sync.Mutex, writeErrors chan error) http.Handler
 		timeoutMessage string
 		wantStatus     int
@@ -89,8 +89,8 @@ func TestTimeToFirstByteTimeoutHandler(t *testing.T) {
 		wantWriteError bool
 		wantPanic      bool
 	}{{
-		name:        "all good",
-		timeoutFunc: StaticTimeoutFunc(longTimeout),
+		name:    "all good",
+		timeout: longTimeout,
 		handler: func(*sync.Mutex, chan error) http.Handler {
 			return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 				w.Write([]byte("hi"))
@@ -99,8 +99,8 @@ func TestTimeToFirstByteTimeoutHandler(t *testing.T) {
 		wantStatus: http.StatusOK,
 		wantBody:   "hi",
 	}, {
-		name:        "custom timeout message",
-		timeoutFunc: StaticTimeoutFunc(immediateTimeout),
+		name:    "custom timeout message",
+		timeout: immediateTimeout,
 		handler: func(mux *sync.Mutex, writeErrors chan error) http.Handler {
 			return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 				mux.Lock()
@@ -114,8 +114,8 @@ func TestTimeToFirstByteTimeoutHandler(t *testing.T) {
 		wantBody:       "request timeout",
 		wantWriteError: true,
 	}, {
-		name:        "propagate panic",
-		timeoutFunc: StaticTimeoutFunc(longTimeout),
+		name:    "propagate panic",
+		timeout: longTimeout,
 		handler: func(*sync.Mutex, chan error) http.Handler {
 			return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 				panic(http.ErrAbortHandler)
@@ -125,8 +125,8 @@ func TestTimeToFirstByteTimeoutHandler(t *testing.T) {
 		wantBody:   "request timeout",
 		wantPanic:  true,
 	}, {
-		name:        "timeout before panic",
-		timeoutFunc: StaticTimeoutFunc(immediateTimeout),
+		name:    "timeout before panic",
+		timeout: immediateTimeout,
 		handler: func(*sync.Mutex, chan error) http.Handler {
 			return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 				time.Sleep(1 * time.Second)
@@ -145,7 +145,7 @@ func TestTimeToFirstByteTimeoutHandler(t *testing.T) {
 			var reqMux sync.Mutex
 			writeErrors := make(chan error, 1)
 			rr := httptest.NewRecorder()
-			handler := NewTimeToFirstByteTimeoutHandler(test.handler(&reqMux, writeErrors), test.timeoutMessage, test.timeoutFunc)
+			handler := NewTimeToFirstByteTimeoutHandler(test.handler(&reqMux, writeErrors), test.timeoutMessage, test.timeout)
 
 			defer func() {
 				if test.wantPanic {
diff --git a/pkg/http/proxy_test.go b/pkg/http/proxy_test.go
index 01e808b75..5ff134c8e 100644
--- a/pkg/http/proxy_test.go
+++ b/pkg/http/proxy_test.go
@@ -24,6 +24,8 @@ import (
 	"testing"
 
 	"github.com/google/go-cmp/cmp"
+
+	"knative.dev/pkg/network"
 )
 
 func TestNewHeaderPruningProxy(t *testing.T) {
@@ -58,10 +60,10 @@ func TestNewHeaderPruningProxy(t *testing.T) {
 		name: "explicit user agent header not removed",
 		url:  "http://example.com/",
 		header: http.Header{
-			"User-Agent": []string{"gold"},
+			network.UserAgentKey: []string{"gold"},
 		},
 		expectHeaders: http.Header{
-			"User-Agent": []string{"gold"},
+			network.UserAgentKey: []string{"gold"},
 		},
 	}}
 
diff --git a/pkg/queue/health/probe_test.go b/pkg/queue/health/probe_test.go
index 72bd6c4b1..adfbb5073 100644
--- a/pkg/queue/health/probe_test.go
+++ b/pkg/queue/health/probe_test.go
@@ -51,26 +51,23 @@ func TestTCPProbe(t *testing.T) {
 }
 
 func TestHTTPProbeSuccess(t *testing.T) {
-	var gotHeader corev1.HTTPHeader
-	var gotKubeletHeader bool
+	var (
+		gotHeader        corev1.HTTPHeader
+		gotKubeletHeader bool
+	)
 	expectedHeader := corev1.HTTPHeader{
 		Name:  "Testkey",
 		Value: "Testval",
 	}
 	var gotPath string
-	expectedPath := "/health"
+	const expectedPath = "/health"
 	server := newTestServer(t, func(w http.ResponseWriter, r *http.Request) {
-		for headerKey, headerValue := range r.Header {
-			// Filtering for expectedHeader.TestKey to avoid other HTTP probe headers
-			if expectedHeader.Name == headerKey {
-				gotHeader = corev1.HTTPHeader{Name: headerKey, Value: headerValue[0]}
-			}
-
-			if headerKey == "User-Agent" && strings.HasPrefix(headerValue[0], network.KubeProbeUAPrefix) {
-				gotKubeletHeader = true
-			}
+		if v := r.Header.Get(expectedHeader.Name); v != "" {
+			gotHeader = corev1.HTTPHeader{Name: expectedHeader.Name, Value: v}
+		}
+		if v := r.Header.Get(network.UserAgentKey); strings.HasPrefix(v, network.KubeProbeUAPrefix) {
+			gotKubeletHeader = true
 		}
-
 		gotPath = r.URL.Path
 		w.WriteHeader(http.StatusOK)
 	})
@@ -83,20 +80,21 @@ func TestHTTPProbeSuccess(t *testing.T) {
 		Timeout:       time.Second,
 		HTTPGetAction: action,
 	}
-	// Connecting to the server should work
+
+	// Connecting to the server should work.
 	if err := HTTPProbe(config); err != nil {
 		t.Error("Expected probe to succeed but it failed with", err)
 	}
 	if d := cmp.Diff(gotHeader, expectedHeader); d != "" {
-		t.Error("Expected probe headers to match but got", d)
+		t.Error("Expected probe headers to match; diff:\n", d)
 	}
 	if !gotKubeletHeader {
 		t.Error("Expected kubelet probe header to be added to request")
 	}
 	if !cmp.Equal(gotPath, expectedPath) {
-		t.Errorf("Expected %s path to match but got %s", expectedPath, gotPath)
+		t.Errorf("Path = %s, want: %s", gotPath, expectedPath)
 	}
-	// Close the server so probing fails afterwards
+	// Close the server so probing fails afterwards.
 	server.Close()
 	if err := HTTPProbe(config); err == nil {
 		t.Error("Expected probe to fail but it didn't")
@@ -217,7 +215,7 @@ func newHTTPGetAction(t *testing.T, serverURL string) *corev1.HTTPGetAction {
 
 	u, err := url.Parse(serverURL)
 	if err != nil {
-		t.Fatalf("Error parsing URL")
+		t.Fatal("Error parsing URL")
 	}
 
 	return &corev1.HTTPGetAction{
diff --git a/pkg/reconciler/domainmapping/resources/ingress_test.go b/pkg/reconciler/domainmapping/resources/ingress_test.go
index 9ae832ef1..3315bb317 100644
--- a/pkg/reconciler/domainmapping/resources/ingress_test.go
+++ b/pkg/reconciler/domainmapping/resources/ingress_test.go
@@ -190,6 +190,16 @@ func TestMakeIngress(t *testing.T) {
 					Visibility: netv1alpha1.IngressVisibilityExternalIP,
 					HTTP: &netv1alpha1.HTTPIngressRuleValue{
 						Paths: []netv1alpha1.HTTPIngressPath{{
+							Path: "/.well-known/acme-challenge/challenge-token",
+							Splits: []netv1alpha1.IngressBackendSplit{{
+								IngressBackend: netv1alpha1.IngressBackend{
+									ServiceNamespace: "test-ns",
+									ServiceName:      "cm-solver",
+									ServicePort:      intstr.FromInt(8090),
+								},
+								Percent: 100,
+							}},
+						}, {
 							RewriteHost: "the-rewrite-host",
 							Splits: []netv1alpha1.IngressBackendSplit{{
 								Percent: 100,
@@ -202,16 +212,6 @@ func TestMakeIngress(t *testing.T) {
 									ServicePort:      intstr.FromInt(80),
 								},
 							}},
-						}, {
-							Path: "/.well-known/acme-challenge/challenge-token",
-							Splits: []netv1alpha1.IngressBackendSplit{{
-								IngressBackend: netv1alpha1.IngressBackend{
-									ServiceNamespace: "test-ns",
-									ServiceName:      "cm-solver",
-									ServicePort:      intstr.FromInt(8090),
-								},
-								Percent: 100,
-							}},
 						}},
 					},
 				}},
diff --git a/pkg/reconciler/route/reconcile_resources_test.go b/pkg/reconciler/route/reconcile_resources_test.go
index 767b3a903..51d35b2af 100644
--- a/pkg/reconciler/route/reconcile_resources_test.go
+++ b/pkg/reconciler/route/reconcile_resources_test.go
@@ -165,12 +165,13 @@ func TestReconcileIngressUpdateReenqueueRollout(t *testing.T) {
 			ing = updated
 
 			// Advance the time by 5s.
-			fakeClock.SetTime(fakeClock.Now().Add(5 * time.Second))
+			const drift = 5
+			fakeClock.SetTime(fakeClock.Now().Add(drift * time.Second))
 
-			// 5s of the duration already spent.
-			totalDuration := float64(rd - 5)
+			// Drift seconds of the duration already spent.
+			totalDuration := float64(rd - drift)
 			// Step count is minimum of % points of traffic allocated to the config (1% already shifted).
-			steps := math.Min(totalDuration/5, allocatedTraffic-1)
+			steps := math.Min(totalDuration/drift, allocatedTraffic-1)
 			stepSize := math.Max(1, math.Round((allocatedTraffic-1)/steps)) // we round the step size.
 			stepDuration := time.Duration(int(totalDuration * float64(time.Second) / steps))
 
@@ -270,7 +271,7 @@ func TestReconcileIngressUpdateReenqueueRolloutAnnotation(t *testing.T) {
 				wasReenqueued = true
 				duration = d
 			}
-			ctx := updateContext(baseCtx, 311) // This should be ignored, since we set annotation.
+			ctx := updateContext(baseCtx, 311 /*rolloutDuration*/) // This should be ignored, since we set annotation.
 			_, ro, err := reconciler.reconcileIngress(ctx, r, tc, tls, "foo-ingress-class")
 			if err != nil {
 				t.Fatal("Unexpected error:", err)
@@ -326,12 +327,13 @@ func TestReconcileIngressUpdateReenqueueRolloutAnnotation(t *testing.T) {
 			ing = updated
 
 			// Advance the time by 5s.
-			fakeClock.SetTime(fakeClock.Now().Add(5 * time.Second))
+			const drift = 5
+			fakeClock.SetTime(fakeClock.Now().Add(drift * time.Second))
 
-			// 5s of the duration already spent.
-			totalDuration := float64(rd - 5)
+			// Drift seconds of the duration already spent.
+			totalDuration := float64(rd - drift)
 			// Step count is minimum of % points of traffic allocated to the config (1% already shifted).
-			steps := math.Min(totalDuration/5, allocatedTraffic-1)
+			steps := math.Min(totalDuration/drift, allocatedTraffic-1)
 			stepSize := math.Max(1, math.Round((allocatedTraffic-1)/steps)) // we round the step size.
 			stepDuration := time.Duration(int(totalDuration * float64(time.Second) / steps))
 
diff --git a/pkg/reconciler/route/resources/service_test.go b/pkg/reconciler/route/resources/service_test.go
index 7a61b73aa..df4a5699e 100644
--- a/pkg/reconciler/route/resources/service_test.go
+++ b/pkg/reconciler/route/resources/service_test.go
@@ -24,9 +24,7 @@ import (
 
 	corev1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-	"k8s.io/apimachinery/pkg/labels"
 	"k8s.io/apimachinery/pkg/util/intstr"
-	"k8s.io/apimachinery/pkg/util/sets"
 
 	network "knative.dev/networking/pkg"
 	"knative.dev/networking/pkg/apis/networking"
@@ -356,13 +354,6 @@ func TestMakeK8sPlaceholderService(t *testing.T) {
 	}
 }
 
-func TestSelectorFromRoute(t *testing.T) {
-	selector := SelectorFromRoute(r)
-	if !selector.Matches(labels.Set{serving.RouteLabelKey: r.Name}) {
-		t.Errorf("Unexpected labels in selector")
-	}
-}
-
 func testConfig() *config.Config {
 	return &config.Config{
 		Domain: &config.Domain{
@@ -390,41 +381,3 @@ func testConfig() *config.Config {
 		},
 	}
 }
-
-func TestGetNames(t *testing.T) {
-	tests := []struct {
-		name     string
-		services []*corev1.Service
-		want     sets.String
-	}{
-		{
-			name: "nil services",
-			want: sets.String{},
-		},
-		{
-			name: "multiple services",
-			services: []*corev1.Service{
-				{ObjectMeta: metav1.ObjectMeta{Name: "svc1"}},
-				{ObjectMeta: metav1.ObjectMeta{Name: "svc2"}},
-				{ObjectMeta: metav1.ObjectMeta{Name: "svc3"}},
-			},
-			want: sets.NewString("svc1", "svc2", "svc3"),
-		},
-		{
-			name: "duplicate services",
-			services: []*corev1.Service{
-				{ObjectMeta: metav1.ObjectMeta{Name: "svc1"}},
-				{ObjectMeta: metav1.ObjectMeta{Name: "svc1"}},
-				{ObjectMeta: metav1.ObjectMeta{Name: "svc1"}},
-			},
-			want: sets.NewString("svc1"),
-		},
-	}
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			if got := GetNames(tt.services); !cmp.Equal(got, tt.want) {
-				t.Error("GetNames() (-want, +got) =", cmp.Diff(tt.want, got))
-			}
-		})
-	}
-}
diff --git a/pkg/reconciler/route/route_test.go b/pkg/reconciler/route/route_test.go
index b8b451c01..efe05a5d9 100644
--- a/pkg/reconciler/route/route_test.go
+++ b/pkg/reconciler/route/route_test.go
@@ -82,9 +82,9 @@ func testConfiguration() *v1.Configuration {
 	}
 }
 
-func revisionForConfig(config *v1.Configuration) *v1.Revision {
+func testRevision() *v1.Revision {
 	return Revision(testNamespace, "p-deadbeef", func(r *v1.Revision) {
-		r.Spec = *config.Spec.GetTemplate().Spec.DeepCopy()
+		r.Spec = *(&v1.ConfigurationSpec{}).GetTemplate().Spec.DeepCopy()
 	}, MarkRevisionReady, WithK8sServiceName)
 }
 
@@ -97,7 +97,7 @@ func newTestSetup(t *testing.T, opts ...reconcilerOption) (
 
 	ctx, cf, informers = SetupFakeContextWithCancel(t)
 	configMapWatcher = &configmap.ManualWatcher{Namespace: system.Namespace()}
-	ctrl = newControllerWithClock(ctx, configMapWatcher, &clock.RealClock{}, opts...)
+	ctrl = newController(ctx, configMapWatcher, &clock.RealClock{}, opts...)
 
 	for _, cfg := range []*corev1.ConfigMap{{
 		ObjectMeta: metav1.ObjectMeta{
@@ -284,7 +284,7 @@ func TestCreateRouteForOneReserveRevision(t *testing.T) {
 			t.Errorf("<-Events = %s, wanted %s", got, want)
 		}
 	case <-time.After(3 * time.Second):
-		t.Error("timed out waiting for expected events.")
+		t.Error("Timed out waiting for expected events.")
 	}
 	select {
 	case got := <-fakeRecorder.Events:
@@ -293,7 +293,7 @@ func TestCreateRouteForOneReserveRevision(t *testing.T) {
 			t.Errorf("<-Events = %s, wanted prefix %s", got, wantPrefix)
 		}
 	case <-time.After(3 * time.Second):
-		t.Error("timed out waiting for expected events.")
+		t.Error("Timed out waiting for expected events.")
 	}
 }
 
@@ -315,7 +315,7 @@ func TestCreateRouteWithMultipleTargets(t *testing.T) {
 	// A configuration and associated revision. Normally the revision would be
 	// created by the configuration reconciler.
 	config := testConfiguration()
-	cfgrev := revisionForConfig(config)
+	cfgrev := testRevision()
 	config.Status.SetLatestCreatedRevisionName(cfgrev.Name)
 	config.Status.SetLatestReadyRevisionName(cfgrev.Name)
 	fakeservingclient.Get(ctx).ServingV1().Configurations(testNamespace).Create(ctx, config, metav1.CreateOptions{})
@@ -431,7 +431,7 @@ func TestCreateRouteWithOneTargetReserve(t *testing.T) {
 	// A configuration and associated revision. Normally the revision would be
 	// created by the configuration reconciler.
 	config := testConfiguration()
-	cfgrev := revisionForConfig(config)
+	cfgrev := testRevision()
 	config.Status.SetLatestCreatedRevisionName(cfgrev.Name)
 	config.Status.SetLatestReadyRevisionName(cfgrev.Name)
 	fakeservingclient.Get(ctx).ServingV1().Configurations(testNamespace).Create(ctx, config, metav1.CreateOptions{})
@@ -545,7 +545,7 @@ func TestCreateRouteWithDuplicateTargets(t *testing.T) {
 	// A configuration and associated revision. Normally the revision would be
 	// created by the configuration reconciler.
 	config := testConfiguration()
-	cfgrev := revisionForConfig(config)
+	cfgrev := testRevision()
 	config.Status.SetLatestCreatedRevisionName(cfgrev.Name)
 	config.Status.SetLatestReadyRevisionName(cfgrev.Name)
 	fakeservingclient.Get(ctx).ServingV1().Configurations(testNamespace).Create(ctx, config, metav1.CreateOptions{})
@@ -749,7 +749,6 @@ func TestCreateRouteWithDuplicateTargets(t *testing.T) {
 	}
 
 	if diff := cmp.Diff(expectedSpec, ci.Spec); diff != "" {
-		fmt.Printf("%+v\n", ci.Spec)
 		t.Error("Unexpected rule spec diff (-want +got):", diff)
 	}
 }
@@ -765,7 +764,7 @@ func TestCreateRouteWithNamedTargets(t *testing.T) {
 	// A configuration and associated revision. Normally the revision would be
 	// created by the configuration reconciler.
 	config := testConfiguration()
-	cfgrev := revisionForConfig(config)
+	cfgrev := testRevision()
 	config.Status.SetLatestCreatedRevisionName(cfgrev.Name)
 	config.Status.SetLatestReadyRevisionName(cfgrev.Name)
 	fakeservingclient.Get(ctx).ServingV1().Configurations(testNamespace).Create(ctx, config, metav1.CreateOptions{})
@@ -832,9 +831,7 @@ func TestCreateRouteWithNamedTargets(t *testing.T) {
 			},
 			Visibility: v1alpha1.IngressVisibilityClusterLocal,
 		}, {
-			Hosts: []string{
-				domain,
-			},
+			Hosts: []string{domain},
 			HTTP: &v1alpha1.HTTPIngressRuleValue{
 				Paths: []v1alpha1.HTTPIngressPath{{
 					Splits: []v1alpha1.IngressBackendSplit{{
@@ -887,9 +884,7 @@ func TestCreateRouteWithNamedTargets(t *testing.T) {
 			},
 			Visibility: v1alpha1.IngressVisibilityClusterLocal,
 		}, {
-			Hosts: []string{
-				"bar-test-route.test.test-domain.dev",
-			},
+			Hosts: []string{"bar-test-route.test.test-domain.dev"},
 			HTTP: &v1alpha1.HTTPIngressRuleValue{
 				Paths: []v1alpha1.HTTPIngressPath{{
 					Splits: []v1alpha1.IngressBackendSplit{{
@@ -931,9 +926,7 @@ func TestCreateRouteWithNamedTargets(t *testing.T) {
 			},
 			Visibility: v1alpha1.IngressVisibilityClusterLocal,
 		}, {
-			Hosts: []string{
-				"foo-test-route.test.test-domain.dev",
-			},
+			Hosts: []string{"foo-test-route.test.test-domain.dev"},
 			HTTP: &v1alpha1.HTTPIngressRuleValue{
 				Paths: []v1alpha1.HTTPIngressPath{{
 					Splits: []v1alpha1.IngressBackendSplit{{
@@ -980,7 +973,7 @@ func TestCreateRouteWithNamedTargetsAndTagBasedRouting(t *testing.T) {
 	// A configuration and associated revision. Normally the revision would be
 	// created by the configuration reconciler.
 	config := testConfiguration()
-	cfgrev := revisionForConfig(config)
+	cfgrev := testRevision()
 	config.Status.SetLatestCreatedRevisionName(cfgrev.Name)
 	config.Status.SetLatestReadyRevisionName(cfgrev.Name)
 	fakeservingclient.Get(ctx).ServingV1().Configurations(testNamespace).Create(ctx, config, metav1.CreateOptions{})
@@ -1089,9 +1082,7 @@ func TestCreateRouteWithNamedTargetsAndTagBasedRouting(t *testing.T) {
 			},
 			Visibility: v1alpha1.IngressVisibilityClusterLocal,
 		}, {
-			Hosts: []string{
-				domain,
-			},
+			Hosts: []string{domain},
 			HTTP: &v1alpha1.HTTPIngressRuleValue{
 				Paths: []v1alpha1.HTTPIngressPath{{
 					Headers: map[string]v1alpha1.HeaderMatch{
@@ -1240,9 +1231,7 @@ func TestCreateRouteWithNamedTargetsAndTagBasedRouting(t *testing.T) {
 			},
 			Visibility: v1alpha1.IngressVisibilityClusterLocal,
 		}, {
-			Hosts: []string{
-				"foo-test-route.test.test-domain.dev",
-			},
+			Hosts: []string{"foo-test-route.test.test-domain.dev"},
 			HTTP: &v1alpha1.HTTPIngressRuleValue{
 				Paths: []v1alpha1.HTTPIngressPath{{
 					Splits: []v1alpha1.IngressBackendSplit{{
@@ -1267,7 +1256,6 @@ func TestCreateRouteWithNamedTargetsAndTagBasedRouting(t *testing.T) {
 	}
 
 	if diff := cmp.Diff(expectedSpec, ci.Spec); diff != "" {
-		fmt.Printf("%+v\n", ci.Spec)
 		t.Error("Unexpected rule spec diff (-want +got):", diff)
 	}
 }
diff --git a/pkg/reconciler/route/table_test.go b/pkg/reconciler/route/table_test.go
index 6f48d08a3..6637c273f 100644
--- a/pkg/reconciler/route/table_test.go
+++ b/pkg/reconciler/route/table_test.go
@@ -61,11 +61,12 @@ import (
 	. "knative.dev/serving/pkg/testing/v1"
 )
 
-const TestIngressClass = "ingress-class-foo"
+const testIngressClass = "ingress-class-foo"
 
-var fakeCurTime = time.Unix(1e9, 0)
-
-var rolloutDurationKey = struct{}{}
+var (
+	fakeCurTime        = time.Unix(1e9, 0)
+	rolloutDurationKey = struct{}{}
+)
 
 // This is heavily based on the way the OpenShift Ingress controller tests its reconciliation method.
 func TestReconcile(t *testing.T) {
@@ -237,7 +238,7 @@ func TestReconcile(t *testing.T) {
 			rev("default", "config", 1, MarkRevisionReady, WithRevName("config-00001"), WithK8sServiceName),
 		},
 		WantCreates: []runtime.Object{
-			ingressWithClass(
+			simpleIngress(
 				Route("default", "becomes-ready", WithConfigTarget("config"), WithURL, WithRouteUID("12-34")),
 				&traffic.Config{
 					Targets: map[string]traffic.RevisionTargets{
@@ -251,7 +252,7 @@ func TestReconcile(t *testing.T) {
 						}},
 					},
 				},
-				"custom-ingress-class",
+				withClass("custom-ingress-class"),
 			),
 			simplePlaceholderK8sService(
 				getContext(),
@@ -341,7 +342,7 @@ func TestReconcile(t *testing.T) {
 			cfg("default", "config",
 				WithConfigGeneration(1), WithLatestCreated("config-00001"), WithLatestReady("config-00001")),
 			rev("default", "config", 1, MarkRevisionReady, WithRevName("config-00001")),
-			simpleReadyIngress(
+			simpleIngress(
 				Route("default", "becomes-ready", WithConfigTarget("config"), WithURL),
 				&traffic.Config{
 					Targets: map[string]traffic.RevisionTargets{
@@ -355,6 +356,7 @@ func TestReconcile(t *testing.T) {
 						}},
 					},
 				},
+				withReadyIngress,
 			),
 		},
 		WantCreates: []runtime.Object{
@@ -388,7 +390,7 @@ func TestReconcile(t *testing.T) {
 			cfg("default", "config",
 				WithConfigGeneration(1), WithLatestCreated("config-00001"), WithLatestReady("config-00001")),
 			rev("default", "config", 1, MarkRevisionReady, WithRevName("config-00001")),
-			simpleReadyIngress(
+			simpleIngress(
 				Route("default", "becomes-ready", WithConfigTarget("config"), WithURL),
 				&traffic.Config{
 					Targets: map[string]traffic.RevisionTargets{
@@ -407,6 +409,7 @@ func TestReconcile(t *testing.T) {
 				}, {
 					RevisionName: "config-00001", Percent: 1,
 				}}, fakeCurTime.Add(-3*time.Second)),
+				withReadyIngress,
 			),
 		},
 		WantCreates: []runtime.Object{
@@ -453,7 +456,9 @@ func TestReconcile(t *testing.T) {
 						// StepDuration is 3, and so next step is `now` + 3.
 						r.Configurations[0].StepParams.NextStepTime = fakeCurTime.Add(3 * time.Second).UnixNano()
 					},
-				)),
+				),
+				withReadyIngress,
+			),
 		}, {
 			Object: simpleK8sService(
 				Route("default", "becomes-ready", WithConfigTarget("config")),
@@ -489,7 +494,7 @@ func TestReconcile(t *testing.T) {
 			cfg("default", "config",
 				WithConfigGeneration(1), WithLatestCreated("config-00001"), WithLatestReady("config-00001")),
 			rev("default", "config", 1, MarkRevisionReady, WithRevName("config-00001"), WithK8sServiceName),
-			simpleReadyIngress(
+			simpleIngress(
 				Route("default", "becomes-ready", WithConfigTarget("config"), WithURL),
 				&traffic.Config{
 					Targets: map[string]traffic.RevisionTargets{
@@ -514,6 +519,7 @@ func TestReconcile(t *testing.T) {
 						StartTime:    fakeCurTime.Add(-time.Hour).UnixNano(),
 						StepDuration: int64(time.Second),
 					})),
+				withReadyIngress,
 			),
 		},
 		WantCreates: []runtime.Object{
@@ -521,7 +527,7 @@ func TestReconcile(t *testing.T) {
 		},
 		WantUpdates: []clientgotesting.UpdateActionImpl{{
 			// ingress should be updated with the new rollout data.
-			Object: simpleReadyIngress(
+			Object: simpleIngress(
 				Route("default", "becomes-ready", WithConfigTarget("config"), WithURL),
 				&traffic.Config{
 					Targets: map[string]traffic.RevisionTargets{
@@ -534,7 +540,9 @@ func TestReconcile(t *testing.T) {
 							},
 						}},
 					},
-				}),
+				},
+				withReadyIngress,
+			),
 		}, {
 			Object: simpleK8sService(
 				Route("default", "becomes-ready", WithConfigTarget("config")),
@@ -676,7 +684,7 @@ func TestReconcile(t *testing.T) {
 				WithConfigLabel("serving.knative.dev/route", "steady-state"),
 			),
 			rev("default", "config", 1, MarkRevisionReady, WithRevName("config-00001")),
-			simpleReadyIngress(
+			simpleIngress(
 				Route("default", "steady-state", WithConfigTarget("config"), WithURL),
 				&traffic.Config{
 					Targets: map[string]traffic.RevisionTargets{
@@ -690,6 +698,7 @@ func TestReconcile(t *testing.T) {
 						}},
 					},
 				},
+				withReadyIngress,
 			),
 			simpleK8sService(Route("default", "steady-state", WithConfigTarget("config")),
 				WithExternalName(pkgnet.GetServiceHostname("private-istio-ingressgateway", "istio-system"))),
@@ -752,7 +761,7 @@ func TestReconcile(t *testing.T) {
 				WithConfigLabel("serving.knative.dev/route", "different-domain"),
 			),
 			rev("default", "config", 1, MarkRevisionReady, WithRevName("config-00001"), WithK8sServiceName),
-			simpleReadyIngress(
+			simpleIngress(
 				Route("default", "different-domain", WithConfigTarget("config"),
 					WithAnotherDomain),
 				&traffic.Config{
@@ -767,11 +776,12 @@ func TestReconcile(t *testing.T) {
 						}},
 					},
 				},
+				withReadyIngress,
 			),
 			simpleK8sService(Route("default", "different-domain", WithConfigTarget("config"))),
 		},
 		WantUpdates: []clientgotesting.UpdateActionImpl{{
-			Object: simpleReadyIngress(
+			Object: simpleIngress(
 				Route("default", "different-domain", WithConfigTarget("config"),
 					WithAnotherDomain, WithRouteGeneration(1), WithRouteLabel(map[string]string{"app": "prod"})),
 				&traffic.Config{
@@ -787,6 +797,7 @@ func TestReconcile(t *testing.T) {
 					},
 				},
 				WithHosts(1, "different-domain.default.another-example.com"),
+				withReadyIngress,
 			),
 		}},
 		Key: "default/different-domain",
@@ -808,7 +819,7 @@ func TestReconcile(t *testing.T) {
 			rev("default", "config", 1, MarkRevisionReady, WithRevName("config-00001"), WithK8sServiceName),
 			// This is the name of the new revision we're referencing above.
 			rev("default", "config", 2, WithInitRevConditions, WithRevName("config-00002")),
-			simpleReadyIngress(
+			simpleIngress(
 				Route("default", "new-latest-created", WithConfigTarget("config"), WithURL),
 				&traffic.Config{
 					Targets: map[string]traffic.RevisionTargets{
@@ -822,6 +833,7 @@ func TestReconcile(t *testing.T) {
 						}},
 					},
 				},
+				withReadyIngress,
 			),
 			simpleK8sService(Route("default", "new-latest-created", WithConfigTarget("config"))),
 		},
@@ -846,7 +858,7 @@ func TestReconcile(t *testing.T) {
 			rev("default", "config", 1, MarkRevisionReady, WithRevName("config-00001"), WithK8sServiceName),
 			// This is the name of the new revision we're referencing above.
 			rev("default", "config", 2, MarkRevisionReady, WithRevName("config-00002"), WithK8sServiceName),
-			simpleReadyIngress(
+			simpleIngress(
 				Route("default", "new-latest-ready", WithConfigTarget("config"), WithURL),
 				&traffic.Config{
 					Targets: map[string]traffic.RevisionTargets{
@@ -860,6 +872,7 @@ func TestReconcile(t *testing.T) {
 						}},
 					},
 				},
+				withReadyIngress,
 			),
 			simpleK8sService(Route("default", "new-latest-ready", WithConfigTarget("config"))),
 		},
@@ -896,7 +909,9 @@ func TestReconcile(t *testing.T) {
 					RevisionName: "config-00001", Percent: 99,
 				}, {
 					RevisionName: "config-00002", Percent: 1,
-				}}, fakeCurTime)),
+				}}, fakeCurTime),
+				withReadyIngress,
+			),
 		}},
 		WantStatusUpdates: []clientgotesting.UpdateActionImpl{{
 			Object: Route("default", "new-latest-ready", WithConfigTarget("config"),
@@ -932,7 +947,7 @@ func TestReconcile(t *testing.T) {
 			rev("default", "config", 1, MarkRevisionReady, WithRevName("config-00001"), WithK8sServiceName),
 			// This is the name of the new revision we're referencing above.
 			rev("default", "config", 2, MarkRevisionReady, WithRevName("config-00002"), WithK8sServiceName),
-			simpleReadyIngress(
+			simpleIngress(
 				Route("default", "new-latest-ready", WithConfigTarget("config"), WithURL),
 				&traffic.Config{
 					Targets: map[string]traffic.RevisionTargets{
@@ -946,12 +961,13 @@ func TestReconcile(t *testing.T) {
 						}},
 					},
 				},
+				withReadyIngress,
 			),
 			simpleK8sService(Route("default", "new-latest-ready", WithConfigTarget("config"))),
 		},
 		// A new LatestReadyRevisionName on the Configuration should result in the new Revision being rolled out.
 		WantUpdates: []clientgotesting.UpdateActionImpl{{
-			Object: simpleReadyIngress(
+			Object: simpleIngress(
 				Route("default", "new-latest-ready", WithConfigTarget("config"), WithURL, WithRouteGeneration(1)),
 				&traffic.Config{
 					Targets: map[string]traffic.RevisionTargets{
@@ -965,7 +981,9 @@ func TestReconcile(t *testing.T) {
 							},
 						}},
 					},
-				}),
+				},
+				withReadyIngress,
+			),
 		}},
 		WantStatusUpdates: []clientgotesting.UpdateActionImpl{{
 			Object: Route("default", "new-latest-ready", WithConfigTarget("config"),
@@ -1126,7 +1144,7 @@ func TestReconcile(t *testing.T) {
 			rev("default", "config", 1, MarkRevisionReady, WithRevName("config-00001"), WithK8sServiceName),
 			// This is the name of the new revision we're referencing above.
 			rev("default", "config", 2, MarkRevisionReady, WithRevName("config-00002"), WithK8sServiceName),
-			simpleReadyIngress(
+			simpleIngress(
 				Route("default", "update-ci-failure", WithConfigTarget("config"), WithURL),
 				&traffic.Config{
 					Targets: map[string]traffic.RevisionTargets{
@@ -1140,11 +1158,12 @@ func TestReconcile(t *testing.T) {
 						}},
 					},
 				},
+				withReadyIngress,
 			),
 			simpleK8sService(Route("default", "update-ci-failure", WithConfigTarget("config"))),
 		},
 		WantUpdates: []clientgotesting.UpdateActionImpl{{
-			Object: simpleReadyIngress(
+			Object: simpleIngress(
 				Route("default", "update-ci-failure", WithConfigTarget("config"), WithURL, WithRouteGeneration(1)),
 				&traffic.Config{
 					Targets: map[string]traffic.RevisionTargets{
@@ -1158,7 +1177,9 @@ func TestReconcile(t *testing.T) {
 							},
 						}},
 					},
-				}),
+				},
+				withReadyIngress,
+			),
 		}},
 		WantStatusUpdates: []clientgotesting.UpdateActionImpl{{
 			Object: Route("default", "update-ci-failure", WithConfigTarget("config"),
@@ -1191,7 +1212,7 @@ func TestReconcile(t *testing.T) {
 				WithConfigLabel("serving.knative.dev/route", "svc-mutation"),
 			),
 			rev("default", "config", 1, MarkRevisionReady, WithRevName("config-00001")),
-			simpleReadyIngress(
+			simpleIngress(
 				Route("default", "svc-mutation", WithConfigTarget("config"), WithURL),
 				&traffic.Config{
 					Targets: map[string]traffic.RevisionTargets{
@@ -1205,6 +1226,7 @@ func TestReconcile(t *testing.T) {
 						}},
 					},
 				},
+				withReadyIngress,
 			),
 			simpleK8sService(Route("default", "svc-mutation",
 				WithConfigTarget("config")), MutateK8sService),
@@ -1235,7 +1257,7 @@ func TestReconcile(t *testing.T) {
 				WithConfigLabel("serving.knative.dev/route", "svc-mutation"),
 			),
 			rev("default", "config", 1, MarkRevisionReady, WithRevName("config-00001")),
-			simpleReadyIngress(
+			simpleIngress(
 				Route("default", "svc-mutation", WithConfigTarget("config"), WithURL),
 				&traffic.Config{
 					Targets: map[string]traffic.RevisionTargets{
@@ -1249,6 +1271,7 @@ func TestReconcile(t *testing.T) {
 						}},
 					},
 				},
+				withReadyIngress,
 			),
 			simpleK8sService(Route("default", "svc-mutation",
 				WithConfigTarget("config")), MutateK8sService),
@@ -1280,7 +1303,7 @@ func TestReconcile(t *testing.T) {
 				WithConfigLabel("serving.knative.dev/route", "cluster-ip"),
 			),
 			rev("default", "config", 1, MarkRevisionReady, WithRevName("config-00001")),
-			simpleReadyIngress(
+			simpleIngress(
 				Route("default", "cluster-ip", WithConfigTarget("config"), WithURL),
 				&traffic.Config{
 					Targets: map[string]traffic.RevisionTargets{
@@ -1294,6 +1317,7 @@ func TestReconcile(t *testing.T) {
 						}},
 					},
 				},
+				withReadyIngress,
 			),
 			simpleK8sService(Route("default", "cluster-ip",
 				WithConfigTarget("config")), WithClusterIP("127.0.0.1")),
@@ -1320,7 +1344,7 @@ func TestReconcile(t *testing.T) {
 				WithConfigLabel("serving.knative.dev/route", "external-name"),
 			),
 			rev("default", "config", 1, MarkRevisionReady, WithRevName("config-00001")),
-			simpleReadyIngress(
+			simpleIngress(
 				Route("default", "external-name", WithConfigTarget("config"), WithURL),
 				&traffic.Config{
 					Targets: map[string]traffic.RevisionTargets{
@@ -1334,6 +1358,7 @@ func TestReconcile(t *testing.T) {
 						}},
 					},
 				},
+				withReadyIngress,
 			),
 			simpleK8sService(Route("default", "external-name",
 				WithConfigTarget("config")), WithExternalName("this-is-the-wrong-name")),
@@ -1359,7 +1384,7 @@ func TestReconcile(t *testing.T) {
 				WithConfigLabel("serving.knative.dev/route", "ingress-mutation"),
 			),
 			rev("default", "config", 1, MarkRevisionReady, WithRevName("config-00001"), WithK8sServiceName),
-			mutateIngress(simpleReadyIngress(
+			mutateIngress(simpleIngress(
 				Route("default", "ingress-mutation", WithConfigTarget("config"), WithURL),
 				&traffic.Config{
 					Targets: map[string]traffic.RevisionTargets{
@@ -1371,11 +1396,12 @@ func TestReconcile(t *testing.T) {
 						}},
 					},
 				},
+				withReadyIngress,
 			)),
 			simpleK8sService(Route("default", "ingress-mutation", WithConfigTarget("config"))),
 		},
 		WantUpdates: []clientgotesting.UpdateActionImpl{{
-			Object: simpleReadyIngress(
+			Object: simpleIngress(
 				Route("default", "ingress-mutation", WithConfigTarget("config"), WithURL, WithRouteGeneration(1)),
 				&traffic.Config{
 					Targets: map[string]traffic.RevisionTargets{
@@ -1389,6 +1415,7 @@ func TestReconcile(t *testing.T) {
 						}},
 					},
 				},
+				withReadyIngress,
 			),
 		}},
 		Key: "default/ingress-mutation",
@@ -1448,7 +1475,7 @@ func TestReconcile(t *testing.T) {
 				WithConfigGeneration(1), WithLatestCreated("config-00001"), WithLatestReady("config-00001")),
 			rev("default", "config", 1, MarkRevisionReady, WithRevName("config-00001")),
 			simpleK8sService(Route("default", "pinned-becomes-ready", WithConfigTarget("config"))),
-			simpleReadyIngress(
+			simpleIngress(
 				Route("default", "pinned-becomes-ready", WithConfigTarget("config"),
 					WithURL),
 				&traffic.Config{
@@ -1461,6 +1488,7 @@ func TestReconcile(t *testing.T) {
 						}},
 					},
 				},
+				withReadyIngress,
 			),
 		},
 		WantStatusUpdates: []clientgotesting.UpdateActionImpl{{
@@ -1740,7 +1768,7 @@ func TestReconcile(t *testing.T) {
 				WithConfigGeneration(2020), WithLatestCreated("green-02021"), WithLatestReady("green-02020")),
 			rev("default", "blue", 1, MarkRevisionReady, WithRevName("blue-00001"), WithK8sServiceName),
 			rev("default", "green", 2020, MarkRevisionReady, WithRevName("green-02020"), WithK8sServiceName),
-			simpleReadyIngress(
+			simpleIngress(
 				Route("default", "switch-configs", WithConfigTarget("blue"), WithURL),
 				&traffic.Config{
 					Targets: map[string]traffic.RevisionTargets{
@@ -1755,11 +1783,12 @@ func TestReconcile(t *testing.T) {
 						}},
 					},
 				},
+				withReadyIngress,
 			),
 			simpleK8sService(Route("default", "switch-configs", WithConfigTarget("blue"))),
 		},
 		WantUpdates: []clientgotesting.UpdateActionImpl{{
-			Object: simpleReadyIngress(
+			Object: simpleIngress(
 				Route("default", "switch-configs", WithConfigTarget("green"), WithURL),
 				&traffic.Config{
 					Targets: map[string]traffic.RevisionTargets{
@@ -1773,6 +1802,7 @@ func TestReconcile(t *testing.T) {
 						}},
 					},
 				},
+				withReadyIngress,
 			),
 		}},
 		WantStatusUpdates: []clientgotesting.UpdateActionImpl{{
@@ -1860,7 +1890,7 @@ func TestReconcile(t *testing.T) {
 				WithConfigLabel("serving.knative.dev/route", "steady-state"),
 			),
 			rev("default", "config", 1, MarkRevisionReady, WithRevName("config-00001")),
-			simpleReadyIngress(
+			simpleIngress(
 				Route("default", "my-route", WithConfigTarget("config"), WithURL),
 				&traffic.Config{
 					Targets: map[string]traffic.RevisionTargets{
@@ -1874,6 +1904,7 @@ func TestReconcile(t *testing.T) {
 						}},
 					},
 				},
+				withReadyIngress,
 			),
 			simpleK8sService(Route("default", "my-route", WithConfigTarget("config"))),
 			simpleK8sService(Route("default", "my-route"), OverrideServiceName("old-service-name")),
@@ -2664,7 +2695,9 @@ func simpleK8sService(r *v1.Route, so ...K8sServiceOption) *corev1.Service {
 
 	// omit the error here, as we are sure the loadbalancer info is provided.
 	// return the service instance only, so that the result can be used in TableRow.
-	svc, _ := resources.MakeK8sService(ctx, r, "", &netv1alpha1.Ingress{Status: readyIngressStatus()}, false, "")
+	svc, _ := resources.MakeK8sService(ctx, r, "", /*targetName*/
+		simpleIngress(r, &traffic.Config{}, withReadyIngress),
+		false, "" /*clusterIP*/)
 
 	for _, opt := range so {
 		opt(svc)
@@ -2674,39 +2707,11 @@ func simpleK8sService(r *v1.Route, so ...K8sServiceOption) *corev1.Service {
 }
 
 func simpleIngress(r *v1.Route, tc *traffic.Config, io ...IngressOption) *netv1alpha1.Ingress {
-	return baseIngressWithClass(r, tc, TestIngressClass, io...)
-}
-
-func ingressWithClass(r *v1.Route, tc *traffic.Config, class string, io ...IngressOption) *netv1alpha1.Ingress {
-	return baseIngressWithClass(r, tc, class, io...)
-}
-
-func baseIngressWithClass(r *v1.Route, tc *traffic.Config, class string, io ...IngressOption) *netv1alpha1.Ingress {
-	ingress, _ := resources.MakeIngress(getContext(), r, tc, nil /*tls*/, class)
-
-	for _, opt := range io {
-		opt(ingress)
-	}
-
-	return ingress
+	return ingressWithTLS(r, tc, nil /*tls*/, nil /*challenges*/, io...)
 }
 
 func ingressWithTLS(r *v1.Route, tc *traffic.Config, tls []netv1alpha1.IngressTLS, challenges []netv1alpha1.HTTP01Challenge, io ...IngressOption) *netv1alpha1.Ingress {
-	return baseIngressWithTLS(r, tc, tls, challenges, io...)
-}
-
-func baseIngressWithTLS(r *v1.Route, tc *traffic.Config, tls []netv1alpha1.IngressTLS, challenges []netv1alpha1.HTTP01Challenge, io ...IngressOption) *netv1alpha1.Ingress {
-	ingress, _ := resources.MakeIngress(getContext(), r, tc, tls, TestIngressClass, challenges...)
-
-	for _, opt := range io {
-		opt(ingress)
-	}
-
-	return ingress
-}
-
-func simpleReadyIngress(r *v1.Route, tc *traffic.Config, io ...IngressOption) *netv1alpha1.Ingress {
-	ingress := ingressWithStatus(r, tc, readyIngressStatus())
+	ingress, _ := resources.MakeIngress(getContext(), r, tc, tls, testIngressClass, challenges...)
 
 	for _, opt := range io {
 		opt(ingress)
@@ -2716,15 +2721,20 @@ func simpleReadyIngress(r *v1.Route, tc *traffic.Config, io ...IngressOption) *n
 }
 
 func ingressWithRollout(r *v1.Route, tc *traffic.Config, ro *traffic.Rollout, io ...IngressOption) *netv1alpha1.Ingress {
-	ingress, _ := resources.MakeIngressWithRollout(getContext(), r, tc, ro, nil /*tls*/, TestIngressClass)
-	ingress.Status = readyIngressStatus()
+	ingress, _ := resources.MakeIngressWithRollout(getContext(), r, tc, ro, nil /*tls*/, testIngressClass)
 	for _, o := range io {
 		o(ingress)
 	}
 	return ingress
 }
 
-func readyIngressStatus() netv1alpha1.IngressStatus {
+func withClass(class string) IngressOption {
+	return func(i *netv1alpha1.Ingress) {
+		i.Annotations[networking.IngressClassAnnotationKey] = class
+	}
+}
+
+func withReadyIngress(i *netv1alpha1.Ingress) {
 	status := netv1alpha1.IngressStatus{}
 	status.InitializeConditions()
 	status.MarkNetworkConfigured()
@@ -2737,19 +2747,11 @@ func readyIngressStatus() netv1alpha1.IngressStatus {
 		}},
 	)
 
-	return status
-}
-
-func ingressWithStatus(r *v1.Route, tc *traffic.Config, status netv1alpha1.IngressStatus) *netv1alpha1.Ingress {
-	ci := simpleIngress(r, tc)
-	ci.SetName(r.Name)
-	ci.Status = status
-
-	return ci
+	i.Status = status
 }
 
 func mutateIngress(ci *netv1alpha1.Ingress) *netv1alpha1.Ingress {
-	// Thor's Hammer.
+	// Thor's Hammer 🔨.
 	ci.Spec = netv1alpha1.IngressSpec{}
 	return ci
 }
@@ -2794,7 +2796,7 @@ func reconcilerTestConfig(enableAutoTLS bool) *config.Config {
 			},
 		},
 		Network: &network.Config{
-			DefaultIngressClass:     TestIngressClass,
+			DefaultIngressClass:     testIngressClass,
 			DefaultCertificateClass: network.CertManagerCertificateClassName,
 			AutoTLS:                 enableAutoTLS,
 			DomainTemplate:          network.DefaultDomainTemplate,
diff --git a/test/test_images/runtime/handlers/handler.go b/test/test_images/runtime/handlers/handler.go
index 9189b96a5..cbae195e2 100644
--- a/test/test_images/runtime/handlers/handler.go
+++ b/test/test_images/runtime/handlers/handler.go
@@ -21,7 +21,6 @@ import (
 	"log"
 	"net/http"
 	"net/http/httputil"
-	"strings"
 
 	network "knative.dev/networking/pkg"
 )
@@ -50,7 +49,7 @@ func withRequestLog(next http.HandlerFunc) http.HandlerFunc {
 
 // withKubeletProbeHeaderCheck checks each health request has Kubelet probe header
 func withKubeletProbeHeaderCheck(w http.ResponseWriter, r *http.Request) {
-	if !strings.HasPrefix(r.Header.Get("User-Agent"), network.KubeProbeUAPrefix) {
+	if !network.IsKubeletProbe(r) {
 		w.WriteHeader(http.StatusBadRequest)
 	} else {
 		w.WriteHeader(http.StatusOK)
diff --git a/third_party/cert-manager-latest/net-certmanager.yaml b/third_party/cert-manager-latest/net-certmanager.yaml
index 054620a26..e037e57c1 100644
--- a/third_party/cert-manager-latest/net-certmanager.yaml
+++ b/third_party/cert-manager-latest/net-certmanager.yaml
@@ -18,7 +18,7 @@ metadata:
   # These are the permissions needed by the `cert-manager` `Certificate` implementation.
   name: knative-serving-certmanager
   labels:
-    serving.knative.dev/release: "v20210217-99cfbfb6"
+    serving.knative.dev/release: "v20210222-ffa73df9"
     serving.knative.dev/controller: "true"
     networking.knative.dev/certificate-provider: cert-manager
 rules:
@@ -49,7 +49,7 @@ kind: ValidatingWebhookConfiguration
 metadata:
   name: config.webhook.net-certmanager.networking.internal.knative.dev
   labels:
-    serving.knative.dev/release: "v20210217-99cfbfb6"
+    serving.knative.dev/release: "v20210222-ffa73df9"
 webhooks:
   - admissionReviewVersions:
       - v1beta1
@@ -86,7 +86,7 @@ metadata:
   name: net-certmanager-webhook-certs
   namespace: knative-serving
   labels:
-    serving.knative.dev/release: "v20210217-99cfbfb6"
+    serving.knative.dev/release: "v20210222-ffa73df9"
 
 ---
 # Copyright 2020 The Knative Authors
@@ -109,7 +109,7 @@ metadata:
   name: config-certmanager
   namespace: knative-serving
   labels:
-    serving.knative.dev/release: "v20210217-99cfbfb6"
+    serving.knative.dev/release: "v20210222-ffa73df9"
     networking.knative.dev/certificate-provider: cert-manager
 data:
   _example: |
@@ -156,7 +156,7 @@ metadata:
   name: networking-certmanager
   namespace: knative-serving
   labels:
-    serving.knative.dev/release: "v20210217-99cfbfb6"
+    serving.knative.dev/release: "v20210222-ffa73df9"
     networking.knative.dev/certificate-provider: cert-manager
 spec:
   selector:
@@ -168,14 +168,14 @@ spec:
         cluster-autoscaler.kubernetes.io/safe-to-evict: "true"
       labels:
         app: networking-certmanager
-        serving.knative.dev/release: "v20210217-99cfbfb6"
+        serving.knative.dev/release: "v20210222-ffa73df9"
     spec:
       serviceAccountName: controller
       containers:
         - name: networking-certmanager
           # This is the Go import path for the binary that is containerized
           # and substituted here.
-          image: gcr.io/knative-nightly/knative.dev/net-certmanager/cmd/controller@sha256:f7f43bb5e0c252d8be413927986dac17bece3c3b27493ae1da3b1d38154e0b96
+          image: gcr.io/knative-nightly/knative.dev/net-certmanager/cmd/controller@sha256:1a7158142daef46614217077f974bfcea23cca1f8c704b0d794d4d369562657f
           resources:
             requests:
               cpu: 30m
@@ -213,7 +213,7 @@ kind: Service
 metadata:
   labels:
     app: networking-certmanager
-    serving.knative.dev/release: "v20210217-99cfbfb6"
+    serving.knative.dev/release: "v20210222-ffa73df9"
     networking.knative.dev/certificate-provider: cert-manager
   name: networking-certmanager
   namespace: knative-serving
@@ -250,7 +250,7 @@ metadata:
   name: net-certmanager-webhook
   namespace: knative-serving
   labels:
-    serving.knative.dev/release: "v20210217-99cfbfb6"
+    serving.knative.dev/release: "v20210222-ffa73df9"
 spec:
   selector:
     matchLabels:
@@ -263,14 +263,14 @@ spec:
       labels:
         app: net-certmanager-webhook
         role: net-certmanager-webhook
-        serving.knative.dev/release: "v20210217-99cfbfb6"
+        serving.knative.dev/release: "v20210222-ffa73df9"
     spec:
       serviceAccountName: controller
       containers:
         - name: webhook
           # This is the Go import path for the binary that is containerized
           # and substituted here.
-          image: gcr.io/knative-nightly/knative.dev/net-certmanager/cmd/webhook@sha256:75970ff398180e8245f4cf108c5156ac3d2bf5241b187db2482fad4a8f2971dd
+          image: gcr.io/knative-nightly/knative.dev/net-certmanager/cmd/webhook@sha256:2a615c24090e7ffb3a146bdb310a1cec2b933f8faea5ec015cbb0859ddabe341
           resources:
             requests:
               cpu: 20m
@@ -329,7 +329,7 @@ metadata:
   namespace: knative-serving
   labels:
     role: net-certmanager-webhook
-    serving.knative.dev/release: "v20210217-99cfbfb6"
+    serving.knative.dev/release: "v20210222-ffa73df9"
 spec:
   ports:
     # Define metrics and profiling for them to be accessible within service meshes.
diff --git a/third_party/contour-latest/contour.yaml b/third_party/contour-latest/contour.yaml
index 3ba9899fc..929c29cf6 100644
--- a/third_party/contour-latest/contour.yaml
+++ b/third_party/contour-latest/contour.yaml
@@ -1641,7 +1641,7 @@ spec:
     spec:
       containers:
         - name: contour
-          image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:7b2cdcf1aebdfdc85ee8c69d07cf8ea8fbf9d11195e9aca91c31a1ca633e001c
+          image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:46da470e6cc45181edd65d7779f23d3d4f17a313c5163cd90945d98c8e687bb2
           imagePullPolicy: Always
           command:
             - contour
@@ -1868,7 +1868,7 @@ spec:
             - --contour-key-file=/certs/tls.key
             - --config-path=/config/contour.yaml
           command: ["contour"]
-          image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:7b2cdcf1aebdfdc85ee8c69d07cf8ea8fbf9d11195e9aca91c31a1ca633e001c
+          image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:46da470e6cc45181edd65d7779f23d3d4f17a313c5163cd90945d98c8e687bb2
           imagePullPolicy: IfNotPresent
           name: contour
           ports:
@@ -1957,7 +1957,7 @@ spec:
           args:
             - envoy
             - shutdown-manager
-          image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:7b2cdcf1aebdfdc85ee8c69d07cf8ea8fbf9d11195e9aca91c31a1ca633e001c
+          image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:46da470e6cc45181edd65d7779f23d3d4f17a313c5163cd90945d98c8e687bb2
           imagePullPolicy: IfNotPresent
           lifecycle:
             preStop:
@@ -2036,7 +2036,7 @@ spec:
             - --envoy-key-file=/certs/tls.key
           command:
             - contour
-          image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:7b2cdcf1aebdfdc85ee8c69d07cf8ea8fbf9d11195e9aca91c31a1ca633e001c
+          image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:46da470e6cc45181edd65d7779f23d3d4f17a313c5163cd90945d98c8e687bb2
           imagePullPolicy: IfNotPresent
           name: envoy-initconfig
           volumeMounts:
@@ -2261,7 +2261,7 @@ spec:
     spec:
       containers:
         - name: contour
-          image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:7b2cdcf1aebdfdc85ee8c69d07cf8ea8fbf9d11195e9aca91c31a1ca633e001c
+          image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:46da470e6cc45181edd65d7779f23d3d4f17a313c5163cd90945d98c8e687bb2
           imagePullPolicy: Always
           command:
             - contour
@@ -2381,7 +2381,7 @@ spec:
             - --contour-key-file=/certs/tls.key
             - --config-path=/config/contour.yaml
           command: ["contour"]
-          image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:7b2cdcf1aebdfdc85ee8c69d07cf8ea8fbf9d11195e9aca91c31a1ca633e001c
+          image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:46da470e6cc45181edd65d7779f23d3d4f17a313c5163cd90945d98c8e687bb2
           imagePullPolicy: IfNotPresent
           name: contour
           ports:
@@ -2470,7 +2470,7 @@ spec:
           args:
             - envoy
             - shutdown-manager
-          image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:7b2cdcf1aebdfdc85ee8c69d07cf8ea8fbf9d11195e9aca91c31a1ca633e001c
+          image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:46da470e6cc45181edd65d7779f23d3d4f17a313c5163cd90945d98c8e687bb2
           imagePullPolicy: IfNotPresent
           lifecycle:
             preStop:
@@ -2549,7 +2549,7 @@ spec:
             - --envoy-key-file=/certs/tls.key
           command:
             - contour
-          image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:7b2cdcf1aebdfdc85ee8c69d07cf8ea8fbf9d11195e9aca91c31a1ca633e001c
+          image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:46da470e6cc45181edd65d7779f23d3d4f17a313c5163cd90945d98c8e687bb2
           imagePullPolicy: IfNotPresent
           name: envoy-initconfig
           volumeMounts:
diff --git a/third_party/contour-latest/net-contour.yaml b/third_party/contour-latest/net-contour.yaml
index c53255d5b..c09644d20 100644
--- a/third_party/contour-latest/net-contour.yaml
+++ b/third_party/contour-latest/net-contour.yaml
@@ -33,7 +33,7 @@ metadata:
   namespace: knative-serving
   labels:
     networking.knative.dev/ingress-provider: contour
-    serving.knative.dev/release: "v20210217-73f0cfdf"
+    serving.knative.dev/release: "v20210222-6f407be6"
 data:
   _example: |
     ################################
@@ -103,7 +103,7 @@ spec:
         - name: controller
           # This is the Go import path for the binary that is containerized
           # and substituted here.
-          image: gcr.io/knative-nightly/knative.dev/net-contour/cmd/controller@sha256:2525c370c649f570786393fe351be333cb15a5498122538589d9f7613879fa52
+          image: gcr.io/knative-nightly/knative.dev/net-contour/cmd/controller@sha256:3f5e4e701932fc16492703b47f69207ea2d035d35a0d471e4703b4c6eacf2c47
           resources:
             requests:
               cpu: 40m
diff --git a/third_party/istio-latest/net-istio.yaml b/third_party/istio-latest/net-istio.yaml
index f4e648897..3d504c990 100644
--- a/third_party/istio-latest/net-istio.yaml
+++ b/third_party/istio-latest/net-istio.yaml
@@ -1,4 +1,4 @@
-# Generated when HEAD was b4a6e6838774ed5705699b20e560025734e5020f
+# Generated when HEAD was 59b2af9679f7997fffd9befb57dedec35e1a302d
 #
 # Copyright 2019 The Knative Authors
 #
@@ -20,7 +20,7 @@ metadata:
   # These are the permissions needed by the Istio Ingress implementation.
   name: knative-serving-istio
   labels:
-    serving.knative.dev/release: "v20210218-b4a6e683"
+    serving.knative.dev/release: "v20210222-59b2af96"
     serving.knative.dev/controller: "true"
     networking.knative.dev/ingress-provider: istio
 rules:
@@ -50,7 +50,7 @@ metadata:
   name: knative-ingress-gateway
   namespace: knative-serving
   labels:
-    serving.knative.dev/release: "v20210218-b4a6e683"
+    serving.knative.dev/release: "v20210222-59b2af96"
     networking.knative.dev/ingress-provider: istio
 spec:
   selector:
@@ -87,7 +87,7 @@ metadata:
   name: knative-local-gateway
   namespace: knative-serving
   labels:
-    serving.knative.dev/release: "v20210218-b4a6e683"
+    serving.knative.dev/release: "v20210222-59b2af96"
     networking.knative.dev/ingress-provider: istio
 spec:
   selector:
@@ -106,7 +106,7 @@ metadata:
   name: knative-local-gateway
   namespace: istio-system
   labels:
-    serving.knative.dev/release: "v20210218-b4a6e683"
+    serving.knative.dev/release: "v20210222-59b2af96"
     networking.knative.dev/ingress-provider: istio
 spec:
   type: ClusterIP
@@ -126,7 +126,7 @@ metadata:
   name: "webhook"
   namespace: "knative-serving"
   labels:
-    serving.knative.dev/release: "v20210218-b4a6e683"
+    serving.knative.dev/release: "v20210222-59b2af96"
     networking.knative.dev/ingress-provider: istio
 spec:
   selector:
@@ -142,7 +142,7 @@ metadata:
   name: "domainmapping-webhook"
   namespace: "knative-serving"
   labels:
-    serving.knative.dev/release: "v20210218-b4a6e683"
+    serving.knative.dev/release: "v20210222-59b2af96"
     networking.knative.dev/ingress-provider: istio
 spec:
   selector:
@@ -158,7 +158,7 @@ metadata:
   name: "istio-webhook"
   namespace: "knative-serving"
   labels:
-    serving.knative.dev/release: "v20210218-b4a6e683"
+    serving.knative.dev/release: "v20210222-59b2af96"
     networking.knative.dev/ingress-provider: istio
 spec:
   selector:
@@ -188,7 +188,7 @@ kind: MutatingWebhookConfiguration
 metadata:
   name: webhook.istio.networking.internal.knative.dev
   labels:
-    serving.knative.dev/release: "v20210218-b4a6e683"
+    serving.knative.dev/release: "v20210222-59b2af96"
     networking.knative.dev/ingress-provider: istio
 webhooks:
   - admissionReviewVersions:
@@ -224,7 +224,7 @@ kind: ValidatingWebhookConfiguration
 metadata:
   name: config.webhook.istio.networking.internal.knative.dev
   labels:
-    serving.knative.dev/release: "v20210218-b4a6e683"
+    serving.knative.dev/release: "v20210222-59b2af96"
     networking.knative.dev/ingress-provider: istio
 webhooks:
   - admissionReviewVersions:
@@ -262,7 +262,7 @@ metadata:
   name: istio-webhook-certs
   namespace: knative-serving
   labels:
-    serving.knative.dev/release: "v20210218-b4a6e683"
+    serving.knative.dev/release: "v20210222-59b2af96"
     networking.knative.dev/ingress-provider: istio
 
 ---
@@ -286,7 +286,7 @@ metadata:
   name: config-istio
   namespace: knative-serving
   labels:
-    serving.knative.dev/release: "v20210218-b4a6e683"
+    serving.knative.dev/release: "v20210222-59b2af96"
     networking.knative.dev/ingress-provider: istio
 data:
   _example: |
@@ -360,7 +360,7 @@ metadata:
   name: networking-istio
   namespace: knative-serving
   labels:
-    serving.knative.dev/release: "v20210218-b4a6e683"
+    serving.knative.dev/release: "v20210222-59b2af96"
     networking.knative.dev/ingress-provider: istio
 spec:
   selector:
@@ -376,14 +376,14 @@ spec:
         sidecar.istio.io/inject: "false"
       labels:
         app: networking-istio
-        serving.knative.dev/release: "v20210218-b4a6e683"
+        serving.knative.dev/release: "v20210222-59b2af96"
     spec:
       serviceAccountName: controller
       containers:
         - name: networking-istio
           # This is the Go import path for the binary that is containerized
           # and substituted here.
-          image: gcr.io/knative-nightly/knative.dev/net-istio/cmd/controller@sha256:f78b8db57a76209c5d2b18730e7e948757c49cd5507f4c649ad1b3452b5f553a
+          image: gcr.io/knative-nightly/knative.dev/net-istio/cmd/controller@sha256:7fcb4b692750908778bc56a9a9e4e5a4614831c55c7d8cdaa2417f83b01600b1
           resources:
             requests:
               cpu: 30m
@@ -440,7 +440,7 @@ metadata:
   name: istio-webhook
   namespace: knative-serving
   labels:
-    serving.knative.dev/release: "v20210218-b4a6e683"
+    serving.knative.dev/release: "v20210222-59b2af96"
     networking.knative.dev/ingress-provider: istio
 spec:
   selector:
@@ -454,14 +454,14 @@ spec:
       labels:
         app: istio-webhook
         role: istio-webhook
-        serving.knative.dev/release: "v20210218-b4a6e683"
+        serving.knative.dev/release: "v20210222-59b2af96"
     spec:
       serviceAccountName: controller
       containers:
         - name: webhook
           # This is the Go import path for the binary that is containerized
           # and substituted here.
-          image: gcr.io/knative-nightly/knative.dev/net-istio/cmd/webhook@sha256:414ea880641e9a2d472b459cfc75279d746db1161506881997e78072a4dd35bc
+          image: gcr.io/knative-nightly/knative.dev/net-istio/cmd/webhook@sha256:be7ac11dc6aee3822d6002187ba399e3c5e3b8134bab4cc51828512a43705842
           resources:
             requests:
               cpu: 20m
@@ -515,7 +515,7 @@ metadata:
   namespace: knative-serving
   labels:
     role: istio-webhook
-    serving.knative.dev/release: "v20210218-b4a6e683"
+    serving.knative.dev/release: "v20210222-59b2af96"
     networking.knative.dev/ingress-provider: istio
 spec:
   ports:
diff --git a/third_party/kourier-latest/kourier.yaml b/third_party/kourier-latest/kourier.yaml
index d7582e97c..fb537022b 100644
--- a/third_party/kourier-latest/kourier.yaml
+++ b/third_party/kourier-latest/kourier.yaml
@@ -18,7 +18,7 @@ metadata:
   name: kourier-system
   labels:
     networking.knative.dev/ingress-provider: kourier
-    serving.knative.dev/release: "v20210217-364c1a22"
+    serving.knative.dev/release: "v20210222-4a442c4c"
 
 ---
 # Copyright 2020 The Knative Authors
@@ -42,7 +42,7 @@ metadata:
   namespace: kourier-system
   labels:
     networking.knative.dev/ingress-provider: kourier
-    serving.knative.dev/release: "v20210217-364c1a22"
+    serving.knative.dev/release: "v20210222-4a442c4c"
 data:
   envoy-bootstrap.yaml: |
     dynamic_resources:
@@ -142,7 +142,7 @@ metadata:
   namespace: knative-serving
   labels:
     networking.knative.dev/ingress-provider: kourier
-    serving.knative.dev/release: "v20210217-364c1a22"
+    serving.knative.dev/release: "v20210222-4a442c4c"
 ---
 apiVersion: rbac.authorization.k8s.io/v1
 kind: ClusterRole
@@ -151,7 +151,7 @@ metadata:
   namespace: knative-serving
   labels:
     networking.knative.dev/ingress-provider: kourier
-    serving.knative.dev/release: "v20210217-364c1a22"
+    serving.knative.dev/release: "v20210222-4a442c4c"
 rules:
   - apiGroups: [""]
     resources: ["events"]
@@ -178,7 +178,7 @@ metadata:
   name: 3scale-kourier
   labels:
     networking.knative.dev/ingress-provider: kourier
-    serving.knative.dev/release: "v20210217-364c1a22"
+    serving.knative.dev/release: "v20210222-4a442c4c"
 roleRef:
   apiGroup: rbac.authorization.k8s.io
   kind: ClusterRole
@@ -210,7 +210,7 @@ metadata:
   namespace: knative-serving
   labels:
     networking.knative.dev/ingress-provider: kourier
-    serving.knative.dev/release: "v20210217-364c1a22"
+    serving.knative.dev/release: "v20210222-4a442c4c"
 spec:
   replicas: 1
   selector:
@@ -222,7 +222,7 @@ spec:
         app: 3scale-kourier-control
     spec:
       containers:
-        - image: gcr.io/knative-nightly/knative.dev/net-kourier/cmd/kourier@sha256:5cdf979fc948b490764a8d5efd264a00d787feb32c9c9521b091517803f1e55d
+        - image: gcr.io/knative-nightly/knative.dev/net-kourier/cmd/kourier@sha256:5ec9c41be4475d325e3cba284f3725d6147ca1f0ac766cd9ff22f97c36a9def5
           name: kourier-control
           env:
             - name: CERTS_SECRET_NAMESPACE
@@ -258,7 +258,7 @@ metadata:
   namespace: knative-serving
   labels:
     networking.knative.dev/ingress-provider: kourier
-    serving.knative.dev/release: "v20210217-364c1a22"
+    serving.knative.dev/release: "v20210222-4a442c4c"
 spec:
   ports:
     - name: grpc-xds
@@ -291,7 +291,7 @@ metadata:
   namespace: kourier-system
   labels:
     networking.knative.dev/ingress-provider: kourier
-    serving.knative.dev/release: "v20210217-364c1a22"
+    serving.knative.dev/release: "v20210222-4a442c4c"
 spec:
   selector:
     matchLabels:
@@ -357,7 +357,7 @@ metadata:
   namespace: kourier-system
   labels:
     networking.knative.dev/ingress-provider: kourier
-    serving.knative.dev/release: "v20210217-364c1a22"
+    serving.knative.dev/release: "v20210222-4a442c4c"
 spec:
   ports:
     - name: http2
@@ -379,7 +379,7 @@ metadata:
   namespace: kourier-system
   labels:
     networking.knative.dev/ingress-provider: kourier
-    serving.knative.dev/release: "v20210217-364c1a22"
+    serving.knative.dev/release: "v20210222-4a442c4c"
 spec:
   ports:
     - name: http2