Repository: knative/serving
Pull request #10092 (2020-11-11 11:38:06)

Use t.TempDir rather than ioutil.TempDir
A little cleanup using the new `t.TempDir` function now that we have go 1.15 available.

/assign @markusthoemmes @vagababov 

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

This pull-request has been approved by: *<a href="https://github.com/knative/serving/pull/10092#" title="Author self-approved">julz</a>*
To complete the [pull request process](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process), please assign **markusthoemmes** after the PR has been reviewed.
You can assign the PR to them by writing `/assign @markusthoemmes` 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:

- **[pkg/reconciler/OWNERS](https://github.com/knative/serving/blob/master/pkg/reconciler/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":["markusthoemmes"]} -->
codecov[bot]: # [Codecov](https://codecov.io/gh/knative/serving/pull/10092?src=pr&el=h1) Report
> Merging [#10092](https://codecov.io/gh/knative/serving/pull/10092?src=pr&el=desc) (feea4a6) into [master](https://codecov.io/gh/knative/serving/commit/6f4f01733249266e6853bcf117b5377ccd6e661d?el=desc) (6f4f017) will **increase** coverage by `0.02%`.
> The diff coverage is `n/a`.

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

```diff
@@            Coverage Diff             @@
##           master   #10092      +/-   ##
==========================================
+ Coverage   87.95%   87.97%   +0.02%     
==========================================
  Files         185      185              
  Lines        8708     8708              
==========================================
+ Hits         7659     7661       +2     
  Misses        797      797              
+ Partials      252      250       -2     
```


| [Impacted Files](https://codecov.io/gh/knative/serving/pull/10092?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [pkg/reconciler/autoscaling/kpa/scaler.go](https://codecov.io/gh/knative/serving/pull/10092/diff?src=pr&el=tree#diff-cGtnL3JlY29uY2lsZXIvYXV0b3NjYWxpbmcva3BhL3NjYWxlci5nbw==) | `88.57% <0.00%> (-1.43%)` | :arrow_down: |
| [pkg/activator/net/revision\_backends.go](https://codecov.io/gh/knative/serving/pull/10092/diff?src=pr&el=tree#diff-cGtnL2FjdGl2YXRvci9uZXQvcmV2aXNpb25fYmFja2VuZHMuZ28=) | `90.49% <0.00%> (-0.91%)` | :arrow_down: |
| [pkg/reconciler/configuration/configuration.go](https://codecov.io/gh/knative/serving/pull/10092/diff?src=pr&el=tree#diff-cGtnL3JlY29uY2lsZXIvY29uZmlndXJhdGlvbi9jb25maWd1cmF0aW9uLmdv) | `88.28% <0.00%> (+1.56%)` | :arrow_up: |
| [pkg/reconciler/nscert/nscert.go](https://codecov.io/gh/knative/serving/pull/10092/diff?src=pr&el=tree#diff-cGtnL3JlY29uY2lsZXIvbnNjZXJ0L25zY2VydC5nbw==) | `72.28% <0.00%> (+4.81%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/knative/serving/pull/10092?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/10092?src=pr&el=footer). Last update [6f4f017...feea4a6](https://codecov.io/gh/knative/serving/pull/10092?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

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

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-knative-serving-unit-tests | feea4a67f46b6b1d9ec7dcc9a36a44eae2022e25 | [link](https://prow.knative.dev/view/gs/knative-prow/pr-logs/pull/knative_serving/10092/pull-knative-serving-unit-tests/1326489402800607232) | `/test pull-knative-serving-unit-tests`

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

<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 -->
julz: haha oops, https://github.com/knative/serving/pull/10061 didn't actually merge yet :)

/hold for https://github.com/knative/serving/pull/10061

Patch:
diff --git a/docs/runtime-contract.md b/docs/runtime-contract.md
index 87a587794..7cc7b0ea7 100644
--- a/docs/runtime-contract.md
+++ b/docs/runtime-contract.md
@@ -504,7 +504,8 @@ changes.
 From the OCI spec:
 
 > `rootfsPropagation` (string, OPTIONAL) sets the rootfs's mount propagation.
-> Its value is either slave, private, shared or unbindable. The
+> Its value is either slave,<!-- wokeignore:rule=slave --> private, shared or
+> unbindable. The
 > [Shared Subtrees](https://www.kernel.org/doc/Documentation/filesystems/sharedsubtree.txt)
 > article in the kernel documentation has more information about mount
 > propagation.
diff --git a/go.mod b/go.mod
index 8907930c9..f48c5c79b 100644
--- a/go.mod
+++ b/go.mod
@@ -1,6 +1,6 @@
 module knative.dev/serving
 
-go 1.14
+go 1.15
 
 require (
 	github.com/davecgh/go-spew v1.1.1
@@ -34,10 +34,10 @@ require (
 	k8s.io/client-go v11.0.1-0.20190805182717-6502b5e7b1b5+incompatible
 	k8s.io/code-generator v0.18.8
 	k8s.io/kube-openapi v0.0.0-20200410145947-bcb3869e6f29
-	knative.dev/caching v0.0.0-20201104174804-1a305923cfbe
-	knative.dev/hack v0.0.0-20201103151104-3d5abc3a0075
-	knative.dev/networking v0.0.0-20201103163404-b9f80f4537af
-	knative.dev/pkg v0.0.0-20201103163404-5514ab0c1fdf
+	knative.dev/caching v0.0.0-20201113182901-ee88f744543c
+	knative.dev/hack v0.0.0-20201112185459-01a34c573bd8
+	knative.dev/networking v0.0.0-20201116165202-57530ee4cbfc
+	knative.dev/pkg v0.0.0-20201116214403-188df22c59ac
 )
 
 replace (
diff --git a/go.sum b/go.sum
index 67ad21792..13cac411b 100644
--- a/go.sum
+++ b/go.sum
@@ -1182,18 +1182,17 @@ k8s.io/legacy-cloud-providers v0.18.8/go.mod h1:tgp4xYf6lvjrWnjQwTOPvWQE9IVqSBGP
 k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
 k8s.io/utils v0.0.0-20200603063816-c1c6865ac451 h1:v8ud2Up6QK1lNOKFgiIVrZdMg7MpmSnvtrOieolJKoE=
 k8s.io/utils v0.0.0-20200603063816-c1c6865ac451/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
-knative.dev/caching v0.0.0-20201104174804-1a305923cfbe h1:isrtdMtP9EvJuYn7vIw0yNv8+wpRVwULMuiGlTOduzA=
-knative.dev/caching v0.0.0-20201104174804-1a305923cfbe/go.mod h1:twy5Yz5LtFbmihtbBG0CcgwJzV5d8RUBoGkZFs7uRQs=
-knative.dev/hack v0.0.0-20201102193445-9349aeeb6701 h1:at6mUfi8gHWlBRd/qNM66JvUQ4C964cOpsy9hzac+7c=
-knative.dev/hack v0.0.0-20201102193445-9349aeeb6701/go.mod h1:PHt8x8yX5Z9pPquBEfIj0X66f8iWkWfR0S/sarACJrI=
+knative.dev/caching v0.0.0-20201113182901-ee88f744543c h1:eVYnIu0dOO/htpbcFUGdawVhDH27A6YAVxds+URb0I8=
+knative.dev/caching v0.0.0-20201113182901-ee88f744543c/go.mod h1:gGr7clElRu3BOrGHex96ZjEPIM7+5dDd5XHeIRle4vE=
 knative.dev/hack v0.0.0-20201103151104-3d5abc3a0075 h1:YAgWplKIy4O5e3F5vUUECmXAAyZ0M5ymo6fCt1jeZhs=
 knative.dev/hack v0.0.0-20201103151104-3d5abc3a0075/go.mod h1:PHt8x8yX5Z9pPquBEfIj0X66f8iWkWfR0S/sarACJrI=
-knative.dev/networking v0.0.0-20201103163404-b9f80f4537af h1:xPS3bRfp30XHb69B0F9Pgv4Nc2eTfJHWR0TzVRHf1hU=
-knative.dev/networking v0.0.0-20201103163404-b9f80f4537af/go.mod h1:0OaR4FLbs3Xn6UjeX1zYql9RWO8sLTO/ZMJS4jDbfFE=
-knative.dev/pkg v0.0.0-20201103150904-7f1970af5b6f h1:Ezruo8zcoA6RA8KiP8JH4K7RSjkddjlhvP9CcooWO4Q=
-knative.dev/pkg v0.0.0-20201103150904-7f1970af5b6f/go.mod h1:2hMxAUviPH2nl3BuODx5L6shYCdzA+7SPzQpdkcg9wc=
-knative.dev/pkg v0.0.0-20201103163404-5514ab0c1fdf h1:QwULgRwcv6R3Ya1GZlf/E1atcaGUNw4DKjxSQUfcR6U=
-knative.dev/pkg v0.0.0-20201103163404-5514ab0c1fdf/go.mod h1:cuKOgUvJvnWHIps/apCXX8wZuMlT0dyMZLqRQfsENbQ=
+knative.dev/hack v0.0.0-20201112185459-01a34c573bd8 h1:RNbZsAjhswBPtl4C5C5gEFX5/GfWIOZQxfYD9DhkHdY=
+knative.dev/hack v0.0.0-20201112185459-01a34c573bd8/go.mod h1:PHt8x8yX5Z9pPquBEfIj0X66f8iWkWfR0S/sarACJrI=
+knative.dev/networking v0.0.0-20201116165202-57530ee4cbfc h1:EULBfbpAFt/k2Fz6N/jwv3ZbbQHJOPeS06YXyo3CJO8=
+knative.dev/networking v0.0.0-20201116165202-57530ee4cbfc/go.mod h1:DCZ5pdCpaPkgvwSvgFzDXSDjZ2dByl+tMIHlXV4wvws=
+knative.dev/pkg v0.0.0-20201112201059-93fedf141385/go.mod h1:5vNHKNtZtzlNeNrcDoUtZIn+dma/8DjmpjfdHiwoQyM=
+knative.dev/pkg v0.0.0-20201116214403-188df22c59ac h1:Oa9KWJQdLWIe7G6sPL8OK8ADynJsOJmZOwYZxPlxYSI=
+knative.dev/pkg v0.0.0-20201116214403-188df22c59ac/go.mod h1:4kXxEyYWdNk3pUR6/cx/ToMKG/dAJvEpDYUfV5RYHeU=
 pgregory.net/rapid v0.3.3 h1:jCjBsY4ln4Atz78QoBWxUEvAHaFyNDQg9+WU62aCn1U=
 pgregory.net/rapid v0.3.3/go.mod h1:UYpPVyjFHzYBGHIxLFoupi8vwk6rXNzRY9OMvVxFIOU=
 rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
diff --git a/pkg/activator/net/helpers.go b/pkg/activator/net/helpers.go
index 5f46d3546..ba51a5377 100644
--- a/pkg/activator/net/helpers.go
+++ b/pkg/activator/net/helpers.go
@@ -29,7 +29,17 @@ import (
 // healthyAddresses takes an endpoints object and a port name and return the set
 // of addresses that implement this port.
 func healthyAddresses(endpoints *corev1.Endpoints, portName string) sets.String {
-	ready := sets.NewString()
+	var addresses int
+	for _, es := range endpoints.Subsets {
+		for _, port := range es.Ports {
+			if port.Name == portName {
+				addresses += len(es.Addresses)
+				break
+			}
+		}
+	}
+
+	ready := make(sets.String, addresses)
 
 	for _, es := range endpoints.Subsets {
 		for _, port := range es.Ports {
@@ -48,8 +58,19 @@ func healthyAddresses(endpoints *corev1.Endpoints, portName string) sets.String
 // endpointsToDests takes an endpoints object and a port name and returns two sets of
 // ready and non-ready l4 dests in the endpoints object which have that port.
 func endpointsToDests(endpoints *corev1.Endpoints, portName string) (ready, notReady sets.String) {
-	ready = sets.NewString()
-	notReady = sets.NewString()
+	var readyAddresses, nonReadyAddresses int
+	for _, es := range endpoints.Subsets {
+		for _, port := range es.Ports {
+			if port.Name == portName {
+				readyAddresses += len(es.Addresses)
+				nonReadyAddresses += len(es.NotReadyAddresses)
+				break
+			}
+		}
+	}
+
+	ready = make(sets.String, readyAddresses)
+	notReady = make(sets.String, nonReadyAddresses)
 
 	for _, es := range endpoints.Subsets {
 		for _, port := range es.Ports {
diff --git a/pkg/autoscaler/metrics/collector.go b/pkg/autoscaler/metrics/collector.go
index ce57d6810..32492c2a9 100644
--- a/pkg/autoscaler/metrics/collector.go
+++ b/pkg/autoscaler/metrics/collector.go
@@ -64,7 +64,7 @@ type Collector interface {
 	// Record allows stats to be captured that came from outside the Collector.
 	Record(key types.NamespacedName, now time.Time, stat Stat)
 	// Delete deletes a Metric and halts collection.
-	Delete(string, string) error
+	Delete(string, string)
 	// Watch registers a singleton function to call when a specific collector's status changes.
 	// The passed name is the namespace/name of the metric owned by the respective collector.
 	Watch(func(types.NamespacedName))
@@ -136,7 +136,7 @@ func (c *MetricCollector) CreateOrUpdate(metric *av1alpha1.Metric) error {
 }
 
 // Delete deletes a Metric and halts collection.
-func (c *MetricCollector) Delete(namespace, name string) error {
+func (c *MetricCollector) Delete(namespace, name string) {
 	c.collectionsMutex.Lock()
 	defer c.collectionsMutex.Unlock()
 
@@ -145,7 +145,6 @@ func (c *MetricCollector) Delete(namespace, name string) error {
 		collection.close()
 		delete(c.collections, key)
 	}
-	return nil
 }
 
 // Record records a stat that's been generated outside of the metric collector.
diff --git a/pkg/autoscaler/scaling/autoscaler.go b/pkg/autoscaler/scaling/autoscaler.go
index fe9d2324b..be2de8bb1 100644
--- a/pkg/autoscaler/scaling/autoscaler.go
+++ b/pkg/autoscaler/scaling/autoscaler.go
@@ -127,12 +127,11 @@ func newAutoscaler(
 }
 
 // Update reconfigures the UniScaler according to the DeciderSpec.
-func (a *autoscaler) Update(deciderSpec *DeciderSpec) error {
+func (a *autoscaler) Update(deciderSpec *DeciderSpec) {
 	a.specMux.Lock()
 	defer a.specMux.Unlock()
 
 	a.deciderSpec = deciderSpec
-	return nil
 }
 
 // Scale calculates the desired scale based on current statistics given the current time.
diff --git a/pkg/autoscaler/scaling/multiscaler.go b/pkg/autoscaler/scaling/multiscaler.go
index 58d63e466..e5aeca353 100644
--- a/pkg/autoscaler/scaling/multiscaler.go
+++ b/pkg/autoscaler/scaling/multiscaler.go
@@ -122,7 +122,7 @@ type UniScaler interface {
 	Scale(context.Context, time.Time) ScaleResult
 
 	// Update reconfigures the UniScaler according to the DeciderSpec.
-	Update(*DeciderSpec) error
+	Update(*DeciderSpec)
 }
 
 // UniScalerFactory creates a UniScaler for a given PA using the given dynamic configuration.
@@ -256,7 +256,7 @@ func (m *MultiScaler) Update(_ context.Context, decider *Decider) (*Decider, err
 }
 
 // Delete stops and removes a Decider.
-func (m *MultiScaler) Delete(_ context.Context, namespace, name string) error {
+func (m *MultiScaler) Delete(_ context.Context, namespace, name string) {
 	key := types.NamespacedName{Namespace: namespace, Name: name}
 	m.scalersMutex.Lock()
 	defer m.scalersMutex.Unlock()
@@ -264,7 +264,6 @@ func (m *MultiScaler) Delete(_ context.Context, namespace, name string) error {
 		close(scaler.stopCh)
 		delete(m.scalers, key)
 	}
-	return nil
 }
 
 // Watch registers a singleton function to call when DeciderStatus is updated.
diff --git a/pkg/queue/readiness/probe.go b/pkg/queue/readiness/probe.go
index 6ce77fde2..ba7463877 100644
--- a/pkg/queue/readiness/probe.go
+++ b/pkg/queue/readiness/probe.go
@@ -143,24 +143,36 @@ func (p *Probe) probeContainerImpl() bool {
 }
 
 func (p *Probe) doProbe(probe func(time.Duration) error) error {
-	if p.IsAggressive() {
-		return wait.PollImmediate(retryInterval, p.pollTimeout, func() (bool, error) {
-			if err := probe(aggressiveProbeTimeout); err != nil {
-				fmt.Fprintln(p.out, "aggressive probe error: ", err)
-				// Reset count of consecutive successes to zero.
-				p.count = 0
-				return false, nil
-			}
-
-			p.count++
-
-			// Return success if count of consecutive successes is equal to or greater
-			// than the probe's SuccessThreshold.
-			return p.count >= p.SuccessThreshold, nil
-		})
+	if !p.IsAggressive() {
+		return probe(time.Duration(p.TimeoutSeconds) * time.Second)
 	}
 
-	return probe(time.Duration(p.TimeoutSeconds) * time.Second)
+	var failCount int
+	var lastProbeErr error
+	pollErr := wait.PollImmediate(retryInterval, p.pollTimeout, func() (bool, error) {
+		if err := probe(aggressiveProbeTimeout); err != nil {
+			// Reset count of consecutive successes to zero.
+			p.count = 0
+			// Don't log this now since we probe every 50ms and some failures are
+			// expected if the user container takes longer than that to start up.
+			// We'll log the lastProbeErr if we don't eventually succeed.
+			lastProbeErr = err
+			failCount++
+			return false, nil
+		}
+
+		p.count++
+
+		// Return success if count of consecutive successes is equal to or greater
+		// than the probe's SuccessThreshold.
+		return p.count >= p.SuccessThreshold, nil
+	})
+
+	if lastProbeErr != nil {
+		fmt.Fprintf(p.out, "aggressive probe error (failed %d times): %v\n", failCount, lastProbeErr)
+	}
+
+	return pollErr
 }
 
 // tcpProbe function executes TCP probe once if its standard probe
diff --git a/pkg/reconciler/autoscaling/kpa/resources/decider.go b/pkg/reconciler/autoscaling/kpa/resources/decider.go
index a2cb42ab2..52e7979b4 100644
--- a/pkg/reconciler/autoscaling/kpa/resources/decider.go
+++ b/pkg/reconciler/autoscaling/kpa/resources/decider.go
@@ -35,7 +35,7 @@ type Deciders interface {
 	Create(ctx context.Context, decider *scaling.Decider) (*scaling.Decider, error)
 
 	// Delete removes the Decider resource for a given key, returning any errors.
-	Delete(ctx context.Context, namespace, name string) error
+	Delete(ctx context.Context, namespace, name string)
 
 	// Watch registers a function to call when Decider change.
 	Watch(watcher func(types.NamespacedName))
diff --git a/pkg/reconciler/route/reconcile_resources.go b/pkg/reconciler/route/reconcile_resources.go
index d8751ab3f..109e38baa 100644
--- a/pkg/reconciler/route/reconcile_resources.go
+++ b/pkg/reconciler/route/reconcile_resources.go
@@ -18,9 +18,11 @@ package route
 
 import (
 	"context"
+	"encoding/json"
 	"errors"
 	"fmt"
 
+	"github.com/davecgh/go-spew/spew"
 	"go.uber.org/zap"
 	"golang.org/x/sync/errgroup"
 	corev1 "k8s.io/api/core/v1"
@@ -30,20 +32,40 @@ import (
 	"k8s.io/apimachinery/pkg/types"
 	"k8s.io/apimachinery/pkg/util/sets"
 
+	"knative.dev/networking/pkg/apis/networking"
 	netv1alpha1 "knative.dev/networking/pkg/apis/networking/v1alpha1"
 	"knative.dev/pkg/apis/duck"
 	"knative.dev/pkg/controller"
+	"knative.dev/pkg/kmeta"
 	"knative.dev/pkg/logging"
 	v1 "knative.dev/serving/pkg/apis/serving/v1"
 	"knative.dev/serving/pkg/reconciler/route/config"
 	"knative.dev/serving/pkg/reconciler/route/resources"
+	"knative.dev/serving/pkg/reconciler/route/resources/names"
 	"knative.dev/serving/pkg/reconciler/route/traffic"
 )
 
-func (c *Reconciler) reconcileIngress(ctx context.Context, r *v1.Route, desired *netv1alpha1.Ingress) (*netv1alpha1.Ingress, error) {
+func (c *Reconciler) reconcileIngress(
+	ctx context.Context, r *v1.Route, tc *traffic.Config,
+	tls []netv1alpha1.IngressTLS,
+	ingressClass string,
+	acmeChallenges ...netv1alpha1.HTTP01Challenge,
+) (*netv1alpha1.Ingress, error) {
 	recorder := controller.GetEventRecorder(ctx)
-	ingress, err := c.ingressLister.Ingresses(desired.Namespace).Get(desired.Name)
+
+	desired, err := resources.MakeIngress(ctx, r, tc, tls, ingressClass, acmeChallenges...)
+	if err != nil {
+		return nil, err
+	}
+	// Get the current rollout state as described by the traffic.
+	curRO := tc.BuildRollout()
+
+	ingress, err := c.ingressLister.Ingresses(r.Namespace).Get(names.Ingress(r))
 	if apierrs.IsNotFound(err) {
+		// If there is no exisiting Ingress, then current rollout is _the_ rollout.
+		desired.Annotations = kmeta.UnionMaps(desired.Annotations, map[string]string{
+			networking.RolloutAnnotationKey: serializeRollout(ctx, curRO),
+		})
 		ingress, err = c.netclient.NetworkingV1alpha1().Ingresses(desired.Namespace).Create(ctx, desired, metav1.CreateOptions{})
 		if err != nil {
 			recorder.Eventf(r, corev1.EventTypeWarning, "CreationFailed", "Failed to create Ingress: %v", err)
@@ -54,25 +76,35 @@ func (c *Reconciler) reconcileIngress(ctx context.Context, r *v1.Route, desired
 		return ingress, nil
 	} else if err != nil {
 		return nil, err
-	} else if !equality.Semantic.DeepEqual(ingress.Spec, desired.Spec) ||
-		!equality.Semantic.DeepEqual(ingress.Annotations, desired.Annotations) ||
-		!equality.Semantic.DeepEqual(ingress.Labels, desired.Labels) {
-		// It is notable that one reason for differences here may be defaulting.
-		// When that is the case, the Update will end up being a nop because the
-		// webhook will bring them into alignment and no new reconciliation will occur.
-		// Also, compare annotation and label in case ingress.Class or parent route's labels
-		// is updated.
-
-		// Don't modify the informers copy
-		origin := ingress.DeepCopy()
-		origin.Spec = desired.Spec
-		origin.Annotations = desired.Annotations
-		origin.Labels = desired.Labels
-		updated, err := c.netclient.NetworkingV1alpha1().Ingresses(origin.Namespace).Update(ctx, origin, metav1.UpdateOptions{})
-		if err != nil {
-			return nil, fmt.Errorf("failed to update Ingress: %w", err)
+	} else {
+		// Ingress exists. We need to compute the rollout spec diff.
+		prevRO := deserializeRollout(ctx, ingress.Annotations[networking.RolloutAnnotationKey])
+		effectiveRO := curRO.Step(prevRO)
+		// Update the annotation.
+		desired.Annotations[networking.RolloutAnnotationKey] = serializeRollout(ctx, effectiveRO)
+		// TODO(vagababov): apply the Rollout to the ingress spec here.
+		if !equality.Semantic.DeepEqual(ingress.Spec, desired.Spec) ||
+			!equality.Semantic.DeepEqual(ingress.Annotations, desired.Annotations) ||
+			!equality.Semantic.DeepEqual(ingress.Labels, desired.Labels) {
+			// It is notable that one reason for differences here may be defaulting.
+			// When that is the case, the Update will end up being a nop because the
+			// webhook will bring them into alignment and no new reconciliation will occur.
+			// Also, compare annotation and label in case ingress.Class or parent route's labels
+			// is updated.
+
+			// Don't modify the informers copy
+			origin := ingress.DeepCopy()
+			origin.Spec = desired.Spec
+			origin.Annotations = desired.Annotations
+			origin.Labels = desired.Labels
+
+			updated, err := c.netclient.NetworkingV1alpha1().Ingresses(origin.Namespace).Update(
+				ctx, origin, metav1.UpdateOptions{})
+			if err != nil {
+				return nil, fmt.Errorf("failed to update Ingress: %w", err)
+			}
+			return updated, nil
 		}
-		return updated, nil
 	}
 
 	return ingress, err
@@ -227,3 +259,30 @@ func (c *Reconciler) reconcileTargetRevisions(ctx context.Context, t *traffic.Co
 	}
 	return eg.Wait()
 }
+
+func serializeRollout(ctx context.Context, r *traffic.Rollout) string {
+	sr, err := json.Marshal(r)
+	if err != nil {
+		// This must never happen in the normal course of things.
+		logging.FromContext(ctx).Warnw("Error serializing Rollout: "+spew.Sprint(r),
+			zap.Error(err))
+		return ""
+	}
+	return string(sr)
+}
+
+func deserializeRollout(ctx context.Context, ro string) *traffic.Rollout {
+	if ro == "" {
+		return nil
+	}
+	r := &traffic.Rollout{}
+	// Failure can happen if users manually tweaked the
+	// annotation or there's etcd corruption. Just log, rollouts
+	// are not mission critical.
+	if err := json.Unmarshal([]byte(ro), r); err != nil {
+		logging.FromContext(ctx).Warnw("Error deserializing Rollout: "+ro,
+			zap.Error(err))
+		return nil
+	}
+	return r
+}
diff --git a/pkg/reconciler/route/resources/ingress.go b/pkg/reconciler/route/resources/ingress.go
index b73590396..129d66e9e 100644
--- a/pkg/reconciler/route/resources/ingress.go
+++ b/pkg/reconciler/route/resources/ingress.go
@@ -18,11 +18,8 @@ package resources
 
 import (
 	"context"
-	"encoding/json"
 	"sort"
 
-	"github.com/davecgh/go-spew/spew"
-	"go.uber.org/zap"
 	corev1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/util/intstr"
@@ -33,7 +30,6 @@ import (
 	netv1alpha1 "knative.dev/networking/pkg/apis/networking/v1alpha1"
 	ingress "knative.dev/networking/pkg/ingress"
 	"knative.dev/pkg/kmeta"
-	"knative.dev/pkg/logging"
 	"knative.dev/serving/pkg/activator"
 	apicfg "knative.dev/serving/pkg/apis/config"
 	"knative.dev/serving/pkg/apis/serving"
@@ -78,7 +74,6 @@ func MakeIngress(
 			}),
 			Annotations: kmeta.FilterMap(kmeta.UnionMaps(map[string]string{
 				networking.IngressClassAnnotationKey: ingressClass,
-				networking.RolloutAnnotationKey:      serializeRollout(ctx, tc.BuildRollout()),
 			}, r.GetAnnotations()), func(key string) bool {
 				return key == corev1.LastAppliedConfigAnnotation
 			}),
@@ -88,17 +83,6 @@ func MakeIngress(
 	}, nil
 }
 
-func serializeRollout(ctx context.Context, r *traffic.Rollout) string {
-	sr, err := json.Marshal(r)
-	if err != nil {
-		// This must not never happen in the normal course of things.
-		logging.FromContext(ctx).Warnw("Error serializing Rollout: "+spew.Sprint(r),
-			zap.Error(err))
-		return ""
-	}
-	return string(sr)
-}
-
 // makeIngressSpec builds a new IngressSpec from inputs.
 func makeIngressSpec(
 	ctx context.Context,
@@ -260,7 +244,7 @@ func makeBaseIngressPath(ns string, targets traffic.RevisionTargets) *netv1alpha
 	// Optimistically allocate |targets| elements.
 	splits := make([]netv1alpha1.IngressBackendSplit, 0, len(targets))
 	for _, t := range targets {
-		if t.Percent == nil || *t.Percent == 0 {
+		if *t.Percent == 0 {
 			continue
 		}
 
diff --git a/pkg/reconciler/route/route.go b/pkg/reconciler/route/route.go
index a6ddb89b1..c149d4833 100644
--- a/pkg/reconciler/route/route.go
+++ b/pkg/reconciler/route/route.go
@@ -154,8 +154,7 @@ func (c *Reconciler) ReconcileKind(ctx context.Context, r *v1.Route) pkgreconcil
 	}
 
 	// Reconcile ingress and its children resources.
-	ingress, err := c.reconcileIngressResources(ctx, r, traffic, tls, ingressClassForRoute(ctx, r), acmeChallenges...)
-
+	ingress, err := c.reconcileIngress(ctx, r, traffic, tls, ingressClassForRoute(ctx, r), acmeChallenges...)
 	if err != nil {
 		return err
 	}
@@ -175,22 +174,6 @@ func (c *Reconciler) ReconcileKind(ctx context.Context, r *v1.Route) pkgreconcil
 	return nil
 }
 
-func (c *Reconciler) reconcileIngressResources(ctx context.Context, r *v1.Route, tc *traffic.Config, tls []netv1alpha1.IngressTLS,
-	ingressClass string, acmeChallenges ...netv1alpha1.HTTP01Challenge) (*netv1alpha1.Ingress, error) {
-
-	desired, err := resources.MakeIngress(ctx, r, tc, tls, ingressClass, acmeChallenges...)
-	if err != nil {
-		return nil, err
-	}
-
-	ingress, err := c.reconcileIngress(ctx, r, desired)
-	if err != nil {
-		return nil, err
-	}
-
-	return ingress, nil
-}
-
 func (c *Reconciler) tls(ctx context.Context, host string, r *v1.Route, traffic *traffic.Config) ([]netv1alpha1.IngressTLS, []netv1alpha1.HTTP01Challenge, error) {
 	tls := []netv1alpha1.IngressTLS{}
 	if !autoTLSEnabled(ctx, r) {
diff --git a/pkg/reconciler/route/traffic/rollout.go b/pkg/reconciler/route/traffic/rollout.go
index d72263fb6..d496ae2a3 100644
--- a/pkg/reconciler/route/traffic/rollout.go
+++ b/pkg/reconciler/route/traffic/rollout.go
@@ -184,7 +184,7 @@ func stepConfig(goal, prev *ConfigurationRollout) *ConfigurationRollout {
 	}
 	// goal will always have just one revision in the list – the current desired revision.
 	// If it matches the last revision of the previous rollout state (or there were no revisions)
-	// then no new rollout hast begun for this configuration.
+	// then no new rollout has begun for this configuration.
 	if len(prev.Revisions) == 0 || goal.Revisions[0].RevisionName == prev.Revisions[pc-1].RevisionName {
 		// TODO(vagababov): here would go the logic to compute new percentages for the rollout,
 		// i.e step function, so return value will change, depending on that.
diff --git a/pkg/reconciler/route/traffic/traffic.go b/pkg/reconciler/route/traffic/traffic.go
index 05e6036b9..c9c233cce 100644
--- a/pkg/reconciler/route/traffic/traffic.go
+++ b/pkg/reconciler/route/traffic/traffic.go
@@ -194,12 +194,12 @@ func buildRolloutForTag(r *Rollout, tag string, rts RevisionTargets) {
 		r.Configurations = append(r.Configurations, ConfigurationRollout{
 			ConfigurationName: rt.ConfigurationName,
 			Tag:               tag,
-			Percent:           int(zeroIfNil(rt.Percent)),
+			Percent:           int(*rt.Percent),
 			Revisions: []RevisionRollout{{
 				RevisionName: rt.RevisionName,
 				// Note: this will match config value in steady state, but
 				// during rollout it will be overridden by the rollout logic.
-				Percent: int(zeroIfNil(rt.Percent)),
+				Percent: int(*rt.Percent),
 			}},
 		})
 	}
@@ -335,21 +335,13 @@ func (cb *configBuilder) addRevisionTarget(tt *v1.TrafficTarget) error {
 	return nil
 }
 
-// zeroIfNil returns `0` if `ptr==nil`, or `*ptr` otherwise.
-func zeroIfNil(ptr *int64) int64 {
-	if ptr == nil {
-		return 0
-	}
-	return *ptr
-}
-
 // This find the exact revision+tag pair and if so, just adds the percentages.
 // This expects single digit lists, so just does an O(N) search.
 func mergeIfNecessary(rts RevisionTargets, rt RevisionTarget) RevisionTargets {
 	for i := range rts {
 		if rts[i].Tag == rt.Tag && rts[i].RevisionName == rt.RevisionName &&
 			*rt.LatestRevision == *rts[i].LatestRevision {
-			rts[i].Percent = ptr.Int64(zeroIfNil(rts[i].Percent) + zeroIfNil(rt.Percent))
+			rts[i].Percent = ptr.Int64(*rts[i].Percent + *rt.Percent)
 			return rts
 		}
 	}
diff --git a/vendor/knative.dev/caching/config/dummy.go b/vendor/knative.dev/caching/config/placeholder.go
similarity index 100%
rename from vendor/knative.dev/caching/config/dummy.go
rename to vendor/knative.dev/caching/config/placeholder.go
diff --git a/vendor/knative.dev/hack/README.md b/vendor/knative.dev/hack/README.md
index af2cbc657..1df3cfe5b 100644
--- a/vendor/knative.dev/hack/README.md
+++ b/vendor/knative.dev/hack/README.md
@@ -220,7 +220,7 @@ benchmarking jobs for each repo. To use it:
    - `SERVICE_ACCOUNT_NAME`: Service account name for controlling GKE clusters
      and interacting with [Mako](https://github.com/google/mako) server. It MUST
      have `Kubernetes Engine Admin` and `Storage Admin` role, and be
-     [whitelisted](https://github.com/google/mako/blob/master/docs/ACCESS.md) by
+     [allowed](https://github.com/google/mako/blob/master/docs/ACCESS.md) by
      Mako admin. Defaults to `mako-job`.
 
 1. [optional] Customize root path of the benchmarks. This root folder should
diff --git a/vendor/knative.dev/hack/library.sh b/vendor/knative.dev/hack/library.sh
index 020eb7206..f37b3f8df 100644
--- a/vendor/knative.dev/hack/library.sh
+++ b/vendor/knative.dev/hack/library.sh
@@ -353,13 +353,10 @@ function report_go_test() {
   report="$(mktemp)"
   local xml
   xml="$(mktemp_with_extension "${ARTIFACTS}"/junit_XXXXXXXX xml)"
-  local json
-  json="$(mktemp_with_extension "${ARTIFACTS}"/json_XXXXXXXX json)"
   echo "Running go test with args: ${go_test_args[*]}"
   # TODO(chizhg): change to `--format testname`?
   capture_output "${report}" gotestsum --format "${GO_TEST_VERBOSITY:-standard-verbose}" \
     --junitfile "${xml}" --junitfile-testsuite-name relative --junitfile-testcase-classname relative \
-    --jsonfile "${json}" \
     -- "${go_test_args[@]}"
   local failed=$?
   echo "Finished run, return code is ${failed}"
@@ -517,7 +514,7 @@ function go_update_deps() {
   echo "=== Update Deps for Golang"
 
   local UPGRADE=0
-  local VERSION="master"
+  local VERSION="v9000.1" # release v9000 is so far in the future, it will always pick the default branch.
   local DOMAIN="knative.dev"
   while [[ $# -ne 0 ]]; do
     parameter=$1
diff --git a/vendor/knative.dev/pkg/logging/config.go b/vendor/knative.dev/pkg/logging/config.go
index 2b5eb696d..e1480033d 100644
--- a/vendor/knative.dev/pkg/logging/config.go
+++ b/vendor/knative.dev/pkg/logging/config.go
@@ -65,7 +65,10 @@ func NewLogger(configJSON string, levelOverride string, opts ...zap.Option) (*za
 	if err2 != nil {
 		panic(err2)
 	}
-	return enrichLoggerWithCommitID(logger.Named(fallbackLoggerName)), loggingCfg.Level
+
+	slogger := enrichLoggerWithCommitID(logger.Named(fallbackLoggerName))
+	slogger.Warnw("Failed to parse logging config - using default zap production config", zap.Error(err))
+	return slogger, loggingCfg.Level
 }
 
 func enrichLoggerWithCommitID(logger *zap.Logger) *zap.SugaredLogger {
diff --git a/vendor/knative.dev/pkg/metrics/config.go b/vendor/knative.dev/pkg/metrics/config.go
index 38ac02e65..d4ae24ad5 100644
--- a/vendor/knative.dev/pkg/metrics/config.go
+++ b/vendor/knative.dev/pkg/metrics/config.go
@@ -60,7 +60,9 @@ const (
 	defaultPrometheusPort = 9090
 	maxPrometheusPort     = 65535
 	minPrometheusPort     = 1024
+	defaultPrometheusHost = "0.0.0.0"
 	prometheusPortEnvName = "METRICS_PROMETHEUS_PORT"
+	prometheusHostEnvName = "METRICS_PROMETHEUS_HOST"
 )
 
 // Metrics backend "enum".
@@ -105,6 +107,10 @@ type metricsConfig struct {
 	// format. It defaults to 9090.
 	prometheusPort int
 
+	// prometheusHost is the host where the metrics are exposed in Prometheus
+	// format. It defaults to "0.0.0.0"
+	prometheusHost string
+
 	// ---- Stackdriver specific below ----
 	// True if backendDestination equals to "stackdriver". Store this in a variable
 	// to reduce string comparison operations.
@@ -240,6 +246,7 @@ func createMetricsConfig(ctx context.Context, ops ExporterOptions) (*metricsConf
 		}
 
 		mc.prometheusPort = pp
+		mc.prometheusHost = prometheusHost()
 	case stackdriver:
 		// If stackdriverClientConfig is not provided for stackdriver backend destination, OpenCensus will try to
 		// use the application default credentials. If that is not available, Opencensus would fail to create the
@@ -341,6 +348,17 @@ func prometheusPort() (int, error) {
 	return int(pp), nil
 }
 
+// prometheusHost returns the host configured via the environment
+// for the Prometheus metrics exporter if it's set, a default value otherwise.
+// No validation is done here.
+func prometheusHost() string {
+	phStr := os.Getenv(prometheusHostEnvName)
+	if phStr == "" {
+		return defaultPrometheusHost
+	}
+	return phStr
+}
+
 // JSONToOptions converts a json string to ExporterOptions.
 func JSONToOptions(jsonOpts string) (*ExporterOptions, error) {
 	var opts ExporterOptions
diff --git a/vendor/knative.dev/pkg/metrics/exporter.go b/vendor/knative.dev/pkg/metrics/exporter.go
index a7411fccb..0c680106e 100644
--- a/vendor/knative.dev/pkg/metrics/exporter.go
+++ b/vendor/knative.dev/pkg/metrics/exporter.go
@@ -66,10 +66,15 @@ type ExporterOptions struct {
 
 	// PrometheusPort is the port to expose metrics if metrics backend is Prometheus.
 	// It should be between maxPrometheusPort and maxPrometheusPort. 0 value means
-	// using the default 9090 value. If is ignored if metrics backend is not
+	// using the default 9090 value. It is ignored if metrics backend is not
 	// Prometheus.
 	PrometheusPort int
 
+	// PrometheusHost is the host to expose metrics on if metrics backend is Prometheus.
+	// The default value is "0.0.0.0". It is ignored if metrics backend is not
+	// Prometheus.
+	PrometheusHost string
+
 	// ConfigMap is the data from config map config-observability. Must be present.
 	// See https://github.com/knative/serving/blob/master/config/config-observability.yaml
 	// for details.
diff --git a/vendor/knative.dev/pkg/metrics/prometheus_exporter.go b/vendor/knative.dev/pkg/metrics/prometheus_exporter.go
index 7f49302cc..784eab2e8 100644
--- a/vendor/knative.dev/pkg/metrics/prometheus_exporter.go
+++ b/vendor/knative.dev/pkg/metrics/prometheus_exporter.go
@@ -17,8 +17,8 @@ limitations under the License.
 package metrics
 
 import (
-	"fmt"
 	"net/http"
+	"strconv"
 	"sync"
 
 	prom "contrib.go.opencensus.io/exporter/prometheus"
@@ -41,6 +41,7 @@ func (emptyPromExporter) ExportView(viewData *view.Data) {
 	// a signal to enrich the internal Meters with Resource information.
 }
 
+//nolint: unparam // False positive of flagging the second result of this function unused.
 func newPrometheusExporter(config *metricsConfig, logger *zap.SugaredLogger) (view.Exporter, ResourceExporterFactory, error) {
 	e, err := prom.NewExporter(prom.Options{Namespace: config.component})
 	if err != nil {
@@ -50,7 +51,7 @@ func newPrometheusExporter(config *metricsConfig, logger *zap.SugaredLogger) (vi
 	logger.Infof("Created Opencensus Prometheus exporter with config: %v. Start the server for Prometheus exporter.", config)
 	// Start the server for Prometheus scraping
 	go func() {
-		srv := startNewPromSrv(e, config.prometheusPort)
+		srv := startNewPromSrv(e, config.prometheusHost, config.prometheusPort)
 		srv.ListenAndServe()
 	}()
 	return e,
@@ -73,7 +74,7 @@ func resetCurPromSrv() {
 	}
 }
 
-func startNewPromSrv(e *prom.Exporter, port int) *http.Server {
+func startNewPromSrv(e *prom.Exporter, host string, port int) *http.Server {
 	sm := http.NewServeMux()
 	sm.Handle("/metrics", e)
 	curPromSrvMux.Lock()
@@ -82,7 +83,7 @@ func startNewPromSrv(e *prom.Exporter, port int) *http.Server {
 		curPromSrv.Close()
 	}
 	curPromSrv = &http.Server{
-		Addr:    fmt.Sprint(":", port),
+		Addr:    host + ":" + strconv.Itoa(port),
 		Handler: sm,
 	}
 	return curPromSrv
diff --git a/vendor/knative.dev/pkg/tracker/enqueue.go b/vendor/knative.dev/pkg/tracker/enqueue.go
index 2e001470c..70fbe0e46 100644
--- a/vendor/knative.dev/pkg/tracker/enqueue.go
+++ b/vendor/knative.dev/pkg/tracker/enqueue.go
@@ -216,9 +216,18 @@ func isExpired(expiry time.Time) bool {
 
 // OnChanged implements Interface.
 func (i *impl) OnChanged(obj interface{}) {
+	observers := i.GetObservers(obj)
+
+	for _, observer := range observers {
+		i.cb(observer)
+	}
+}
+
+// GetObservers implements Interface.
+func (i *impl) GetObservers(obj interface{}) []types.NamespacedName {
 	item, err := kmeta.DeletionHandlingAccessor(obj)
 	if err != nil {
-		return
+		return nil
 	}
 
 	or := kmeta.ObjectReference(item)
@@ -229,14 +238,9 @@ func (i *impl) OnChanged(obj interface{}) {
 		Name:       or.Name,
 	}
 
-	i.m.Lock()
-	// Call the callbacks without the lock held.
 	var keys []types.NamespacedName
-	defer func(cb func(types.NamespacedName)) {
-		for _, key := range keys {
-			cb(key)
-		}
-	}(i.cb) // read i.cb with the lock held
+
+	i.m.Lock()
 	defer i.m.Unlock()
 
 	// Handle exact matches.
@@ -274,6 +278,8 @@ func (i *impl) OnChanged(obj interface{}) {
 			delete(i.exact, ref)
 		}
 	}
+
+	return keys
 }
 
 // OnChanged implements Interface.
diff --git a/vendor/knative.dev/pkg/tracker/interface.go b/vendor/knative.dev/pkg/tracker/interface.go
index c8ab479fa..bfcda9cf2 100644
--- a/vendor/knative.dev/pkg/tracker/interface.go
+++ b/vendor/knative.dev/pkg/tracker/interface.go
@@ -23,6 +23,7 @@ import (
 	corev1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/runtime/schema"
+	"k8s.io/apimachinery/pkg/types"
 	"k8s.io/apimachinery/pkg/util/validation"
 
 	"knative.dev/pkg/apis"
@@ -71,6 +72,10 @@ type Interface interface {
 	// so that we are notified for appropriate object changes.
 	OnChanged(obj interface{})
 
+	// GetObservers returns the names of all observers for the given
+	// object.
+	GetObservers(obj interface{}) []types.NamespacedName
+
 	// OnDeletedObserver is a callback to register with the InformerFactory
 	// so that we are notified for deletions of a watching parent to
 	// remove the respective tracking.
diff --git a/vendor/modules.txt b/vendor/modules.txt
index b9bc3b554..92a0cea0c 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -952,7 +952,7 @@ k8s.io/utils/buffer
 k8s.io/utils/integer
 k8s.io/utils/pointer
 k8s.io/utils/trace
-# knative.dev/caching v0.0.0-20201104174804-1a305923cfbe
+# knative.dev/caching v0.0.0-20201113182901-ee88f744543c
 ## explicit
 knative.dev/caching/config
 knative.dev/caching/pkg/apis/caching
@@ -973,10 +973,10 @@ knative.dev/caching/pkg/client/injection/informers/caching/v1alpha1/image/fake
 knative.dev/caching/pkg/client/injection/informers/factory
 knative.dev/caching/pkg/client/injection/informers/factory/fake
 knative.dev/caching/pkg/client/listers/caching/v1alpha1
-# knative.dev/hack v0.0.0-20201103151104-3d5abc3a0075
+# knative.dev/hack v0.0.0-20201112185459-01a34c573bd8
 ## explicit
 knative.dev/hack
-# knative.dev/networking v0.0.0-20201103163404-b9f80f4537af
+# knative.dev/networking v0.0.0-20201116165202-57530ee4cbfc
 ## explicit
 knative.dev/networking/config
 knative.dev/networking/pkg
@@ -1009,7 +1009,7 @@ knative.dev/networking/test/conformance/ingress
 knative.dev/networking/test/defaultsystem
 knative.dev/networking/test/test_images/grpc-ping/proto
 knative.dev/networking/test/types
-# knative.dev/pkg v0.0.0-20201103163404-5514ab0c1fdf
+# knative.dev/pkg v0.0.0-20201116214403-188df22c59ac
 ## explicit
 knative.dev/pkg/apiextensions/storageversion
 knative.dev/pkg/apiextensions/storageversion/cmd/migrate


Test patch:
diff --git a/.github/workflows/kind-e2e.yaml b/.github/workflows/kind-e2e.yaml
index ab73f23ba..242a60249 100644
--- a/.github/workflows/kind-e2e.yaml
+++ b/.github/workflows/kind-e2e.yaml
@@ -53,12 +53,6 @@ jobs:
         - test-suite: ./test/conformance/api/v1alpha1
           test-flags: "--enable-alpha"
 
-        exclude:
-          # TODO(#9874): Un-exclude this when Kourier implements the
-          # RewriteHost feature DomainMappings relies on.
-        - test-suite: ./test/conformance/api/v1alpha1
-          k8s-version: v1.18.8
-
     env:
       GOPATH: ${{ github.workspace }}
       GO111MODULE: off
diff --git a/pkg/activator/net/helpers_test.go b/pkg/activator/net/helpers_test.go
index 59cdf5f30..7ff592459 100644
--- a/pkg/activator/net/helpers_test.go
+++ b/pkg/activator/net/helpers_test.go
@@ -17,6 +17,7 @@ limitations under the License.
 package net
 
 import (
+	"fmt"
 	"testing"
 
 	"github.com/google/go-cmp/cmp"
@@ -168,3 +169,54 @@ func TestGetServicePort(t *testing.T) {
 		})
 	}
 }
+
+func BenchmarkHealthyAddresses(b *testing.B) {
+	for _, n := range []int{1, 10, 100, 1000, 10000} {
+		b.Run(fmt.Sprint("addresses-", n), func(b *testing.B) {
+			ep := eps(10, n)
+			for i := 0; i < b.N; i++ {
+				healthyAddresses(ep, networking.ServicePortNameHTTP1)
+			}
+		})
+	}
+}
+
+func BenchmarkEndpointsToDests(b *testing.B) {
+	for _, n := range []int{1, 10, 100, 1000, 10000} {
+		b.Run(fmt.Sprint("addresses-", n), func(b *testing.B) {
+			ep := eps(10, n)
+			for i := 0; i < b.N; i++ {
+				endpointsToDests(ep, networking.ServicePortNameHTTP1)
+			}
+		})
+	}
+}
+
+func eps(activators, apps int) *corev1.Endpoints {
+	return &corev1.Endpoints{
+		Subsets: []corev1.EndpointSubset{{
+			Addresses: addresses("activator", activators),
+			Ports: []corev1.EndpointPort{{
+				Name: networking.ServicePortNameHTTP1,
+				Port: 1234,
+			}},
+		}, {
+			Addresses:         addresses("app", apps),
+			NotReadyAddresses: addresses("app-non-ready", apps),
+			Ports: []corev1.EndpointPort{{
+				Name: networking.ServicePortNameHTTP1,
+				Port: 1234,
+			}},
+		}},
+	}
+}
+
+func addresses(prefix string, n int) []corev1.EndpointAddress {
+	addrs := make([]corev1.EndpointAddress, 0, n)
+	for i := 0; i < n; i++ {
+		addrs = append(addrs, corev1.EndpointAddress{
+			IP: fmt.Sprintf("%s-%d", prefix, i),
+		})
+	}
+	return addrs
+}
diff --git a/pkg/autoscaler/metrics/collector_test.go b/pkg/autoscaler/metrics/collector_test.go
index ea7868baf..f054c39e9 100644
--- a/pkg/autoscaler/metrics/collector_test.go
+++ b/pkg/autoscaler/metrics/collector_test.go
@@ -111,9 +111,7 @@ func TestMetricCollectorCRUD(t *testing.T) {
 			t.Errorf("Updated scraper URL = %s, want: %s, diff: %s", got, want, cmp.Diff(got, want))
 		}
 
-		if err := coll.Delete(defaultNamespace, defaultName); err != nil {
-			t.Errorf("Delete() = %v, want no error", err)
-		}
+		coll.Delete(defaultNamespace, defaultName)
 	})
 }
 
diff --git a/pkg/autoscaler/scaling/multiscaler_test.go b/pkg/autoscaler/scaling/multiscaler_test.go
index 429be6b2b..03e01a65d 100644
--- a/pkg/autoscaler/scaling/multiscaler_test.go
+++ b/pkg/autoscaler/scaling/multiscaler_test.go
@@ -171,9 +171,7 @@ func TestMultiScalerScaling(t *testing.T) {
 		t.Fatal(err)
 	}
 
-	if err := ms.Delete(ctx, decider.Namespace, decider.Name); err != nil {
-		t.Error("Delete() =", err)
-	}
+	ms.Delete(ctx, decider.Namespace, decider.Name)
 
 	// Verify that we stop seeing "ticks"
 	mtp.Channel <- time.Now()
@@ -206,9 +204,7 @@ func TestMultiscalerCreateTBC42(t *testing.T) {
 	if got, want := d.Status.ExcessBurstCapacity, int32(50-42); got != want {
 		t.Errorf("Decider.Status.ExcessBurstCapacity = %d, want: %d", got, want)
 	}
-	if err := ms.Delete(ctx, decider.Namespace, decider.Name); err != nil {
-		t.Error("Delete() =", err)
-	}
+	ms.Delete(ctx, decider.Namespace, decider.Name)
 }
 
 func TestMultiscalerCreateTBCMinus1(t *testing.T) {
@@ -233,9 +229,7 @@ func TestMultiscalerCreateTBCMinus1(t *testing.T) {
 	if got, want := d.Status.ExcessBurstCapacity, int32(-1); got != want {
 		t.Errorf("Decider.Status.ExcessBurstCapacity = %d, want: %d", got, want)
 	}
-	if err := ms.Delete(ctx, decider.Namespace, decider.Name); err != nil {
-		t.Error("Delete() =", err)
-	}
+	ms.Delete(ctx, decider.Namespace, decider.Name)
 }
 
 func TestMultiScalerOnlyCapacityChange(t *testing.T) {
@@ -273,9 +267,7 @@ func TestMultiScalerOnlyCapacityChange(t *testing.T) {
 		t.Fatal(err)
 	}
 
-	if err := ms.Delete(ctx, decider.Namespace, decider.Name); err != nil {
-		t.Error("Delete() =", err)
-	}
+	ms.Delete(ctx, decider.Namespace, decider.Name)
 
 	// Verify that we stop seeing "ticks".
 	mtp.Channel <- time.Now()
@@ -316,10 +308,7 @@ func TestMultiScalerScaleToZero(t *testing.T) {
 		t.Fatal(err)
 	}
 
-	err = ms.Delete(ctx, decider.Namespace, decider.Name)
-	if err != nil {
-		t.Error("Delete() =", err)
-	}
+	ms.Delete(ctx, decider.Namespace, decider.Name)
 
 	// Verify that we stop seeing "ticks"
 	mtp.Channel <- time.Now()
@@ -365,9 +354,7 @@ func TestMultiScalerScaleFromZero(t *testing.T) {
 	if err := verifyTick(errCh); err != nil {
 		t.Fatal(err)
 	}
-	if err := ms.Delete(ctx, decider.Namespace, decider.Name); err != nil {
-		t.Error("Delete() =", err)
-	}
+	ms.Delete(ctx, decider.Namespace, decider.Name)
 }
 
 func TestMultiScalerUpdate(t *testing.T) {
@@ -404,9 +391,7 @@ func TestMultiScalerUpdate(t *testing.T) {
 	if got, want := m.Spec.TargetValue, 10.0; got != want {
 		t.Errorf("Got target concurrency %v. Wanted %v", got, want)
 	}
-	if err := ms.Delete(ctx, decider.Namespace, decider.Name); err != nil {
-		t.Error("Delete() =", err)
-	}
+	ms.Delete(ctx, decider.Namespace, decider.Name)
 }
 
 func createMultiScaler(ctx context.Context, l *zap.SugaredLogger) (*MultiScaler, *fakeUniScaler) {
@@ -445,9 +430,7 @@ func (u *fakeUniScaler) setScaleResult(replicas, surplus, na int32, scaled bool)
 	u.numActivators = na
 }
 
-func (u *fakeUniScaler) Update(*DeciderSpec) error {
-	return nil
-}
+func (u *fakeUniScaler) Update(*DeciderSpec) {}
 
 func newDecider() *Decider {
 	return &Decider{
diff --git a/pkg/queue/readiness/probe_test.go b/pkg/queue/readiness/probe_test.go
index b747f7574..6a94eedbe 100644
--- a/pkg/queue/readiness/probe_test.go
+++ b/pkg/queue/readiness/probe_test.go
@@ -24,6 +24,7 @@ import (
 	"net/http"
 	"net/http/httptest"
 	"net/url"
+	"strings"
 	"testing"
 	"time"
 
@@ -79,6 +80,29 @@ func TestTCPFailure(t *testing.T) {
 	}
 }
 
+func TestAggressiveFailureOnlyLogsOnce(t *testing.T) {
+	pb := NewProbe(&corev1.Probe{
+		PeriodSeconds:    0, // Aggressive probe.
+		TimeoutSeconds:   1,
+		SuccessThreshold: 1,
+		FailureThreshold: 1,
+		Handler: corev1.Handler{
+			TCPSocket: &corev1.TCPSocketAction{
+				Host: "127.0.0.1",
+				Port: intstr.FromInt(12345),
+			},
+		},
+	})
+
+	var buf bytes.Buffer
+	pb.out = &buf
+
+	pb.ProbeContainer()
+	if got := strings.Count(buf.String(), "aggressive probe error"); got != 1 {
+		t.Error("Expected exactly one instance of 'aggressive probe error' in the log, got", got)
+	}
+}
+
 func TestEmptyHandler(t *testing.T) {
 	pb := NewProbe(&corev1.Probe{
 		PeriodSeconds:    1,
@@ -637,7 +661,7 @@ func TestKnTCPProbeSuccessThresholdIncludesFailure(t *testing.T) {
 	}
 
 	if probeErr := <-errChan; !probeErr {
-		t.Error("Wanted ProbeContainer() successed but got error")
+		t.Error("Wanted ProbeContainer() to succeed, but got error")
 	}
 	if got := pb.count; got < successThreshold {
 		t.Errorf("Count = %d, want: %d", got, successThreshold)
diff --git a/pkg/reconciler/autoscaling/kpa/kpa_test.go b/pkg/reconciler/autoscaling/kpa/kpa_test.go
index 540148222..001891b68 100644
--- a/pkg/reconciler/autoscaling/kpa/kpa_test.go
+++ b/pkg/reconciler/autoscaling/kpa/kpa_test.go
@@ -1671,7 +1671,7 @@ func (km *testDeciders) Create(ctx context.Context, decider *scaling.Decider) (*
 	return decider, nil
 }
 
-func (km *testDeciders) Delete(ctx context.Context, namespace, name string) error {
+func (km *testDeciders) Delete(ctx context.Context, namespace, name string) {
 	km.mutex.Lock()
 	defer km.mutex.Unlock()
 
@@ -1681,7 +1681,6 @@ func (km *testDeciders) Delete(ctx context.Context, namespace, name string) erro
 		km.deleteBeforeCreate.Store(true)
 	}
 	km.deleteCall <- struct{}{}
-	return nil
 }
 
 func (km *testDeciders) Update(ctx context.Context, decider *scaling.Decider) (*scaling.Decider, error) {
@@ -1699,7 +1698,6 @@ func (km *testDeciders) Watch(fn func(types.NamespacedName)) {}
 type failingDeciders struct {
 	getErr    error
 	createErr error
-	deleteErr error
 }
 
 func (km *failingDeciders) Get(ctx context.Context, namespace, name string) (*scaling.Decider, error) {
@@ -1710,9 +1708,7 @@ func (km *failingDeciders) Create(ctx context.Context, decider *scaling.Decider)
 	return nil, km.createErr
 }
 
-func (km *failingDeciders) Delete(ctx context.Context, namespace, name string) error {
-	return km.deleteErr
-}
+func (km *failingDeciders) Delete(ctx context.Context, namespace, name string) {}
 
 func (km *failingDeciders) Watch(fn func(types.NamespacedName)) {
 }
diff --git a/pkg/reconciler/metric/metric_test.go b/pkg/reconciler/metric/metric_test.go
index d17365552..2b5cf6c49 100644
--- a/pkg/reconciler/metric/metric_test.go
+++ b/pkg/reconciler/metric/metric_test.go
@@ -267,7 +267,6 @@ type testCollector struct {
 	createOrUpdateError error
 
 	deleteCalls atomic.Int32
-	deleteError error
 }
 
 func (c *testCollector) CreateOrUpdate(metric *av1alpha1.Metric) error {
@@ -275,9 +274,8 @@ func (c *testCollector) CreateOrUpdate(metric *av1alpha1.Metric) error {
 	return c.createOrUpdateError
 }
 
-func (c *testCollector) Delete(namespace, name string) error {
+func (c *testCollector) Delete(namespace, name string) {
 	c.deleteCalls.Inc()
-	return c.deleteError
 }
 
 func (c *testCollector) Watch(func(types.NamespacedName)) {}
diff --git a/pkg/reconciler/revision/resolve_test.go b/pkg/reconciler/revision/resolve_test.go
index 8b896bb9f..ca2b43468 100644
--- a/pkg/reconciler/revision/resolve_test.go
+++ b/pkg/reconciler/revision/resolve_test.go
@@ -513,11 +513,7 @@ yE+vPxsiUkvQHdO2fojCkY8jg70jxM+gu59tPDNbw3Uh/2Ij310FgTHsnGQMyA==
 		wantErr:            true,
 	}}
 
-	tmpDir, err := ioutil.TempDir("", "TestNewResolverTransport-")
-	if err != nil {
-		t.Fatal("Failed to create tempdir for certs:", err)
-	}
-	defer os.RemoveAll(tmpDir)
+	tmpDir := t.TempDir()
 
 	for i, tc := range cases {
 		i, tc := i, tc
diff --git a/pkg/reconciler/route/reconcile_resources_test.go b/pkg/reconciler/route/reconcile_resources_test.go
index 24fecf20a..e0f3426bf 100644
--- a/pkg/reconciler/route/reconcile_resources_test.go
+++ b/pkg/reconciler/route/reconcile_resources_test.go
@@ -27,7 +27,7 @@ import (
 
 	"knative.dev/networking/pkg/apis/networking"
 	netv1alpha1 "knative.dev/networking/pkg/apis/networking/v1alpha1"
-	fakeciinformer "knative.dev/networking/pkg/client/injection/informers/networking/v1alpha1/ingress/fake"
+	fakeingressinformer "knative.dev/networking/pkg/client/injection/informers/networking/v1alpha1/ingress/fake"
 	"knative.dev/pkg/ptr"
 	"knative.dev/serving/pkg/apis/serving"
 	v1 "knative.dev/serving/pkg/apis/serving/v1"
@@ -35,7 +35,6 @@ import (
 	fakerevisioninformer "knative.dev/serving/pkg/client/injection/informers/serving/v1/revision/fake"
 	"knative.dev/serving/pkg/gc"
 	"knative.dev/serving/pkg/reconciler/route/config"
-	"knative.dev/serving/pkg/reconciler/route/resources"
 	"knative.dev/serving/pkg/reconciler/route/traffic"
 
 	. "knative.dev/serving/pkg/testing/v1"
@@ -49,9 +48,8 @@ func TestReconcileIngressInsert(t *testing.T) {
 	defer cancel()
 
 	r := Route("test-ns", "test-route")
-	ci := newTestIngress(t, r)
-
-	if _, err := reconciler.reconcileIngress(ctx, r, ci); err != nil {
+	tc, tls := testIngressParams(t, r)
+	if _, err := reconciler.reconcileIngress(updateContext(ctx), r, tc, tls, "foo-ingress"); err != nil {
 		t.Error("Unexpected error:", err)
 	}
 }
@@ -65,15 +63,15 @@ func TestReconcileIngressUpdate(t *testing.T) {
 
 	r := Route("test-ns", "test-route")
 
-	ci := newTestIngress(t, r)
-	if _, err := reconciler.reconcileIngress(ctx, r, ci); err != nil {
+	tc, tls := testIngressParams(t, r)
+	if _, err := reconciler.reconcileIngress(updateContext(ctx), r, tc, tls, "foo-ingress"); err != nil {
 		t.Error("Unexpected error:", err)
 	}
 
-	updated := getRouteIngressFromClient(ctx, t, r)
-	fakeciinformer.Get(ctx).Informer().GetIndexer().Add(updated)
+	initial := getRouteIngressFromClient(ctx, t, r)
+	fakeingressinformer.Get(ctx).Informer().GetIndexer().Add(initial)
 
-	ci2 := newTestIngress(t, r, func(tc *traffic.Config) {
+	tc, tls = testIngressParams(t, r, func(tc *traffic.Config) {
 		tc.Targets[traffic.DefaultTarget][0].TrafficTarget.Percent = ptr.Int64(50)
 		tc.Targets[traffic.DefaultTarget] = append(tc.Targets[traffic.DefaultTarget], traffic.RevisionTarget{
 			TrafficTarget: v1.TrafficTarget{
@@ -82,15 +80,12 @@ func TestReconcileIngressUpdate(t *testing.T) {
 			},
 		})
 	})
-	if _, err := reconciler.reconcileIngress(ctx, r, ci2); err != nil {
+	if _, err := reconciler.reconcileIngress(updateContext(ctx), r, tc, tls, "foo-ingress"); err != nil {
 		t.Error("Unexpected error:", err)
 	}
 
-	updated = getRouteIngressFromClient(ctx, t, r)
-	if diff := cmp.Diff(ci2, updated); diff != "" {
-		t.Error("Unexpected diff (-want +got):", diff)
-	}
-	if diff := cmp.Diff(ci, updated); diff == "" {
+	updated := getRouteIngressFromClient(ctx, t, r)
+	if diff := cmp.Diff(initial, updated); diff == "" {
 		t.Error("Expected difference, but found none")
 	}
 }
@@ -128,7 +123,7 @@ func TestReconcileTargetValidRevision(t *testing.T) {
 		t.Fatal("Error getting last pinned:", err)
 	}
 
-	if err = reconciler.reconcileTargetRevisions(ctx, &tc, r); err != nil {
+	if err = reconciler.reconcileTargetRevisions(updateContext(ctx), &tc, r); err != nil {
 		t.Fatal("Error reconciling target revisions:", err)
 	}
 
@@ -197,7 +192,8 @@ func getLastPinnedTimestamp(t *testing.T, rev *v1.Revision) (string, error) {
 	return lastPinnedTime, nil
 }
 
-func newTestIngress(t *testing.T, r *v1.Route, trafficOpts ...func(tc *traffic.Config)) *netv1alpha1.Ingress {
+func testIngressParams(t *testing.T, r *v1.Route, trafficOpts ...func(tc *traffic.Config)) (*traffic.Config,
+	[]netv1alpha1.IngressTLS) {
 	tc := &traffic.Config{Targets: map[string]traffic.RevisionTargets{
 		traffic.DefaultTarget: {{
 			TrafficTarget: v1.TrafficTarget{
@@ -215,11 +211,7 @@ func newTestIngress(t *testing.T, r *v1.Route, trafficOpts ...func(tc *traffic.C
 		SecretName:      "test-secret",
 		SecretNamespace: "test-ns",
 	}}
-	ingress, err := resources.MakeIngress(getContext(), r, tc, tls, "foo-ingress")
-	if err != nil {
-		t.Error("Unexpected error:", err)
-	}
-	return ingress
+	return tc, tls
 }
 
 func TestReconcileIngressClassAnnotation(t *testing.T) {
@@ -232,19 +224,15 @@ func TestReconcileIngressClassAnnotation(t *testing.T) {
 	const expClass = "foo.ingress.networking.knative.dev"
 
 	r := Route("test-ns", "test-route")
-	ci := newTestIngress(t, r)
-	if _, err := reconciler.reconcileIngress(ctx, r, ci); err != nil {
+	tc, tls := testIngressParams(t, r)
+	if _, err := reconciler.reconcileIngress(updateContext(ctx), r, tc, tls, "foo-ingress"); err != nil {
 		t.Error("Unexpected error:", err)
 	}
 
 	updated := getRouteIngressFromClient(ctx, t, r)
-	fakeciinformer.Get(ctx).Informer().GetIndexer().Add(updated)
-
-	ci2 := newTestIngress(t, r)
-	// Add ingress.class annotation.
-	ci2.Annotations[networking.IngressClassAnnotationKey] = expClass
+	fakeingressinformer.Get(ctx).Informer().GetIndexer().Add(updated)
 
-	if _, err := reconciler.reconcileIngress(ctx, r, ci2); err != nil {
+	if _, err := reconciler.reconcileIngress(updateContext(ctx), r, tc, tls, expClass); err != nil {
 		t.Error("Unexpected error:", err)
 	}
 
@@ -255,7 +243,11 @@ func TestReconcileIngressClassAnnotation(t *testing.T) {
 	}
 }
 
-func getContext() context.Context {
+func updateContext(ctx context.Context) context.Context {
 	cfg := reconcilerTestConfig(false)
-	return config.ToContext(context.Background(), cfg)
+	return config.ToContext(ctx, cfg)
+}
+
+func getContext() context.Context {
+	return updateContext(context.Background())
 }
diff --git a/pkg/reconciler/route/resources/ingress_test.go b/pkg/reconciler/route/resources/ingress_test.go
index 4c894bce3..c3e5753d5 100644
--- a/pkg/reconciler/route/resources/ingress_test.go
+++ b/pkg/reconciler/route/resources/ingress_test.go
@@ -51,8 +51,6 @@ const (
 	testRouteName       = "test-route"
 	testAnnotationValue = "test-annotation-value"
 	testIngressClass    = "test-ingress"
-
-	emptyRollout = "{}"
 )
 
 func TestMakeIngressCorrectMetadata(t *testing.T) {
@@ -81,7 +79,6 @@ func TestMakeIngressCorrectMetadata(t *testing.T) {
 			// Make sure to get passdownIngressClass instead of ingressClass
 			networking.IngressClassAnnotationKey: passdownIngressClass,
 			"test-annotation":                    "bar",
-			networking.RolloutAnnotationKey:      emptyRollout,
 		},
 		OwnerReferences: []metav1.OwnerReference{*kmeta.NewControllerRef(r)},
 	}
@@ -133,7 +130,6 @@ func TestMakeIngressWithRollout(t *testing.T) {
 			// Make sure to get passdownIngressClass instead of ingressClass
 			networking.IngressClassAnnotationKey: passdownIngressClass,
 			"test-annotation":                    "bar",
-			networking.RolloutAnnotationKey:      serializeRollout(context.Background(), cfg.BuildRollout()),
 		},
 		OwnerReferences: []metav1.OwnerReference{*kmeta.NewControllerRef(r)},
 	}
@@ -625,7 +621,7 @@ func TestMakeIngressRuleZeroPercentTarget(t *testing.T) {
 	}
 }
 
-// One active target and a target of nil (implied zero) percent.
+// One active target and a target of 0 percent (nil is now impossible with defaulting to 0).
 func TestMakeIngressRuleNilPercentTarget(t *testing.T) {
 	targets := []traffic.RevisionTarget{{
 		TrafficTarget: v1.TrafficTarget{
@@ -638,6 +634,7 @@ func TestMakeIngressRuleNilPercentTarget(t *testing.T) {
 		TrafficTarget: v1.TrafficTarget{
 			ConfigurationName: "new-config",
 			RevisionName:      "new-revision",
+			Percent:           ptr.Int64(0),
 		},
 	}}
 	domains := []string{"test.org"}
@@ -865,7 +862,7 @@ func TestMakeIngressRuleZeroPercentTargetInactive(t *testing.T) {
 	}
 }
 
-func TestMakeIngressRuleNilPercentTargetInactive(t *testing.T) {
+func TestMakeIngressRuleImplicit0PercentTargetInactive(t *testing.T) {
 	targets := []traffic.RevisionTarget{{
 		TrafficTarget: v1.TrafficTarget{
 			ConfigurationName: "config",
@@ -877,7 +874,7 @@ func TestMakeIngressRuleNilPercentTargetInactive(t *testing.T) {
 		TrafficTarget: v1.TrafficTarget{
 			ConfigurationName: "new-config",
 			RevisionName:      "new-revision",
-			Percent:           nil,
+			Percent:           ptr.Int64(0),
 		},
 	}}
 	domains := []string{"test.org"}
@@ -922,7 +919,6 @@ func TestMakeIngressWithTLS(t *testing.T) {
 			Namespace: ns,
 			Annotations: map[string]string{
 				networking.IngressClassAnnotationKey: ingressClass,
-				networking.RolloutAnnotationKey:      emptyRollout,
 			},
 			Labels: map[string]string{
 				serving.RouteLabelKey:          "test-route",
diff --git a/pkg/reconciler/route/table_test.go b/pkg/reconciler/route/table_test.go
index 95cbbe892..054439d1e 100644
--- a/pkg/reconciler/route/table_test.go
+++ b/pkg/reconciler/route/table_test.go
@@ -713,7 +713,11 @@ func TestReconcile(t *testing.T) {
 						}},
 					},
 				},
-			),
+				simpleRollout("config", []traffic.RevisionRollout{{
+					RevisionName: "config-00001", Percent: 99,
+				}, {
+					RevisionName: "config-00002", Percent: 1,
+				}})),
 		}},
 		WantStatusUpdates: []clientgotesting.UpdateActionImpl{{
 			Object: Route("default", "new-latest-ready", WithConfigTarget("config"),
@@ -913,7 +917,11 @@ func TestReconcile(t *testing.T) {
 						}},
 					},
 				},
-			),
+				simpleRollout("config", []traffic.RevisionRollout{{
+					RevisionName: "config-00001", Percent: 99,
+				}, {
+					RevisionName: "config-00002", Percent: 1,
+				}})),
 		}},
 		WantStatusUpdates: []clientgotesting.UpdateActionImpl{{
 			Object: Route("default", "update-ci-failure", WithConfigTarget("config"),
@@ -2555,6 +2563,12 @@ func ingressWithClass(r *v1.Route, tc *traffic.Config, class string, io ...Ingre
 func baseIngressWithClass(r *v1.Route, tc *traffic.Config, class string, io ...IngressOption) *netv1alpha1.Ingress {
 	ingress, _ := resources.MakeIngress(getContext(), r, tc, nil, class)
 
+	// By default attach current rollout.
+	ro := tc.BuildRollout()
+	ingress.Annotations = kmeta.UnionMaps(ingress.Annotations, map[string]string{
+		networking.RolloutAnnotationKey: serializeRollout(context.Background(), ro),
+	})
+
 	for _, opt := range io {
 		opt(ingress)
 	}
@@ -2569,6 +2583,12 @@ func ingressWithTLS(r *v1.Route, tc *traffic.Config, tls []netv1alpha1.IngressTL
 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...)
 
+	// By default attach current rollout.
+	ro := tc.BuildRollout()
+	ingress.Annotations = kmeta.UnionMaps(ingress.Annotations, map[string]string{
+		networking.RolloutAnnotationKey: serializeRollout(context.Background(), ro),
+	})
+
 	for _, opt := range io {
 		opt(ingress)
 	}
@@ -2724,3 +2744,17 @@ func setResponsiveGCFeature(ctx context.Context, flag cfgmap.Flag) context.Conte
 	c.Features.ResponsiveRevisionGC = flag
 	return cfgmap.ToContext(ctx, c)
 }
+
+func simpleRollout(cfg string, revs []traffic.RevisionRollout) IngressOption {
+	return func(i *netv1alpha1.Ingress) {
+		r := &traffic.Rollout{
+			Configurations: []traffic.ConfigurationRollout{{
+				ConfigurationName: cfg,
+				Percent:           100,
+				Revisions:         revs,
+			}},
+		}
+		ro := serializeRollout(context.Background(), r)
+		i.Annotations[networking.RolloutAnnotationKey] = ro
+	}
+}
diff --git a/pkg/reconciler/route/traffic/traffic_test.go b/pkg/reconciler/route/traffic/traffic_test.go
index 863b2e870..6f610d74c 100644
--- a/pkg/reconciler/route/traffic/traffic_test.go
+++ b/pkg/reconciler/route/traffic/traffic_test.go
@@ -63,6 +63,10 @@ var (
 	unreadyConfig *v1.Configuration
 	unreadyRev    *v1.Revision
 
+	readyUnreadyConfig *v1.Configuration
+	readyRevision      *v1.Revision
+	newUnreadyRev      *v1.Revision
+
 	// failedConfig only has failedRev, and it fails to be ready.
 	failedConfig *v1.Configuration
 	failedRev    *v1.Revision
@@ -94,6 +98,7 @@ func setUp() {
 	emptyConfig = getTestEmptyConfig("empty")
 	revDeletedConfig = testConfigWithDeletedRevision("latest-rev-deleted")
 	unreadyConfig, unreadyRev = getTestUnreadyConfig("unready")
+	readyUnreadyConfig, readyRevision, newUnreadyRev = createReadyUnreadyConfig("ready-unready")
 	failedConfig, failedRev = getTestFailedConfig("failed")
 	inactiveConfig, inactiveRev = getTestInactiveConfig("inactive")
 	goodConfig, goodOldRev, goodNewRev = getTestReadyConfig("good")
@@ -117,6 +122,7 @@ func setUp() {
 		emptyConfig,
 		goodConfig, goodOldRev, goodNewRev,
 		niceConfig, niceOldRev, niceNewRev,
+		readyUnreadyConfig, readyRevision, newUnreadyRev,
 	}
 
 	for _, obj := range objs {
@@ -1136,6 +1142,65 @@ func TestBuildTrafficConfigurationNotRoutableRevision(t *testing.T) {
 	}
 }
 
+func TestBuildTrafficConfigurationReadyNotReadyConfig(t *testing.T) {
+	expected := &Config{
+		Targets: map[string]RevisionTargets{
+			DefaultTarget: {{
+				TrafficTarget: v1.TrafficTarget{
+					RevisionName:      readyRevision.Name,
+					ConfigurationName: readyUnreadyConfig.Name,
+					LatestRevision:    ptr.Bool(true),
+					Percent:           ptr.Int64(100),
+				},
+				Protocol: net.ProtocolHTTP1,
+			}},
+		},
+		revisionTargets: []RevisionTarget{{
+			TrafficTarget: v1.TrafficTarget{
+				RevisionName:      readyRevision.Name,
+				ConfigurationName: readyUnreadyConfig.Name,
+				LatestRevision:    ptr.Bool(true),
+				Percent:           ptr.Int64(100),
+			},
+			Protocol: net.ProtocolHTTP1,
+		}},
+		Revisions: map[string]*v1.Revision{
+			readyRevision.Name: readyRevision,
+		},
+		Configurations: map[string]*v1.Configuration{
+			readyUnreadyConfig.Name: readyUnreadyConfig,
+		},
+	}
+	tc, err := BuildTrafficConfiguration(
+		configLister, revLister,
+		testRouteWithTrafficTargets(WithSpecTraffic(v1.TrafficTarget{
+			ConfigurationName: readyUnreadyConfig.Name,
+			LatestRevision:    ptr.Bool(true),
+			Percent:           ptr.Int64(100),
+		},
+		)))
+	if err != nil {
+		t.Fatal("BuildTrafficConfiguration =", err)
+	}
+	if got, want := tc, expected; !cmp.Equal(want, got, cmpOpts...) {
+		t.Errorf("Incorrect trafficm diff:(-want +got):\n%s", cmp.Diff(want, got, cmpOpts...))
+	}
+	gotR := tc.BuildRollout()
+	wantR := &Rollout{
+		Configurations: []ConfigurationRollout{{
+			ConfigurationName: readyUnreadyConfig.Name,
+			Percent:           100,
+			Revisions: []RevisionRollout{{
+				RevisionName: readyRevision.Name,
+				Percent:      100,
+			}},
+		}},
+	}
+	if !cmp.Equal(gotR, wantR) {
+		t.Errorf("Rollout mismatch, diff(-want,+got):\n%s", cmp.Diff(wantR, gotR))
+	}
+}
+
 func TestBuildTrafficConfigurationNotRoutableConfiguration(t *testing.T) {
 	expected := &Config{
 		Targets:        map[string]RevisionTargets{},
@@ -1358,8 +1423,23 @@ func testConfigWithDeletedRevision(name string) *v1.Configuration {
 	return config
 }
 
+func createReadyUnreadyConfig(name string) (*v1.Configuration, *v1.Revision, *v1.Revision) {
+	config := testConfig(name + "-config")
+
+	rev1 := testRevForConfig(config, name+"-revision-1")
+	rev1.Status.MarkResourcesAvailableTrue()
+	rev1.Status.MarkContainerHealthyTrue()
+	rev1.Status.MarkActiveTrue()
+	config.Status.SetLatestReadyRevisionName(rev1.Name)
+
+	rev2 := testRevForConfig(config, name+"-revision")
+	config.Status.SetLatestCreatedRevisionName(rev2.Name)
+	return config, rev1, rev2
+}
+
 func getTestUnreadyConfig(name string) (*v1.Configuration, *v1.Revision) {
 	config := testConfig(name + "-config")
+
 	rev := testRevForConfig(config, name+"-revision")
 	config.Status.SetLatestCreatedRevisionName(rev.Name)
 	return config, rev
diff --git a/test/conformance/api/v1/service_test.go b/test/conformance/api/v1/service_test.go
index 2d9b8f5df..b35151899 100644
--- a/test/conformance/api/v1/service_test.go
+++ b/test/conformance/api/v1/service_test.go
@@ -598,35 +598,32 @@ func TestServiceCreateWithMultipleContainers(t *testing.T) {
 
 	names := test.ResourceNames{
 		Service: test.ObjectNameForTest(t),
+		Image:   test.ServingContainer,
+		Sidecars: []string{
+			test.SidecarContainer,
+		},
 	}
 
 	// Clean up on test failure or interrupt
 	test.EnsureTearDown(t, clients, &names)
-	// images are used to validate digest in validateControlPlane function
-	images := map[string]string{
-		"serving-container": test.ServingContainer,
-		"sidecar-container": test.SidecarContainer,
-	}
 	containers := []corev1.Container{{
-		Name:  "serving-container",
-		Image: pkgTest.ImagePath(test.ServingContainer),
+		Image: pkgTest.ImagePath(names.Image),
 		Ports: []corev1.ContainerPort{{
 			ContainerPort: 8881,
 		}},
 	}, {
-		Name:  "sidecar-container",
-		Image: pkgTest.ImagePath(test.SidecarContainer),
+		Image: pkgTest.ImagePath(names.Sidecars[0]),
 	}}
 
 	// Setup initial Service
-	if _, err := v1test.CreateServiceReadyForMultiContainer(t, clients, &names, func(svc *v1.Service) {
+	if _, err := v1test.CreateServiceReady(t, clients, &names, func(svc *v1.Service) {
 		svc.Spec.Template.Spec.Containers = containers
 	}); err != nil {
 		t.Fatalf("Failed to create initial Service %v: %v", names.Service, err)
 	}
 
 	// Validate State after Creation
-	if err := validateControlPlane(t, clients, names, "1" /*1 is the expected generation value*/, images); err != nil {
+	if err := validateControlPlane(t, clients, names, "1" /*1 is the expected generation value*/); err != nil {
 		t.Error(err)
 	}
 
diff --git a/test/conformance/api/v1/util.go b/test/conformance/api/v1/util.go
index bf453a0e3..5d5f9d6f0 100644
--- a/test/conformance/api/v1/util.go
+++ b/test/conformance/api/v1/util.go
@@ -121,26 +121,17 @@ func validateDataPlane(t testing.TB, clients *test.Clients, names test.ResourceN
 // Validates the state of Configuration, Revision, and Route objects for a runLatest Service.
 // The checks in this method should be able to be performed at any point in a
 // runLatest Service's lifecycle so long as the service is in a "Ready" state.
-func validateControlPlane(t *testing.T, clients *test.Clients, names test.ResourceNames, expectedGeneration string, imagesForMultipleContainers ...map[string]string) error {
+func validateControlPlane(t *testing.T, clients *test.Clients, names test.ResourceNames, expectedGeneration string) error {
 	t.Log("Checking to ensure Revision is in desired state with", "generation", expectedGeneration)
 	if err := v1test.CheckRevisionState(clients.ServingClient, names.Revision, func(r *v1.Revision) (bool, error) {
 		if ready, err := v1test.IsRevisionReady(r); !ready {
 			return false, fmt.Errorf("revision %s did not become ready to serve traffic: %w", names.Revision, err)
 		}
-		// for multi containers there will be more than one container and names.Image is a string,
-		// so in order to validate imageDigest for each images validateControlPlane accepting optional field called imagesForMultipleContainers
-		if names.Image == "" {
-			for _, value := range imagesForMultipleContainers {
-				for _, v := range r.Status.ContainerStatuses {
-					if image, ok := value[v.Name]; ok {
-						if validDigest, err := shared.ValidateImageDigest(t, image, v.ImageDigest); !validDigest {
-							return false, fmt.Errorf("imageDigest %s is not valid for imageName %s: %w", v.ImageDigest, image, err)
-						}
-					}
-				}
+		images := append([]string{names.Image}, names.Sidecars...)
+		for i, v := range r.Status.ContainerStatuses {
+			if validDigest, err := shared.ValidateImageDigest(t, images[i], v.ImageDigest); !validDigest {
+				return false, fmt.Errorf("imageDigest %s is not valid for imageName %s: %w", v.ImageDigest, images[i], err)
 			}
-		} else if validDigest, err := shared.ValidateImageDigest(t, names.Image, r.Status.ContainerStatuses[0].ImageDigest); !validDigest {
-			return false, fmt.Errorf("imageDigest %s is not valid for imageName %s: %w", r.Status.ContainerStatuses[0].ImageDigest, names.Image, err)
 		}
 		return true, nil
 	}); err != nil {
diff --git a/test/conformance/api/v1alpha1/domain_mapping_test.go b/test/conformance/api/v1alpha1/domain_mapping_test.go
index d8eec4cf0..98e6906b3 100644
--- a/test/conformance/api/v1alpha1/domain_mapping_test.go
+++ b/test/conformance/api/v1alpha1/domain_mapping_test.go
@@ -30,6 +30,7 @@ import (
 	"knative.dev/serving/pkg/apis/serving/v1alpha1"
 	"knative.dev/serving/test"
 	"knative.dev/serving/test/conformance/api/shared"
+	"knative.dev/serving/test/e2e"
 	v1test "knative.dev/serving/test/v1"
 )
 
@@ -43,13 +44,13 @@ func TestDomainMapping(t *testing.T) {
 
 	names := test.ResourceNames{
 		Service: test.ObjectNameForTest(t),
-		Image:   test.HelloWorld,
+		Image:   test.PizzaPlanet1,
 	}
 
 	// Clean up on test failure or interrupt.
 	test.EnsureTearDown(t, clients, &names)
 
-	// Setup initial Service.
+	// Set up initial Service.
 	svc, err := v1test.CreateServiceReady(t, clients, &names)
 	if err != nil {
 		t.Fatalf("Failed to create initial Service %v: %v", names.Service, err)
@@ -99,7 +100,88 @@ func TestDomainMapping(t *testing.T) {
 	}
 
 	// Should be able to access the test image text via the mapped domain.
-	if err := shared.CheckDistribution(ctx, t, clients, &url.URL{Host: host, Scheme: "http"}, test.ConcurrentRequests, test.ConcurrentRequests, []string{test.HelloWorldText}); err != nil {
+	if err := shared.CheckDistribution(ctx, t, clients, &url.URL{Host: host, Scheme: "http"}, test.ConcurrentRequests, test.ConcurrentRequests, []string{test.PizzaPlanetText1}); err != nil {
+		t.Errorf("CheckDistribution=%v, expected no error", err)
+	}
+
+	altClients := e2e.SetupAlternativeNamespace(t)
+	altNames := test.ResourceNames{
+		Service: test.ObjectNameForTest(t),
+		Image:   test.PizzaPlanet2,
+	}
+	test.EnsureTearDown(t, altClients, &altNames)
+
+	// Set up second Service in alt namespace.
+	altSvc, err := v1test.CreateServiceReady(t, altClients, &altNames)
+	if err != nil {
+		t.Fatalf("Failed to create initial Service %v: %v", altNames.Service, err)
+	}
+
+	// Create second domain mapping with same name in alt namespace - this will collide with the existing mapping.
+	var altDm *v1alpha1.DomainMapping
+	if err := reconciler.RetryTestErrors(func(int) error {
+		altDm, err = altClients.ServingAlphaClient.DomainMappings.Create(ctx, &v1alpha1.DomainMapping{
+			ObjectMeta: metav1.ObjectMeta{
+				Name:      host,
+				Namespace: altSvc.Service.Namespace,
+			},
+			Spec: v1alpha1.DomainMappingSpec{
+				Ref: duckv1.KReference{
+					Namespace:  altSvc.Service.Namespace,
+					Name:       altSvc.Service.Name,
+					APIVersion: "serving.knative.dev/v1",
+					Kind:       "Service",
+				},
+			},
+		}, metav1.CreateOptions{})
+		return err
+	}); err != nil {
+		t.Fatalf("Create(DomainMapping) = %v, expected no error", err)
+	}
+
+	t.Cleanup(func() {
+		altClients.ServingAlphaClient.DomainMappings.Delete(ctx, altDm.Name, metav1.DeleteOptions{})
+	})
+
+	// Second domain mapping should go to DomainMappingConditionDomainClaimed=false state.
+	waitErr = wait.PollImmediate(test.PollInterval, test.PollTimeout, func() (bool, error) {
+		state, err := altClients.ServingAlphaClient.DomainMappings.Get(context.Background(), dm.Name, metav1.GetOptions{})
+		if err != nil {
+			return true, err
+		}
+
+		return state.Generation == state.Status.ObservedGeneration &&
+			state.Status.GetCondition(v1alpha1.DomainMappingConditionDomainClaimed).IsFalse(), nil
+	})
+	if waitErr != nil {
+		t.Fatalf("The second DomainMapping %s did not enter DomainMappingConditionDomainClaimed=false state: %v", altDm.Name, waitErr)
+	}
+
+	// Because the second DomainMapping collided with the first, it should not have taken effect.
+	if err := shared.CheckDistribution(ctx, t, clients, &url.URL{Host: host, Scheme: "http"}, test.ConcurrentRequests, test.ConcurrentRequests, []string{test.PizzaPlanetText1}); err != nil {
+		t.Errorf("CheckDistribution=%v, expected no error", err)
+	}
+
+	// Delete the first DomainMapping.
+	if err := clients.ServingAlphaClient.DomainMappings.Delete(ctx, dm.Name, metav1.DeleteOptions{}); err != nil {
+		t.Fatalf("Delete=%v, expected no error", err)
+	}
+
+	// The second DomainMapping should now be able to claim the domain.
+	waitErr = wait.PollImmediate(test.PollInterval, test.PollTimeout, func() (bool, error) {
+		state, err := altClients.ServingAlphaClient.DomainMappings.Get(context.Background(), altDm.Name, metav1.GetOptions{})
+		if err != nil {
+			return true, err
+		}
+
+		return state.IsReady(), nil
+	})
+	if waitErr != nil {
+		t.Fatalf("The second DomainMapping %s was not marked as Ready: %v", dm.Name, waitErr)
+	}
+
+	// The domain name should now point to the second service.
+	if err := shared.CheckDistribution(ctx, t, clients, &url.URL{Host: host, Scheme: "http"}, test.ConcurrentRequests, test.ConcurrentRequests, []string{test.PizzaPlanetText2}); err != nil {
 		t.Errorf("CheckDistribution=%v, expected no error", err)
 	}
 }
diff --git a/test/crd.go b/test/crd.go
index 9f45c8b53..260fdd7d4 100644
--- a/test/crd.go
+++ b/test/crd.go
@@ -33,6 +33,7 @@ type ResourceNames struct {
 	TrafficTarget string
 	URL           *url.URL
 	Image         string
+	Sidecars      []string
 }
 
 // AppendRandomString will generate a random string that begins with prefix. This is useful
diff --git a/test/e2e-networking-library.sh b/test/e2e-networking-library.sh
index c9cec53ca..635cab9fa 100644
--- a/test/e2e-networking-library.sh
+++ b/test/e2e-networking-library.sh
@@ -20,8 +20,14 @@ function install_istio() {
   fi
 
   if [[ -z "${NET_ISTIO_COMMIT}" ]]; then
-    # TODO: Figure out the commit of net-istio.yaml from net-istio.yaml
-    readonly NET_ISTIO_COMMIT="8102cd3d32f05be1c58260a9717d532a4a6d2f60"
+    NET_ISTIO_COMMIT=$(head -n 1 ${1} | grep "# Generated when HEAD was" | sed 's/^.* //')
+    echo "Got NET_ISTIO_COMMIT from ${1}: ${NET_ISTIO_COMMIT}"
+  fi
+
+  # TODO: remove this when all the net-istio.yaml in use contain a commit ID
+  if [[ -z "${NET_ISTIO_COMMIT}" ]]; then
+    NET_ISTIO_COMMIT="8102cd3d32f05be1c58260a9717d532a4a6d2f60"
+    echo "Hard coded NET_ISTIO_COMMIT: ${NET_ISTIO_COMMIT}"
   fi
 
   # And checkout the setup script based on that commit.
@@ -157,7 +163,7 @@ function install_contour() {
 function wait_until_ingress_running() {
   if [[ -n "${ISTIO_VERSION}" ]]; then
     wait_until_pods_running istio-system || return 1
-    wait_until_service_has_external_http_address istio-system istio-ingressgateway
+    wait_until_service_has_external_http_address istio-system istio-ingressgateway || return 1
   fi
   if [[ -n "${GLOO_VERSION}" ]]; then
     # we must set these override values to allow the test spoofing client to work with Gloo
diff --git a/test/e2e-tests.sh b/test/e2e-tests.sh
index 599cb76b6..7feac7b0a 100755
--- a/test/e2e-tests.sh
+++ b/test/e2e-tests.sh
@@ -86,10 +86,12 @@ sleep 30
 
 # Run conformance and e2e tests.
 
-# Currently only Istio and Contour implement the alpha features.
-# TODO(#9874): Remove this guard once other ingresses implement these too.
+# Currently only Istio, Contour and Kourier implement the alpha features.
 alpha=""
-if [[ -z "${INGRESS_CLASS}" || "${INGRESS_CLASS}" == "istio.ingress.networking.knative.dev" || "${INGRESS_CLASS}" == "contour.ingress.networking.knative.dev" ]]; then
+if [[ -z "${INGRESS_CLASS}" \
+  || "${INGRESS_CLASS}" == "istio.ingress.networking.knative.dev" \
+  || "${INGRESS_CLASS}" == "contour.ingress.networking.knative.dev" \
+  || "${INGRESS_CLASS}" == "kourier.ingress.networking.knative.dev" ]]; then
   alpha="--enable-alpha"
 fi
 
diff --git a/test/e2e/multicontainer/multicontainer_test.go b/test/e2e/multicontainer/multicontainer_test.go
index 0138deac3..1f1e735de 100644
--- a/test/e2e/multicontainer/multicontainer_test.go
+++ b/test/e2e/multicontainer/multicontainer_test.go
@@ -36,23 +36,27 @@ func TestMultiContainer(t *testing.T) {
 
 	clients := e2e.Setup(t)
 
+	names := test.ResourceNames{
+		Service: test.ObjectNameForTest(t),
+		Image:   test.ServingContainer,
+		Sidecars: []string{
+			test.SidecarContainer,
+		},
+	}
+
 	containers := []corev1.Container{{
-		Image: pkgTest.ImagePath(test.ServingContainer),
+		Image: pkgTest.ImagePath(names.Image),
 		Ports: []corev1.ContainerPort{{
 			ContainerPort: 8881,
 		}},
 	}, {
-		Image: pkgTest.ImagePath(test.SidecarContainer),
+		Image: pkgTest.ImagePath(names.Sidecars[0]),
 	}}
 
-	names := test.ResourceNames{
-		Service: test.ObjectNameForTest(t),
-	}
-
 	test.EnsureTearDown(t, clients, &names)
 	t.Log("Creating a new Service")
 
-	resources, err := v1test.CreateServiceReadyForMultiContainer(t, clients, &names, func(svc *v1.Service) {
+	resources, err := v1test.CreateServiceReady(t, clients, &names, func(svc *v1.Service) {
 		svc.Spec.Template.Spec.Containers = containers
 	})
 	if err != nil {
diff --git a/test/performance/README.md b/test/performance/README.md
index 76ab1e3f6..de0a1a562 100644
--- a/test/performance/README.md
+++ b/test/performance/README.md
@@ -1,9 +1,9 @@
 # Performance tests
 
 Knative performance tests are tests geared towards producing useful performance
-metrics of the knative system. As such they can choose to take a blackbox
+metrics of the knative system. As such they can choose to take a closed-box
 point-of-view of the system and use it just like an end-user might see it. They
-can also go more whiteboxy to narrow down the components under test.
+can also go more open-boxy to narrow down the components under test.
 
 ## Load Generator
 
diff --git a/test/v1/service.go b/test/v1/service.go
index 572154c9f..4415ec9cb 100644
--- a/test/v1/service.go
+++ b/test/v1/service.go
@@ -87,20 +87,6 @@ func GetResourceObjects(clients *test.Clients, names test.ResourceNames) (*Resou
 	}, nil
 }
 
-// CreateServiceReadyForMultiContainer creates a new Service for multi container in 'Ready' state . This function expects Service
-// name passed in through 'names'. Names is updated with the Route and Configuration created by the Service
-// and ResourceObjects is returned with the Service, Route, and Configuration objects.
-// Returns error if the service does not come up correctly.
-func CreateServiceReadyForMultiContainer(t testing.TB, clients *test.Clients, names *test.ResourceNames, fopt ...rtesting.ServiceOption) (*ResourceObjects, error) {
-	t.Log("Creating a new Service", "service", names.Service)
-	svc := rtesting.ServiceWithoutNamespace(names.Service, fopt...)
-	svc, err := createService(t, clients, svc)
-	if err != nil {
-		return nil, err
-	}
-	return getResourceObjects(t, clients, names, svc)
-}
-
 // CreateServiceReady creates a new Service in state 'Ready'. This function expects Service and Image name
 // passed in through 'names'.  Names is updated with the Route and Configuration created by the Service
 // and ResourceObjects is returned with the Service, Route, and Configuration objects.
@@ -227,10 +213,13 @@ func WaitForServiceLatestRevision(clients *test.Clients, names test.ResourceName
 // Service returns a Service object in namespace with the name names.Service
 // that uses the image specified by names.Image.
 func Service(names test.ResourceNames, fopt ...rtesting.ServiceOption) *v1.Service {
-	a := append([]rtesting.ServiceOption{
-		rtesting.WithConfigSpec(ConfigurationSpec(pkgTest.ImagePath(names.Image))),
-	}, fopt...)
-	return rtesting.ServiceWithoutNamespace(names.Service, a...)
+	if names.Image != "" && len(names.Sidecars) == 0 {
+		a := append([]rtesting.ServiceOption{
+			rtesting.WithConfigSpec(ConfigurationSpec(pkgTest.ImagePath(names.Image))),
+		}, fopt...)
+		return rtesting.ServiceWithoutNamespace(names.Service, a...)
+	}
+	return rtesting.ServiceWithoutNamespace(names.Service, fopt...)
 }
 
 // WaitForServiceState polls the status of the Service called name
diff --git a/third_party/contour-latest/net-contour.yaml b/third_party/contour-latest/net-contour.yaml
index 00330d23c..4c8ff5388 100644
--- a/third_party/contour-latest/net-contour.yaml
+++ b/third_party/contour-latest/net-contour.yaml
@@ -34,7 +34,7 @@ metadata:
   namespace: knative-serving
   labels:
     networking.knative.dev/ingress-provider: contour
-    serving.knative.dev/release: "v20201110-2ae0c66f"
+    serving.knative.dev/release: "v20201114-2ae0c66f"
 data:
   _example: |
     ################################
@@ -105,7 +105,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:79097613e8368fc0a29e64cbf7e00197a4075279faf18f2ab1200bc27bb45dc6
+          image: gcr.io/knative-nightly/knative.dev/net-contour/cmd/controller@sha256:6a1866086c4ee0570306239ece6d0a95504042b50c081f39516247063f3e341a
           resources:
             requests:
               cpu: 40m
diff --git a/third_party/istio-latest/net-istio.yaml b/third_party/istio-latest/net-istio.yaml
index 5700608d6..fe5004350 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 40b59920910828a29cf584c77bd785c8c6cf4a90
+# Generated when HEAD was cbc1a3d4e2ab6826fc042e3dad501c24d26dc327
 #
 # 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: "v20201110-40b59920"
+    serving.knative.dev/release: "v20201111-cbc1a3d4"
     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: "v20201110-40b59920"
+    serving.knative.dev/release: "v20201111-cbc1a3d4"
     networking.knative.dev/ingress-provider: istio
 spec:
   selector:
@@ -87,7 +87,7 @@ metadata:
   name: cluster-local-gateway
   namespace: knative-serving
   labels:
-    serving.knative.dev/release: "v20201110-40b59920"
+    serving.knative.dev/release: "v20201111-cbc1a3d4"
     networking.knative.dev/ingress-provider: istio
 spec:
   selector:
@@ -106,7 +106,7 @@ metadata:
   name: knative-local-gateway
   namespace: knative-serving
   labels:
-    serving.knative.dev/release: "v20201110-40b59920"
+    serving.knative.dev/release: "v20201111-cbc1a3d4"
     networking.knative.dev/ingress-provider: istio
 spec:
   selector:
@@ -125,7 +125,7 @@ metadata:
   name: knative-local-gateway
   namespace: istio-system
   labels:
-    serving.knative.dev/release: "v20201110-40b59920"
+    serving.knative.dev/release: "v20201111-cbc1a3d4"
     networking.knative.dev/ingress-provider: istio
 spec:
   type: ClusterIP
@@ -145,7 +145,7 @@ metadata:
   name: "webhook"
   namespace: "knative-serving"
   labels:
-    serving.knative.dev/release: "v20201110-40b59920"
+    serving.knative.dev/release: "v20201111-cbc1a3d4"
     networking.knative.dev/ingress-provider: istio
 spec:
   selector:
@@ -160,7 +160,7 @@ metadata:
   name: "istio-webhook"
   namespace: "knative-serving"
   labels:
-    serving.knative.dev/release: "v20201110-40b59920"
+    serving.knative.dev/release: "v20201111-cbc1a3d4"
     networking.knative.dev/ingress-provider: istio
 spec:
   selector:
@@ -189,7 +189,7 @@ kind: MutatingWebhookConfiguration
 metadata:
   name: webhook.istio.networking.internal.knative.dev
   labels:
-    serving.knative.dev/release: "v20201110-40b59920"
+    serving.knative.dev/release: "v20201111-cbc1a3d4"
     networking.knative.dev/ingress-provider: istio
 webhooks:
   - admissionReviewVersions:
@@ -225,7 +225,7 @@ kind: ValidatingWebhookConfiguration
 metadata:
   name: config.webhook.istio.networking.internal.knative.dev
   labels:
-    serving.knative.dev/release: "v20201110-40b59920"
+    serving.knative.dev/release: "v20201111-cbc1a3d4"
     networking.knative.dev/ingress-provider: istio
 webhooks:
   - admissionReviewVersions:
@@ -263,7 +263,7 @@ metadata:
   name: istio-webhook-certs
   namespace: knative-serving
   labels:
-    serving.knative.dev/release: "v20201110-40b59920"
+    serving.knative.dev/release: "v20201111-cbc1a3d4"
     networking.knative.dev/ingress-provider: istio
 
 ---
@@ -287,7 +287,7 @@ metadata:
   name: config-istio
   namespace: knative-serving
   labels:
-    serving.knative.dev/release: "v20201110-40b59920"
+    serving.knative.dev/release: "v20201111-cbc1a3d4"
     networking.knative.dev/ingress-provider: istio
 data:
   _example: |
@@ -357,7 +357,7 @@ metadata:
   name: networking-istio
   namespace: knative-serving
   labels:
-    serving.knative.dev/release: "v20201110-40b59920"
+    serving.knative.dev/release: "v20201111-cbc1a3d4"
     networking.knative.dev/ingress-provider: istio
 spec:
   selector:
@@ -373,14 +373,14 @@ spec:
         sidecar.istio.io/inject: "false"
       labels:
         app: networking-istio
-        serving.knative.dev/release: "v20201110-40b59920"
+        serving.knative.dev/release: "v20201111-cbc1a3d4"
     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:0ef2abf0e613ab19ff927cd2687273dceaadf1f04a6d7c45a33cc0d3e6448146
+          image: gcr.io/knative-nightly/knative.dev/net-istio/cmd/controller@sha256:604660e3e300ae8e4ebb92724cefea9eb14d997b664ec9cf76be2efc5c86bf20
           resources:
             requests:
               cpu: 30m
@@ -437,7 +437,7 @@ metadata:
   name: istio-webhook
   namespace: knative-serving
   labels:
-    serving.knative.dev/release: "v20201110-40b59920"
+    serving.knative.dev/release: "v20201111-cbc1a3d4"
     networking.knative.dev/ingress-provider: istio
 spec:
   selector:
@@ -451,14 +451,14 @@ spec:
       labels:
         app: istio-webhook
         role: istio-webhook
-        serving.knative.dev/release: "v20201110-40b59920"
+        serving.knative.dev/release: "v20201111-cbc1a3d4"
     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:66e4b06f933e56461161af236ced64adb04c2c1bb9e5376a8a86f2ddc4a36859
+          image: gcr.io/knative-nightly/knative.dev/net-istio/cmd/webhook@sha256:17bc9958b175fb5d58995d35614bae730fbe84bdc48b7adacdad2f556c78d9d6
           resources:
             requests:
               cpu: 20m
@@ -512,7 +512,7 @@ metadata:
   namespace: knative-serving
   labels:
     role: istio-webhook
-    serving.knative.dev/release: "v20201110-40b59920"
+    serving.knative.dev/release: "v20201111-cbc1a3d4"
     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 c0b798f01..7d63e78d4 100644
--- a/third_party/kourier-latest/kourier.yaml
+++ b/third_party/kourier-latest/kourier.yaml
@@ -117,7 +117,7 @@ spec:
         app: 3scale-kourier-control
     spec:
       containers:
-        - image: gcr.io/knative-nightly/knative.dev/net-kourier/cmd/kourier@sha256:c54e716803231005fd3d4b946013d139e5c5ac7d9921924efb41974a25eb9cc0
+        - image: gcr.io/knative-nightly/knative.dev/net-kourier/cmd/kourier@sha256:28183c42d1b02e927db16861ed9984c653cc9c0cc72b5d9ab450f3c229c2872e
           name: kourier-control
           env:
             - name: CERTS_SECRET_NAMESPACE
diff --git a/vendor/knative.dev/networking/config/dummy.go b/vendor/knative.dev/networking/config/placeholder.go
similarity index 100%
rename from vendor/knative.dev/networking/config/dummy.go
rename to vendor/knative.dev/networking/config/placeholder.go
diff --git a/vendor/knative.dev/networking/test/conformance/ingress/class.go b/vendor/knative.dev/networking/test/conformance/ingress/class.go
index 5a251e275..6d881da90 100644
--- a/vendor/knative.dev/networking/test/conformance/ingress/class.go
+++ b/vendor/knative.dev/networking/test/conformance/ingress/class.go
@@ -61,6 +61,8 @@ func TestIngressClass(t *testing.T) {
 
 	for _, test := range tests {
 		t.Run(test.name, func(t *testing.T) {
+			t.Parallel()
+
 			verifyIngressWithAnnotations(ctx, t, clients, test.annotations, ingressBackend)
 		})
 	}
diff --git a/vendor/knative.dev/networking/test/conformance/ingress/headers.go b/vendor/knative.dev/networking/test/conformance/ingress/headers.go
index fe9f8a219..80ac97c6b 100644
--- a/vendor/knative.dev/networking/test/conformance/ingress/headers.go
+++ b/vendor/knative.dev/networking/test/conformance/ingress/headers.go
@@ -80,6 +80,8 @@ func TestProbeHeaders(t *testing.T) {
 
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
+			t.Parallel()
+
 			ros := []RequestOption{}
 
 			ros = append(ros, func(r *http.Request) {
@@ -181,6 +183,8 @@ func TestTagHeaders(t *testing.T) {
 
 	for _, tt := range tests {
 		t.Run(tt.Name, func(t *testing.T) {
+			t.Parallel()
+
 			ros := []RequestOption{}
 
 			if tt.TagHeader != nil {
@@ -235,6 +239,8 @@ func TestPreSplitSetHeaders(t *testing.T) {
 	})
 
 	t.Run("Check without passing header", func(t *testing.T) {
+		t.Parallel()
+
 		ri := RuntimeRequest(ctx, t, client, "http://"+name+".example.com")
 		if ri == nil {
 			return
@@ -246,6 +252,8 @@ func TestPreSplitSetHeaders(t *testing.T) {
 	})
 
 	t.Run("Check with passing header", func(t *testing.T) {
+		t.Parallel()
+
 		ri := RuntimeRequest(ctx, t, client, "http://"+name+".example.com", func(req *http.Request) {
 			// Specify a value for the header to verify that implementations
 			// use set vs. append semantics.
@@ -307,6 +315,8 @@ func TestPostSplitSetHeaders(t *testing.T) {
 	})
 
 	t.Run("Check without passing header", func(t *testing.T) {
+		t.Parallel()
+
 		// Make enough requests that the likelihood of us seeing each variation is high,
 		// but don't check the distribution of requests, as that isn't the point of this
 		// particular test.
@@ -328,6 +338,8 @@ func TestPostSplitSetHeaders(t *testing.T) {
 	})
 
 	t.Run("Check with passing header", func(t *testing.T) {
+		t.Parallel()
+
 		// Make enough requests that the likelihood of us seeing each variation is high,
 		// but don't check the distribution of requests, as that isn't the point of this
 		// particular test.
diff --git a/vendor/knative.dev/networking/test/conformance/ingress/path.go b/vendor/knative.dev/networking/test/conformance/ingress/path.go
index 828681857..6ef4863a5 100644
--- a/vendor/knative.dev/networking/test/conformance/ingress/path.go
+++ b/vendor/knative.dev/networking/test/conformance/ingress/path.go
@@ -128,6 +128,8 @@ func TestPath(t *testing.T) {
 
 	for path, want := range tests {
 		t.Run(path, func(t *testing.T) {
+			t.Parallel()
+
 			ri := RuntimeRequest(ctx, t, client, "http://"+name+".example.com"+path)
 			if ri == nil {
 				return
diff --git a/vendor/knative.dev/networking/test/conformance/ingress/timeout.go b/vendor/knative.dev/networking/test/conformance/ingress/timeout.go
index 81d693871..7bacfbe0d 100644
--- a/vendor/knative.dev/networking/test/conformance/ingress/timeout.go
+++ b/vendor/knative.dev/networking/test/conformance/ingress/timeout.go
@@ -76,6 +76,8 @@ func TestTimeout(t *testing.T) {
 
 	for _, test := range tests {
 		t.Run(test.name, func(t *testing.T) {
+			t.Parallel()
+
 			checkTimeout(ctx, t, client, name, test.code, test.initialDelay, test.delay)
 		})
 	}
diff --git a/vendor/knative.dev/networking/test/conformance/ingress/tls.go b/vendor/knative.dev/networking/test/conformance/ingress/tls.go
index c2e0e89bc..2943d7b37 100644
--- a/vendor/knative.dev/networking/test/conformance/ingress/tls.go
+++ b/vendor/knative.dev/networking/test/conformance/ingress/tls.go
@@ -60,13 +60,11 @@ func TestIngressTLS(t *testing.T) {
 		}},
 	})
 
-	t.Run("verify HTTP", func(t *testing.T) {
-		RuntimeRequest(ctx, t, client, "http://"+name+".example.com")
-	})
+	// Check without TLS.
+	RuntimeRequest(ctx, t, client, "http://"+name+".example.com")
 
-	t.Run("verify HTTPS", func(t *testing.T) {
-		RuntimeRequest(ctx, t, client, "https://"+name+".example.com")
-	})
+	// Check with TLS.
+	RuntimeRequest(ctx, t, client, "https://"+name+".example.com")
 }
 
 // TODO(mattmoor): Consider adding variants where we have multiple hosts with distinct certificates.
diff --git a/vendor/knative.dev/networking/test/conformance/ingress/util.go b/vendor/knative.dev/networking/test/conformance/ingress/util.go
index b3255e5da..163b6150b 100644
--- a/vendor/knative.dev/networking/test/conformance/ingress/util.go
+++ b/vendor/knative.dev/networking/test/conformance/ingress/util.go
@@ -35,7 +35,6 @@ import (
 	"net"
 	"net/http"
 	"net/http/httputil"
-	"net/url"
 	"strconv"
 	"strings"
 	"testing"
@@ -533,7 +532,13 @@ func createService(ctx context.Context, t *testing.T, clients *test.Clients, svc
 		clients.KubeClient.CoreV1().Services(svc.Namespace).Delete(ctx, svc.Name, metav1.DeleteOptions{})
 	})
 	if err := reconciler.RetryTestErrors(func(attempts int) error {
+		if attempts > 0 {
+			t.Logf("Attempt %d creating service %s", attempts, svc.Name)
+		}
 		_, err := clients.KubeClient.CoreV1().Services(svc.Namespace).Create(ctx, svc, metav1.CreateOptions{})
+		if err != nil {
+			t.Logf("Attempt %d creating service failed with: %v", attempts, err)
+		}
 		return err
 	}); err != nil {
 		t.Fatalf("Error creating Service %q: %v", svcName, err)
@@ -548,6 +553,8 @@ func createService(ctx context.Context, t *testing.T, clients *test.Clients, svc
 }
 
 func createExternalNameService(ctx context.Context, t *testing.T, clients *test.Clients, target, gatewayDomain string) context.CancelFunc {
+	t.Helper()
+
 	targetName := strings.SplitN(target, ".", 3)
 	externalNameSvc := &corev1.Service{
 		ObjectMeta: metav1.ObjectMeta{
@@ -581,7 +588,13 @@ func createPodAndService(ctx context.Context, t *testing.T, clients *test.Client
 		clients.KubeClient.CoreV1().Pods(pod.Namespace).Delete(ctx, pod.Name, metav1.DeleteOptions{})
 	})
 	if err := reconciler.RetryTestErrors(func(attempts int) error {
+		if attempts > 0 {
+			t.Logf("Attempt %d creating pod %s", attempts, pod.Name)
+		}
 		_, err := clients.KubeClient.CoreV1().Pods(pod.Namespace).Create(ctx, pod, metav1.CreateOptions{})
+		if err != nil {
+			t.Logf("Attempt %d creating pod failed with: %v", attempts, err)
+		}
 		return err
 	}); err != nil {
 		t.Fatalf("Error creating Pod %q: %v", podName, err)
@@ -591,7 +604,13 @@ func createPodAndService(ctx context.Context, t *testing.T, clients *test.Client
 		clients.KubeClient.CoreV1().Services(svc.Namespace).Delete(ctx, svc.Name, metav1.DeleteOptions{})
 	})
 	if err := reconciler.RetryTestErrors(func(attempts int) error {
+		if attempts > 0 {
+			t.Logf("Attempt %d creating service %s", attempts, svc.Name)
+		}
 		_, err := clients.KubeClient.CoreV1().Services(svc.Namespace).Create(ctx, svc, metav1.CreateOptions{})
+		if err != nil {
+			t.Logf("Attempt %d creating service failed with: %v", attempts, err)
+		}
 		return err
 	}); err != nil {
 		t.Fatalf("Error creating Service %q: %v", svcName, err)
@@ -674,7 +693,13 @@ func createIngress(ctx context.Context, t *testing.T, clients *test.Clients, spe
 
 	t.Cleanup(func() { clients.NetworkingClient.Ingresses.Delete(ctx, ing.Name, metav1.DeleteOptions{}) })
 	if err := reconciler.RetryTestErrors(func(attempts int) (err error) {
+		if attempts > 0 {
+			t.Logf("Attempt %d creating ingress %s", attempts, ing.Name)
+		}
 		ing, err = clients.NetworkingClient.Ingresses.Create(ctx, ing, metav1.CreateOptions{})
+		if err != nil {
+			t.Logf("Attempt %d creating ingress failed with: %v", attempts, err)
+		}
 		return err
 	}); err != nil {
 		t.Fatalf("Error creating Ingress %q: %v", ingName, err)
@@ -1027,11 +1052,11 @@ func StatusCodeExpectation(statusCodes sets.Int) ResponseExpectation {
 }
 
 func IsDialError(err error) bool {
-	if err, ok := err.(*url.Error); ok {
-		err, ok := err.Err.(*net.OpError)
-		return ok && err.Op == "dial"
+	var errNetOp *net.OpError
+	if !errors.As(err, &errNetOp) {
+		return false
 	}
-	return false
+	return errNetOp.Op == "dial"
 }
 
 // WaitForIngressState polls the status of the Ingress called name from client every
diff --git a/vendor/knative.dev/networking/test/conformance/ingress/visibility.go b/vendor/knative.dev/networking/test/conformance/ingress/visibility.go
index 915eb2e76..77e4b36e1 100644
--- a/vendor/knative.dev/networking/test/conformance/ingress/visibility.go
+++ b/vendor/knative.dev/networking/test/conformance/ingress/visibility.go
@@ -39,13 +39,11 @@ func TestVisibility(t *testing.T) {
 	// Create the private backend
 	name, port, _ := CreateRuntimeService(ctx, t, clients, networking.ServicePortNameHTTP1)
 
-	privateServiceName := test.ObjectNameForTest(t)
-	shortName := privateServiceName + "." + test.ServingNamespace
-
+	// Generate a different hostname for each of these tests, so that they do not fail when run concurrently.
 	var privateHostNames = map[string]string{
-		"fqdn":     shortName + ".svc." + test.NetworkingFlags.ClusterSuffix,
-		"short":    shortName + ".svc",
-		"shortest": shortName,
+		"fqdn":     test.ObjectNameForTest(t) + "." + test.ServingNamespace + ".svc." + test.NetworkingFlags.ClusterSuffix,
+		"short":    test.ObjectNameForTest(t) + "." + test.ServingNamespace + ".svc",
+		"shortest": test.ObjectNameForTest(t) + "." + test.ServingNamespace,
 	}
 	ingress, client, _ := CreateIngressReady(ctx, t, clients, v1alpha1.IngressSpec{
 		Rules: []v1alpha1.IngressRule{{
@@ -70,8 +68,11 @@ func TestVisibility(t *testing.T) {
 		RuntimeRequestWithExpectations(ctx, t, client, "http://"+privateHostName, []ResponseExpectation{StatusCodeExpectation(sets.NewInt(http.StatusNotFound))}, true)
 	}
 
-	for name, privateHostName := range privateHostNames {
+	for name := range privateHostNames {
+		privateHostName := privateHostNames[name] // avoid the Go iterator capture issue.
 		t.Run(name, func(t *testing.T) {
+			t.Parallel()
+
 			testProxyToHelloworld(ctx, t, ingress, clients, privateHostName)
 		})
 	}
@@ -361,6 +362,8 @@ func TestVisibilityPath(t *testing.T) {
 
 	for path, want := range tests {
 		t.Run(path, func(t *testing.T) {
+			t.Parallel()
+
 			ri := RuntimeRequest(ctx, t, client, "http://"+publicHostName+path)
 			if ri == nil {
 				return
diff --git a/vendor/knative.dev/pkg/reconciler/testing/tracker.go b/vendor/knative.dev/pkg/reconciler/testing/tracker.go
index 35a15f896..e586097d9 100644
--- a/vendor/knative.dev/pkg/reconciler/testing/tracker.go
+++ b/vendor/knative.dev/pkg/reconciler/testing/tracker.go
@@ -41,6 +41,31 @@ var _ tracker.Interface = (*FakeTracker)(nil)
 // OnChanged implements OnChanged.
 func (*FakeTracker) OnChanged(interface{}) {}
 
+// GetObservers implements GetObservers.
+func (n *FakeTracker) GetObservers(obj interface{}) []types.NamespacedName {
+	item, err := kmeta.DeletionHandlingAccessor(obj)
+	if err != nil {
+		return nil
+	}
+
+	or := kmeta.ObjectReference(item)
+	ref := tracker.Reference{
+		APIVersion: or.APIVersion,
+		Kind:       or.Kind,
+		Namespace:  or.Namespace,
+		Name:       or.Name,
+	}
+
+	n.Lock()
+	defer n.Unlock()
+
+	keys := make([]types.NamespacedName, 0, len(n.references[ref]))
+	for key := range n.references[ref] {
+		keys = append(keys, key)
+	}
+	return keys
+}
+
 // OnDeletedObserver implements OnDeletedObserver.
 func (n *FakeTracker) OnDeletedObserver(obj interface{}) {
 	item, err := kmeta.DeletionHandlingAccessor(obj)
diff --git a/vendor/knative.dev/pkg/test/logging/.gitattributes b/vendor/knative.dev/pkg/test/logging/.gitattributes
deleted file mode 100644
index 19c29c12f..000000000
--- a/vendor/knative.dev/pkg/test/logging/.gitattributes
+++ /dev/null
@@ -1,1 +0,0 @@
-memory_encoder.go coverage-excluded=true
diff --git a/vendor/knative.dev/pkg/test/logging/doc.go b/vendor/knative.dev/pkg/test/logging/doc.go
deleted file mode 100644
index e76b9cbe9..000000000
--- a/vendor/knative.dev/pkg/test/logging/doc.go
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
-Copyright 2020 The Knative Authors
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-/*
-Package logging assists setting up test logging and using leveled logging in tests.
-
-The TLogger is designed to assist the test writer in creating more useful tests and
-collecting log data in multiple streams, optimizing for human readability in one and
-machine readability in another. It's designed to mimic the testing.T object rather closely and
-use Zap logging semantics, both things already in use in Knative, to minimize the time developers
-need to spend learning the tool.
-
-Inspired by and uses go-logr.
-
-Advantages
-
-The TLogger enhances test design through subtle nudges and affordances:
-
-* It encourages only logging with .V(), giving the writer a nudge to think about how important it is,
-but without requiring them to fit it in a narrowly-defined category.
-
-* Reduces boilerplate of carrying around context for errors in several different variables,
-using .WithValues(), which results in more consistent and reusable code across the tests.
-
-Porting
-
-To port code from using testing.T to logging.TLogger, the interfaces knative.dev/pkg/test.T and
-knative.dev/pkg/test.TLegacy have been created. All library functions should be refactored to use
-one interface and all .Log() calls rewritten to use structured format, which works with testing and
-TLogger. If a library function needs test functions not available even in test.TLegacy,
-it's probably badly written.
-
-Then any test can be incrementally rewritten to use TLogger, as it coexists with testing.T without issue.
-
-*/
-package logging
diff --git a/vendor/knative.dev/pkg/test/logging/error.go b/vendor/knative.dev/pkg/test/logging/error.go
deleted file mode 100644
index 774a60612..000000000
--- a/vendor/knative.dev/pkg/test/logging/error.go
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
-Copyright 2020 The Knative Authors
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package logging
-
-import (
-	"fmt"
-
-	"github.com/davecgh/go-spew/spew"
-)
-
-// StructuredError is an error which can hold arbitrary key-value arguments.
-//
-// TODO(coryrc): The Structured Error is experimental and likely to be removed, but is currently in use in a refactored test.
-type StructuredError interface {
-	error
-	GetValues() []interface{}
-	WithValues(...interface{}) StructuredError
-	DisableValuePrinting()
-	EnableValuePrinting()
-}
-
-type structuredError struct {
-	msg           string
-	keysAndValues []interface{}
-	print         bool
-}
-
-func keysAndValuesToSpewedMap(args ...interface{}) map[string]string {
-	m := make(map[string]string, len(args)/2)
-	for i := 0; i < len(args); i += 2 {
-		key, val := args[i], args[i+1]
-		if keyStr, ok := key.(string); ok {
-			m[keyStr] = spew.Sdump(val)
-		}
-	}
-	return m
-}
-
-// Error implements `error` interface
-func (e structuredError) Error() string {
-	// TODO(coryrc): accept zap.Field entries?
-	if e.print {
-		// %v for fmt.Sprintf does print keys sorted
-		return fmt.Sprintf("Error: %s\nContext:\n%v", e.msg, keysAndValuesToSpewedMap(e.keysAndValues...))
-	}
-	return e.msg
-}
-
-// GetValues gives you the structured key values in a plist
-func (e structuredError) GetValues() []interface{} {
-	return e.keysAndValues
-}
-
-// DisableValuePrinting disables printing out the keys and values from the Error() method
-func (e *structuredError) DisableValuePrinting() {
-	e.print = false
-}
-
-// EnableValuePrinting enables printing out the keys and values from the Error() method
-func (e *structuredError) EnableValuePrinting() {
-	e.print = true
-}
-
-// Create a StructuredError. Gives a little better logging when given to a TLogger.
-// This may prove to not be useful if users use the logger's WithValues() better.
-func Error(msg string, keysAndValues ...interface{}) error {
-	return &structuredError{msg, keysAndValues, true}
-}
-
-// WithValues operates just like TLogger's WithValues but stores them in the error object.
-func (e *structuredError) WithValues(keysAndValues ...interface{}) StructuredError {
-	newKAV := make([]interface{}, 0, len(keysAndValues)+len(e.keysAndValues))
-	newKAV = append(newKAV, e.keysAndValues...)
-	newKAV = append(newKAV, keysAndValues...)
-	return &structuredError{e.msg, newKAV, e.print}
-}
diff --git a/vendor/knative.dev/pkg/test/logging/logger.go b/vendor/knative.dev/pkg/test/logging/logger.go
deleted file mode 100644
index b8f3e4a71..000000000
--- a/vendor/knative.dev/pkg/test/logging/logger.go
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright 2020 The Knative Authors
-// Copyright (c) 2017 Uber Technologies, Inc.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-// Copying testingWriter from zaptest and allowing it to be disabled
-
-package logging
-
-import (
-	"bytes"
-	"errors"
-	"testing"
-)
-
-// testingWriter is a WriteSyncer that writes to the given testing.TB.
-type testingWriter struct {
-	t *testing.T
-
-	// If true, the test will be marked as failed if this testingWriter is
-	// ever used.
-	markFailed bool
-}
-
-func newTestingWriter(t *testing.T) testingWriter {
-	return testingWriter{t: t}
-}
-
-// WithMarkFailed returns a copy of this testingWriter with markFailed set to
-// the provided value.
-func (w testingWriter) WithMarkFailed(v bool) testingWriter {
-	w.markFailed = v
-	return w
-}
-
-func (w testingWriter) Write(p []byte) (n int, err error) {
-	if w.t == nil {
-		return 0, errors.New("Write to buffer after test function completed")
-	}
-	n = len(p)
-
-	// Strip trailing newline because t.Log always adds one.
-	p = bytes.TrimRight(p, "\n")
-
-	// Note: t.Log is safe for concurrent use.
-	w.t.Logf("%s", p)
-	if w.markFailed {
-		w.t.Fail()
-	}
-
-	return n, nil
-}
-
-func (w testingWriter) Sync() error {
-	return nil
-}
-
-func (w *testingWriter) Disable() {
-	w.t = nil
-}
diff --git a/vendor/knative.dev/pkg/test/logging/memory_encoder.go b/vendor/knative.dev/pkg/test/logging/memory_encoder.go
deleted file mode 100644
index 248046b62..000000000
--- a/vendor/knative.dev/pkg/test/logging/memory_encoder.go
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright 2020 The Knative Authors
-// Copyright (c) 2016 Uber Technologies, Inc.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-package logging
-
-import (
-	"time"
-
-	"go.uber.org/zap/zapcore"
-)
-
-// sliceArrayEncoder is an ArrayEncoder backed by a simple []interface{}. Like
-// the MapObjectEncoder, it's not designed for production use.
-type sliceArrayEncoder struct {
-	elems []interface{}
-}
-
-func (s *sliceArrayEncoder) AppendArray(v zapcore.ArrayMarshaler) error {
-	enc := &sliceArrayEncoder{}
-	err := v.MarshalLogArray(enc)
-	s.elems = append(s.elems, enc.elems)
-	return err
-}
-
-func (s *sliceArrayEncoder) AppendObject(v zapcore.ObjectMarshaler) error {
-	m := zapcore.NewMapObjectEncoder()
-	err := v.MarshalLogObject(m)
-	s.elems = append(s.elems, m.Fields)
-	return err
-}
-
-func (s *sliceArrayEncoder) AppendReflected(v interface{}) error {
-	s.elems = append(s.elems, v)
-	return nil
-}
-
-func (s *sliceArrayEncoder) AppendBool(v bool)              { s.elems = append(s.elems, v) }
-func (s *sliceArrayEncoder) AppendByteString(v []byte)      { s.elems = append(s.elems, v) }
-func (s *sliceArrayEncoder) AppendComplex128(v complex128)  { s.elems = append(s.elems, v) }
-func (s *sliceArrayEncoder) AppendComplex64(v complex64)    { s.elems = append(s.elems, v) }
-func (s *sliceArrayEncoder) AppendDuration(v time.Duration) { s.elems = append(s.elems, v) }
-func (s *sliceArrayEncoder) AppendFloat64(v float64)        { s.elems = append(s.elems, v) }
-func (s *sliceArrayEncoder) AppendFloat32(v float32)        { s.elems = append(s.elems, v) }
-func (s *sliceArrayEncoder) AppendInt(v int)                { s.elems = append(s.elems, v) }
-func (s *sliceArrayEncoder) AppendInt64(v int64)            { s.elems = append(s.elems, v) }
-func (s *sliceArrayEncoder) AppendInt32(v int32)            { s.elems = append(s.elems, v) }
-func (s *sliceArrayEncoder) AppendInt16(v int16)            { s.elems = append(s.elems, v) }
-func (s *sliceArrayEncoder) AppendInt8(v int8)              { s.elems = append(s.elems, v) }
-func (s *sliceArrayEncoder) AppendString(v string)          { s.elems = append(s.elems, v) }
-func (s *sliceArrayEncoder) AppendTime(v time.Time)         { s.elems = append(s.elems, v) }
-func (s *sliceArrayEncoder) AppendUint(v uint)              { s.elems = append(s.elems, v) }
-func (s *sliceArrayEncoder) AppendUint64(v uint64)          { s.elems = append(s.elems, v) }
-func (s *sliceArrayEncoder) AppendUint32(v uint32)          { s.elems = append(s.elems, v) }
-func (s *sliceArrayEncoder) AppendUint16(v uint16)          { s.elems = append(s.elems, v) }
-func (s *sliceArrayEncoder) AppendUint8(v uint8)            { s.elems = append(s.elems, v) }
-func (s *sliceArrayEncoder) AppendUintptr(v uintptr)        { s.elems = append(s.elems, v) }
diff --git a/vendor/knative.dev/pkg/test/logging/spew_encoder.go b/vendor/knative.dev/pkg/test/logging/spew_encoder.go
deleted file mode 100644
index 38c83c854..000000000
--- a/vendor/knative.dev/pkg/test/logging/spew_encoder.go
+++ /dev/null
@@ -1,196 +0,0 @@
-// Copyright 2020 The Knative Authors
-// Copyright (c) 2016 Uber Technologies, Inc.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-package logging
-
-import (
-	"fmt"
-	"sort"
-	"strings"
-	"sync"
-
-	"go.uber.org/zap"
-	"go.uber.org/zap/buffer"
-	"go.uber.org/zap/zapcore"
-)
-
-var (
-	_pool             = buffer.NewPool()
-	_sliceEncoderPool = sync.Pool{
-		New: func() interface{} {
-			return &sliceArrayEncoder{elems: make([]interface{}, 0, 2)}
-		},
-	}
-)
-
-func init() {
-	zap.RegisterEncoder("spew", func(encoderConfig zapcore.EncoderConfig) (zapcore.Encoder, error) {
-		return NewSpewEncoder(encoderConfig), nil
-	})
-}
-
-// NewSpewEncoder encodes logs using the spew library.
-//
-// The JSON encoder (also used by the console encoder) included in Zap can only print objects that
-// can be serialized to JSON and doesn't print them in the most readable way. This spew encoder is
-// designed to make human-readable log only and get the most information to the user on any data type.
-//
-// Code is mostly from console_encoder.go in zapcore.
-func NewSpewEncoder(cfg zapcore.EncoderConfig) *SpewEncoder {
-	enc := SpewEncoder{}
-	enc.MapObjectEncoder = zapcore.NewMapObjectEncoder()
-	enc.EncoderConfig = &cfg
-	return &enc
-}
-
-// SpewEncoder implements zapcore.Encoder interface
-type SpewEncoder struct {
-	*zapcore.MapObjectEncoder
-	*zapcore.EncoderConfig
-}
-
-// Implements zapcore.Encoder interface
-func (enc *SpewEncoder) Clone() zapcore.Encoder {
-	n := NewSpewEncoder(*(enc.EncoderConfig))
-	for k, v := range enc.Fields {
-		n.Fields[k] = v
-	}
-	return n
-}
-
-func getSliceEncoder() *sliceArrayEncoder {
-	return _sliceEncoderPool.Get().(*sliceArrayEncoder)
-}
-
-func putSliceEncoder(e *sliceArrayEncoder) {
-	e.elems = e.elems[:0]
-	_sliceEncoderPool.Put(e)
-}
-
-// Implements zapcore.Encoder interface.
-func (enc *SpewEncoder) EncodeEntry(ent zapcore.Entry, fields []zapcore.Field) (*buffer.Buffer, error) {
-	line := _pool.Get()
-
-	// Could probably rewrite this portion and remove the copied
-	// memory_encoder.go from this folder
-	arr := getSliceEncoder()
-	defer putSliceEncoder(arr)
-
-	if enc.TimeKey != "" && enc.EncodeTime != nil {
-		enc.EncodeTime(ent.Time, arr)
-	}
-	if enc.LevelKey != "" && enc.EncodeLevel != nil {
-		enc.EncodeLevel(ent.Level, arr)
-	}
-
-	if ent.LoggerName != "" && enc.NameKey != "" {
-		nameEncoder := enc.EncodeName
-
-		if nameEncoder == nil {
-			// Fall back to FullNameEncoder for backward compatibility.
-			nameEncoder = zapcore.FullNameEncoder
-		}
-
-		nameEncoder(ent.LoggerName, arr)
-	}
-	if ent.Caller.Defined && enc.CallerKey != "" && enc.EncodeCaller != nil {
-		enc.EncodeCaller(ent.Caller, arr)
-	}
-	for i := range arr.elems {
-		if i > 0 {
-			line.AppendByte('\t')
-		}
-		fmt.Fprint(line, arr.elems[i])
-	}
-
-	// Add the message itself.
-	if enc.MessageKey != "" {
-		enc.addTabIfNecessary(line)
-		line.AppendString(ent.Message)
-	}
-
-	// Add any structured context.
-	enc.writeContext(line, fields)
-
-	// If there's no stacktrace key, honor that; this allows users to force
-	// single-line output.
-	if ent.Stack != "" && enc.StacktraceKey != "" {
-		line.AppendByte('\n')
-		line.AppendString(ent.Stack)
-	}
-
-	if enc.LineEnding != "" {
-		line.AppendString(enc.LineEnding)
-	} else {
-		line.AppendString(zapcore.DefaultLineEnding)
-	}
-	return line, nil
-}
-
-func (enc *SpewEncoder) writeContext(line *buffer.Buffer, extra []zapcore.Field) {
-	if len(extra) == 0 && len(enc.Fields) == 0 {
-		return
-	}
-
-	// This could probably be more efficient, but .AddTo() is convenient
-
-	context := zapcore.NewMapObjectEncoder()
-	for k, v := range enc.Fields {
-		context.Fields[k] = v
-	}
-	for i := range extra {
-		extra[i].AddTo(context)
-	}
-
-	enc.addTabIfNecessary(line)
-	line.AppendString("\nContext:\n")
-	keys := make([]string, 0, len(context.Fields))
-	for k := range context.Fields {
-		keys = append(keys, k)
-	}
-	sort.Strings(keys)
-	for _, k := range keys {
-		line.AppendString(k)
-		line.AppendString(": ")
-		line.AppendString(stringify(context.Fields[k]))
-		line.TrimNewline()
-		line.AppendString("\n")
-	}
-}
-
-func stringify(a interface{}) string {
-	s, ok := a.(string)
-	if !ok {
-		s = strings.TrimSuffix(spewConfig.Sdump(a), "\n")
-	}
-	ret := strings.ReplaceAll(s, "\n", "\n ")
-	hasNewlines := s != ret
-	if hasNewlines {
-		return "\n " + ret
-	}
-	return s
-}
-
-func (enc *SpewEncoder) addTabIfNecessary(line *buffer.Buffer) {
-	if line.Len() > 0 {
-		line.AppendByte('\t')
-	}
-}
diff --git a/vendor/knative.dev/pkg/test/logging/sugar.go b/vendor/knative.dev/pkg/test/logging/sugar.go
deleted file mode 100644
index 01fc6b29f..000000000
--- a/vendor/knative.dev/pkg/test/logging/sugar.go
+++ /dev/null
@@ -1,114 +0,0 @@
-// Copyright 2020 Knative Authors
-// Copyright (c) 2016 Uber Technologies, Inc.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-package logging
-
-import (
-	"github.com/davecgh/go-spew/spew"
-	"go.uber.org/zap"
-	"go.uber.org/zap/zapcore"
-
-	"go.uber.org/multierr"
-)
-
-const (
-	_oddNumberErrMsg    = "Ignored key without a value."
-	_nonStringKeyErrMsg = "Ignored key-value pairs with non-string keys."
-)
-
-var spewConfig *spew.ConfigState
-
-func init() {
-	spewConfig = spew.NewDefaultConfig()
-	spewConfig.DisableCapacities = true
-	spewConfig.SortKeys = true
-	spewConfig.SpewKeys = true
-	spewConfig.ContinueOnMethod = true
-}
-
-func (o *TLogger) handleFields(args []interface{}) []zap.Field {
-	if len(args) == 0 {
-		return nil
-	}
-	s := o.l.Sugar()
-
-	// Allocate enough space for the worst case; if users pass only structured
-	// fields, we shouldn't penalize them with extra allocations.
-	fields := make([]zap.Field, 0, len(args))
-	var invalid invalidPairs
-
-	for i := 0; i < len(args); {
-		// This is a strongly-typed field. Consume it and move on.
-		if f, ok := args[i].(zap.Field); ok {
-			fields = append(fields, f)
-			i++
-			continue
-		}
-
-		// Make sure this element isn't a dangling key.
-		if i == len(args)-1 {
-			s.DPanic(_oddNumberErrMsg, zap.Any("ignored", args[i]))
-			break
-		}
-
-		// Consume this value and the next, treating them as a key-value pair. If the
-		// key isn't a string, add this pair to the slice of invalid pairs.
-		key, val := args[i], args[i+1]
-		if keyStr, ok := key.(string); !ok {
-			// Subsequent errors are likely, so allocate once up front.
-			if cap(invalid) == 0 {
-				invalid = make(invalidPairs, 0, len(args)/2)
-			}
-			invalid = append(invalid, invalidPair{i, key, val})
-		} else {
-			fields = append(fields, zap.Any(keyStr, val))
-		}
-		i += 2
-	}
-
-	// If we encountered any invalid key-value pairs, log an error.
-	if len(invalid) > 0 {
-		s.DPanic(_nonStringKeyErrMsg, zap.Array("invalid", invalid), zap.String("all_input", spew.Sprintf("%#+v", args)))
-	}
-	return fields
-}
-
-type invalidPair struct {
-	position   int
-	key, value interface{}
-}
-
-func (p invalidPair) MarshalLogObject(enc zapcore.ObjectEncoder) error {
-	enc.AddInt64("position", int64(p.position))
-	zap.Any("key", p.key).AddTo(enc)
-	zap.Any("value", p.value).AddTo(enc)
-	return nil
-}
-
-type invalidPairs []invalidPair
-
-func (ps invalidPairs) MarshalLogArray(enc zapcore.ArrayEncoder) error {
-	var err error
-	for i := range ps {
-		err = multierr.Append(err, enc.AppendObject(ps[i]))
-	}
-	return err
-}
diff --git a/vendor/knative.dev/pkg/test/logging/tlogger.go b/vendor/knative.dev/pkg/test/logging/tlogger.go
deleted file mode 100644
index f6e05c5ce..000000000
--- a/vendor/knative.dev/pkg/test/logging/tlogger.go
+++ /dev/null
@@ -1,372 +0,0 @@
-/*
-Copyright 2020 The Knative Authors
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package logging
-
-import (
-	"errors"
-	"fmt"
-	"testing"
-
-	"github.com/go-logr/logr"
-	"go.uber.org/zap"
-	"go.uber.org/zap/zapcore"
-)
-
-// TLogger is TLogger
-type TLogger struct {
-	l        *zap.Logger
-	level    int
-	t        *testing.T
-	errs     map[string][]interface{} // For Collect()
-	dontFail bool
-}
-
-// V() returns an InfoLogger from go-logr.
-//
-// This should be the main way your tests log.
-// Most frequent usage is used directly:
-//   t.V(2).Info("Something at regular level")
-// But if something computationally difficult is to be done, can do:
-//   if l := t.V(8); l.Enabled() {
-//     x := somethingExpensive()
-//     l.Info("logging it", "expensiveThing", x)
-//   }
-//
-// Elsewhere in this documentation refers to a hypothetical .V(errorLevel) to simplify explanations.
-// The V() function cannot write to the error level; the Error, ErrorIfErr, Fatal, and
-// FatalIfErr methods are the only way to write to the error level.
-func (o *TLogger) V(level int) logr.InfoLogger {
-	// Consider adding || (level <= logrZapDebugLevel && o.l.Core().Enabled(zapLevelFromLogrLevel(level)))
-	// Reason to add it is even if you ask for verbosity=1, in case of error you'll get up to verbosity=3 in the debug output
-	// but since zapTest uses Debug, you always get V(<=3) even when verbosity < 3
-	// Probable solution is to write to t.Log at Info level?
-	if level <= o.level {
-		return &infoLogger{
-			logrLevel: o.level,
-			t:         o,
-		}
-	}
-	return disabledInfoLogger
-}
-
-// WithValues() acts like Zap's With() method.
-// Consistent with logr.Logger.WithValues()
-// Whenever anything is logged with the returned TLogger,
-// it will act as if these keys and values were passed into every logging call.
-func (o *TLogger) WithValues(keysAndValues ...interface{}) *TLogger {
-	return o.cloneWithNewLogger(o.l.With(o.handleFields(keysAndValues)...))
-}
-
-// WithName() acts like Zap's Named() method.
-// Consistent with logr.Logger.WithName()
-// Appends the name onto the current logger
-func (o *TLogger) WithName(name string) *TLogger {
-	return o.cloneWithNewLogger(o.l.Named(name))
-}
-
-// Custom additions:
-
-// ErrorIfErr fails the current test if the err != nil.
-// Remaining arguments function as if passed to .V(errorLevel).Info() (were that a thing)
-// Same signature as logr.Logger.Error() method, but as this is a test, it functions slightly differently.
-func (o *TLogger) ErrorIfErr(err error, msg string, keysAndValues ...interface{}) {
-	if err != nil {
-		o.error(err, msg, keysAndValues)
-		o.fail()
-	}
-}
-
-// FatalIfErr is just like ErrorIfErr() but test execution stops immediately
-func (o *TLogger) FatalIfErr(err error, msg string, keysAndValues ...interface{}) {
-	if err != nil {
-		o.error(err, msg, keysAndValues)
-		o.failNow()
-	}
-}
-
-// Error is essentially a .V(errorLevel).Info() followed by failing the test.
-// Intended usage is Error(msg string, key-value alternating arguments)
-// Same effect as testing.T.Error
-// Generic definition for compatibility with test.T interface
-// Implements test.T
-func (o *TLogger) Error(stringThenKeysAndValues ...interface{}) {
-	// Using o.error to have consistent call depth for Error, FatalIfErr, Info, etc
-	o.error(o.errorWithRuntimeCheck(stringThenKeysAndValues...))
-	o.fail()
-}
-
-// Fatal is essentially a .V(errorLevel).Info() followed by failing and immediately stopping the test.
-// Intended usage is Fatal(msg string, key-value alternating arguments)
-// Same effect as testing.T.Fatal
-// Generic definition for compatibility with test.TLegacy interface
-// Implements test.TLegacy
-func (o *TLogger) Fatal(stringThenKeysAndValues ...interface{}) {
-	o.error(o.errorWithRuntimeCheck(stringThenKeysAndValues...))
-	o.failNow()
-}
-
-func (o *TLogger) fail() {
-	if o.t != nil && !o.dontFail {
-		o.t.Fail()
-	}
-}
-
-func (o *TLogger) failNow() {
-	if o.t != nil && !o.dontFail {
-		o.t.FailNow()
-	}
-}
-
-func validateKeysAndValues(keysAndValues ...interface{}) bool {
-	length := len(keysAndValues)
-	for i := 0; i < length; {
-		_, isField := keysAndValues[i].(zapcore.Field)
-		_, isString := keysAndValues[i].(string)
-		if isField {
-			i++
-		} else if isString {
-			if i == length-1 {
-				return false
-			}
-			i += 2
-		} else {
-			return false
-		}
-	}
-	return true
-}
-
-func (o *TLogger) interfacesToFields(things ...interface{}) []interface{} {
-	o.V(5).Info("DEPRECATED Error/Fatal usage", zap.Stack("callstack"))
-	fields := make([]interface{}, 2*len(things))
-	for i, d := range things {
-		fields[i*2] = fmt.Sprintf("arg %d", i)
-		fields[i*2+1] = d
-	}
-	return fields
-}
-
-func (o *TLogger) errorWithRuntimeCheck(stringThenKeysAndValues ...interface{}) (error, string, []interface{}) { //nolint // Returning the error first is okay and expected here.
-	if len(stringThenKeysAndValues) == 0 {
-		return nil, "", nil
-	}
-	s, isString := stringThenKeysAndValues[0].(string)
-	if isString {
-		// Desired case (hopefully)
-		remainder := stringThenKeysAndValues[1:]
-		if !validateKeysAndValues(remainder...) {
-			remainder = o.interfacesToFields(remainder...)
-		}
-		return nil, s, remainder
-	}
-	e, isError := stringThenKeysAndValues[0].(error)
-	if isError && len(stringThenKeysAndValues) == 1 {
-		return e, "", nil
-	}
-	return nil, "unstructured error", o.interfacesToFields(stringThenKeysAndValues...)
-}
-
-// Cleanup registers a cleanup callback.
-func (o *TLogger) Cleanup(c func()) {
-	o.t.Cleanup(c)
-}
-
-// Run a subtest. Just like testing.T.Run but creates a TLogger.
-func (o *TLogger) Run(name string, f func(t *TLogger)) {
-	tfunc := func(ts *testing.T) {
-		tl, cancel := newTLogger(ts, o.level, o.dontFail)
-		defer cancel()
-		f(tl)
-	}
-	o.t.Run(name, tfunc)
-}
-
-// Name is just like testing.T.Name()
-// Implements test.T
-func (o *TLogger) Name() string {
-	return o.t.Name()
-}
-
-// Helper cannot work as an indirect call, so just do nothing :(
-// Implements test.T
-func (o *TLogger) Helper() {
-}
-
-// SkipNow immediately stops test execution
-// Implements test.T
-func (o *TLogger) SkipNow() {
-	o.t.SkipNow()
-}
-
-// Log is deprecated: only existing for test.T compatibility
-// Please use leveled logging via .V().Info()
-// Will panic if given data incompatible with Info() function
-// Implements test.T
-func (o *TLogger) Log(args ...interface{}) {
-	// This is complicated to ensure exactly 2 levels of indirection
-	i := o.V(2)
-	iL, ok := i.(*infoLogger)
-	if ok {
-		iL.indirectWrite(args[0].(string), args[1:]...)
-	}
-}
-
-// Parallel allows tests or subtests to run in parallel
-// Just calls the testing.T.Parallel() under the hood
-func (o *TLogger) Parallel() {
-	o.t.Parallel()
-}
-
-// Logf is deprecated: only existing for test.TLegacy compatibility
-// Please use leveled logging via .V().Info()
-// Implements test.TLegacy
-func (o *TLogger) Logf(fmtS string, args ...interface{}) {
-	// This is complicated to ensure exactly 2 levels of indirection
-	iL, ok := o.V(2).(*infoLogger)
-	if ok {
-		iL.indirectWrite(fmt.Sprintf(fmtS, args...))
-	}
-}
-
-func (o *TLogger) error(err error, msg string, keysAndValues []interface{}) {
-	var newKAV []interface{}
-	var serr StructuredError
-	if errors.As(err, &serr) {
-		serr.DisableValuePrinting()
-		defer serr.EnableValuePrinting()
-		newLen := len(keysAndValues) + len(serr.GetValues())
-		newKAV = make([]interface{}, 0, newLen+2)
-		newKAV = append(newKAV, keysAndValues...)
-		newKAV = append(newKAV, serr.GetValues()...)
-	}
-	if err != nil {
-		if msg == "" { // This is used if just the error is given to .Error() or .Fatal()
-			msg = err.Error()
-		} else {
-			if newKAV == nil {
-				newKAV = make([]interface{}, 0, len(keysAndValues)+1)
-				newKAV = append(newKAV, keysAndValues...)
-			}
-			newKAV = append(newKAV, zap.Error(err))
-		}
-	}
-	if newKAV != nil {
-		keysAndValues = newKAV
-	}
-	if checkedEntry := o.l.Check(zap.ErrorLevel, msg); checkedEntry != nil {
-		checkedEntry.Write(o.handleFields(keysAndValues)...)
-	}
-}
-
-// Creation and Teardown
-
-// Create a TLogger object using the global Zap logger and the current testing.T
-// `defer` a call to second return value immediately after.
-func NewTLogger(t *testing.T) (*TLogger, func()) {
-	return newTLogger(t, verbosity, false)
-}
-
-func newTLogger(t *testing.T, verbosity int, dontFail bool) (*TLogger, func()) {
-	testOptions := []zap.Option{
-		zap.AddCaller(),
-		zap.AddCallerSkip(2),
-		zap.Development(),
-	}
-	writer := newTestingWriter(t)
-	// Based off zap.NewDevelopmentEncoderConfig()
-	cfg := zapcore.EncoderConfig{
-		// Wanted keys can be anything except the empty string.
-		TimeKey:        "",
-		LevelKey:       "",
-		NameKey:        "",
-		CallerKey:      "C",
-		MessageKey:     "M",
-		StacktraceKey:  "S",
-		LineEnding:     zapcore.DefaultLineEnding,
-		EncodeLevel:    zapcore.CapitalLevelEncoder,
-		EncodeTime:     zapcore.ISO8601TimeEncoder,
-		EncodeDuration: zapcore.StringDurationEncoder,
-		EncodeCaller:   zapcore.ShortCallerEncoder,
-	}
-	core := zapcore.NewCore(
-		NewSpewEncoder(cfg),
-		writer,
-		zapcore.DebugLevel,
-	)
-	if zapCore != nil {
-		core = zapcore.NewTee(
-			zapCore,
-			core,
-			// TODO(coryrc): Open new file (maybe creating JUnit!?) with test output?
-		)
-	}
-	log := zap.New(core, testOptions...).Named(t.Name())
-	tlogger := TLogger{
-		l:        log,
-		level:    verbosity,
-		t:        t,
-		errs:     make(map[string][]interface{}),
-		dontFail: dontFail,
-	}
-	return &tlogger, func() {
-		tlogger.handleCollectedErrors()
-		// Sometimes goroutines exist after a test and they cause panics if they attempt to call t.Log().
-		// Prevent this panic by disabling writes to the testing.T (we'll still get them everywhere else).
-		writer.Disable()
-	}
-}
-
-func (o *TLogger) cloneWithNewLogger(l *zap.Logger) *TLogger {
-	t := TLogger{
-		l:        l,
-		level:    o.level,
-		t:        o.t,
-		errs:     o.errs,
-		dontFail: o.dontFail,
-	}
-	return &t
-}
-
-// Collect allows you to commingle multiple validations during one test execution.
-// Under the hood, it creates a sub-test during cleanup and iterates through the collected values, printing them.
-// If any are errors, it fails the subtest.
-// Currently experimental and likely to be removed
-func (o *TLogger) Collect(key string, value interface{}) {
-	list, hasKey := o.errs[key]
-	if hasKey {
-		list = append(list, value)
-	} else {
-		list = make([]interface{}, 1)
-		list[0] = value
-	}
-	o.errs[key] = list
-}
-
-func (o *TLogger) handleCollectedErrors() {
-	for name, list := range o.errs {
-		o.Run(name, func(t *TLogger) {
-			for _, item := range list {
-				_, isError := item.(error)
-				if isError {
-					t.Error(item)
-				} else {
-					t.V(3).Info(spewConfig.Sprint(item))
-				}
-			}
-		})
-	}
-}
diff --git a/vendor/knative.dev/pkg/test/logging/zapr.go b/vendor/knative.dev/pkg/test/logging/zapr.go
deleted file mode 100644
index c0b9f5858..000000000
--- a/vendor/knative.dev/pkg/test/logging/zapr.go
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2020 Knative Authors
-// Copyright 2018 Solly Ross
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// The useful parts of this file have been preserved
-// from their origin at https://github.com/go-logr/zapr/tree/8f2487342d52a33a1793e50e3ca04bc1767aa65c
-
-package logging
-
-// noopInfoLogger is a logr.InfoLogger that's always disabled, and does nothing.
-type noopInfoLogger struct{}
-
-func (l *noopInfoLogger) Enabled() bool                   { return false }
-func (l *noopInfoLogger) Info(_ string, _ ...interface{}) {}
-
-var disabledInfoLogger = &noopInfoLogger{}
-
-// infoLogger is a logr.InfoLogger that uses Zap to log at a particular
-// level.
-type infoLogger struct {
-	logrLevel int
-	t         *TLogger
-}
-
-func (i *infoLogger) Enabled() bool { return true }
-func (i *infoLogger) Info(msg string, keysAndVals ...interface{}) {
-	i.indirectWrite(msg, keysAndVals...)
-}
-
-// This function just exists to have consistent 2-level call depth for Zap proxying
-func (i *infoLogger) indirectWrite(msg string, keysAndVals ...interface{}) {
-	lvl := zapLevelFromLogrLevel(i.logrLevel)
-	if checkedEntry := i.t.l.Check(lvl, msg); checkedEntry != nil {
-		checkedEntry.Write(i.t.handleFields(keysAndVals)...)
-	}
-}