Repository: knative/serving
Pull request #9953 (2020-10-27 15:50:40)

add Traffic fields to the Service Schema
Related to #912 

## Proposed Changes

* This adds just the Traffic section to the Service schema. 

**Release Note**

```release-note
Updated the Service schema to include the Traffic fields.
```

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

This pull-request has been approved by: *<a href="https://github.com/knative/serving/pull/9953#" title="Author self-approved">joshuawilson</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:

- **[config/OWNERS](https://github.com/knative/serving/blob/master/config/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/9953?src=pr&el=h1) Report
> Merging [#9953](https://codecov.io/gh/knative/serving/pull/9953?src=pr&el=desc) into [master](https://codecov.io/gh/knative/serving/commit/3e6dae5dbf9d773d9987474e0cbc540dd6062aa0?el=desc) will **increase** coverage by `0.02%`.
> The diff coverage is `n/a`.

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

```diff
@@            Coverage Diff             @@
##           master    #9953      +/-   ##
==========================================
+ Coverage   87.78%   87.81%   +0.02%     
==========================================
  Files         183      183              
  Lines        8631     8631              
==========================================
+ Hits         7577     7579       +2     
+ Misses        802      801       -1     
+ Partials      252      251       -1     
```


| [Impacted Files](https://codecov.io/gh/knative/serving/pull/9953?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [pkg/reconciler/autoscaling/kpa/scaler.go](https://codecov.io/gh/knative/serving/pull/9953/diff?src=pr&el=tree#diff-cGtnL3JlY29uY2lsZXIvYXV0b3NjYWxpbmcva3BhL3NjYWxlci5nbw==) | `90.00% <0.00%> (+1.42%)` | :arrow_up: |

------

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

dprotaso: /assign @dprotaso 
joshuawilson: /retest
knative-prow-robot: [APPROVALNOTIFIER] This PR is **NOT APPROVED**

This pull-request has been approved by: *<a href="https://github.com/knative/serving/pull/9953#" title="Author self-approved">joshuawilson</a>*
To complete the [pull request process](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process), please assign **dprotaso** after the PR has been reviewed.
You can assign the PR to them by writing `/assign @dprotaso` in a comment when ready.

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

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

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

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":["dprotaso"]} -->

Patch:
diff --git a/.github/workflows/knative-releasability.yaml b/.github/workflows/knative-releasability.yaml
index fd934ab75..e3e928013 100644
--- a/.github/workflows/knative-releasability.yaml
+++ b/.github/workflows/knative-releasability.yaml
@@ -36,8 +36,8 @@ jobs:
     env:
       #########################################
       #   Update this section each release.   #
-      RELEASE: 'v0.18'
-      SLACK_CHANNEL: 'release-18'
+      RELEASE: 'v0.19'
+      SLACK_CHANNEL: 'release-19'
       #########################################
 
     steps:
diff --git a/.github/workflows/knative-style.yaml b/.github/workflows/knative-style.yaml
index 116c5a13a..a57a71a23 100644
--- a/.github/workflows/knative-style.yaml
+++ b/.github/workflows/knative-style.yaml
@@ -121,7 +121,7 @@ jobs:
         if: steps.golangci_configuration.outputs.files_exists == 'true'
         uses: golangci/golangci-lint-action@v2
         with:
-          version: v1.30
+          version: v1.32
 
       - name: misspell
         shell: bash
diff --git a/.golangci.yaml b/.golangci.yaml
index 5b3f3737c..7f73e1adf 100644
--- a/.golangci.yaml
+++ b/.golangci.yaml
@@ -19,10 +19,12 @@ run:
 linters:
   enable:
     - asciicheck
+    - errorlint
     - golint
     - gosec
     - prealloc
     - stylecheck
+    - tparallel
     - unconvert
     - unparam
   disable:
diff --git a/cmd/activator/main.go b/cmd/activator/main.go
index 51e5009fc..475667fb2 100644
--- a/cmd/activator/main.go
+++ b/cmd/activator/main.go
@@ -219,7 +219,7 @@ func main() {
 	for name, server := range servers {
 		go func(name string, s *http.Server) {
 			// Don't forward ErrServerClosed as that indicates we're already shutting down.
-			if err := s.ListenAndServe(); err != nil && err != http.ErrServerClosed {
+			if err := s.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
 				errCh <- fmt.Errorf("%s server failed: %w", name, err)
 			}
 		}(name, server)
diff --git a/cmd/autoscaler/main.go b/cmd/autoscaler/main.go
index a99d58d8c..e29936703 100644
--- a/cmd/autoscaler/main.go
+++ b/cmd/autoscaler/main.go
@@ -19,6 +19,7 @@ package main
 
 import (
 	"context"
+	"errors"
 	"fmt"
 	"log"
 	"net/http"
@@ -182,7 +183,7 @@ func main() {
 	statsServer.Shutdown(5 * time.Second)
 	profilingServer.Shutdown(context.Background())
 	// Don't forward ErrServerClosed as that indicates we're already shutting down.
-	if err := eg.Wait(); err != nil && err != http.ErrServerClosed {
+	if err := eg.Wait(); err != nil && !errors.Is(err, http.ErrServerClosed) {
 		logger.Errorw("Error while running server", zap.Error(err))
 	}
 }
diff --git a/cmd/queue/main.go b/cmd/queue/main.go
index 205bf2729..d6bc76446 100644
--- a/cmd/queue/main.go
+++ b/cmd/queue/main.go
@@ -18,6 +18,7 @@ package main
 
 import (
 	"context"
+	"errors"
 	"flag"
 	"fmt"
 	"net"
@@ -25,7 +26,6 @@ import (
 	"net/http/httputil"
 	"net/url"
 	"os"
-	"path/filepath"
 	"strconv"
 	"time"
 
@@ -63,7 +63,9 @@ const (
 
 var (
 	readinessProbeTimeout = flag.Duration("probe-period", -1, "run readiness probe with given timeout")
-	unixSocketPath        = filepath.Join(os.TempDir(), "queue.sock")
+
+	// This creates an abstract socket instead of an actual file.
+	unixSocketPath = "@/knative.dev/serving/queue.sock"
 )
 
 type config struct {
@@ -194,7 +196,7 @@ func main() {
 			}
 
 			// Don't forward ErrServerClosed as that indicates we're already shutting down.
-			if err := s.Serve(l); err != nil && err != http.ErrServerClosed {
+			if err := s.Serve(l); err != nil && !errors.Is(err, http.ErrServerClosed) {
 				errCh <- fmt.Errorf("%s server failed to serve: %w", name, err)
 			}
 		}(name, server)
diff --git a/config/core/300-resources/service.yaml b/config/core/300-resources/service.yaml
index e9045badb..c8c81ba78 100644
--- a/config/core/300-resources/service.yaml
+++ b/config/core/300-resources/service.yaml
@@ -58,6 +58,44 @@ spec:
                 items:
                   type: object
                   x-kubernetes-preserve-unknown-fields: true
+                  properties:
+                    revisionName:
+                      type: string
+                      description: |
+                        A specific revision to which to send this portion
+                        of traffic.
+                        This is mutually exclusive with configurationName.
+                    configurationName:
+                      type: string
+                      description: |
+                        ConfigurationName of a configuration to whose latest revision we will send
+                        this portion of traffic. When the "status.latestReadyRevisionName" of the
+                        referenced configuration changes, we will automatically migrate traffic
+                        from the prior "latest ready" revision to the new one.  This field is never
+                        set in Route's status, only its spec.
+                        This is mutually exclusive with RevisionName.
+                    latestRevision:
+                      type: boolean
+                      description: |
+                        `latestRevision` may be optionally provided to indicate
+                        that the latest ready Revision of the Configuration should be used
+                        for this traffic target. When provided latestRevision MUST be true
+                        if revisionName is empty, and it MUST be false when revisionName is non-empty.
+                    tag:
+                      type: string
+                      description: |
+                        Tag is optionally used to expose a dedicated URL for
+                        referencing this target exclusively. The dedicated URL MUST include
+                        in it the string provided by tag.
+                    percent:
+                      type: integer
+                      description: |
+                        The percentage of requests which should be allocated
+                        from the main Route domain name to the specified `revisionName` or
+                        `configurationName`.
+                        All `percent` values in `traffic` MUST sum to 100.
+                      minimum: 0
+                      maximum: 100
           status:
             type: object
             x-kubernetes-preserve-unknown-fields: true
diff --git a/config/core/deployments/activator.yaml b/config/core/deployments/activator.yaml
index 4afde6e31..073cdd102 100644
--- a/config/core/deployments/activator.yaml
+++ b/config/core/deployments/activator.yaml
@@ -78,6 +78,9 @@ spec:
           allowPrivilegeEscalation: false
           readOnlyRootFilesystem: true
           runAsNonRoot: true
+          capabilities:
+            drop:
+            - all
 
         ports:
         - name: metrics
diff --git a/config/core/deployments/autoscaler.yaml b/config/core/deployments/autoscaler.yaml
index 5c3678cf7..f17c5948c 100644
--- a/config/core/deployments/autoscaler.yaml
+++ b/config/core/deployments/autoscaler.yaml
@@ -83,6 +83,9 @@ spec:
           allowPrivilegeEscalation: false
           readOnlyRootFilesystem: true
           runAsNonRoot: true
+          capabilities:
+            drop:
+            - all
 
         ports:
         - name: metrics
diff --git a/config/core/deployments/controller.yaml b/config/core/deployments/controller.yaml
index 44eef0d5e..70d6ca82a 100644
--- a/config/core/deployments/controller.yaml
+++ b/config/core/deployments/controller.yaml
@@ -79,6 +79,9 @@ spec:
           allowPrivilegeEscalation: false
           readOnlyRootFilesystem: true
           runAsNonRoot: true
+          capabilities:
+            drop:
+            - all
 
         ports:
         - name: metrics
diff --git a/config/core/deployments/webhook.yaml b/config/core/deployments/webhook.yaml
index 5ee2b40f5..bfda2d924 100644
--- a/config/core/deployments/webhook.yaml
+++ b/config/core/deployments/webhook.yaml
@@ -83,6 +83,9 @@ spec:
           allowPrivilegeEscalation: false
           readOnlyRootFilesystem: true
           runAsNonRoot: true
+          capabilities:
+            drop:
+            - all
 
         ports:
         - name: metrics
diff --git a/config/domain-mapping/controller.yaml b/config/domain-mapping/controller.yaml
index ecb838983..cf91f35ad 100644
--- a/config/domain-mapping/controller.yaml
+++ b/config/domain-mapping/controller.yaml
@@ -73,6 +73,11 @@ spec:
 
         securityContext:
           allowPrivilegeEscalation: false
+          readOnlyRootFilesystem: true
+          runAsNonRoot: true
+          capabilities:
+            drop:
+            - all
 
         ports:
         - name: metrics
diff --git a/config/hpa-autoscaling/controller.yaml b/config/hpa-autoscaling/controller.yaml
index b1c69be94..5bf80cc51 100644
--- a/config/hpa-autoscaling/controller.yaml
+++ b/config/hpa-autoscaling/controller.yaml
@@ -74,6 +74,11 @@ spec:
 
         securityContext:
           allowPrivilegeEscalation: false
+          readOnlyRootFilesystem: true
+          runAsNonRoot: true
+          capabilities:
+            drop:
+            - all
 
         ports:
         - name: metrics
diff --git a/config/namespace-wildcard-certs/controller.yaml b/config/namespace-wildcard-certs/controller.yaml
index f28e8cd30..721f54320 100644
--- a/config/namespace-wildcard-certs/controller.yaml
+++ b/config/namespace-wildcard-certs/controller.yaml
@@ -74,6 +74,11 @@ spec:
 
         securityContext:
           allowPrivilegeEscalation: false
+          readOnlyRootFilesystem: true
+          runAsNonRoot: true
+          capabilities:
+            drop:
+            - all
 
         ports:
         - name: metrics
diff --git a/go.mod b/go.mod
index 4d7519bcc..803e7c296 100644
--- a/go.mod
+++ b/go.mod
@@ -20,6 +20,7 @@ require (
 	go.opencensus.io v0.22.5
 	go.uber.org/atomic v1.7.0
 	go.uber.org/automaxprocs v1.3.0
+	go.uber.org/goleak v1.1.10
 	go.uber.org/zap v1.16.0
 	golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43
 	golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9
@@ -31,10 +32,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-20201027231233-cc1d9d2e090f
-	knative.dev/hack v0.0.0-20201027221733-0d7f2f064b7b
-	knative.dev/networking v0.0.0-20201027230234-f0e013a2a1e2
-	knative.dev/pkg v0.0.0-20201028121234-58d43f05028e
+	knative.dev/caching v0.0.0-20201029165635-7983fcd03d68
+	knative.dev/hack v0.0.0-20201028205534-fe80f1c8af68
+	knative.dev/networking v0.0.0-20201029132834-0fb5d8bc0634
+	knative.dev/pkg v0.0.0-20201030122234-256ae893994a
 )
 
 replace (
diff --git a/go.sum b/go.sum
index fcafcb412..eddbe9910 100644
--- a/go.sum
+++ b/go.sum
@@ -63,10 +63,12 @@ contrib.go.opencensus.io/exporter/stackdriver v0.12.1/go.mod h1:iwB6wGarfphGGe/e
 contrib.go.opencensus.io/exporter/stackdriver v0.12.8/go.mod h1:XyyafDnFOsqoxHJgTFycKZMrRUrPThLh2iYTJF6uoO0=
 contrib.go.opencensus.io/exporter/stackdriver v0.12.9-0.20191108183826-59d068f8d8ff/go.mod h1:XyyafDnFOsqoxHJgTFycKZMrRUrPThLh2iYTJF6uoO0=
 contrib.go.opencensus.io/exporter/stackdriver v0.13.1/go.mod h1:z2tyTZtPmQ2HvWH4cOmVDgtY+1lomfKdbLnkJvZdc8c=
-contrib.go.opencensus.io/exporter/stackdriver v0.13.2 h1:5lKLBwUuq4S6pTbYaBtWmnay3eJfKNS3qL8M8HM5fM4=
-contrib.go.opencensus.io/exporter/stackdriver v0.13.2/go.mod h1:aXENhDJ1Y4lIg4EUaVTwzvYETVNZk10Pu26tevFKLUc=
+contrib.go.opencensus.io/exporter/stackdriver v0.13.4 h1:ksUxwH3OD5sxkjzEqGxNTl+Xjsmu3BnC/300MhSVTSc=
+contrib.go.opencensus.io/exporter/stackdriver v0.13.4/go.mod h1:aXENhDJ1Y4lIg4EUaVTwzvYETVNZk10Pu26tevFKLUc=
 contrib.go.opencensus.io/exporter/zipkin v0.1.1 h1:PR+1zWqY8ceXs1qDQQIlgXe+sdiwCf0n32bH4+Epk8g=
 contrib.go.opencensus.io/exporter/zipkin v0.1.1/go.mod h1:GMvdSl3eJ2gapOaLKzTKE3qDgUkJ86k9k3yY2eqwkzc=
+contrib.go.opencensus.io/exporter/zipkin v0.1.2 h1:YqE293IZrKtqPnpwDPH/lOqTWD/s3Iwabycam74JV3g=
+contrib.go.opencensus.io/exporter/zipkin v0.1.2/go.mod h1:mP5xM3rrgOjpn79MM8fZbj3gsxcuytSqtH0dxSWW1RE=
 contrib.go.opencensus.io/integrations/ocsql v0.1.4/go.mod h1:8DsSdjz3F+APR+0z0WkU1aRorQCFfRxvqjUUPMbF3fE=
 contrib.go.opencensus.io/resource v0.1.1/go.mod h1:F361eGI91LCmW1I/Saf+rX0+OFcigGlFvXwEGEnkRLA=
 dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
@@ -1001,6 +1003,8 @@ github.com/openzipkin/zipkin-go v0.2.0/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnh
 github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
 github.com/openzipkin/zipkin-go v0.2.2 h1:nY8Hti+WKaP0cRsSeQ026wU03QsM762XBeCXBb9NAWI=
 github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
+github.com/openzipkin/zipkin-go v0.2.5 h1:UwtQQx2pyPIgWYHRg+epgdx1/HnBQTgN3/oIYEJTQzU=
+github.com/openzipkin/zipkin-go v0.2.5/go.mod h1:KpXfKdgRDnnhsxw4pNIH9Md5lyFqKUa4YDFlwRYAMyE=
 github.com/otiai10/copy v1.0.2/go.mod h1:c7RpqBkwMom4bYTSkLSym4VSJz/XtncWRAj/J4PEIMY=
 github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE=
 github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo=
@@ -1299,11 +1303,15 @@ go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
 go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
 go.uber.org/automaxprocs v1.3.0 h1:II28aZoGdaglS5vVNnspf28lnZpXScxtIozx1lAjdb0=
 go.uber.org/automaxprocs v1.3.0/go.mod h1:9CWT6lKIep8U41DDaPiH6eFscnTyjfTANNQNx6LrIcA=
+go.uber.org/goleak v1.1.10 h1:z+mqJhf6ss6BSfSM671tgKyZBFPTTJM+HLxnhPC3wu0=
+go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
 go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
 go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
 go.uber.org/multierr v1.4.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
 go.uber.org/multierr v1.5.0 h1:KCa4XfM8CWFCpxXRGok+Q0SS/0XBhMDbHHGABQLvD2A=
 go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
+go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
+go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
 go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4=
 go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
 go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
@@ -1536,7 +1544,6 @@ golang.org/x/sys v0.0.0-20200610111108-226ff32320da/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200828194041-157a740278f4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f h1:Fqb3ao1hUmOR3GkUOg/Y+BadLwykBIzs5q8Ez2SbHyc=
 golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211 h1:9UQO31fZ+0aKQOFldThf7BKPMJTiBfWycGh/u3UoO88=
@@ -1649,7 +1656,6 @@ golang.org/x/tools v0.0.0-20200709181711-e327e1019dfe/go.mod h1:njjCfa9FT2d7l9Bc
 golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
 golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
 golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
-golang.org/x/tools v0.0.0-20200828161849-5deb26317202/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
 golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
 golang.org/x/tools v0.0.0-20200916195026-c9a70fc28ce3 h1:DywqrEscRX7O2phNjkT0L6lhHKGBoMLCNX+XcAe7t6s=
 golang.org/x/tools v0.0.0-20200916195026-c9a70fc28ce3/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
@@ -1691,8 +1697,6 @@ google.golang.org/api v0.26.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0M
 google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
 google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
 google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
-google.golang.org/api v0.31.0 h1:1w5Sz/puhxFo9lTtip2n47k7toB/U2nCqOKNHd3Yrbo=
-google.golang.org/api v0.31.0/go.mod h1:CL+9IBCa2WWU6gRuBWaKqGWLFFwbEUXkfeMkHLQWYWo=
 google.golang.org/api v0.34.0 h1:k40adF3uR+6x/+hO5Dh4ZFUqFp67vxvbpafFiJxl10A=
 google.golang.org/api v0.34.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
 google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
@@ -1754,7 +1758,6 @@ google.golang.org/genproto v0.0.0-20200709005830-7a2ca40e9dc3/go.mod h1:FWY/as6D
 google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
 google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
 google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20200831141814-d751682dd103/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
 google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d h1:92D1fum1bJLKSdr11OJ+54YeCMCGYIygTA7R/YZxH5M=
 google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
 google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
@@ -1929,15 +1932,14 @@ k8s.io/utils v0.0.0-20200603063816-c1c6865ac451 h1:v8ud2Up6QK1lNOKFgiIVrZdMg7Mpm
 k8s.io/utils v0.0.0-20200603063816-c1c6865ac451/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
 knative.dev/caching v0.0.0-20190719140829-2032732871ff/go.mod h1:dHXFU6CGlLlbzaWc32g80cR92iuBSpsslDNBWI8C7eg=
 knative.dev/caching v0.0.0-20200116200605-67bca2c83dfa/go.mod h1:dHXFU6CGlLlbzaWc32g80cR92iuBSpsslDNBWI8C7eg=
-knative.dev/caching v0.0.0-20201027231233-cc1d9d2e090f h1:6b/IQWfu+3YLwXVVnxp0AidrZv5mXBsz86Y72Gadx3o=
-knative.dev/caching v0.0.0-20201027231233-cc1d9d2e090f/go.mod h1:bY9AT326jU9YHUp82C47avB2S4nXP34h7fBleHYPE+8=
+knative.dev/caching v0.0.0-20201029165635-7983fcd03d68 h1:+1U1mrKyf3GmUDwW/NHQGAAX6Op/byg1sfXoXuJqKrI=
+knative.dev/caching v0.0.0-20201029165635-7983fcd03d68/go.mod h1:IITT+yByNfodPX0JOxNvojV237O2PZjn/i8kZZh7hm8=
 knative.dev/eventing-contrib v0.6.1-0.20190723221543-5ce18048c08b/go.mod h1:SnXZgSGgMSMLNFTwTnpaOH7hXDzTFtw0J8OmHflNx3g=
 knative.dev/eventing-contrib v0.11.2/go.mod h1:SnXZgSGgMSMLNFTwTnpaOH7hXDzTFtw0J8OmHflNx3g=
-knative.dev/hack v0.0.0-20201027201633-1763a666eb41/go.mod h1:PHt8x8yX5Z9pPquBEfIj0X66f8iWkWfR0S/sarACJrI=
-knative.dev/hack v0.0.0-20201027221733-0d7f2f064b7b h1:tBUkvMhcWZny+7CJTs5Ona8S3OCKJkgAwgZ7mkgWL3Y=
-knative.dev/hack v0.0.0-20201027221733-0d7f2f064b7b/go.mod h1:PHt8x8yX5Z9pPquBEfIj0X66f8iWkWfR0S/sarACJrI=
-knative.dev/networking v0.0.0-20201027230234-f0e013a2a1e2 h1:Xu3k2KIh3yo4h1DUv8ggFEJ69TTJyaOa0Zi0ZOS9lOI=
-knative.dev/networking v0.0.0-20201027230234-f0e013a2a1e2/go.mod h1:syCunAb44zGXGYPyiN6fXaSmFSy6Kb4fyZxaaxodOXQ=
+knative.dev/hack v0.0.0-20201028205534-fe80f1c8af68 h1:ygwpOK8B0PXurq88GHhym2uxKiiMJ+bRFwFeZHqGJNc=
+knative.dev/hack v0.0.0-20201028205534-fe80f1c8af68/go.mod h1:PHt8x8yX5Z9pPquBEfIj0X66f8iWkWfR0S/sarACJrI=
+knative.dev/networking v0.0.0-20201029132834-0fb5d8bc0634 h1:PWOKjvIetCNvHR302XhGEBb/B2vt4dF1LuAwhKH5ViE=
+knative.dev/networking v0.0.0-20201029132834-0fb5d8bc0634/go.mod h1:MogwjngWMF4suyf8htoTj53UpY3CXNKn1pTpyeBtu2I=
 knative.dev/pkg v0.0.0-20191101194912-56c2594e4f11/go.mod h1:pgODObA1dTyhNoFxPZTTjNWfx6F0aKsKzn+vaT9XO/Q=
 knative.dev/pkg v0.0.0-20191111150521-6d806b998379/go.mod h1:pgODObA1dTyhNoFxPZTTjNWfx6F0aKsKzn+vaT9XO/Q=
 knative.dev/pkg v0.0.0-20200207155214-fef852970f43/go.mod h1:pgODObA1dTyhNoFxPZTTjNWfx6F0aKsKzn+vaT9XO/Q=
@@ -1946,10 +1948,10 @@ knative.dev/pkg v0.0.0-20200505191044-3da93ebb24c2/go.mod h1:Q6sL35DdGs8hIQZKdaC
 knative.dev/pkg v0.0.0-20200515002500-16d7b963416f/go.mod h1:tMOHGbxtRz8zYFGEGpV/bpoTEM1o89MwYFC4YJXl3GY=
 knative.dev/pkg v0.0.0-20200528142800-1c6815d7e4c9/go.mod h1:QgNZTxnwpB/oSpNcfnLVlw+WpEwwyKAvJlvR3hgeltA=
 knative.dev/pkg v0.0.0-20200711004937-22502028e31a/go.mod h1:AqAJV6rYi8IGikDjJ/9ZQd9qKdkXVlesVnVjwx62YB8=
-knative.dev/pkg v0.0.0-20201027223833-826303ca0653 h1:p+cyfEvM3tIVVrgekbEiIZh23DfdVeqwEjxyqY+nROI=
-knative.dev/pkg v0.0.0-20201027223833-826303ca0653/go.mod h1:QE0oLfNTKMOrbh5kpt8O58nDxbvEvz3t6R8xTdaWZrg=
-knative.dev/pkg v0.0.0-20201028121234-58d43f05028e h1:hUiaQjWDH2zye0rdVbkEpXQE4UWETEd+H7TGht7iems=
-knative.dev/pkg v0.0.0-20201028121234-58d43f05028e/go.mod h1:2K9UlkXASBzY9j0aDoOnqs1xsNi+hz/39X6xVap+nlE=
+knative.dev/pkg v0.0.0-20201029122234-6d905b3f84a6 h1:J7VRiR73Mnc7UeiPo0mCPBIZVYcBBKZO+wPqFc8nlrM=
+knative.dev/pkg v0.0.0-20201029122234-6d905b3f84a6/go.mod h1:G805KH4tlnB6CIVHWIpE82pjx3/+2r9gUqNSOa78tns=
+knative.dev/pkg v0.0.0-20201030122234-256ae893994a h1:TDlfIVQcrnepgnVMln8BIKSvo3+G4WGCLjWhLIyjg54=
+knative.dev/pkg v0.0.0-20201030122234-256ae893994a/go.mod h1:G805KH4tlnB6CIVHWIpE82pjx3/+2r9gUqNSOa78tns=
 knative.dev/test-infra v0.0.0-20200407185800-1b88cb3b45a5/go.mod h1:xcdUkMJrLlBswIZqL5zCuBFOC22WIPMQoVX1L35i0vQ=
 knative.dev/test-infra v0.0.0-20200505052144-5ea2f705bb55/go.mod h1:WqF1Azka+FxPZ20keR2zCNtiQA1MP9ZB4BH4HuI+SIU=
 knative.dev/test-infra v0.0.0-20200513011557-d03429a76034/go.mod h1:aMif0KXL4g19YCYwsy4Ocjjz5xgPlseYV+B95Oo4JGE=
diff --git a/pkg/activator/handler/handler.go b/pkg/activator/handler/handler.go
index 0e3eeee1a..22c08659f 100644
--- a/pkg/activator/handler/handler.go
+++ b/pkg/activator/handler/handler.go
@@ -18,6 +18,7 @@ package handler
 
 import (
 	"context"
+	"errors"
 	"net/http"
 	"net/http/httputil"
 	"net/url"
@@ -94,10 +95,9 @@ func (a *activationHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 
 		logger.Errorw("Throttler try error", zap.Error(err))
 
-		switch err {
-		case context.DeadlineExceeded, queue.ErrRequestQueueFull:
+		if errors.Is(err, context.DeadlineExceeded) || errors.Is(err, queue.ErrRequestQueueFull) {
 			http.Error(w, err.Error(), http.StatusServiceUnavailable)
-		default:
+		} else {
 			w.WriteHeader(http.StatusInternalServerError)
 		}
 	}
diff --git a/pkg/apis/autoscaling/annotation_validation.go b/pkg/apis/autoscaling/annotation_validation.go
index 6251ea7ce..d4230a165 100644
--- a/pkg/apis/autoscaling/annotation_validation.go
+++ b/pkg/apis/autoscaling/annotation_validation.go
@@ -18,6 +18,7 @@ package autoscaling
 
 import (
 	"context"
+	"errors"
 	"fmt"
 	"math"
 	"strconv"
@@ -36,7 +37,7 @@ func getIntGE0(m map[string]string, k string) (int32, *apis.FieldError) {
 	// Parsing as uint gives a bad format error, rather than invalid range, unfortunately.
 	i, err := strconv.ParseInt(v, 10, 32)
 	if err != nil {
-		if nerr, ok := err.(*strconv.NumError); ok && nerr.Err == strconv.ErrRange {
+		if errors.Is(err, strconv.ErrRange) {
 			return 0, apis.ErrOutOfBoundsValue(v, 0, math.MaxInt32, k)
 		}
 		return 0, apis.ErrInvalidValue(v, k)
diff --git a/pkg/autoscaler/metrics/collector.go b/pkg/autoscaler/metrics/collector.go
index ef9d3c7d0..ce57d6810 100644
--- a/pkg/autoscaler/metrics/collector.go
+++ b/pkg/autoscaler/metrics/collector.go
@@ -340,7 +340,7 @@ func (c *collection) updateLastError(err error) bool {
 	c.mux.Lock()
 	defer c.mux.Unlock()
 
-	if c.lastErr == err {
+	if errors.Is(err, c.lastErr) {
 		return false
 	}
 	c.lastErr = err
diff --git a/pkg/autoscaler/metrics/stats_scraper.go b/pkg/autoscaler/metrics/stats_scraper.go
index 1122ea3de..ecd9082eb 100644
--- a/pkg/autoscaler/metrics/stats_scraper.go
+++ b/pkg/autoscaler/metrics/stats_scraper.go
@@ -207,7 +207,7 @@ func (s *serviceScraper) Scrape(window time.Duration) (stat Stat, err error) {
 	if s.podsAddressable {
 		stat, err := s.scrapePods(window)
 		// Some pods were scraped, but not enough.
-		if err != errNoPodsScraped {
+		if !errors.Is(err, errNoPodsScraped) {
 			return stat, err
 		}
 		// Else fall back to service scrape.
@@ -385,7 +385,7 @@ func (s *serviceScraper) scrapeService(window time.Duration, readyPods int) (Sta
 	// Return the inner error, if any.
 	if err := grp.Wait(); err != nil {
 		// Ignore the error if we have received enough statistics.
-		if err != ErrDidNotReceiveStat || len(oldStatCh)+len(youngStatCh) < sampleSize {
+		if !errors.Is(err, ErrDidNotReceiveStat) || len(oldStatCh)+len(youngStatCh) < sampleSize {
 			return emptyStat, fmt.Errorf("unsuccessful scrape, sampleSize=%d: %w", sampleSize, err)
 		}
 	}
diff --git a/pkg/autoscaler/scaling/autoscaler.go b/pkg/autoscaler/scaling/autoscaler.go
index 00accc067..fe9d2324b 100644
--- a/pkg/autoscaler/scaling/autoscaler.go
+++ b/pkg/autoscaler/scaling/autoscaler.go
@@ -18,6 +18,7 @@ package scaling
 
 import (
 	"context"
+	"errors"
 	"math"
 	"sync"
 	"time"
@@ -172,7 +173,7 @@ func (a *autoscaler) Scale(ctx context.Context, now time.Time) ScaleResult {
 	logger = logger.With(zap.String("metric", metricName))
 
 	if err != nil {
-		if err == metrics.ErrNoData {
+		if errors.Is(err, metrics.ErrNoData) {
 			logger.Debug("No data to scale on yet")
 		} else {
 			logger.Errorw("Failed to obtain metrics", zap.Error(err))
diff --git a/pkg/autoscaler/statforwarder/forwarder.go b/pkg/autoscaler/statforwarder/forwarder.go
index 6926ed589..8523c8193 100644
--- a/pkg/autoscaler/statforwarder/forwarder.go
+++ b/pkg/autoscaler/statforwarder/forwarder.go
@@ -24,7 +24,7 @@ import (
 
 	"go.uber.org/zap"
 	coordinationv1 "k8s.io/api/coordination/v1"
-	v1 "k8s.io/api/core/v1"
+	corev1 "k8s.io/api/core/v1"
 	"k8s.io/apimachinery/pkg/api/equality"
 	apierrs "k8s.io/apimachinery/pkg/api/errors"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -228,13 +228,13 @@ func (f *Forwarder) leaseUpdated(obj interface{}) {
 func (f *Forwarder) createService(ctx context.Context, ns, n string) error {
 	var lastErr error
 	if err := wait.PollImmediate(retryInterval, retryTimeout, func() (bool, error) {
-		_, lastErr = f.kc.CoreV1().Services(ns).Create(ctx, &v1.Service{
+		_, lastErr = f.kc.CoreV1().Services(ns).Create(ctx, &corev1.Service{
 			ObjectMeta: metav1.ObjectMeta{
 				Name:      n,
 				Namespace: ns,
 			},
-			Spec: v1.ServiceSpec{
-				Ports: []v1.ServicePort{{
+			Spec: corev1.ServiceSpec{
+				Ports: []corev1.ServicePort{{
 					Name:       autoscalerPortName,
 					Port:       autoscalerPort,
 					TargetPort: intstr.FromInt(autoscalerPort),
@@ -259,14 +259,14 @@ func (f *Forwarder) createService(ctx context.Context, ns, n string) error {
 // name, and the Forwarder.selfIP. If the Endpoints object already
 // exists, it will update the Endpoints with the Forwarder.selfIP.
 func (f *Forwarder) createOrUpdateEndpoints(ctx context.Context, ns, n string) error {
-	wantSubsets := []v1.EndpointSubset{{
-		Addresses: []v1.EndpointAddress{{
+	wantSubsets := []corev1.EndpointSubset{{
+		Addresses: []corev1.EndpointAddress{{
 			IP: f.selfIP,
 		}},
-		Ports: []v1.EndpointPort{{
+		Ports: []corev1.EndpointPort{{
 			Name:     autoscalerPortName,
 			Port:     autoscalerPort,
-			Protocol: v1.ProtocolTCP,
+			Protocol: corev1.ProtocolTCP,
 		}}},
 	}
 
@@ -307,7 +307,7 @@ func (f *Forwarder) createOrUpdateEndpoints(ctx context.Context, ns, n string) e
 	}
 
 	if err := wait.PollImmediate(retryInterval, retryTimeout, func() (bool, error) {
-		_, lastErr = f.kc.CoreV1().Endpoints(ns).Create(ctx, &v1.Endpoints{
+		_, lastErr = f.kc.CoreV1().Endpoints(ns).Create(ctx, &corev1.Endpoints{
 			ObjectMeta: metav1.ObjectMeta{
 				Name:      n,
 				Namespace: ns,
diff --git a/pkg/autoscaler/statserver/server.go b/pkg/autoscaler/statserver/server.go
index 175fe364a..8ce7db577 100644
--- a/pkg/autoscaler/statserver/server.go
+++ b/pkg/autoscaler/statserver/server.go
@@ -20,6 +20,7 @@ import (
 	"bytes"
 	"context"
 	"encoding/json"
+	"errors"
 	"net"
 	"net/http"
 	"strings"
@@ -100,7 +101,7 @@ func (s *Server) listen() (net.Listener, error) {
 
 func (s *Server) serve(l net.Listener) error {
 	close(s.servingCh)
-	if err := s.wsSrv.Serve(l); err != http.ErrServerClosed {
+	if err := s.wsSrv.Serve(l); !errors.Is(err, http.ErrServerClosed) {
 		return err
 	}
 	return nil
@@ -221,7 +222,7 @@ func (s *Server) Shutdown(timeout time.Duration) {
 	defer cancel()
 	err := s.wsSrv.Shutdown(ctx)
 	if err != nil {
-		if err == context.DeadlineExceeded {
+		if errors.Is(err, context.DeadlineExceeded) {
 			s.logger.Warn("Shutdown timed out")
 		} else {
 			s.logger.Errorw("Shutdown failed.", zap.Error(err))
diff --git a/pkg/queue/handler.go b/pkg/queue/handler.go
index 1dea5c04e..a92198f22 100644
--- a/pkg/queue/handler.go
+++ b/pkg/queue/handler.go
@@ -18,6 +18,7 @@ package queue
 
 import (
 	"context"
+	"errors"
 	"net/http"
 	"time"
 
@@ -63,10 +64,9 @@ func ProxyHandler(breaker *Breaker, stats *network.RequestStats, tracingEnabled
 				next.ServeHTTP(w, r)
 			}); err != nil {
 				waitSpan.End()
-				switch err {
-				case context.DeadlineExceeded, ErrRequestQueueFull:
+				if errors.Is(err, context.DeadlineExceeded) || errors.Is(err, ErrRequestQueueFull) {
 					http.Error(w, err.Error(), http.StatusServiceUnavailable)
-				default:
+				} else {
 					// This line is most likely untestable :-).
 					w.WriteHeader(http.StatusInternalServerError)
 				}
diff --git a/pkg/reconciler/accessor/errors.go b/pkg/reconciler/accessor/errors.go
index a5962ee87..ef4e7fe6b 100644
--- a/pkg/reconciler/accessor/errors.go
+++ b/pkg/reconciler/accessor/errors.go
@@ -16,7 +16,10 @@ limitations under the License.
 
 package accessor
 
-import "strings"
+import (
+	"errors"
+	"strings"
+)
 
 // Error defines a type of error coming from Accessor.
 type Error struct {
@@ -43,8 +46,8 @@ func (a Error) Error() string {
 
 // IsNotOwned returns true if the error is caused by NotOwnResource.
 func IsNotOwned(err error) bool {
-	accessorError, ok := err.(Error)
-	if !ok {
+	var accessorError Error
+	if !errors.As(err, &accessorError) {
 		return false
 	}
 	return accessorError.errorReason == NotOwnResource
diff --git a/pkg/reconciler/gc/v1/gc.go b/pkg/reconciler/gc/v1/gc.go
index 297bbdb22..875a9c8f8 100644
--- a/pkg/reconciler/gc/v1/gc.go
+++ b/pkg/reconciler/gc/v1/gc.go
@@ -18,6 +18,7 @@ package v1
 
 import (
 	"context"
+	"errors"
 	"sort"
 	"time"
 
@@ -88,7 +89,8 @@ func isRevisionStale(ctx context.Context, rev *v1.Revision, config *v1.Configura
 
 	lastPin, err := rev.GetLastPinned()
 	if err != nil {
-		if err.(v1.LastPinnedParseError).Type != v1.AnnotationParseErrorTypeMissing {
+		var errLastPinned v1.LastPinnedParseError
+		if errors.As(err, &errLastPinned) && errLastPinned.Type != v1.AnnotationParseErrorTypeMissing {
 			logger.Errorw("Failed to determine revision last pinned", zap.Error(err))
 		} else {
 			// Revision was never pinned and its RevisionConditionReady is not true after staleRevisionCreateDelay.
diff --git a/pkg/reconciler/metric/metric.go b/pkg/reconciler/metric/metric.go
index 5f42ea225..b1c491397 100644
--- a/pkg/reconciler/metric/metric.go
+++ b/pkg/reconciler/metric/metric.go
@@ -18,6 +18,7 @@ package metric
 
 import (
 	"context"
+	"errors"
 
 	"knative.dev/serving/pkg/apis/autoscaling/v1alpha1"
 	"knative.dev/serving/pkg/autoscaler/metrics"
@@ -37,10 +38,10 @@ var _ metricreconciler.Interface = (*reconciler)(nil)
 // ReconcileKind implements Interface.ReconcileKind.
 func (r *reconciler) ReconcileKind(ctx context.Context, metric *v1alpha1.Metric) pkgreconciler.Event {
 	if err := r.collector.CreateOrUpdate(metric); err != nil {
-		switch err {
-		case metrics.ErrFailedGetEndpoints:
+		switch {
+		case errors.Is(err, metrics.ErrFailedGetEndpoints):
 			metric.Status.MarkMetricNotReady("NoEndpoints", err.Error())
-		case metrics.ErrDidNotReceiveStat:
+		case errors.Is(err, metrics.ErrDidNotReceiveStat):
 			metric.Status.MarkMetricFailed("DidNotReceiveStat", err.Error())
 		default:
 			metric.Status.MarkMetricFailed("CollectionFailed",
diff --git a/pkg/reconciler/revision/resources/queue.go b/pkg/reconciler/revision/resources/queue.go
index fefdde926..008234072 100644
--- a/pkg/reconciler/revision/resources/queue.go
+++ b/pkg/reconciler/revision/resources/queue.go
@@ -75,6 +75,11 @@ var (
 
 	queueSecurityContext = &corev1.SecurityContext{
 		AllowPrivilegeEscalation: ptr.Bool(false),
+		ReadOnlyRootFilesystem:   ptr.Bool(true),
+		RunAsNonRoot:             ptr.Bool(true),
+		Capabilities: &corev1.Capabilities{
+			Drop: []corev1.Capability{"all"},
+		},
 	}
 )
 
diff --git a/pkg/reconciler/route/reconcile_resources.go b/pkg/reconciler/route/reconcile_resources.go
index c641aa330..34c4f9367 100644
--- a/pkg/reconciler/route/reconcile_resources.go
+++ b/pkg/reconciler/route/reconcile_resources.go
@@ -18,6 +18,7 @@ package route
 
 import (
 	"context"
+	"errors"
 	"fmt"
 
 	"go.uber.org/zap"
@@ -202,7 +203,8 @@ func (c *Reconciler) reconcileTargetRevisions(ctx context.Context, t *traffic.Co
 				lastPin, err := newRev.GetLastPinned()
 				if err != nil {
 					// Missing is an expected error case for a not yet pinned revision.
-					if err.(v1.LastPinnedParseError).Type != v1.AnnotationParseErrorTypeMissing {
+					var errLastPinned v1.LastPinnedParseError
+					if errors.As(err, &errLastPinned) && errLastPinned.Type != v1.AnnotationParseErrorTypeMissing {
 						return err
 					}
 				} else {
diff --git a/pkg/reconciler/route/resources/labels/labels.go b/pkg/reconciler/route/resources/labels/labels.go
index 865360f4e..986af6031 100644
--- a/pkg/reconciler/route/resources/labels/labels.go
+++ b/pkg/reconciler/route/resources/labels/labels.go
@@ -17,18 +17,18 @@ limitations under the License.
 package labels
 
 import (
-	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	network "knative.dev/networking/pkg"
 	"knative.dev/serving/pkg/apis/serving"
 )
 
 // IsObjectLocalVisibility returns whether an ObjectMeta is of cluster-local visibility
-func IsObjectLocalVisibility(meta *v1.ObjectMeta) bool {
+func IsObjectLocalVisibility(meta *metav1.ObjectMeta) bool {
 	return meta.Labels[network.VisibilityLabelKey] != "" || meta.Labels[serving.VisibilityLabelKeyObsolete] != ""
 }
 
 // SetVisibility sets the visibility on an ObjectMeta
-func SetVisibility(meta *v1.ObjectMeta, isClusterLocal bool) {
+func SetVisibility(meta *metav1.ObjectMeta, isClusterLocal bool) {
 	if isClusterLocal {
 		SetLabel(meta, network.VisibilityLabelKey, serving.VisibilityClusterLocal)
 	} else {
@@ -37,7 +37,7 @@ func SetVisibility(meta *v1.ObjectMeta, isClusterLocal bool) {
 }
 
 // SetLabel sets/update the label of the an ObjectMeta
-func SetLabel(meta *v1.ObjectMeta, key, value string) {
+func SetLabel(meta *metav1.ObjectMeta, key, value string) {
 	if meta.Labels == nil {
 		meta.Labels = make(map[string]string, 1)
 	}
@@ -46,6 +46,6 @@ func SetLabel(meta *v1.ObjectMeta, key, value string) {
 }
 
 // DeleteLabel removes a label from the ObjectMeta
-func DeleteLabel(meta *v1.ObjectMeta, key string) {
+func DeleteLabel(meta *metav1.ObjectMeta, key string) {
 	delete(meta.Labels, key)
 }
diff --git a/pkg/reconciler/route/route.go b/pkg/reconciler/route/route.go
index c4bf6cae5..a6ddb89b1 100644
--- a/pkg/reconciler/route/route.go
+++ b/pkg/reconciler/route/route.go
@@ -18,6 +18,7 @@ package route
 
 import (
 	"context"
+	"errors"
 	"sort"
 	"strconv"
 	"strings"
@@ -325,7 +326,8 @@ func (c *Reconciler) configureTraffic(ctx context.Context, r *v1.Route) (*traffi
 		}
 	}
 
-	badTarget, isTargetError := trafficErr.(traffic.TargetError)
+	var badTarget traffic.TargetError
+	isTargetError := errors.As(trafficErr, &badTarget)
 	if trafficErr != nil && !isTargetError {
 		// An error that's not due to missing traffic target should
 		// make us fail fast.
diff --git a/pkg/reconciler/route/traffic/rollout.go b/pkg/reconciler/route/traffic/rollout.go
index 32e4afcde..460c392fe 100644
--- a/pkg/reconciler/route/traffic/rollout.go
+++ b/pkg/reconciler/route/traffic/rollout.go
@@ -21,7 +21,11 @@ limitations under the License.
 
 package traffic
 
-import "knative.dev/networking/pkg/apis/networking"
+import (
+	"sort"
+
+	"knative.dev/networking/pkg/apis/networking"
+)
 
 // RolloutAnnotationKey is the annotation key for storing
 // the rollout state in the Annotations of the Kingress or Route.Status.
@@ -33,6 +37,7 @@ const RolloutAnnotationKey = networking.GroupName + "/rollout"
 // There may be several rollouts going on at the same time for the
 // same configuration if there is a tag configured traffic target.
 type Rollout struct {
+	// Configurations are sorted by tag first and within same tag, by configuration name.
 	Configurations []ConfigurationRollout `json:"configurations,omitempty"`
 }
 
@@ -70,3 +75,134 @@ type RevisionRollout struct {
 	// target percentage.
 	Percent int `json:"percent"`
 }
+
+// Step merges this rollout object with the previous state and
+// returns a new Rollout object representing the merged state.
+// At the end of the call the returned object will contain the
+// desired traffic shape.
+// Step will return cur if no previous state was available.
+func (cur *Rollout) Step(prev *Rollout) *Rollout {
+	if prev == nil || len(prev.Configurations) == 0 {
+		return cur
+	}
+
+	// The algorithm below is simplest, but probably not the most performant.
+	// TODO: optimize in the later passes.
+
+	// Map the configs by tag.
+	currConfigs, prevConfigs := map[string][]*ConfigurationRollout{}, map[string][]*ConfigurationRollout{}
+	for i, cfg := range cur.Configurations {
+		currConfigs[cfg.Tag] = append(currConfigs[cfg.Tag], &cur.Configurations[i])
+	}
+	for i, cfg := range prev.Configurations {
+		prevConfigs[cfg.Tag] = append(prevConfigs[cfg.Tag], &prev.Configurations[i])
+	}
+
+	var ret []ConfigurationRollout
+	for t, ccfgs := range currConfigs {
+		pcfgs, ok := prevConfigs[t]
+		// A new tag was added, so we have no previous state to roll from,
+		// thus just add it to the return, we'll rollout to 100% from the get go (and it is
+		// always 100%, since default tag is _always_ there).
+		// So just append to the return list.
+		if !ok {
+			ret = append(ret, *ccfgs[0])
+			continue
+		}
+		// This is basically an intersect algorithm,
+		// It relies on the fact that inputs are sorted.
+		for i, j := 0, 0; i < len(ccfgs) && j < len(pcfgs); {
+			switch {
+			case j >= len(pcfgs):
+				// Those are the new configs that were added during this reconciliation.
+				// So we just copy them to the result.
+				ret = append(ret, *ccfgs[i])
+			case ccfgs[i].ConfigurationName == pcfgs[j].ConfigurationName:
+				// Config might have 0% traffic assigned, if it is a tag only route (i.e.
+				// receives no traffic via default tag).
+				if ccfgs[i].Percent != 0 {
+					ret = append(ret, *stepConfig(ccfgs[i], pcfgs[j]))
+				}
+				i++
+				j++
+			case ccfgs[i].ConfigurationName < pcfgs[j].ConfigurationName:
+				// A new config, has been added. No action for rollout though.
+				ret = append(ret, *ccfgs[i])
+				i++
+			default: // cur > prev.
+				// A config has been removed during this update.
+				// Again, no action for rollout, since this will no longer
+				// be rolling it out (or sending traffic to it overall).
+				j++
+			}
+		}
+	}
+	ro := &Rollout{Configurations: ret}
+	// We need to sort the rollout, since we have map iterations in between,
+	// which are random.
+	sortRollout(ro)
+	return ro
+}
+
+// stepConfig takes previous and goal configuration shapes and returns a new
+// config rollout, after computing the percetage allocations.
+func stepConfig(goal, prev *ConfigurationRollout) *ConfigurationRollout {
+	pc := len(prev.Revisions)
+	ret := &ConfigurationRollout{
+		ConfigurationName: goal.ConfigurationName,
+		Tag:               goal.Tag,
+		Percent:           goal.Percent,
+	}
+	// goal will always have just one revision in the list – the current desired revision.
+	if 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.
+		// TODO(vagababov): percentage might change, so this should trigger recompute of existing
+		// revision rollouts.
+		ret.Revisions = goal.Revisions
+		return ret
+	}
+
+	// Go backwards and find first revision with traffic assignment > 0.
+	// Reduce it by one, so we can give that 1% to the new revision.
+	// By design we drain newest revision first.
+	for i := len(prev.Revisions) - 1; i >= 0; i-- {
+		if prev.Revisions[i].Percent > 0 {
+			prev.Revisions[i].Percent--
+			break
+		}
+	}
+
+	// Allocate optimistically.
+	out := make([]RevisionRollout, 0, len(prev.Revisions)+1)
+
+	// Copy the non 0% objects over.
+	for _, r := range prev.Revisions {
+		if r.Percent == 0 {
+			// Skip the zeroed out items. This can be the 1%->0% from above, but
+			// generally speaking should not happen otherwise, aside from
+			// users modifying the annotation manually.
+			continue
+		}
+		out = append(out, r)
+	}
+
+	// Append the new revision, to the list of previous ones.
+	// This is how we start the rollout.
+	goalRev := goal.Revisions[0]
+	goalRev.Percent = 1
+	ret.Revisions = append(out, goalRev)
+	return ret
+}
+
+// sortRollout sorts the rollout based on tag so it's consistent
+// from run to run, since input to the process is map iterator.
+func sortRollout(r *Rollout) {
+	sort.Slice(r.Configurations, func(i, j int) bool {
+		// Sort by tag and within tag sort by config name.
+		if r.Configurations[i].Tag == r.Configurations[j].Tag {
+			return r.Configurations[i].ConfigurationName < r.Configurations[j].ConfigurationName
+		}
+		return r.Configurations[i].Tag < r.Configurations[j].Tag
+	})
+}
diff --git a/pkg/reconciler/route/traffic/traffic.go b/pkg/reconciler/route/traffic/traffic.go
index 649765c57..05e6036b9 100644
--- a/pkg/reconciler/route/traffic/traffic.go
+++ b/pkg/reconciler/route/traffic/traffic.go
@@ -18,10 +18,10 @@ package traffic
 
 import (
 	"context"
-	"sort"
+	"errors"
 
 	corev1 "k8s.io/api/core/v1"
-	"k8s.io/apimachinery/pkg/api/errors"
+	apierrs "k8s.io/apimachinery/pkg/api/errors"
 
 	net "knative.dev/networking/pkg/apis/networking"
 	netv1alpha1 "knative.dev/networking/pkg/apis/networking/v1alpha1"
@@ -179,18 +179,6 @@ func (cfg *Config) BuildRollout() *Rollout {
 	return rollout
 }
 
-// sortRollout sorts the rollout based on tag so it's consistent
-// from run to run, since input to the process is map iterator.
-func sortRollout(r *Rollout) {
-	sort.Slice(r.Configurations, func(i, j int) bool {
-		// Sort by tag and within tag sort by config name.
-		if r.Configurations[i].Tag == r.Configurations[j].Tag {
-			return r.Configurations[i].ConfigurationName < r.Configurations[j].ConfigurationName
-		}
-		return r.Configurations[i].Tag < r.Configurations[j].Tag
-	})
-}
-
 // buildRolloutForTag builds the current rollout state.
 // It is expected to be invoked after applySpecTraffic.
 // TODO(vagababov): actually deal with rollouts, vs just report desired state.
@@ -232,7 +220,7 @@ func (cb *configBuilder) getConfiguration(name string) (*v1.Configuration, error
 	if !ok {
 		var err error
 		config, err = cb.configLister.Get(name)
-		if errors.IsNotFound(err) {
+		if apierrs.IsNotFound(err) {
 			return nil, errMissingConfiguration(name)
 		} else if err != nil {
 			return nil, err
@@ -247,7 +235,7 @@ func (cb *configBuilder) getRevision(name string) (*v1.Revision, error) {
 	if !ok {
 		var err error
 		rev, err = cb.revLister.Get(name)
-		if errors.IsNotFound(err) {
+		if apierrs.IsNotFound(err) {
 			return nil, errMissingRevision(name)
 		} else if err != nil {
 			return nil, err
@@ -272,23 +260,28 @@ func (cb *configBuilder) addTrafficTarget(tt *v1.TrafficTarget) error {
 	} else if tt.ConfigurationName != "" {
 		err = cb.addConfigurationTarget(tt)
 	}
-	if err, ok := err.(*missingTargetError); err != nil && ok {
-		apiVersion, kind := v1.SchemeGroupVersion.
-			WithKind(err.kind).
-			ToAPIVersionAndKind()
-
-		cb.missingTargets = append(cb.missingTargets, corev1.ObjectReference{
-			APIVersion: apiVersion,
-			Kind:       kind,
-			Name:       err.name,
-			Namespace:  cb.route.Namespace,
-		})
-	}
-	if err, ok := err.(TargetError); err != nil && ok {
-		// Defer target errors, as we still want to compile a list of
-		// all referred targets, including missing ones.
-		cb.deferTargetError(err)
-		return nil
+	if err != nil {
+		var errMissingTarget *missingTargetError
+		if errors.As(err, &errMissingTarget) {
+			apiVersion, kind := v1.SchemeGroupVersion.
+				WithKind(errMissingTarget.kind).
+				ToAPIVersionAndKind()
+
+			cb.missingTargets = append(cb.missingTargets, corev1.ObjectReference{
+				APIVersion: apiVersion,
+				Kind:       kind,
+				Name:       errMissingTarget.name,
+				Namespace:  cb.route.Namespace,
+			})
+		}
+
+		var errTarget TargetError
+		if errors.As(err, &errTarget) {
+			// Defer target errors, as we still want to compile a list of
+			// all referred targets, including missing ones.
+			cb.deferTargetError(errTarget)
+			return nil
+		}
 	}
 	return err
 }
diff --git a/vendor/contrib.go.opencensus.io/exporter/stackdriver/metrics_batcher.go b/vendor/contrib.go.opencensus.io/exporter/stackdriver/metrics_batcher.go
index ccd6ee4a6..628471e9e 100644
--- a/vendor/contrib.go.opencensus.io/exporter/stackdriver/metrics_batcher.go
+++ b/vendor/contrib.go.opencensus.io/exporter/stackdriver/metrics_batcher.go
@@ -17,6 +17,8 @@ package stackdriver
 import (
 	"context"
 	"fmt"
+	"regexp"
+	"strconv"
 	"strings"
 	"sync"
 	"time"
@@ -131,16 +133,45 @@ func (mb *metricsBatcher) sendReqToChan() {
 	mb.reqsChan <- req
 }
 
+// regex to extract min-max ranges from error response strings in the format "timeSeries[(min-max,...)] ..." (max is optional)
+var timeSeriesErrRegex = regexp.MustCompile(`: timeSeries\[([0-9]+(?:-[0-9]+)?(?:,[0-9]+(?:-[0-9]+)?)*)\]`)
+
 // sendReq sends create time series requests to Stackdriver,
 // and returns the count of dropped time series and error.
 func sendReq(ctx context.Context, c *monitoring.MetricClient, req *monitoringpb.CreateTimeSeriesRequest) (int, error) {
-	if c != nil { // c==nil only happens in unit tests where we don't make real calls to Stackdriver server
-		err := createTimeSeries(ctx, c, req)
-		if err != nil {
-			return len(req.TimeSeries), err
+	// c == nil only happens in unit tests where we don't make real calls to Stackdriver server
+	if c == nil {
+		return 0, nil
+	}
+
+	err := createTimeSeries(ctx, c, req)
+	if err == nil {
+		return 0, nil
+	}
+
+	droppedTimeSeriesRangeMatches := timeSeriesErrRegex.FindAllStringSubmatch(err.Error(), -1)
+	if !strings.HasPrefix(err.Error(), "One or more TimeSeries could not be written:") || len(droppedTimeSeriesRangeMatches) == 0 {
+		return len(req.TimeSeries), err
+	}
+
+	dropped := 0
+	for _, submatches := range droppedTimeSeriesRangeMatches {
+		for i := 1; i < len(submatches); i++ {
+			for _, rng := range strings.Split(submatches[i], ",") {
+				rngSlice := strings.Split(rng, "-")
+
+				// strconv errors not possible due to regex above
+				min, _ := strconv.Atoi(rngSlice[0])
+				max := min
+				if len(rngSlice) > 1 {
+					max, _ = strconv.Atoi(rngSlice[1])
+				}
+
+				dropped += max - min + 1
+			}
 		}
 	}
-	return 0, nil
+	return dropped, err
 }
 
 type worker struct {
diff --git a/vendor/contrib.go.opencensus.io/exporter/stackdriver/stackdriver.go b/vendor/contrib.go.opencensus.io/exporter/stackdriver/stackdriver.go
index fc9695537..1e253f9dd 100644
--- a/vendor/contrib.go.opencensus.io/exporter/stackdriver/stackdriver.go
+++ b/vendor/contrib.go.opencensus.io/exporter/stackdriver/stackdriver.go
@@ -60,6 +60,7 @@ import (
 	metadataapi "cloud.google.com/go/compute/metadata"
 	traceapi "cloud.google.com/go/trace/apiv2"
 	"contrib.go.opencensus.io/exporter/stackdriver/monitoredresource"
+	opencensus "go.opencensus.io"
 	"go.opencensus.io/resource"
 	"go.opencensus.io/resource/resourcekeys"
 	"go.opencensus.io/stats/view"
@@ -279,12 +280,18 @@ type Options struct {
 	// time-series then it will result into an error for the entire CreateTimeSeries request
 	// which may contain more than one time-series.
 	ResourceByDescriptor func(*metricdata.Descriptor, map[string]string) (map[string]string, monitoredresource.Interface)
+
+	// Override the user agent value supplied to Monitoring APIs and included as an
+	// attribute in trace data.
+	UserAgent string
 }
 
 const defaultTimeout = 5 * time.Second
 
 var defaultDomain = path.Join("custom.googleapis.com", "opencensus")
 
+var defaultUserAgent = fmt.Sprintf("opencensus-go %s; stackdriver-exporter %s", opencensus.Version(), version)
+
 // Exporter is a stats and trace exporter that uploads data to Stackdriver.
 //
 // You can create a single Exporter and register it as both a trace exporter
@@ -362,6 +369,9 @@ func NewExporter(o Options) (*Exporter, error) {
 	if o.MetricPrefix != "" && !strings.HasSuffix(o.MetricPrefix, "/") {
 		o.MetricPrefix = o.MetricPrefix + "/"
 	}
+	if o.UserAgent == "" {
+		o.UserAgent = defaultUserAgent
+	}
 
 	se, err := newStatsExporter(o)
 	if err != nil {
diff --git a/vendor/contrib.go.opencensus.io/exporter/stackdriver/stats.go b/vendor/contrib.go.opencensus.io/exporter/stackdriver/stats.go
index 0dea6e404..895945b4e 100644
--- a/vendor/contrib.go.opencensus.io/exporter/stackdriver/stats.go
+++ b/vendor/contrib.go.opencensus.io/exporter/stackdriver/stats.go
@@ -26,7 +26,6 @@ import (
 	"sync"
 	"time"
 
-	opencensus "go.opencensus.io"
 	"go.opencensus.io/stats"
 	"go.opencensus.io/stats/view"
 	"go.opencensus.io/tag"
@@ -52,11 +51,9 @@ const (
 	opencensusTaskKey         = "opencensus_task"
 	opencensusTaskDescription = "Opencensus task identifier"
 	defaultDisplayNamePrefix  = "OpenCensus"
-	version                   = "0.10.0"
+	version                   = "0.13.3"
 )
 
-var userAgent = fmt.Sprintf("opencensus-go %s; stackdriver-exporter %s", opencensus.Version(), version)
-
 // statsExporter exports stats to the Stackdriver Monitoring.
 type statsExporter struct {
 	o Options
@@ -89,7 +86,7 @@ func newStatsExporter(o Options) (*statsExporter, error) {
 		return nil, errBlankProjectID
 	}
 
-	opts := append(o.MonitoringClientOptions, option.WithUserAgent(userAgent))
+	opts := append(o.MonitoringClientOptions, option.WithUserAgent(o.UserAgent))
 	ctx := o.Context
 	if ctx == nil {
 		ctx = context.Background()
@@ -365,6 +362,10 @@ func (e *statsExporter) createMetricDescriptorFromView(ctx context.Context, v *v
 }
 
 func (e *statsExporter) displayName(suffix string) string {
+	if hasDomain(suffix) {
+		// If the display name suffix is already prefixed with domain, skip adding extra prefix
+		return suffix
+	}
 	return path.Join(defaultDisplayNamePrefix, suffix)
 }
 
diff --git a/vendor/contrib.go.opencensus.io/exporter/stackdriver/trace.go b/vendor/contrib.go.opencensus.io/exporter/stackdriver/trace.go
index ae9fa4e19..a1066138e 100644
--- a/vendor/contrib.go.opencensus.io/exporter/stackdriver/trace.go
+++ b/vendor/contrib.go.opencensus.io/exporter/stackdriver/trace.go
@@ -98,7 +98,7 @@ func newTraceExporterWithClient(o Options, c *tracingclient.Client) *traceExport
 
 // ExportSpan exports a SpanData to Stackdriver Trace.
 func (e *traceExporter) ExportSpan(s *trace.SpanData) {
-	protoSpan := protoFromSpanData(s, e.projectID, e.o.Resource)
+	protoSpan := protoFromSpanData(s, e.projectID, e.o.Resource, e.o.UserAgent)
 	protoSize := proto.Size(protoSpan)
 	err := e.bundler.Add(protoSpan, protoSize)
 	switch err {
@@ -137,7 +137,7 @@ func (e *traceExporter) pushTraceSpans(ctx context.Context, node *commonpb.Node,
 	}
 
 	for _, span := range spans {
-		protoSpans = append(protoSpans, protoFromSpanData(span, e.projectID, res))
+		protoSpans = append(protoSpans, protoFromSpanData(span, e.projectID, res, e.o.UserAgent))
 	}
 
 	req := tracepb.BatchWriteSpansRequest{
diff --git a/vendor/contrib.go.opencensus.io/exporter/stackdriver/trace_proto.go b/vendor/contrib.go.opencensus.io/exporter/stackdriver/trace_proto.go
index 422a98026..b44957fe4 100644
--- a/vendor/contrib.go.opencensus.io/exporter/stackdriver/trace_proto.go
+++ b/vendor/contrib.go.opencensus.io/exporter/stackdriver/trace_proto.go
@@ -44,7 +44,7 @@ const (
 )
 
 // proto returns a protocol buffer representation of a SpanData.
-func protoFromSpanData(s *trace.SpanData, projectID string, mr *monitoredrespb.MonitoredResource) *tracepb.Span {
+func protoFromSpanData(s *trace.SpanData, projectID string, mr *monitoredrespb.MonitoredResource, userAgent string) *tracepb.Span {
 	if s == nil {
 		return nil
 	}
@@ -109,6 +109,10 @@ func protoFromSpanData(s *trace.SpanData, projectID string, mr *monitoredrespb.M
 	// Only set the agent label if it is not already set. That enables the
 	// OpenCensus agent/collector to set the agent label based on the library that
 	// sent the span to the agent.
+	//
+	// We now provide a config option to set the userAgent explicitly, which is
+	// used both here and in request headers when sending metric data, but have
+	// retained this non-override functionality for backwards compatibility.
 	if _, hasAgent := sp.Attributes.AttributeMap[agentLabel]; !hasAgent {
 		sp.Attributes.AttributeMap[agentLabel] = &tracepb.AttributeValue{
 			Value: &tracepb.AttributeValue_StringValue{
diff --git a/vendor/contrib.go.opencensus.io/exporter/zipkin/go.mod b/vendor/contrib.go.opencensus.io/exporter/zipkin/go.mod
index 29cc5b90b..eeb6a9be4 100644
--- a/vendor/contrib.go.opencensus.io/exporter/zipkin/go.mod
+++ b/vendor/contrib.go.opencensus.io/exporter/zipkin/go.mod
@@ -1,6 +1,7 @@
 module contrib.go.opencensus.io/exporter/zipkin
 
 require (
-	github.com/openzipkin/zipkin-go v0.1.6
-	go.opencensus.io v0.21.0
+	github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect
+	github.com/openzipkin/zipkin-go v0.2.2
+	go.opencensus.io v0.22.4
 )
diff --git a/vendor/contrib.go.opencensus.io/exporter/zipkin/go.sum b/vendor/contrib.go.opencensus.io/exporter/zipkin/go.sum
index cdb0ba62b..1a2ecef01 100644
--- a/vendor/contrib.go.opencensus.io/exporter/zipkin/go.sum
+++ b/vendor/contrib.go.opencensus.io/exporter/zipkin/go.sum
@@ -3,67 +3,83 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
 github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
 github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
 github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
 github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
 github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
+github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g=
 github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
+github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s=
 github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
+github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 h1:ZgQEtGgCBiWRM39fZuwSd1LwSqqSW0hOdXCYYDX0R3I=
+github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY=
+github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
 github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
 github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
 github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
-github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
+github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
 github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8=
 github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
 github.com/gorilla/mux v1.6.2 h1:Pgr17XVTNXAk3q/r4CpKzC5xBM/qW1uVLV+IhRZpIIk=
 github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
-github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo=
-github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
 github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
-github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
+github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ=
 github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
 github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
 github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
-github.com/openzipkin/zipkin-go v0.1.6 h1:yXiysv1CSK7Q5yjGy1710zZGnsbMUIjluWBxtLXHPBo=
-github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
-github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
+github.com/openzipkin/zipkin-go v0.2.2 h1:nY8Hti+WKaP0cRsSeQ026wU03QsM762XBeCXBb9NAWI=
+github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
+github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
+github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
-go.opencensus.io v0.21.0 h1:mU6zScU4U1YAFPHEHYk+3JC4SY7JxgkqS10ZOSyksNg=
-go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
+github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
+go.opencensus.io v0.22.4 h1:LYy1Hy3MJdrCdMwwzxA/dRok4ejH+RwNGbuoD9fCjto=
+go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
 golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
+golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
 golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628=
 golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
-golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
+golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
 google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
 google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
 google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
-google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
-google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
+google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
 google.golang.org/grpc v1.19.0 h1:cfg4PD8YEdSFnm7qLV4++93WcmhH2nIUhMjhdCvl3j8=
 google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
+google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM=
+google.golang.org/grpc v1.20.1 h1:Hz2g2wirWK7H0qIIhGIqRGTuMwTE8HEKFnDZZ7lm9NU=
+google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
 gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
 gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
diff --git a/vendor/github.com/openzipkin/zipkin-go/.travis.yml b/vendor/github.com/openzipkin/zipkin-go/.travis.yml
index d440ed07f..5834b5eb7 100644
--- a/vendor/github.com/openzipkin/zipkin-go/.travis.yml
+++ b/vendor/github.com/openzipkin/zipkin-go/.travis.yml
@@ -4,21 +4,17 @@ dist: trusty
 services:
   - rabbitmq
 
-sudo: false
-
 matrix:
   include:
-    - go: "1.9.x"
-    - go: "1.10.x"
-    - go: "1.11.x"
-      env:
-        - GO111MODULE=on
     - go: "1.12.x"
       env:
         - GO111MODULE=on
-    - go: "tip"
+    - go: "1.13.x"
       env:
         - GO111MODULE=on
+    - go: "1.14.x"
+    - go: "1.15.x"
+    - go: "tip"
 
 before_install:
   - go get golang.org/x/tools/cmd/cover
diff --git a/vendor/github.com/openzipkin/zipkin-go/Makefile b/vendor/github.com/openzipkin/zipkin-go/Makefile
index b4271c614..93631714d 100644
--- a/vendor/github.com/openzipkin/zipkin-go/Makefile
+++ b/vendor/github.com/openzipkin/zipkin-go/Makefile
@@ -11,8 +11,9 @@ bench:
 
 .PHONY: protoc
 protoc:
-	protoc --go_out=. proto/v2/zipkin.proto
-	protoc --go_out=plugins=grpc:. proto/testing/service.proto
+	protoc --go_out=module=github.com/openzipkin/zipkin-go:. proto/zipkin_proto3/zipkin.proto
+	protoc --go_out=module=github.com/openzipkin/zipkin-go:. proto/testing/service.proto
+	protoc --go-grpc_out=module=github.com/openzipkin/zipkin-go:. proto/testing/service.proto
 
 .PHONY: lint
 lint:
diff --git a/vendor/github.com/openzipkin/zipkin-go/go.mod b/vendor/github.com/openzipkin/zipkin-go/go.mod
index ed37c1c2c..fad564e8b 100644
--- a/vendor/github.com/openzipkin/zipkin-go/go.mod
+++ b/vendor/github.com/openzipkin/zipkin-go/go.mod
@@ -7,8 +7,7 @@ require (
 	github.com/eapache/go-resiliency v1.1.0 // indirect
 	github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21 // indirect
 	github.com/eapache/queue v1.1.0 // indirect
-	github.com/gogo/protobuf v1.2.0
-	github.com/golang/protobuf v1.2.0
+	github.com/golang/protobuf v1.4.2
 	github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db // indirect
 	github.com/gorilla/context v1.1.1 // indirect
 	github.com/gorilla/mux v1.6.2
@@ -17,9 +16,8 @@ require (
 	github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1 // indirect
 	github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a // indirect
 	github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94
-	golang.org/x/net v0.0.0-20190311183353-d8887717615a
-	golang.org/x/sync v0.0.0-20181108010431-42b317875d0f // indirect
-	google.golang.org/grpc v1.20.0
+	google.golang.org/grpc v1.30.0
+	google.golang.org/protobuf v1.25.0
 )
 
 go 1.12
diff --git a/vendor/github.com/openzipkin/zipkin-go/go.sum b/vendor/github.com/openzipkin/zipkin-go/go.sum
index 5274bc9f4..135cc7d22 100644
--- a/vendor/github.com/openzipkin/zipkin-go/go.sum
+++ b/vendor/github.com/openzipkin/zipkin-go/go.sum
@@ -4,7 +4,9 @@ github.com/Shopify/sarama v1.19.0 h1:9oksLxC6uxVPHPVYUmq6xhr1BOF/hHobWH2UzO67z1s
 github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
 github.com/Shopify/toxiproxy v2.1.4+incompatible h1:TKdv8HiTLgE5wdJuEML90aBgNWsokNbMijUGhmcoBJc=
 github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
+github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
 github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
+github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/eapache/go-resiliency v1.1.0 h1:1NtRmCAqadE2FN4ZcN6g90TP3uk8cg9rn9eNK2197aU=
@@ -13,26 +15,40 @@ github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21 h1:YEetp8
 github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
 github.com/eapache/queue v1.1.0 h1:YOEu7KNc61ntiQlcEeUIoDTJ2o8mQznoNvUhiigpIqc=
 github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
-github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g=
+github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
+github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
+github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
+github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
 github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
 github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
-github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s=
-github.com/gogo/protobuf v1.2.0 h1:xU6/SpYbvkNYiptHJYEDRseDLvYE7wSqhYYNy0QSUzI=
-github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
 github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
 github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
 github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
+github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
+github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
+github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
+github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
+github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
+github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
+github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
+github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
 github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w=
 github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
+github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
+github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8=
 github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
 github.com/gorilla/mux v1.6.2 h1:Pgr17XVTNXAk3q/r4CpKzC5xBM/qW1uVLV+IhRZpIIk=
 github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
 github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
 github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
-github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ=
 github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
 github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs=
 github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
@@ -41,30 +57,62 @@ github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1Cpa
 github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1 h1:VGcrWe3yk6o+t7BdVNy5UDPWa4OZuDWtE1W1ZbS7Kyw=
 github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
 github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
+github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
 github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a h1:9ZKAASQSHhDYGoxY8uLVpewe1GDZ2vu2Tr/vTdVAkFQ=
 github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
 github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94 h1:0ngsPmuP6XIjiFRNFYlvKwSr5zff2v+uPHaffZ6/M4k=
 github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
+golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
+golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
 golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628=
 golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20181108010431-42b317875d0f h1:Bl/8QSvNqXvPGPGXa2z5xUTmV7VDcZyvRZ+QQXkXTZQ=
 golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
 golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
+google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
 google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc=
 google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
-google.golang.org/grpc v1.20.0 h1:DlsSIrgEBuZAUFJcta2B5i/lzeHHbnfkNFAfFXLVFYQ=
-google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM=
+google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
+google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY=
+google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
+google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
+google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
+google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
+google.golang.org/grpc v1.27.0 h1:rRYRFMVgRv6E0D70Skyfsr28tDXIuuPZyWGMPdMcnXg=
+google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/grpc v1.30.0 h1:M5a8xTlYTxwMn5ZFkwhRabsygDY5G8TYLyQDBxJNAxE=
+google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
+google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
+google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
+google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
+google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
+google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
+google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
+google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
@@ -74,3 +122,4 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWD
 gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
 gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
diff --git a/vendor/github.com/openzipkin/zipkin-go/model/endpoint.go b/vendor/github.com/openzipkin/zipkin-go/model/endpoint.go
index 58880bd15..edb01eb75 100644
--- a/vendor/github.com/openzipkin/zipkin-go/model/endpoint.go
+++ b/vendor/github.com/openzipkin/zipkin-go/model/endpoint.go
@@ -14,14 +14,33 @@
 
 package model
 
-import "net"
+import (
+	"encoding/json"
+	"net"
+	"strings"
+)
 
 // Endpoint holds the network context of a node in the service graph.
 type Endpoint struct {
-	ServiceName string `json:"serviceName,omitempty"`
-	IPv4        net.IP `json:"ipv4,omitempty"`
-	IPv6        net.IP `json:"ipv6,omitempty"`
-	Port        uint16 `json:"port,omitempty"`
+	ServiceName string
+	IPv4        net.IP
+	IPv6        net.IP
+	Port        uint16
+}
+
+// MarshalJSON exports our Endpoint into the correct format for the Zipkin V2 API.
+func (e Endpoint) MarshalJSON() ([]byte, error) {
+	return json.Marshal(&struct {
+		ServiceName string `json:"serviceName,omitempty"`
+		IPv4        net.IP `json:"ipv4,omitempty"`
+		IPv6        net.IP `json:"ipv6,omitempty"`
+		Port        uint16 `json:"port,omitempty"`
+	}{
+		strings.ToLower(e.ServiceName),
+		e.IPv4,
+		e.IPv6,
+		e.Port,
+	})
 }
 
 // Empty returns if all Endpoint properties are empty / unspecified.
diff --git a/vendor/github.com/openzipkin/zipkin-go/model/span.go b/vendor/github.com/openzipkin/zipkin-go/model/span.go
index f428413f1..4eddfbb19 100644
--- a/vendor/github.com/openzipkin/zipkin-go/model/span.go
+++ b/vendor/github.com/openzipkin/zipkin-go/model/span.go
@@ -17,6 +17,7 @@ package model
 import (
 	"encoding/json"
 	"errors"
+	"strings"
 	"time"
 )
 
@@ -87,6 +88,8 @@ func (s SpanModel) MarshalJSON() ([]byte, error) {
 		s.Duration += 500 * time.Nanosecond
 	}
 
+	s.Name = strings.ToLower(s.Name)
+
 	if s.LocalEndpoint.Empty() {
 		s.LocalEndpoint = nil
 	}
diff --git a/vendor/github.com/openzipkin/zipkin-go/reporter/http/http.go b/vendor/github.com/openzipkin/zipkin-go/reporter/http/http.go
index fe3df454d..a01f68992 100644
--- a/vendor/github.com/openzipkin/zipkin-go/reporter/http/http.go
+++ b/vendor/github.com/openzipkin/zipkin-go/reporter/http/http.go
@@ -19,6 +19,7 @@ package http
 
 import (
 	"bytes"
+	"context"
 	"log"
 	"net/http"
 	"os"
@@ -31,16 +32,21 @@ import (
 
 // defaults
 const (
-	defaultTimeout       = time.Second * 5 // timeout for http request in seconds
-	defaultBatchInterval = time.Second * 1 // BatchInterval in seconds
+	defaultTimeout       = 5 * time.Second // timeout for http request in seconds
+	defaultBatchInterval = 1 * time.Second // BatchInterval in seconds
 	defaultBatchSize     = 100
 	defaultMaxBacklog    = 1000
 )
 
+// HTTPDoer will do a request to the Zipkin HTTP Collector
+type HTTPDoer interface {
+	Do(req *http.Request) (*http.Response, error)
+}
+
 // httpReporter will send spans to a Zipkin HTTP Collector using Zipkin V2 API.
 type httpReporter struct {
 	url           string
-	client        *http.Client
+	client        HTTPDoer
 	logger        *log.Logger
 	batchInterval time.Duration
 	batchSize     int
@@ -52,6 +58,7 @@ type httpReporter struct {
 	quit          chan struct{}
 	shutdown      chan error
 	reqCallback   RequestCallbackFn
+	reqTimeout    time.Duration
 	serializer    reporter.SpanSerializer
 }
 
@@ -145,12 +152,21 @@ func (r *httpReporter) sendBatch() error {
 		r.logger.Printf("failed when creating the request: %s\n", err.Error())
 		return err
 	}
+
+	// By default we send b3:0 header to mitigate trace reporting amplification in
+	// service mesh environments where the sidecar proxies might trace the call
+	// we do here towards the Zipkin collector.
+	req.Header.Set("b3", "0")
+
 	req.Header.Set("Content-Type", r.serializer.ContentType())
 	if r.reqCallback != nil {
 		r.reqCallback(req)
 	}
 
-	resp, err := r.client.Do(req)
+	ctx, cancel := context.WithTimeout(req.Context(), r.reqTimeout)
+	defer cancel()
+
+	resp, err := r.client.Do(req.WithContext(ctx))
 	if err != nil {
 		r.logger.Printf("failed to send the request: %s\n", err.Error())
 		return err
@@ -176,9 +192,9 @@ type RequestCallbackFn func(*http.Request)
 // ReporterOption sets a parameter for the HTTP Reporter
 type ReporterOption func(r *httpReporter)
 
-// Timeout sets maximum timeout for http request.
+// Timeout sets maximum timeout for the http request through its context.
 func Timeout(duration time.Duration) ReporterOption {
-	return func(r *httpReporter) { r.client.Timeout = duration }
+	return func(r *httpReporter) { r.reqTimeout = duration }
 }
 
 // BatchSize sets the maximum batch size, after which a collect will be
@@ -199,8 +215,9 @@ func BatchInterval(d time.Duration) ReporterOption {
 	return func(r *httpReporter) { r.batchInterval = d }
 }
 
-// Client sets a custom http client to use.
-func Client(client *http.Client) ReporterOption {
+// Client sets a custom http client to use under the interface HTTPDoer
+// which includes a `Do` method with same signature as the *http.Client
+func Client(client HTTPDoer) ReporterOption {
 	return func(r *httpReporter) { r.client = client }
 }
 
@@ -233,7 +250,7 @@ func NewReporter(url string, opts ...ReporterOption) reporter.Reporter {
 	r := httpReporter{
 		url:           url,
 		logger:        log.New(os.Stderr, "", log.LstdFlags),
-		client:        &http.Client{Timeout: defaultTimeout},
+		client:        &http.Client{},
 		batchInterval: defaultBatchInterval,
 		batchSize:     defaultBatchSize,
 		maxBacklog:    defaultMaxBacklog,
@@ -244,6 +261,7 @@ func NewReporter(url string, opts ...ReporterOption) reporter.Reporter {
 		shutdown:      make(chan error, 1),
 		batchMtx:      &sync.Mutex{},
 		serializer:    reporter.JSONSerializer{},
+		reqTimeout:    defaultTimeout,
 	}
 
 	for _, opt := range opts {
diff --git a/vendor/go.uber.org/goleak/.gitignore b/vendor/go.uber.org/goleak/.gitignore
new file mode 100644
index 000000000..0fff519a4
--- /dev/null
+++ b/vendor/go.uber.org/goleak/.gitignore
@@ -0,0 +1,5 @@
+vendor/
+/bin
+/lint.log
+/cover.out
+/cover.html
diff --git a/vendor/go.uber.org/goleak/.travis.yml b/vendor/go.uber.org/goleak/.travis.yml
new file mode 100644
index 000000000..dfdb5b6d9
--- /dev/null
+++ b/vendor/go.uber.org/goleak/.travis.yml
@@ -0,0 +1,25 @@
+sudo: false
+language: go
+go_import_path: go.uber.org/goleak
+
+env:
+  global:
+    - GO111MODULE=on
+
+matrix:
+  include:
+  - go: 1.12.x
+  - go: 1.13.x
+  - go: 1.14.x
+    env: LINT=1
+
+install:
+  - make install
+
+script:
+  - test -z "$LINT" || make lint
+  - make test
+
+after_success:
+  - make cover
+  - bash <(curl -s https://codecov.io/bash)
diff --git a/vendor/go.uber.org/goleak/CHANGELOG.md b/vendor/go.uber.org/goleak/CHANGELOG.md
new file mode 100644
index 000000000..ba3df4f37
--- /dev/null
+++ b/vendor/go.uber.org/goleak/CHANGELOG.md
@@ -0,0 +1,24 @@
+# Changelog
+All notable changes to this project will be documented in this file.
+
+The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
+and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
+
+## [1.1.0]
+### Added
+- [#49]: Add option to ignore current goroutines, which checks for any additional leaks and allows for incremental adoption of goleak in larger projects.
+
+Thanks to @denis-tingajkin for their contributions to this release.
+
+## [1.0.0]
+### Changed
+- Migrate to Go modules.
+
+### Fixed
+- Ignore trace related goroutines that cause false positives with -trace.
+
+## 0.10.0
+- Initial release.
+
+[1.0.0]: https://github.com/uber-go/goleak/compare/v0.10.0...v1.0.0
+[#49]: https://github.com/uber-go/goleak/pull/49
diff --git a/vendor/go.uber.org/goleak/LICENSE b/vendor/go.uber.org/goleak/LICENSE
new file mode 100644
index 000000000..6c9bde216
--- /dev/null
+++ b/vendor/go.uber.org/goleak/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2018 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.
diff --git a/vendor/go.uber.org/goleak/Makefile b/vendor/go.uber.org/goleak/Makefile
new file mode 100644
index 000000000..53763fa8d
--- /dev/null
+++ b/vendor/go.uber.org/goleak/Makefile
@@ -0,0 +1,41 @@
+export GOBIN ?= $(shell pwd)/bin
+
+GOLINT = $(GOBIN)/golint
+
+GO_FILES := $(shell \
+	find . '(' -path '*/.*' -o -path './vendor' ')' -prune \
+	-o -name '*.go' -print | cut -b3-)
+
+.PHONY: build
+build:
+	go build ./...
+
+.PHONY: install
+install:
+	go mod download
+
+.PHONY: test
+test:
+	go test -v -race ./...
+	go test -v -trace=/dev/null .
+
+.PHONY: cover
+cover:
+	go test -race -coverprofile=cover.out -coverpkg=./... ./...
+	go tool cover -html=cover.out -o cover.html
+
+$(GOLINT):
+	go install golang.org/x/lint/golint
+
+.PHONY: lint
+lint: $(GOLINT)
+	@rm -rf lint.log
+	@echo "Checking formatting..."
+	@gofmt -d -s $(GO_FILES) 2>&1 | tee lint.log
+	@echo "Checking vet..."
+	@go vet ./... 2>&1 | tee -a lint.log
+	@echo "Checking lint..."
+	@$(GOLINT) ./... 2>&1 | tee -a lint.log
+	@echo "Checking for unresolved FIXMEs..."
+	@git grep -i fixme | grep -v -e '^vendor/' -e '^Makefile' | tee -a lint.log
+	@[ ! -s lint.log ]
diff --git a/vendor/go.uber.org/goleak/README.md b/vendor/go.uber.org/goleak/README.md
new file mode 100644
index 000000000..b8a748b08
--- /dev/null
+++ b/vendor/go.uber.org/goleak/README.md
@@ -0,0 +1,71 @@
+# goleak [![GoDoc][doc-img]][doc] [![Build Status][ci-img]][ci] [![Coverage Status][cov-img]][cov]
+
+Goroutine leak detector to help avoid Goroutine leaks.
+
+## Installation
+
+You can use `go get` to get the latest version:
+
+`go get -u go.uber.org/goleak`
+
+`goleak` also supports semver releases. It is compatible with Go 1.5+.
+
+## Quick Start
+
+To verify that there are no unexpected goroutines running at the end of a test:
+
+```go
+func TestA(t *testing.T) {
+	defer goleak.VerifyNone(t)
+
+	// test logic here.
+}
+```
+
+Instead of checking for leaks at the end of every test, `goleak` can also be run
+at the end of every test package by creating a `TestMain` function for your
+package:
+
+```go
+func TestMain(m *testing.M) {
+	goleak.VerifyTestMain(m)
+}
+```
+
+## Determine Source of Package Leaks
+
+When verifying leaks using `TestMain`, the leak test is only run once after all tests
+have been run. This is typically enough to ensure there's no goroutines leaked from
+tests, but when there are leaks, it's hard to determine which test is causing them.
+
+You can use the following bash script to determine the source of the failing test:
+
+```sh
+# Create a test binary which will be used to run each test individually
+$ go test -c -o tests
+
+# Run each test individually, printing "." for successful tests, or the test name
+# for failing tests.
+$ for test in $(go test -list . | grep -E "^(Test|Example)"); do ./tests -test.run "^$test\$" &>/dev/null && echo -n "." || echo "\n$test failed"; done
+```
+
+This will only print names of failing tests which can be investigated individually. E.g.,
+
+```
+.....
+TestLeakyTest failed
+.......
+```
+
+## Stability
+
+goleak is v1 and follows [SemVer](http://semver.org/) strictly.
+
+No breaking changes will be made to exported APIs before 2.0.
+
+[doc-img]: https://godoc.org/go.uber.org/goleak?status.svg
+[doc]: https://godoc.org/go.uber.org/goleak
+[ci-img]: https://travis-ci.com/uber-go/goleak.svg?branch=master
+[ci]: https://travis-ci.com/uber-go/goleak
+[cov-img]: https://codecov.io/gh/uber-go/goleak/branch/master/graph/badge.svg
+[cov]: https://codecov.io/gh/uber-go/goleak
diff --git a/vendor/go.uber.org/goleak/doc.go b/vendor/go.uber.org/goleak/doc.go
new file mode 100644
index 000000000..3832f8dbc
--- /dev/null
+++ b/vendor/go.uber.org/goleak/doc.go
@@ -0,0 +1,22 @@
+// Copyright (c) 2018 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 goleak is a Goroutine leak detector.
+package goleak // import "go.uber.org/goleak"
diff --git a/vendor/go.uber.org/goleak/glide.yaml b/vendor/go.uber.org/goleak/glide.yaml
new file mode 100644
index 000000000..c6e7a00a0
--- /dev/null
+++ b/vendor/go.uber.org/goleak/glide.yaml
@@ -0,0 +1,8 @@
+package: go.uber.org/goleak
+import: []
+testImport:
+- package: github.com/stretchr/testify
+  version: ^1.1.4
+  subpackages:
+  - assert
+  - require
diff --git a/vendor/go.uber.org/goleak/go.mod b/vendor/go.uber.org/goleak/go.mod
new file mode 100644
index 000000000..742547abd
--- /dev/null
+++ b/vendor/go.uber.org/goleak/go.mod
@@ -0,0 +1,11 @@
+module go.uber.org/goleak
+
+go 1.13
+
+require (
+	github.com/kr/pretty v0.1.0 // indirect
+	github.com/stretchr/testify v1.4.0
+	golang.org/x/lint v0.0.0-20190930215403-16217165b5de
+	golang.org/x/tools v0.0.0-20191108193012-7d206e10da11 // indirect
+	gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
+)
diff --git a/vendor/go.uber.org/goleak/go.sum b/vendor/go.uber.org/goleak/go.sum
new file mode 100644
index 000000000..09b27d7ee
--- /dev/null
+++ b/vendor/go.uber.org/goleak/go.sum
@@ -0,0 +1,30 @@
+github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
+github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
+github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
+github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
+github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
+github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs=
+golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20191108193012-7d206e10da11 h1:Yq9t9jnGoR+dBuitxdo9l6Q7xh/zOyNnYUtDKaQ3x0E=
+golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
+gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
+gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
diff --git a/vendor/go.uber.org/goleak/internal/stack/stacks.go b/vendor/go.uber.org/goleak/internal/stack/stacks.go
new file mode 100644
index 000000000..94f82e4c0
--- /dev/null
+++ b/vendor/go.uber.org/goleak/internal/stack/stacks.go
@@ -0,0 +1,155 @@
+// 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.
+
+package stack
+
+import (
+	"bufio"
+	"bytes"
+	"fmt"
+	"io"
+	"runtime"
+	"strconv"
+	"strings"
+)
+
+const _defaultBufferSize = 64 * 1024 // 64 KiB
+
+// Stack represents a single Goroutine's stack.
+type Stack struct {
+	id            int
+	state         string
+	firstFunction string
+	fullStack     *bytes.Buffer
+}
+
+// ID returns the goroutine ID.
+func (s Stack) ID() int {
+	return s.id
+}
+
+// State returns the Goroutine's state.
+func (s Stack) State() string {
+	return s.state
+}
+
+// Full returns the full stack trace for this goroutine.
+func (s Stack) Full() string {
+	return s.fullStack.String()
+}
+
+// FirstFunction returns the name of the first function on the stack.
+func (s Stack) FirstFunction() string {
+	return s.firstFunction
+}
+
+func (s Stack) String() string {
+	return fmt.Sprintf(
+		"Goroutine %v in state %v, with %v on top of the stack:\n%s",
+		s.id, s.state, s.firstFunction, s.Full())
+}
+
+func getStacks(all bool) []Stack {
+	var stacks []Stack
+
+	var curStack *Stack
+	stackReader := bufio.NewReader(bytes.NewReader(getStackBuffer(all)))
+	for {
+		line, err := stackReader.ReadString('\n')
+		if err == io.EOF {
+			break
+		}
+		if err != nil {
+			// We're reading using bytes.NewReader which should never fail.
+			panic("bufio.NewReader failed on a fixed string")
+		}
+
+		// If we see the goroutine header, start a new stack.
+		isFirstLine := false
+		if strings.HasPrefix(line, "goroutine ") {
+			// flush any previous stack
+			if curStack != nil {
+				stacks = append(stacks, *curStack)
+			}
+			id, goState := parseGoStackHeader(line)
+			curStack = &Stack{
+				id:        id,
+				state:     goState,
+				fullStack: &bytes.Buffer{},
+			}
+			isFirstLine = true
+		}
+		curStack.fullStack.WriteString(line)
+		if !isFirstLine && curStack.firstFunction == "" {
+			curStack.firstFunction = parseFirstFunc(line)
+		}
+	}
+
+	if curStack != nil {
+		stacks = append(stacks, *curStack)
+	}
+	return stacks
+}
+
+// All returns the stacks for all running goroutines.
+func All() []Stack {
+	return getStacks(true)
+}
+
+// Current returns the stack for the current goroutine.
+func Current() Stack {
+	return getStacks(false)[0]
+}
+
+func getStackBuffer(all bool) []byte {
+	for i := _defaultBufferSize; ; i *= 2 {
+		buf := make([]byte, i)
+		if n := runtime.Stack(buf, all); n < i {
+			return buf[:n]
+		}
+	}
+}
+
+func parseFirstFunc(line string) string {
+	line = strings.TrimSpace(line)
+	if idx := strings.LastIndex(line, "("); idx > 0 {
+		return line[:idx]
+	}
+	panic(fmt.Sprintf("function calls missing parents: %q", line))
+}
+
+// parseGoStackHeader parses a stack header that looks like:
+// goroutine 643 [runnable]:\n
+// And returns the goroutine ID, and the state.
+func parseGoStackHeader(line string) (goroutineID int, state string) {
+	line = strings.TrimSuffix(line, ":\n")
+	parts := strings.SplitN(line, " ", 3)
+	if len(parts) != 3 {
+		panic(fmt.Sprintf("unexpected stack header format: %q", line))
+	}
+
+	id, err := strconv.Atoi(parts[1])
+	if err != nil {
+		panic(fmt.Sprintf("failed to parse goroutine ID: %v in line %q", parts[1], line))
+	}
+
+	state = strings.TrimSuffix(strings.TrimPrefix(parts[2], "["), "]")
+	return id, state
+}
diff --git a/vendor/go.uber.org/goleak/leaks.go b/vendor/go.uber.org/goleak/leaks.go
new file mode 100644
index 000000000..468dbaf95
--- /dev/null
+++ b/vendor/go.uber.org/goleak/leaks.go
@@ -0,0 +1,80 @@
+// 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.
+
+package goleak
+
+import (
+	"fmt"
+
+	"go.uber.org/goleak/internal/stack"
+)
+
+// TestingT is the minimal subset of testing.TB that we use.
+type TestingT interface {
+	Error(...interface{})
+}
+
+// filterStacks will filter any stacks excluded by the given opts.
+// filterStacks modifies the passed in stacks slice.
+func filterStacks(stacks []stack.Stack, skipID int, opts *opts) []stack.Stack {
+	filtered := stacks[:0]
+	for _, stack := range stacks {
+		// Always skip the running goroutine.
+		if stack.ID() == skipID {
+			continue
+		}
+		// Run any default or user-specified filters.
+		if opts.filter(stack) {
+			continue
+		}
+		filtered = append(filtered, stack)
+	}
+	return filtered
+}
+
+// Find looks for extra goroutines, and returns a descriptive error if
+// any are found.
+func Find(options ...Option) error {
+	cur := stack.Current().ID()
+
+	opts := buildOpts(options...)
+	var stacks []stack.Stack
+	retry := true
+	for i := 0; retry; i++ {
+		stacks = filterStacks(stack.All(), cur, opts)
+
+		if len(stacks) == 0 {
+			return nil
+		}
+		retry = opts.retry(i)
+	}
+
+	return fmt.Errorf("found unexpected goroutines:\n%s", stacks)
+}
+
+// VerifyNone marks the given TestingT as failed if any extra goroutines are
+// found by Find. This is a helper method to make it easier to integrate in
+// tests by doing:
+// 	defer VerifyNone(t)
+func VerifyNone(t TestingT, options ...Option) {
+	if err := Find(options...); err != nil {
+		t.Error(err)
+	}
+}
diff --git a/vendor/go.uber.org/goleak/options.go b/vendor/go.uber.org/goleak/options.go
new file mode 100644
index 000000000..0f6bd9e79
--- /dev/null
+++ b/vendor/go.uber.org/goleak/options.go
@@ -0,0 +1,164 @@
+// 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.
+
+package goleak
+
+import (
+	"strings"
+	"time"
+
+	"go.uber.org/goleak/internal/stack"
+)
+
+// Option lets users specify custom verifications.
+type Option interface {
+	apply(*opts)
+}
+
+// We retry up to 20 times if we can't find the goroutine that
+// we are looking for. In between each attempt, we will sleep for
+// a short while to let any running goroutines complete.
+const _defaultRetries = 20
+
+type opts struct {
+	filters    []func(stack.Stack) bool
+	maxRetries int
+	maxSleep   time.Duration
+}
+
+// optionFunc lets us easily write options without a custom type.
+type optionFunc func(*opts)
+
+func (f optionFunc) apply(opts *opts) { f(opts) }
+
+// IgnoreTopFunction ignores any goroutines where the specified function
+// is at the top of the stack. The function name should be fully qualified,
+// e.g., go.uber.org/goleak.IgnoreTopFunction
+func IgnoreTopFunction(f string) Option {
+	return addFilter(func(s stack.Stack) bool {
+		return s.FirstFunction() == f
+	})
+}
+
+// IgnoreCurrent records all current goroutines when the option is created, and ignores
+// them in any future Find/Verify calls.
+func IgnoreCurrent() Option {
+	excludeIDSet := map[int]bool{}
+	for _, s := range stack.All() {
+		excludeIDSet[s.ID()] = true
+	}
+	return addFilter(func(s stack.Stack) bool {
+		return excludeIDSet[s.ID()]
+	})
+}
+
+func maxSleep(d time.Duration) Option {
+	return optionFunc(func(opts *opts) {
+		opts.maxSleep = d
+	})
+}
+
+func addFilter(f func(stack.Stack) bool) Option {
+	return optionFunc(func(opts *opts) {
+		opts.filters = append(opts.filters, f)
+	})
+}
+
+func buildOpts(options ...Option) *opts {
+	opts := &opts{
+		maxRetries: _defaultRetries,
+		maxSleep:   100 * time.Millisecond,
+	}
+	opts.filters = append(opts.filters,
+		isTestStack,
+		isSyscallStack,
+		isStdLibStack,
+		isTraceStack,
+	)
+	for _, option := range options {
+		option.apply(opts)
+	}
+	return opts
+}
+
+func (vo *opts) filter(s stack.Stack) bool {
+	for _, filter := range vo.filters {
+		if filter(s) {
+			return true
+		}
+	}
+	return false
+}
+
+func (vo *opts) retry(i int) bool {
+	if i >= vo.maxRetries {
+		return false
+	}
+
+	d := time.Duration(int(time.Microsecond) << uint(i))
+	if d > vo.maxSleep {
+		d = vo.maxSleep
+	}
+	time.Sleep(d)
+	return true
+}
+
+// isTestStack is a default filter installed to automatically skip goroutines
+// that the testing package runs while the user's tests are running.
+func isTestStack(s stack.Stack) bool {
+	// Until go1.7, the main goroutine ran RunTests, which started
+	// the test in a separate goroutine and waited for that test goroutine
+	// to end by waiting on a channel.
+	// Since go1.7, a separate goroutine is started to wait for signals.
+	// T.Parallel is for parallel tests, which are blocked until all serial
+	// tests have run with T.Parallel at the top of the stack.
+	switch s.FirstFunction() {
+	case "testing.RunTests", "testing.(*T).Run", "testing.(*T).Parallel":
+		// In pre1.7 and post-1.7, background goroutines started by the testing
+		// package are blocked waiting on a channel.
+		return strings.HasPrefix(s.State(), "chan receive")
+	}
+	return false
+}
+
+func isSyscallStack(s stack.Stack) bool {
+	// Typically runs in the background when code uses CGo:
+	// https://github.com/golang/go/issues/16714
+	return s.FirstFunction() == "runtime.goexit" && strings.HasPrefix(s.State(), "syscall")
+}
+
+func isStdLibStack(s stack.Stack) bool {
+	// Importing os/signal starts a background goroutine.
+	// The name of the function at the top has changed between versions.
+	if f := s.FirstFunction(); f == "os/signal.signal_recv" || f == "os/signal.loop" {
+		return true
+	}
+
+	// Using signal.Notify will start a runtime goroutine.
+	return strings.Contains(s.Full(), "runtime.ensureSigM")
+}
+
+func isTraceStack(s stack.Stack) bool {
+	if f := s.FirstFunction(); f != "runtime.goparkunlock" {
+		return false
+	}
+
+	return strings.Contains(s.Full(), "runtime.ReadTrace")
+}
diff --git a/vendor/go.uber.org/goleak/tools.go b/vendor/go.uber.org/goleak/tools.go
new file mode 100644
index 000000000..6a87612cc
--- /dev/null
+++ b/vendor/go.uber.org/goleak/tools.go
@@ -0,0 +1,28 @@
+// Copyright (c) 2019 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.
+
+// +build tools
+
+package goleak
+
+import (
+	// Tools we use during development.
+	_ "golang.org/x/lint/golint"
+)
diff --git a/vendor/go.uber.org/multierr/.travis.yml b/vendor/go.uber.org/multierr/.travis.yml
index 786c917a3..8636ab42a 100644
--- a/vendor/go.uber.org/multierr/.travis.yml
+++ b/vendor/go.uber.org/multierr/.travis.yml
@@ -4,17 +4,11 @@ go_import_path: go.uber.org/multierr
 
 env:
   global:
-    - GO15VENDOREXPERIMENT=1
     - GO111MODULE=on
 
 go:
-  - 1.11.x
-  - 1.12.x
-  - 1.13.x
-
-cache:
-  directories:
-    - vendor
+  - oldstable
+  - stable
 
 before_install:
 - go version
diff --git a/vendor/go.uber.org/multierr/CHANGELOG.md b/vendor/go.uber.org/multierr/CHANGELOG.md
index 3110c5af0..6f1db9ef4 100644
--- a/vendor/go.uber.org/multierr/CHANGELOG.md
+++ b/vendor/go.uber.org/multierr/CHANGELOG.md
@@ -1,6 +1,12 @@
 Releases
 ========
 
+v1.6.0 (2020-09-14)
+===================
+
+-   Actually drop library dependency on development-time tooling.
+
+
 v1.5.0 (2020-02-24)
 ===================
 
diff --git a/vendor/go.uber.org/multierr/Makefile b/vendor/go.uber.org/multierr/Makefile
index 416018237..316004400 100644
--- a/vendor/go.uber.org/multierr/Makefile
+++ b/vendor/go.uber.org/multierr/Makefile
@@ -21,12 +21,12 @@ gofmt:
 
 .PHONY: golint
 golint:
-	@go install golang.org/x/lint/golint
+	@cd tools && go install golang.org/x/lint/golint
 	@$(GOBIN)/golint ./...
 
 .PHONY: staticcheck
 staticcheck:
-	@go install honnef.co/go/tools/cmd/staticcheck
+	@cd tools && go install honnef.co/go/tools/cmd/staticcheck
 	@$(GOBIN)/staticcheck ./...
 
 .PHONY: lint
@@ -38,5 +38,5 @@ cover:
 	go tool cover -html=cover.out -o cover.html
 
 update-license:
-	@go install go.uber.org/tools/update-license
+	@cd tools && go install go.uber.org/tools/update-license
 	@$(GOBIN)/update-license $(GO_FILES)
diff --git a/vendor/go.uber.org/multierr/error.go b/vendor/go.uber.org/multierr/error.go
index 04eb9618c..5c9b67d53 100644
--- a/vendor/go.uber.org/multierr/error.go
+++ b/vendor/go.uber.org/multierr/error.go
@@ -54,7 +54,7 @@
 //
 // 	errors := multierr.Errors(err)
 // 	if len(errors) > 0 {
-// 		fmt.Println("The following errors occurred:")
+// 		fmt.Println("The following errors occurred:", errors)
 // 	}
 //
 // Advanced Usage
diff --git a/vendor/go.uber.org/multierr/go.mod b/vendor/go.uber.org/multierr/go.mod
index 58d5f90bb..ff8bdf95f 100644
--- a/vendor/go.uber.org/multierr/go.mod
+++ b/vendor/go.uber.org/multierr/go.mod
@@ -4,9 +4,5 @@ go 1.12
 
 require (
 	github.com/stretchr/testify v1.3.0
-	go.uber.org/atomic v1.6.0
-	go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee
-	golang.org/x/lint v0.0.0-20190930215403-16217165b5de
-	golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5 // indirect
-	honnef.co/go/tools v0.0.1-2019.2.3
+	go.uber.org/atomic v1.7.0
 )
diff --git a/vendor/go.uber.org/multierr/go.sum b/vendor/go.uber.org/multierr/go.sum
index 557fbba28..ecfc28657 100644
--- a/vendor/go.uber.org/multierr/go.sum
+++ b/vendor/go.uber.org/multierr/go.sum
@@ -1,45 +1,11 @@
-github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
-github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
 github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
-github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
-github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
-github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
-github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
-github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
 github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
-go.uber.org/atomic v1.6.0 h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk=
-go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
-go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4=
-go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
-golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
-golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs=
-golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
-golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
-golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
-golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
-golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI=
-golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
-golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
-golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
-golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c h1:IGkKhmfzcztjm6gYkykvu/NiS8kaqbCWAEWWAyf8J5U=
-golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5 h1:hKsoRgsbwY1NafxrwTs+k64bikrLBkAgPir1TNCj3Zs=
-golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
-honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM=
-honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
+go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
+go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
diff --git a/vendor/golang.org/x/lint/.travis.yml b/vendor/golang.org/x/lint/.travis.yml
new file mode 100644
index 000000000..50553ebd0
--- /dev/null
+++ b/vendor/golang.org/x/lint/.travis.yml
@@ -0,0 +1,19 @@
+sudo: false
+language: go
+go:
+  - 1.10.x
+  - 1.11.x
+  - master
+
+go_import_path: golang.org/x/lint
+
+install:
+  - go get -t -v ./...
+
+script:
+  - go test -v -race ./...
+
+matrix:
+  allow_failures:
+    - go: master
+  fast_finish: true
diff --git a/vendor/golang.org/x/lint/CONTRIBUTING.md b/vendor/golang.org/x/lint/CONTRIBUTING.md
new file mode 100644
index 000000000..1fadda62d
--- /dev/null
+++ b/vendor/golang.org/x/lint/CONTRIBUTING.md
@@ -0,0 +1,15 @@
+# Contributing to Golint
+
+## Before filing an issue:
+
+### Are you having trouble building golint?
+
+Check you have the latest version of its dependencies. Run
+```
+go get -u golang.org/x/lint/golint
+```
+If you still have problems, consider searching for existing issues before filing a new issue.
+
+## Before sending a pull request:
+
+Have you understood the purpose of golint? Make sure to carefully read `README`.
diff --git a/vendor/golang.org/x/lint/LICENSE b/vendor/golang.org/x/lint/LICENSE
new file mode 100644
index 000000000..65d761bc9
--- /dev/null
+++ b/vendor/golang.org/x/lint/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2013 The Go Authors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+   * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+   * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/golang.org/x/lint/README.md b/vendor/golang.org/x/lint/README.md
new file mode 100644
index 000000000..4968b13ae
--- /dev/null
+++ b/vendor/golang.org/x/lint/README.md
@@ -0,0 +1,88 @@
+Golint is a linter for Go source code.
+
+[![Build Status](https://travis-ci.org/golang/lint.svg?branch=master)](https://travis-ci.org/golang/lint)
+
+## Installation
+
+Golint requires a
+[supported release of Go](https://golang.org/doc/devel/release.html#policy).
+
+    go get -u golang.org/x/lint/golint
+
+To find out where `golint` was installed you can run `go list -f {{.Target}} golang.org/x/lint/golint`. For `golint` to be used globally add that directory to the `$PATH` environment setting.
+
+## Usage
+
+Invoke `golint` with one or more filenames, directories, or packages named
+by its import path. Golint uses the same
+[import path syntax](https://golang.org/cmd/go/#hdr-Import_path_syntax) as
+the `go` command and therefore
+also supports relative import paths like `./...`. Additionally the `...`
+wildcard can be used as suffix on relative and absolute file paths to recurse
+into them.
+
+The output of this tool is a list of suggestions in Vim quickfix format,
+which is accepted by lots of different editors.
+
+## Purpose
+
+Golint differs from gofmt. Gofmt reformats Go source code, whereas
+golint prints out style mistakes.
+
+Golint differs from govet. Govet is concerned with correctness, whereas
+golint is concerned with coding style. Golint is in use at Google, and it
+seeks to match the accepted style of the open source Go project.
+
+The suggestions made by golint are exactly that: suggestions.
+Golint is not perfect, and has both false positives and false negatives.
+Do not treat its output as a gold standard. We will not be adding pragmas
+or other knobs to suppress specific warnings, so do not expect or require
+code to be completely "lint-free".
+In short, this tool is not, and will never be, trustworthy enough for its
+suggestions to be enforced automatically, for example as part of a build process.
+Golint makes suggestions for many of the mechanically checkable items listed in
+[Effective Go](https://golang.org/doc/effective_go.html) and the
+[CodeReviewComments wiki page](https://golang.org/wiki/CodeReviewComments).
+
+## Scope
+
+Golint is meant to carry out the stylistic conventions put forth in
+[Effective Go](https://golang.org/doc/effective_go.html) and
+[CodeReviewComments](https://golang.org/wiki/CodeReviewComments).
+Changes that are not aligned with those documents will not be considered.
+
+## Contributions
+
+Contributions to this project are welcome provided they are [in scope](#scope),
+though please send mail before starting work on anything major.
+Contributors retain their copyright, so we need you to fill out
+[a short form](https://developers.google.com/open-source/cla/individual)
+before we can accept your contribution.
+
+## Vim
+
+Add this to your ~/.vimrc:
+
+    set rtp+=$GOPATH/src/golang.org/x/lint/misc/vim
+
+If you have multiple entries in your GOPATH, replace `$GOPATH` with the right value.
+
+Running `:Lint` will run golint on the current file and populate the quickfix list.
+
+Optionally, add this to your `~/.vimrc` to automatically run `golint` on `:w`
+
+    autocmd BufWritePost,FileWritePost *.go execute 'Lint' | cwindow
+
+
+## Emacs
+
+Add this to your `.emacs` file:
+
+    (add-to-list 'load-path (concat (getenv "GOPATH")  "/src/golang.org/x/lint/misc/emacs/"))
+    (require 'golint)
+
+If you have multiple entries in your GOPATH, replace `$GOPATH` with the right value.
+
+Running M-x golint will run golint on the current file.
+
+For more usage, see [Compilation-Mode](http://www.gnu.org/software/emacs/manual/html_node/emacs/Compilation-Mode.html).
diff --git a/vendor/golang.org/x/lint/go.mod b/vendor/golang.org/x/lint/go.mod
new file mode 100644
index 000000000..b32309c45
--- /dev/null
+++ b/vendor/golang.org/x/lint/go.mod
@@ -0,0 +1,5 @@
+module golang.org/x/lint
+
+go 1.11
+
+require golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7
diff --git a/vendor/golang.org/x/lint/go.sum b/vendor/golang.org/x/lint/go.sum
new file mode 100644
index 000000000..2ad45cae2
--- /dev/null
+++ b/vendor/golang.org/x/lint/go.sum
@@ -0,0 +1,12 @@
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7 h1:EBZoQjiKKPaLbPrbpssUfuHtwM6KV/vb4U85g/cigFY=
+golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
diff --git a/vendor/golang.org/x/lint/golint/golint.go b/vendor/golang.org/x/lint/golint/golint.go
new file mode 100644
index 000000000..ac024b6d2
--- /dev/null
+++ b/vendor/golang.org/x/lint/golint/golint.go
@@ -0,0 +1,159 @@
+// Copyright (c) 2013 The Go Authors. All rights reserved.
+//
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file or at
+// https://developers.google.com/open-source/licenses/bsd.
+
+// golint lints the Go source files named on its command line.
+package main
+
+import (
+	"flag"
+	"fmt"
+	"go/build"
+	"io/ioutil"
+	"os"
+	"path/filepath"
+	"strings"
+
+	"golang.org/x/lint"
+)
+
+var (
+	minConfidence = flag.Float64("min_confidence", 0.8, "minimum confidence of a problem to print it")
+	setExitStatus = flag.Bool("set_exit_status", false, "set exit status to 1 if any issues are found")
+	suggestions   int
+)
+
+func usage() {
+	fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
+	fmt.Fprintf(os.Stderr, "\tgolint [flags] # runs on package in current directory\n")
+	fmt.Fprintf(os.Stderr, "\tgolint [flags] [packages]\n")
+	fmt.Fprintf(os.Stderr, "\tgolint [flags] [directories] # where a '/...' suffix includes all sub-directories\n")
+	fmt.Fprintf(os.Stderr, "\tgolint [flags] [files] # all must belong to a single package\n")
+	fmt.Fprintf(os.Stderr, "Flags:\n")
+	flag.PrintDefaults()
+}
+
+func main() {
+	flag.Usage = usage
+	flag.Parse()
+
+	if flag.NArg() == 0 {
+		lintDir(".")
+	} else {
+		// dirsRun, filesRun, and pkgsRun indicate whether golint is applied to
+		// directory, file or package targets. The distinction affects which
+		// checks are run. It is no valid to mix target types.
+		var dirsRun, filesRun, pkgsRun int
+		var args []string
+		for _, arg := range flag.Args() {
+			if strings.HasSuffix(arg, "/...") && isDir(arg[:len(arg)-len("/...")]) {
+				dirsRun = 1
+				for _, dirname := range allPackagesInFS(arg) {
+					args = append(args, dirname)
+				}
+			} else if isDir(arg) {
+				dirsRun = 1
+				args = append(args, arg)
+			} else if exists(arg) {
+				filesRun = 1
+				args = append(args, arg)
+			} else {
+				pkgsRun = 1
+				args = append(args, arg)
+			}
+		}
+
+		if dirsRun+filesRun+pkgsRun != 1 {
+			usage()
+			os.Exit(2)
+		}
+		switch {
+		case dirsRun == 1:
+			for _, dir := range args {
+				lintDir(dir)
+			}
+		case filesRun == 1:
+			lintFiles(args...)
+		case pkgsRun == 1:
+			for _, pkg := range importPaths(args) {
+				lintPackage(pkg)
+			}
+		}
+	}
+
+	if *setExitStatus && suggestions > 0 {
+		fmt.Fprintf(os.Stderr, "Found %d lint suggestions; failing.\n", suggestions)
+		os.Exit(1)
+	}
+}
+
+func isDir(filename string) bool {
+	fi, err := os.Stat(filename)
+	return err == nil && fi.IsDir()
+}
+
+func exists(filename string) bool {
+	_, err := os.Stat(filename)
+	return err == nil
+}
+
+func lintFiles(filenames ...string) {
+	files := make(map[string][]byte)
+	for _, filename := range filenames {
+		src, err := ioutil.ReadFile(filename)
+		if err != nil {
+			fmt.Fprintln(os.Stderr, err)
+			continue
+		}
+		files[filename] = src
+	}
+
+	l := new(lint.Linter)
+	ps, err := l.LintFiles(files)
+	if err != nil {
+		fmt.Fprintf(os.Stderr, "%v\n", err)
+		return
+	}
+	for _, p := range ps {
+		if p.Confidence >= *minConfidence {
+			fmt.Printf("%v: %s\n", p.Position, p.Text)
+			suggestions++
+		}
+	}
+}
+
+func lintDir(dirname string) {
+	pkg, err := build.ImportDir(dirname, 0)
+	lintImportedPackage(pkg, err)
+}
+
+func lintPackage(pkgname string) {
+	pkg, err := build.Import(pkgname, ".", 0)
+	lintImportedPackage(pkg, err)
+}
+
+func lintImportedPackage(pkg *build.Package, err error) {
+	if err != nil {
+		if _, nogo := err.(*build.NoGoError); nogo {
+			// Don't complain if the failure is due to no Go source files.
+			return
+		}
+		fmt.Fprintln(os.Stderr, err)
+		return
+	}
+
+	var files []string
+	files = append(files, pkg.GoFiles...)
+	files = append(files, pkg.CgoFiles...)
+	files = append(files, pkg.TestGoFiles...)
+	if pkg.Dir != "." {
+		for i, f := range files {
+			files[i] = filepath.Join(pkg.Dir, f)
+		}
+	}
+	// TODO(dsymonds): Do foo_test too (pkg.XTestGoFiles)
+
+	lintFiles(files...)
+}
diff --git a/vendor/golang.org/x/lint/golint/import.go b/vendor/golang.org/x/lint/golint/import.go
new file mode 100644
index 000000000..2ba9dea77
--- /dev/null
+++ b/vendor/golang.org/x/lint/golint/import.go
@@ -0,0 +1,309 @@
+package main
+
+/*
+
+This file holds a direct copy of the import path matching code of
+https://github.com/golang/go/blob/master/src/cmd/go/main.go. It can be
+replaced when https://golang.org/issue/8768 is resolved.
+
+It has been updated to follow upstream changes in a few ways.
+
+*/
+
+import (
+	"fmt"
+	"go/build"
+	"log"
+	"os"
+	"path"
+	"path/filepath"
+	"regexp"
+	"runtime"
+	"strings"
+)
+
+var (
+	buildContext = build.Default
+	goroot       = filepath.Clean(runtime.GOROOT())
+	gorootSrc    = filepath.Join(goroot, "src")
+)
+
+// importPathsNoDotExpansion returns the import paths to use for the given
+// command line, but it does no ... expansion.
+func importPathsNoDotExpansion(args []string) []string {
+	if len(args) == 0 {
+		return []string{"."}
+	}
+	var out []string
+	for _, a := range args {
+		// Arguments are supposed to be import paths, but
+		// as a courtesy to Windows developers, rewrite \ to /
+		// in command-line arguments.  Handles .\... and so on.
+		if filepath.Separator == '\\' {
+			a = strings.Replace(a, `\`, `/`, -1)
+		}
+
+		// Put argument in canonical form, but preserve leading ./.
+		if strings.HasPrefix(a, "./") {
+			a = "./" + path.Clean(a)
+			if a == "./." {
+				a = "."
+			}
+		} else {
+			a = path.Clean(a)
+		}
+		if a == "all" || a == "std" {
+			out = append(out, allPackages(a)...)
+			continue
+		}
+		out = append(out, a)
+	}
+	return out
+}
+
+// importPaths returns the import paths to use for the given command line.
+func importPaths(args []string) []string {
+	args = importPathsNoDotExpansion(args)
+	var out []string
+	for _, a := range args {
+		if strings.Contains(a, "...") {
+			if build.IsLocalImport(a) {
+				out = append(out, allPackagesInFS(a)...)
+			} else {
+				out = append(out, allPackages(a)...)
+			}
+			continue
+		}
+		out = append(out, a)
+	}
+	return out
+}
+
+// matchPattern(pattern)(name) reports whether
+// name matches pattern.  Pattern is a limited glob
+// pattern in which '...' means 'any string' and there
+// is no other special syntax.
+func matchPattern(pattern string) func(name string) bool {
+	re := regexp.QuoteMeta(pattern)
+	re = strings.Replace(re, `\.\.\.`, `.*`, -1)
+	// Special case: foo/... matches foo too.
+	if strings.HasSuffix(re, `/.*`) {
+		re = re[:len(re)-len(`/.*`)] + `(/.*)?`
+	}
+	reg := regexp.MustCompile(`^` + re + `$`)
+	return func(name string) bool {
+		return reg.MatchString(name)
+	}
+}
+
+// hasPathPrefix reports whether the path s begins with the
+// elements in prefix.
+func hasPathPrefix(s, prefix string) bool {
+	switch {
+	default:
+		return false
+	case len(s) == len(prefix):
+		return s == prefix
+	case len(s) > len(prefix):
+		if prefix != "" && prefix[len(prefix)-1] == '/' {
+			return strings.HasPrefix(s, prefix)
+		}
+		return s[len(prefix)] == '/' && s[:len(prefix)] == prefix
+	}
+}
+
+// treeCanMatchPattern(pattern)(name) reports whether
+// name or children of name can possibly match pattern.
+// Pattern is the same limited glob accepted by matchPattern.
+func treeCanMatchPattern(pattern string) func(name string) bool {
+	wildCard := false
+	if i := strings.Index(pattern, "..."); i >= 0 {
+		wildCard = true
+		pattern = pattern[:i]
+	}
+	return func(name string) bool {
+		return len(name) <= len(pattern) && hasPathPrefix(pattern, name) ||
+			wildCard && strings.HasPrefix(name, pattern)
+	}
+}
+
+// allPackages returns all the packages that can be found
+// under the $GOPATH directories and $GOROOT matching pattern.
+// The pattern is either "all" (all packages), "std" (standard packages)
+// or a path including "...".
+func allPackages(pattern string) []string {
+	pkgs := matchPackages(pattern)
+	if len(pkgs) == 0 {
+		fmt.Fprintf(os.Stderr, "warning: %q matched no packages\n", pattern)
+	}
+	return pkgs
+}
+
+func matchPackages(pattern string) []string {
+	match := func(string) bool { return true }
+	treeCanMatch := func(string) bool { return true }
+	if pattern != "all" && pattern != "std" {
+		match = matchPattern(pattern)
+		treeCanMatch = treeCanMatchPattern(pattern)
+	}
+
+	have := map[string]bool{
+		"builtin": true, // ignore pseudo-package that exists only for documentation
+	}
+	if !buildContext.CgoEnabled {
+		have["runtime/cgo"] = true // ignore during walk
+	}
+	var pkgs []string
+
+	// Commands
+	cmd := filepath.Join(goroot, "src/cmd") + string(filepath.Separator)
+	filepath.Walk(cmd, func(path string, fi os.FileInfo, err error) error {
+		if err != nil || !fi.IsDir() || path == cmd {
+			return nil
+		}
+		name := path[len(cmd):]
+		if !treeCanMatch(name) {
+			return filepath.SkipDir
+		}
+		// Commands are all in cmd/, not in subdirectories.
+		if strings.Contains(name, string(filepath.Separator)) {
+			return filepath.SkipDir
+		}
+
+		// We use, e.g., cmd/gofmt as the pseudo import path for gofmt.
+		name = "cmd/" + name
+		if have[name] {
+			return nil
+		}
+		have[name] = true
+		if !match(name) {
+			return nil
+		}
+		_, err = buildContext.ImportDir(path, 0)
+		if err != nil {
+			if _, noGo := err.(*build.NoGoError); !noGo {
+				log.Print(err)
+			}
+			return nil
+		}
+		pkgs = append(pkgs, name)
+		return nil
+	})
+
+	for _, src := range buildContext.SrcDirs() {
+		if (pattern == "std" || pattern == "cmd") && src != gorootSrc {
+			continue
+		}
+		src = filepath.Clean(src) + string(filepath.Separator)
+		root := src
+		if pattern == "cmd" {
+			root += "cmd" + string(filepath.Separator)
+		}
+		filepath.Walk(root, func(path string, fi os.FileInfo, err error) error {
+			if err != nil || !fi.IsDir() || path == src {
+				return nil
+			}
+
+			// Avoid .foo, _foo, and testdata directory trees.
+			_, elem := filepath.Split(path)
+			if strings.HasPrefix(elem, ".") || strings.HasPrefix(elem, "_") || elem == "testdata" {
+				return filepath.SkipDir
+			}
+
+			name := filepath.ToSlash(path[len(src):])
+			if pattern == "std" && (strings.Contains(name, ".") || name == "cmd") {
+				// The name "std" is only the standard library.
+				// If the name is cmd, it's the root of the command tree.
+				return filepath.SkipDir
+			}
+			if !treeCanMatch(name) {
+				return filepath.SkipDir
+			}
+			if have[name] {
+				return nil
+			}
+			have[name] = true
+			if !match(name) {
+				return nil
+			}
+			_, err = buildContext.ImportDir(path, 0)
+			if err != nil {
+				if _, noGo := err.(*build.NoGoError); noGo {
+					return nil
+				}
+			}
+			pkgs = append(pkgs, name)
+			return nil
+		})
+	}
+	return pkgs
+}
+
+// allPackagesInFS is like allPackages but is passed a pattern
+// beginning ./ or ../, meaning it should scan the tree rooted
+// at the given directory.  There are ... in the pattern too.
+func allPackagesInFS(pattern string) []string {
+	pkgs := matchPackagesInFS(pattern)
+	if len(pkgs) == 0 {
+		fmt.Fprintf(os.Stderr, "warning: %q matched no packages\n", pattern)
+	}
+	return pkgs
+}
+
+func matchPackagesInFS(pattern string) []string {
+	// Find directory to begin the scan.
+	// Could be smarter but this one optimization
+	// is enough for now, since ... is usually at the
+	// end of a path.
+	i := strings.Index(pattern, "...")
+	dir, _ := path.Split(pattern[:i])
+
+	// pattern begins with ./ or ../.
+	// path.Clean will discard the ./ but not the ../.
+	// We need to preserve the ./ for pattern matching
+	// and in the returned import paths.
+	prefix := ""
+	if strings.HasPrefix(pattern, "./") {
+		prefix = "./"
+	}
+	match := matchPattern(pattern)
+
+	var pkgs []string
+	filepath.Walk(dir, func(path string, fi os.FileInfo, err error) error {
+		if err != nil || !fi.IsDir() {
+			return nil
+		}
+		if path == dir {
+			// filepath.Walk starts at dir and recurses. For the recursive case,
+			// the path is the result of filepath.Join, which calls filepath.Clean.
+			// The initial case is not Cleaned, though, so we do this explicitly.
+			//
+			// This converts a path like "./io/" to "io". Without this step, running
+			// "cd $GOROOT/src/pkg; go list ./io/..." would incorrectly skip the io
+			// package, because prepending the prefix "./" to the unclean path would
+			// result in "././io", and match("././io") returns false.
+			path = filepath.Clean(path)
+		}
+
+		// Avoid .foo, _foo, and testdata directory trees, but do not avoid "." or "..".
+		_, elem := filepath.Split(path)
+		dot := strings.HasPrefix(elem, ".") && elem != "." && elem != ".."
+		if dot || strings.HasPrefix(elem, "_") || elem == "testdata" {
+			return filepath.SkipDir
+		}
+
+		name := prefix + filepath.ToSlash(path)
+		if !match(name) {
+			return nil
+		}
+		if _, err = build.ImportDir(path, 0); err != nil {
+			if _, noGo := err.(*build.NoGoError); !noGo {
+				log.Print(err)
+			}
+			return nil
+		}
+		pkgs = append(pkgs, name)
+		return nil
+	})
+	return pkgs
+}
diff --git a/vendor/golang.org/x/lint/golint/importcomment.go b/vendor/golang.org/x/lint/golint/importcomment.go
new file mode 100644
index 000000000..d5b32f734
--- /dev/null
+++ b/vendor/golang.org/x/lint/golint/importcomment.go
@@ -0,0 +1,13 @@
+// Copyright (c) 2018 The Go Authors. All rights reserved.
+//
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file or at
+// https://developers.google.com/open-source/licenses/bsd.
+
+// +build go1.12
+
+// Require use of the correct import path only for Go 1.12+ users, so
+// any breakages coincide with people updating their CI configs or
+// whatnot.
+
+package main // import "golang.org/x/lint/golint"
diff --git a/vendor/golang.org/x/lint/lint.go b/vendor/golang.org/x/lint/lint.go
new file mode 100644
index 000000000..7d813e061
--- /dev/null
+++ b/vendor/golang.org/x/lint/lint.go
@@ -0,0 +1,1615 @@
+// Copyright (c) 2013 The Go Authors. All rights reserved.
+//
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file or at
+// https://developers.google.com/open-source/licenses/bsd.
+
+// Package lint contains a linter for Go source code.
+package lint // import "golang.org/x/lint"
+
+import (
+	"bufio"
+	"bytes"
+	"fmt"
+	"go/ast"
+	"go/parser"
+	"go/printer"
+	"go/token"
+	"go/types"
+	"regexp"
+	"sort"
+	"strconv"
+	"strings"
+	"unicode"
+	"unicode/utf8"
+
+	"golang.org/x/tools/go/ast/astutil"
+	"golang.org/x/tools/go/gcexportdata"
+)
+
+const styleGuideBase = "https://golang.org/wiki/CodeReviewComments"
+
+// A Linter lints Go source code.
+type Linter struct {
+}
+
+// Problem represents a problem in some source code.
+type Problem struct {
+	Position   token.Position // position in source file
+	Text       string         // the prose that describes the problem
+	Link       string         // (optional) the link to the style guide for the problem
+	Confidence float64        // a value in (0,1] estimating the confidence in this problem's correctness
+	LineText   string         // the source line
+	Category   string         // a short name for the general category of the problem
+
+	// If the problem has a suggested fix (the minority case),
+	// ReplacementLine is a full replacement for the relevant line of the source file.
+	ReplacementLine string
+}
+
+func (p *Problem) String() string {
+	if p.Link != "" {
+		return p.Text + "\n\n" + p.Link
+	}
+	return p.Text
+}
+
+type byPosition []Problem
+
+func (p byPosition) Len() int      { return len(p) }
+func (p byPosition) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
+
+func (p byPosition) Less(i, j int) bool {
+	pi, pj := p[i].Position, p[j].Position
+
+	if pi.Filename != pj.Filename {
+		return pi.Filename < pj.Filename
+	}
+	if pi.Line != pj.Line {
+		return pi.Line < pj.Line
+	}
+	if pi.Column != pj.Column {
+		return pi.Column < pj.Column
+	}
+
+	return p[i].Text < p[j].Text
+}
+
+// Lint lints src.
+func (l *Linter) Lint(filename string, src []byte) ([]Problem, error) {
+	return l.LintFiles(map[string][]byte{filename: src})
+}
+
+// LintFiles lints a set of files of a single package.
+// The argument is a map of filename to source.
+func (l *Linter) LintFiles(files map[string][]byte) ([]Problem, error) {
+	pkg := &pkg{
+		fset:  token.NewFileSet(),
+		files: make(map[string]*file),
+	}
+	var pkgName string
+	for filename, src := range files {
+		if isGenerated(src) {
+			continue // See issue #239
+		}
+		f, err := parser.ParseFile(pkg.fset, filename, src, parser.ParseComments)
+		if err != nil {
+			return nil, err
+		}
+		if pkgName == "" {
+			pkgName = f.Name.Name
+		} else if f.Name.Name != pkgName {
+			return nil, fmt.Errorf("%s is in package %s, not %s", filename, f.Name.Name, pkgName)
+		}
+		pkg.files[filename] = &file{
+			pkg:      pkg,
+			f:        f,
+			fset:     pkg.fset,
+			src:      src,
+			filename: filename,
+		}
+	}
+	if len(pkg.files) == 0 {
+		return nil, nil
+	}
+	return pkg.lint(), nil
+}
+
+var (
+	genHdr = []byte("// Code generated ")
+	genFtr = []byte(" DO NOT EDIT.")
+)
+
+// isGenerated reports whether the source file is generated code
+// according the rules from https://golang.org/s/generatedcode.
+func isGenerated(src []byte) bool {
+	sc := bufio.NewScanner(bytes.NewReader(src))
+	for sc.Scan() {
+		b := sc.Bytes()
+		if bytes.HasPrefix(b, genHdr) && bytes.HasSuffix(b, genFtr) && len(b) >= len(genHdr)+len(genFtr) {
+			return true
+		}
+	}
+	return false
+}
+
+// pkg represents a package being linted.
+type pkg struct {
+	fset  *token.FileSet
+	files map[string]*file
+
+	typesPkg  *types.Package
+	typesInfo *types.Info
+
+	// sortable is the set of types in the package that implement sort.Interface.
+	sortable map[string]bool
+	// main is whether this is a "main" package.
+	main bool
+
+	problems []Problem
+}
+
+func (p *pkg) lint() []Problem {
+	if err := p.typeCheck(); err != nil {
+		/* TODO(dsymonds): Consider reporting these errors when golint operates on entire packages.
+		if e, ok := err.(types.Error); ok {
+			pos := p.fset.Position(e.Pos)
+			conf := 1.0
+			if strings.Contains(e.Msg, "can't find import: ") {
+				// Golint is probably being run in a context that doesn't support
+				// typechecking (e.g. package files aren't found), so don't warn about it.
+				conf = 0
+			}
+			if conf > 0 {
+				p.errorfAt(pos, conf, category("typechecking"), e.Msg)
+			}
+
+			// TODO(dsymonds): Abort if !e.Soft?
+		}
+		*/
+	}
+
+	p.scanSortable()
+	p.main = p.isMain()
+
+	for _, f := range p.files {
+		f.lint()
+	}
+
+	sort.Sort(byPosition(p.problems))
+
+	return p.problems
+}
+
+// file represents a file being linted.
+type file struct {
+	pkg      *pkg
+	f        *ast.File
+	fset     *token.FileSet
+	src      []byte
+	filename string
+}
+
+func (f *file) isTest() bool { return strings.HasSuffix(f.filename, "_test.go") }
+
+func (f *file) lint() {
+	f.lintPackageComment()
+	f.lintImports()
+	f.lintBlankImports()
+	f.lintExported()
+	f.lintNames()
+	f.lintElses()
+	f.lintRanges()
+	f.lintErrorf()
+	f.lintErrors()
+	f.lintErrorStrings()
+	f.lintReceiverNames()
+	f.lintIncDec()
+	f.lintErrorReturn()
+	f.lintUnexportedReturn()
+	f.lintTimeNames()
+	f.lintContextKeyTypes()
+	f.lintContextArgs()
+}
+
+type link string
+type category string
+
+// The variadic arguments may start with link and category types,
+// and must end with a format string and any arguments.
+// It returns the new Problem.
+func (f *file) errorf(n ast.Node, confidence float64, args ...interface{}) *Problem {
+	pos := f.fset.Position(n.Pos())
+	if pos.Filename == "" {
+		pos.Filename = f.filename
+	}
+	return f.pkg.errorfAt(pos, confidence, args...)
+}
+
+func (p *pkg) errorfAt(pos token.Position, confidence float64, args ...interface{}) *Problem {
+	problem := Problem{
+		Position:   pos,
+		Confidence: confidence,
+	}
+	if pos.Filename != "" {
+		// The file might not exist in our mapping if a //line directive was encountered.
+		if f, ok := p.files[pos.Filename]; ok {
+			problem.LineText = srcLine(f.src, pos)
+		}
+	}
+
+argLoop:
+	for len(args) > 1 { // always leave at least the format string in args
+		switch v := args[0].(type) {
+		case link:
+			problem.Link = string(v)
+		case category:
+			problem.Category = string(v)
+		default:
+			break argLoop
+		}
+		args = args[1:]
+	}
+
+	problem.Text = fmt.Sprintf(args[0].(string), args[1:]...)
+
+	p.problems = append(p.problems, problem)
+	return &p.problems[len(p.problems)-1]
+}
+
+var newImporter = func(fset *token.FileSet) types.ImporterFrom {
+	return gcexportdata.NewImporter(fset, make(map[string]*types.Package))
+}
+
+func (p *pkg) typeCheck() error {
+	config := &types.Config{
+		// By setting a no-op error reporter, the type checker does as much work as possible.
+		Error:    func(error) {},
+		Importer: newImporter(p.fset),
+	}
+	info := &types.Info{
+		Types:  make(map[ast.Expr]types.TypeAndValue),
+		Defs:   make(map[*ast.Ident]types.Object),
+		Uses:   make(map[*ast.Ident]types.Object),
+		Scopes: make(map[ast.Node]*types.Scope),
+	}
+	var anyFile *file
+	var astFiles []*ast.File
+	for _, f := range p.files {
+		anyFile = f
+		astFiles = append(astFiles, f.f)
+	}
+	pkg, err := config.Check(anyFile.f.Name.Name, p.fset, astFiles, info)
+	// Remember the typechecking info, even if config.Check failed,
+	// since we will get partial information.
+	p.typesPkg = pkg
+	p.typesInfo = info
+	return err
+}
+
+func (p *pkg) typeOf(expr ast.Expr) types.Type {
+	if p.typesInfo == nil {
+		return nil
+	}
+	return p.typesInfo.TypeOf(expr)
+}
+
+func (p *pkg) isNamedType(typ types.Type, importPath, name string) bool {
+	n, ok := typ.(*types.Named)
+	if !ok {
+		return false
+	}
+	tn := n.Obj()
+	return tn != nil && tn.Pkg() != nil && tn.Pkg().Path() == importPath && tn.Name() == name
+}
+
+// scopeOf returns the tightest scope encompassing id.
+func (p *pkg) scopeOf(id *ast.Ident) *types.Scope {
+	var scope *types.Scope
+	if obj := p.typesInfo.ObjectOf(id); obj != nil {
+		scope = obj.Parent()
+	}
+	if scope == p.typesPkg.Scope() {
+		// We were given a top-level identifier.
+		// Use the file-level scope instead of the package-level scope.
+		pos := id.Pos()
+		for _, f := range p.files {
+			if f.f.Pos() <= pos && pos < f.f.End() {
+				scope = p.typesInfo.Scopes[f.f]
+				break
+			}
+		}
+	}
+	return scope
+}
+
+func (p *pkg) scanSortable() {
+	p.sortable = make(map[string]bool)
+
+	// bitfield for which methods exist on each type.
+	const (
+		Len = 1 << iota
+		Less
+		Swap
+	)
+	nmap := map[string]int{"Len": Len, "Less": Less, "Swap": Swap}
+	has := make(map[string]int)
+	for _, f := range p.files {
+		f.walk(func(n ast.Node) bool {
+			fn, ok := n.(*ast.FuncDecl)
+			if !ok || fn.Recv == nil || len(fn.Recv.List) == 0 {
+				return true
+			}
+			// TODO(dsymonds): We could check the signature to be more precise.
+			recv := receiverType(fn)
+			if i, ok := nmap[fn.Name.Name]; ok {
+				has[recv] |= i
+			}
+			return false
+		})
+	}
+	for typ, ms := range has {
+		if ms == Len|Less|Swap {
+			p.sortable[typ] = true
+		}
+	}
+}
+
+func (p *pkg) isMain() bool {
+	for _, f := range p.files {
+		if f.isMain() {
+			return true
+		}
+	}
+	return false
+}
+
+func (f *file) isMain() bool {
+	if f.f.Name.Name == "main" {
+		return true
+	}
+	return false
+}
+
+// lintPackageComment checks package comments. It complains if
+// there is no package comment, or if it is not of the right form.
+// This has a notable false positive in that a package comment
+// could rightfully appear in a different file of the same package,
+// but that's not easy to fix since this linter is file-oriented.
+func (f *file) lintPackageComment() {
+	if f.isTest() {
+		return
+	}
+
+	const ref = styleGuideBase + "#package-comments"
+	prefix := "Package " + f.f.Name.Name + " "
+
+	// Look for a detached package comment.
+	// First, scan for the last comment that occurs before the "package" keyword.
+	var lastCG *ast.CommentGroup
+	for _, cg := range f.f.Comments {
+		if cg.Pos() > f.f.Package {
+			// Gone past "package" keyword.
+			break
+		}
+		lastCG = cg
+	}
+	if lastCG != nil && strings.HasPrefix(lastCG.Text(), prefix) {
+		endPos := f.fset.Position(lastCG.End())
+		pkgPos := f.fset.Position(f.f.Package)
+		if endPos.Line+1 < pkgPos.Line {
+			// There isn't a great place to anchor this error;
+			// the start of the blank lines between the doc and the package statement
+			// is at least pointing at the location of the problem.
+			pos := token.Position{
+				Filename: endPos.Filename,
+				// Offset not set; it is non-trivial, and doesn't appear to be needed.
+				Line:   endPos.Line + 1,
+				Column: 1,
+			}
+			f.pkg.errorfAt(pos, 0.9, link(ref), category("comments"), "package comment is detached; there should be no blank lines between it and the package statement")
+			return
+		}
+	}
+
+	if f.f.Doc == nil {
+		f.errorf(f.f, 0.2, link(ref), category("comments"), "should have a package comment, unless it's in another file for this package")
+		return
+	}
+	s := f.f.Doc.Text()
+	if ts := strings.TrimLeft(s, " \t"); ts != s {
+		f.errorf(f.f.Doc, 1, link(ref), category("comments"), "package comment should not have leading space")
+		s = ts
+	}
+	// Only non-main packages need to keep to this form.
+	if !f.pkg.main && !strings.HasPrefix(s, prefix) {
+		f.errorf(f.f.Doc, 1, link(ref), category("comments"), `package comment should be of the form "%s..."`, prefix)
+	}
+}
+
+// lintBlankImports complains if a non-main package has blank imports that are
+// not documented.
+func (f *file) lintBlankImports() {
+	// In package main and in tests, we don't complain about blank imports.
+	if f.pkg.main || f.isTest() {
+		return
+	}
+
+	// The first element of each contiguous group of blank imports should have
+	// an explanatory comment of some kind.
+	for i, imp := range f.f.Imports {
+		pos := f.fset.Position(imp.Pos())
+
+		if !isBlank(imp.Name) {
+			continue // Ignore non-blank imports.
+		}
+		if i > 0 {
+			prev := f.f.Imports[i-1]
+			prevPos := f.fset.Position(prev.Pos())
+			if isBlank(prev.Name) && prevPos.Line+1 == pos.Line {
+				continue // A subsequent blank in a group.
+			}
+		}
+
+		// This is the first blank import of a group.
+		if imp.Doc == nil && imp.Comment == nil {
+			ref := ""
+			f.errorf(imp, 1, link(ref), category("imports"), "a blank import should be only in a main or test package, or have a comment justifying it")
+		}
+	}
+}
+
+// lintImports examines import blocks.
+func (f *file) lintImports() {
+	for i, is := range f.f.Imports {
+		_ = i
+		if is.Name != nil && is.Name.Name == "." && !f.isTest() {
+			f.errorf(is, 1, link(styleGuideBase+"#import-dot"), category("imports"), "should not use dot imports")
+		}
+
+	}
+}
+
+const docCommentsLink = styleGuideBase + "#doc-comments"
+
+// lintExported examines the exported names.
+// It complains if any required doc comments are missing,
+// or if they are not of the right form. The exact rules are in
+// lintFuncDoc, lintTypeDoc and lintValueSpecDoc; this function
+// also tracks the GenDecl structure being traversed to permit
+// doc comments for constants to be on top of the const block.
+// It also complains if the names stutter when combined with
+// the package name.
+func (f *file) lintExported() {
+	if f.isTest() {
+		return
+	}
+
+	var lastGen *ast.GenDecl // last GenDecl entered.
+
+	// Set of GenDecls that have already had missing comments flagged.
+	genDeclMissingComments := make(map[*ast.GenDecl]bool)
+
+	f.walk(func(node ast.Node) bool {
+		switch v := node.(type) {
+		case *ast.GenDecl:
+			if v.Tok == token.IMPORT {
+				return false
+			}
+			// token.CONST, token.TYPE or token.VAR
+			lastGen = v
+			return true
+		case *ast.FuncDecl:
+			f.lintFuncDoc(v)
+			if v.Recv == nil {
+				// Only check for stutter on functions, not methods.
+				// Method names are not used package-qualified.
+				f.checkStutter(v.Name, "func")
+			}
+			// Don't proceed inside funcs.
+			return false
+		case *ast.TypeSpec:
+			// inside a GenDecl, which usually has the doc
+			doc := v.Doc
+			if doc == nil {
+				doc = lastGen.Doc
+			}
+			f.lintTypeDoc(v, doc)
+			f.checkStutter(v.Name, "type")
+			// Don't proceed inside types.
+			return false
+		case *ast.ValueSpec:
+			f.lintValueSpecDoc(v, lastGen, genDeclMissingComments)
+			return false
+		}
+		return true
+	})
+}
+
+var (
+	allCapsRE = regexp.MustCompile(`^[A-Z0-9_]+$`)
+	anyCapsRE = regexp.MustCompile(`[A-Z]`)
+)
+
+// knownNameExceptions is a set of names that are known to be exempt from naming checks.
+// This is usually because they are constrained by having to match names in the
+// standard library.
+var knownNameExceptions = map[string]bool{
+	"LastInsertId": true, // must match database/sql
+	"kWh":          true,
+}
+
+func isInTopLevel(f *ast.File, ident *ast.Ident) bool {
+	path, _ := astutil.PathEnclosingInterval(f, ident.Pos(), ident.End())
+	for _, f := range path {
+		switch f.(type) {
+		case *ast.File, *ast.GenDecl, *ast.ValueSpec, *ast.Ident:
+			continue
+		}
+		return false
+	}
+	return true
+}
+
+// lintNames examines all names in the file.
+// It complains if any use underscores or incorrect known initialisms.
+func (f *file) lintNames() {
+	// Package names need slightly different handling than other names.
+	if strings.Contains(f.f.Name.Name, "_") && !strings.HasSuffix(f.f.Name.Name, "_test") {
+		f.errorf(f.f, 1, link("http://golang.org/doc/effective_go.html#package-names"), category("naming"), "don't use an underscore in package name")
+	}
+	if anyCapsRE.MatchString(f.f.Name.Name) {
+		f.errorf(f.f, 1, link("http://golang.org/doc/effective_go.html#package-names"), category("mixed-caps"), "don't use MixedCaps in package name; %s should be %s", f.f.Name.Name, strings.ToLower(f.f.Name.Name))
+	}
+
+	check := func(id *ast.Ident, thing string) {
+		if id.Name == "_" {
+			return
+		}
+		if knownNameExceptions[id.Name] {
+			return
+		}
+
+		// Handle two common styles from other languages that don't belong in Go.
+		if len(id.Name) >= 5 && allCapsRE.MatchString(id.Name) && strings.Contains(id.Name, "_") {
+			capCount := 0
+			for _, c := range id.Name {
+				if 'A' <= c && c <= 'Z' {
+					capCount++
+				}
+			}
+			if capCount >= 2 {
+				f.errorf(id, 0.8, link(styleGuideBase+"#mixed-caps"), category("naming"), "don't use ALL_CAPS in Go names; use CamelCase")
+				return
+			}
+		}
+		if thing == "const" || (thing == "var" && isInTopLevel(f.f, id)) {
+			if len(id.Name) > 2 && id.Name[0] == 'k' && id.Name[1] >= 'A' && id.Name[1] <= 'Z' {
+				should := string(id.Name[1]+'a'-'A') + id.Name[2:]
+				f.errorf(id, 0.8, link(styleGuideBase+"#mixed-caps"), category("naming"), "don't use leading k in Go names; %s %s should be %s", thing, id.Name, should)
+			}
+		}
+
+		should := lintName(id.Name)
+		if id.Name == should {
+			return
+		}
+
+		if len(id.Name) > 2 && strings.Contains(id.Name[1:], "_") {
+			f.errorf(id, 0.9, link("http://golang.org/doc/effective_go.html#mixed-caps"), category("naming"), "don't use underscores in Go names; %s %s should be %s", thing, id.Name, should)
+			return
+		}
+		f.errorf(id, 0.8, link(styleGuideBase+"#initialisms"), category("naming"), "%s %s should be %s", thing, id.Name, should)
+	}
+	checkList := func(fl *ast.FieldList, thing string) {
+		if fl == nil {
+			return
+		}
+		for _, f := range fl.List {
+			for _, id := range f.Names {
+				check(id, thing)
+			}
+		}
+	}
+	f.walk(func(node ast.Node) bool {
+		switch v := node.(type) {
+		case *ast.AssignStmt:
+			if v.Tok == token.ASSIGN {
+				return true
+			}
+			for _, exp := range v.Lhs {
+				if id, ok := exp.(*ast.Ident); ok {
+					check(id, "var")
+				}
+			}
+		case *ast.FuncDecl:
+			if f.isTest() && (strings.HasPrefix(v.Name.Name, "Example") || strings.HasPrefix(v.Name.Name, "Test") || strings.HasPrefix(v.Name.Name, "Benchmark")) {
+				return true
+			}
+
+			thing := "func"
+			if v.Recv != nil {
+				thing = "method"
+			}
+
+			// Exclude naming warnings for functions that are exported to C but
+			// not exported in the Go API.
+			// See https://github.com/golang/lint/issues/144.
+			if ast.IsExported(v.Name.Name) || !isCgoExported(v) {
+				check(v.Name, thing)
+			}
+
+			checkList(v.Type.Params, thing+" parameter")
+			checkList(v.Type.Results, thing+" result")
+		case *ast.GenDecl:
+			if v.Tok == token.IMPORT {
+				return true
+			}
+			var thing string
+			switch v.Tok {
+			case token.CONST:
+				thing = "const"
+			case token.TYPE:
+				thing = "type"
+			case token.VAR:
+				thing = "var"
+			}
+			for _, spec := range v.Specs {
+				switch s := spec.(type) {
+				case *ast.TypeSpec:
+					check(s.Name, thing)
+				case *ast.ValueSpec:
+					for _, id := range s.Names {
+						check(id, thing)
+					}
+				}
+			}
+		case *ast.InterfaceType:
+			// Do not check interface method names.
+			// They are often constrainted by the method names of concrete types.
+			for _, x := range v.Methods.List {
+				ft, ok := x.Type.(*ast.FuncType)
+				if !ok { // might be an embedded interface name
+					continue
+				}
+				checkList(ft.Params, "interface method parameter")
+				checkList(ft.Results, "interface method result")
+			}
+		case *ast.RangeStmt:
+			if v.Tok == token.ASSIGN {
+				return true
+			}
+			if id, ok := v.Key.(*ast.Ident); ok {
+				check(id, "range var")
+			}
+			if id, ok := v.Value.(*ast.Ident); ok {
+				check(id, "range var")
+			}
+		case *ast.StructType:
+			for _, f := range v.Fields.List {
+				for _, id := range f.Names {
+					check(id, "struct field")
+				}
+			}
+		}
+		return true
+	})
+}
+
+// lintName returns a different name if it should be different.
+func lintName(name string) (should string) {
+	// Fast path for simple cases: "_" and all lowercase.
+	if name == "_" {
+		return name
+	}
+	allLower := true
+	for _, r := range name {
+		if !unicode.IsLower(r) {
+			allLower = false
+			break
+		}
+	}
+	if allLower {
+		return name
+	}
+
+	// Split camelCase at any lower->upper transition, and split on underscores.
+	// Check each word for common initialisms.
+	runes := []rune(name)
+	w, i := 0, 0 // index of start of word, scan
+	for i+1 <= len(runes) {
+		eow := false // whether we hit the end of a word
+		if i+1 == len(runes) {
+			eow = true
+		} else if runes[i+1] == '_' {
+			// underscore; shift the remainder forward over any run of underscores
+			eow = true
+			n := 1
+			for i+n+1 < len(runes) && runes[i+n+1] == '_' {
+				n++
+			}
+
+			// Leave at most one underscore if the underscore is between two digits
+			if i+n+1 < len(runes) && unicode.IsDigit(runes[i]) && unicode.IsDigit(runes[i+n+1]) {
+				n--
+			}
+
+			copy(runes[i+1:], runes[i+n+1:])
+			runes = runes[:len(runes)-n]
+		} else if unicode.IsLower(runes[i]) && !unicode.IsLower(runes[i+1]) {
+			// lower->non-lower
+			eow = true
+		}
+		i++
+		if !eow {
+			continue
+		}
+
+		// [w,i) is a word.
+		word := string(runes[w:i])
+		if u := strings.ToUpper(word); commonInitialisms[u] {
+			// Keep consistent case, which is lowercase only at the start.
+			if w == 0 && unicode.IsLower(runes[w]) {
+				u = strings.ToLower(u)
+			}
+			// All the common initialisms are ASCII,
+			// so we can replace the bytes exactly.
+			copy(runes[w:], []rune(u))
+		} else if w > 0 && strings.ToLower(word) == word {
+			// already all lowercase, and not the first word, so uppercase the first character.
+			runes[w] = unicode.ToUpper(runes[w])
+		}
+		w = i
+	}
+	return string(runes)
+}
+
+// commonInitialisms is a set of common initialisms.
+// Only add entries that are highly unlikely to be non-initialisms.
+// For instance, "ID" is fine (Freudian code is rare), but "AND" is not.
+var commonInitialisms = map[string]bool{
+	"ACL":   true,
+	"API":   true,
+	"ASCII": true,
+	"CPU":   true,
+	"CSS":   true,
+	"DNS":   true,
+	"EOF":   true,
+	"GUID":  true,
+	"HTML":  true,
+	"HTTP":  true,
+	"HTTPS": true,
+	"ID":    true,
+	"IP":    true,
+	"JSON":  true,
+	"LHS":   true,
+	"QPS":   true,
+	"RAM":   true,
+	"RHS":   true,
+	"RPC":   true,
+	"SLA":   true,
+	"SMTP":  true,
+	"SQL":   true,
+	"SSH":   true,
+	"TCP":   true,
+	"TLS":   true,
+	"TTL":   true,
+	"UDP":   true,
+	"UI":    true,
+	"UID":   true,
+	"UUID":  true,
+	"URI":   true,
+	"URL":   true,
+	"UTF8":  true,
+	"VM":    true,
+	"XML":   true,
+	"XMPP":  true,
+	"XSRF":  true,
+	"XSS":   true,
+}
+
+// lintTypeDoc examines the doc comment on a type.
+// It complains if they are missing from an exported type,
+// or if they are not of the standard form.
+func (f *file) lintTypeDoc(t *ast.TypeSpec, doc *ast.CommentGroup) {
+	if !ast.IsExported(t.Name.Name) {
+		return
+	}
+	if doc == nil {
+		f.errorf(t, 1, link(docCommentsLink), category("comments"), "exported type %v should have comment or be unexported", t.Name)
+		return
+	}
+
+	s := doc.Text()
+	articles := [...]string{"A", "An", "The"}
+	for _, a := range articles {
+		if strings.HasPrefix(s, a+" ") {
+			s = s[len(a)+1:]
+			break
+		}
+	}
+	if !strings.HasPrefix(s, t.Name.Name+" ") {
+		f.errorf(doc, 1, link(docCommentsLink), category("comments"), `comment on exported type %v should be of the form "%v ..." (with optional leading article)`, t.Name, t.Name)
+	}
+}
+
+var commonMethods = map[string]bool{
+	"Error":     true,
+	"Read":      true,
+	"ServeHTTP": true,
+	"String":    true,
+	"Write":     true,
+	"Unwrap":    true,
+}
+
+// lintFuncDoc examines doc comments on functions and methods.
+// It complains if they are missing, or not of the right form.
+// It has specific exclusions for well-known methods (see commonMethods above).
+func (f *file) lintFuncDoc(fn *ast.FuncDecl) {
+	if !ast.IsExported(fn.Name.Name) {
+		// func is unexported
+		return
+	}
+	kind := "function"
+	name := fn.Name.Name
+	if fn.Recv != nil && len(fn.Recv.List) > 0 {
+		// method
+		kind = "method"
+		recv := receiverType(fn)
+		if !ast.IsExported(recv) {
+			// receiver is unexported
+			return
+		}
+		if commonMethods[name] {
+			return
+		}
+		switch name {
+		case "Len", "Less", "Swap":
+			if f.pkg.sortable[recv] {
+				return
+			}
+		}
+		name = recv + "." + name
+	}
+	if fn.Doc == nil {
+		f.errorf(fn, 1, link(docCommentsLink), category("comments"), "exported %s %s should have comment or be unexported", kind, name)
+		return
+	}
+	s := fn.Doc.Text()
+	prefix := fn.Name.Name + " "
+	if !strings.HasPrefix(s, prefix) {
+		f.errorf(fn.Doc, 1, link(docCommentsLink), category("comments"), `comment on exported %s %s should be of the form "%s..."`, kind, name, prefix)
+	}
+}
+
+// lintValueSpecDoc examines package-global variables and constants.
+// It complains if they are not individually declared,
+// or if they are not suitably documented in the right form (unless they are in a block that is commented).
+func (f *file) lintValueSpecDoc(vs *ast.ValueSpec, gd *ast.GenDecl, genDeclMissingComments map[*ast.GenDecl]bool) {
+	kind := "var"
+	if gd.Tok == token.CONST {
+		kind = "const"
+	}
+
+	if len(vs.Names) > 1 {
+		// Check that none are exported except for the first.
+		for _, n := range vs.Names[1:] {
+			if ast.IsExported(n.Name) {
+				f.errorf(vs, 1, category("comments"), "exported %s %s should have its own declaration", kind, n.Name)
+				return
+			}
+		}
+	}
+
+	// Only one name.
+	name := vs.Names[0].Name
+	if !ast.IsExported(name) {
+		return
+	}
+
+	if vs.Doc == nil && gd.Doc == nil {
+		if genDeclMissingComments[gd] {
+			return
+		}
+		block := ""
+		if kind == "const" && gd.Lparen.IsValid() {
+			block = " (or a comment on this block)"
+		}
+		f.errorf(vs, 1, link(docCommentsLink), category("comments"), "exported %s %s should have comment%s or be unexported", kind, name, block)
+		genDeclMissingComments[gd] = true
+		return
+	}
+	// If this GenDecl has parens and a comment, we don't check its comment form.
+	if gd.Lparen.IsValid() && gd.Doc != nil {
+		return
+	}
+	// The relevant text to check will be on either vs.Doc or gd.Doc.
+	// Use vs.Doc preferentially.
+	doc := vs.Doc
+	if doc == nil {
+		doc = gd.Doc
+	}
+	prefix := name + " "
+	if !strings.HasPrefix(doc.Text(), prefix) {
+		f.errorf(doc, 1, link(docCommentsLink), category("comments"), `comment on exported %s %s should be of the form "%s..."`, kind, name, prefix)
+	}
+}
+
+func (f *file) checkStutter(id *ast.Ident, thing string) {
+	pkg, name := f.f.Name.Name, id.Name
+	if !ast.IsExported(name) {
+		// unexported name
+		return
+	}
+	// A name stutters if the package name is a strict prefix
+	// and the next character of the name starts a new word.
+	if len(name) <= len(pkg) {
+		// name is too short to stutter.
+		// This permits the name to be the same as the package name.
+		return
+	}
+	if !strings.EqualFold(pkg, name[:len(pkg)]) {
+		return
+	}
+	// We can assume the name is well-formed UTF-8.
+	// If the next rune after the package name is uppercase or an underscore
+	// the it's starting a new word and thus this name stutters.
+	rem := name[len(pkg):]
+	if next, _ := utf8.DecodeRuneInString(rem); next == '_' || unicode.IsUpper(next) {
+		f.errorf(id, 0.8, link(styleGuideBase+"#package-names"), category("naming"), "%s name will be used as %s.%s by other packages, and that stutters; consider calling this %s", thing, pkg, name, rem)
+	}
+}
+
+// zeroLiteral is a set of ast.BasicLit values that are zero values.
+// It is not exhaustive.
+var zeroLiteral = map[string]bool{
+	"false": true, // bool
+	// runes
+	`'\x00'`: true,
+	`'\000'`: true,
+	// strings
+	`""`: true,
+	"``": true,
+	// numerics
+	"0":   true,
+	"0.":  true,
+	"0.0": true,
+	"0i":  true,
+}
+
+// lintElses examines else blocks. It complains about any else block whose if block ends in a return.
+func (f *file) lintElses() {
+	// We don't want to flag if { } else if { } else { } constructions.
+	// They will appear as an IfStmt whose Else field is also an IfStmt.
+	// Record such a node so we ignore it when we visit it.
+	ignore := make(map[*ast.IfStmt]bool)
+
+	f.walk(func(node ast.Node) bool {
+		ifStmt, ok := node.(*ast.IfStmt)
+		if !ok || ifStmt.Else == nil {
+			return true
+		}
+		if elseif, ok := ifStmt.Else.(*ast.IfStmt); ok {
+			ignore[elseif] = true
+			return true
+		}
+		if ignore[ifStmt] {
+			return true
+		}
+		if _, ok := ifStmt.Else.(*ast.BlockStmt); !ok {
+			// only care about elses without conditions
+			return true
+		}
+		if len(ifStmt.Body.List) == 0 {
+			return true
+		}
+		shortDecl := false // does the if statement have a ":=" initialization statement?
+		if ifStmt.Init != nil {
+			if as, ok := ifStmt.Init.(*ast.AssignStmt); ok && as.Tok == token.DEFINE {
+				shortDecl = true
+			}
+		}
+		lastStmt := ifStmt.Body.List[len(ifStmt.Body.List)-1]
+		if _, ok := lastStmt.(*ast.ReturnStmt); ok {
+			extra := ""
+			if shortDecl {
+				extra = " (move short variable declaration to its own line if necessary)"
+			}
+			f.errorf(ifStmt.Else, 1, link(styleGuideBase+"#indent-error-flow"), category("indent"), "if block ends with a return statement, so drop this else and outdent its block"+extra)
+		}
+		return true
+	})
+}
+
+// lintRanges examines range clauses. It complains about redundant constructions.
+func (f *file) lintRanges() {
+	f.walk(func(node ast.Node) bool {
+		rs, ok := node.(*ast.RangeStmt)
+		if !ok {
+			return true
+		}
+
+		if isIdent(rs.Key, "_") && (rs.Value == nil || isIdent(rs.Value, "_")) {
+			p := f.errorf(rs.Key, 1, category("range-loop"), "should omit values from range; this loop is equivalent to `for range ...`")
+
+			newRS := *rs // shallow copy
+			newRS.Value = nil
+			newRS.Key = nil
+			p.ReplacementLine = f.firstLineOf(&newRS, rs)
+
+			return true
+		}
+
+		if isIdent(rs.Value, "_") {
+			p := f.errorf(rs.Value, 1, category("range-loop"), "should omit 2nd value from range; this loop is equivalent to `for %s %s range ...`", f.render(rs.Key), rs.Tok)
+
+			newRS := *rs // shallow copy
+			newRS.Value = nil
+			p.ReplacementLine = f.firstLineOf(&newRS, rs)
+		}
+
+		return true
+	})
+}
+
+// lintErrorf examines errors.New and testing.Error calls. It complains if its only argument is an fmt.Sprintf invocation.
+func (f *file) lintErrorf() {
+	f.walk(func(node ast.Node) bool {
+		ce, ok := node.(*ast.CallExpr)
+		if !ok || len(ce.Args) != 1 {
+			return true
+		}
+		isErrorsNew := isPkgDot(ce.Fun, "errors", "New")
+		var isTestingError bool
+		se, ok := ce.Fun.(*ast.SelectorExpr)
+		if ok && se.Sel.Name == "Error" {
+			if typ := f.pkg.typeOf(se.X); typ != nil {
+				isTestingError = typ.String() == "*testing.T"
+			}
+		}
+		if !isErrorsNew && !isTestingError {
+			return true
+		}
+		if !f.imports("errors") {
+			return true
+		}
+		arg := ce.Args[0]
+		ce, ok = arg.(*ast.CallExpr)
+		if !ok || !isPkgDot(ce.Fun, "fmt", "Sprintf") {
+			return true
+		}
+		errorfPrefix := "fmt"
+		if isTestingError {
+			errorfPrefix = f.render(se.X)
+		}
+		p := f.errorf(node, 1, category("errors"), "should replace %s(fmt.Sprintf(...)) with %s.Errorf(...)", f.render(se), errorfPrefix)
+
+		m := f.srcLineWithMatch(ce, `^(.*)`+f.render(se)+`\(fmt\.Sprintf\((.*)\)\)(.*)$`)
+		if m != nil {
+			p.ReplacementLine = m[1] + errorfPrefix + ".Errorf(" + m[2] + ")" + m[3]
+		}
+
+		return true
+	})
+}
+
+// lintErrors examines global error vars. It complains if they aren't named in the standard way.
+func (f *file) lintErrors() {
+	for _, decl := range f.f.Decls {
+		gd, ok := decl.(*ast.GenDecl)
+		if !ok || gd.Tok != token.VAR {
+			continue
+		}
+		for _, spec := range gd.Specs {
+			spec := spec.(*ast.ValueSpec)
+			if len(spec.Names) != 1 || len(spec.Values) != 1 {
+				continue
+			}
+			ce, ok := spec.Values[0].(*ast.CallExpr)
+			if !ok {
+				continue
+			}
+			if !isPkgDot(ce.Fun, "errors", "New") && !isPkgDot(ce.Fun, "fmt", "Errorf") {
+				continue
+			}
+
+			id := spec.Names[0]
+			prefix := "err"
+			if id.IsExported() {
+				prefix = "Err"
+			}
+			if !strings.HasPrefix(id.Name, prefix) {
+				f.errorf(id, 0.9, category("naming"), "error var %s should have name of the form %sFoo", id.Name, prefix)
+			}
+		}
+	}
+}
+
+func lintErrorString(s string) (isClean bool, conf float64) {
+	const basicConfidence = 0.8
+	const capConfidence = basicConfidence - 0.2
+	first, firstN := utf8.DecodeRuneInString(s)
+	last, _ := utf8.DecodeLastRuneInString(s)
+	if last == '.' || last == ':' || last == '!' || last == '\n' {
+		return false, basicConfidence
+	}
+	if unicode.IsUpper(first) {
+		// People use proper nouns and exported Go identifiers in error strings,
+		// so decrease the confidence of warnings for capitalization.
+		if len(s) <= firstN {
+			return false, capConfidence
+		}
+		// Flag strings starting with something that doesn't look like an initialism.
+		if second, _ := utf8.DecodeRuneInString(s[firstN:]); !unicode.IsUpper(second) {
+			return false, capConfidence
+		}
+	}
+	return true, 0
+}
+
+// lintErrorStrings examines error strings.
+// It complains if they are capitalized or end in punctuation or a newline.
+func (f *file) lintErrorStrings() {
+	f.walk(func(node ast.Node) bool {
+		ce, ok := node.(*ast.CallExpr)
+		if !ok {
+			return true
+		}
+		if !isPkgDot(ce.Fun, "errors", "New") && !isPkgDot(ce.Fun, "fmt", "Errorf") {
+			return true
+		}
+		if len(ce.Args) < 1 {
+			return true
+		}
+		str, ok := ce.Args[0].(*ast.BasicLit)
+		if !ok || str.Kind != token.STRING {
+			return true
+		}
+		s, _ := strconv.Unquote(str.Value) // can assume well-formed Go
+		if s == "" {
+			return true
+		}
+		clean, conf := lintErrorString(s)
+		if clean {
+			return true
+		}
+
+		f.errorf(str, conf, link(styleGuideBase+"#error-strings"), category("errors"),
+			"error strings should not be capitalized or end with punctuation or a newline")
+		return true
+	})
+}
+
+// lintReceiverNames examines receiver names. It complains about inconsistent
+// names used for the same type and names such as "this".
+func (f *file) lintReceiverNames() {
+	typeReceiver := map[string]string{}
+	f.walk(func(n ast.Node) bool {
+		fn, ok := n.(*ast.FuncDecl)
+		if !ok || fn.Recv == nil || len(fn.Recv.List) == 0 {
+			return true
+		}
+		names := fn.Recv.List[0].Names
+		if len(names) < 1 {
+			return true
+		}
+		name := names[0].Name
+		const ref = styleGuideBase + "#receiver-names"
+		if name == "_" {
+			f.errorf(n, 1, link(ref), category("naming"), `receiver name should not be an underscore, omit the name if it is unused`)
+			return true
+		}
+		if name == "this" || name == "self" {
+			f.errorf(n, 1, link(ref), category("naming"), `receiver name should be a reflection of its identity; don't use generic names such as "this" or "self"`)
+			return true
+		}
+		recv := receiverType(fn)
+		if prev, ok := typeReceiver[recv]; ok && prev != name {
+			f.errorf(n, 1, link(ref), category("naming"), "receiver name %s should be consistent with previous receiver name %s for %s", name, prev, recv)
+			return true
+		}
+		typeReceiver[recv] = name
+		return true
+	})
+}
+
+// lintIncDec examines statements that increment or decrement a variable.
+// It complains if they don't use x++ or x--.
+func (f *file) lintIncDec() {
+	f.walk(func(n ast.Node) bool {
+		as, ok := n.(*ast.AssignStmt)
+		if !ok {
+			return true
+		}
+		if len(as.Lhs) != 1 {
+			return true
+		}
+		if !isOne(as.Rhs[0]) {
+			return true
+		}
+		var suffix string
+		switch as.Tok {
+		case token.ADD_ASSIGN:
+			suffix = "++"
+		case token.SUB_ASSIGN:
+			suffix = "--"
+		default:
+			return true
+		}
+		f.errorf(as, 0.8, category("unary-op"), "should replace %s with %s%s", f.render(as), f.render(as.Lhs[0]), suffix)
+		return true
+	})
+}
+
+// lintErrorReturn examines function declarations that return an error.
+// It complains if the error isn't the last parameter.
+func (f *file) lintErrorReturn() {
+	f.walk(func(n ast.Node) bool {
+		fn, ok := n.(*ast.FuncDecl)
+		if !ok || fn.Type.Results == nil {
+			return true
+		}
+		ret := fn.Type.Results.List
+		if len(ret) <= 1 {
+			return true
+		}
+		if isIdent(ret[len(ret)-1].Type, "error") {
+			return true
+		}
+		// An error return parameter should be the last parameter.
+		// Flag any error parameters found before the last.
+		for _, r := range ret[:len(ret)-1] {
+			if isIdent(r.Type, "error") {
+				f.errorf(fn, 0.9, category("arg-order"), "error should be the last type when returning multiple items")
+				break // only flag one
+			}
+		}
+		return true
+	})
+}
+
+// lintUnexportedReturn examines exported function declarations.
+// It complains if any return an unexported type.
+func (f *file) lintUnexportedReturn() {
+	f.walk(func(n ast.Node) bool {
+		fn, ok := n.(*ast.FuncDecl)
+		if !ok {
+			return true
+		}
+		if fn.Type.Results == nil {
+			return false
+		}
+		if !fn.Name.IsExported() {
+			return false
+		}
+		thing := "func"
+		if fn.Recv != nil && len(fn.Recv.List) > 0 {
+			thing = "method"
+			if !ast.IsExported(receiverType(fn)) {
+				// Don't report exported methods of unexported types,
+				// such as private implementations of sort.Interface.
+				return false
+			}
+		}
+		for _, ret := range fn.Type.Results.List {
+			typ := f.pkg.typeOf(ret.Type)
+			if exportedType(typ) {
+				continue
+			}
+			f.errorf(ret.Type, 0.8, category("unexported-type-in-api"),
+				"exported %s %s returns unexported type %s, which can be annoying to use",
+				thing, fn.Name.Name, typ)
+			break // only flag one
+		}
+		return false
+	})
+}
+
+// exportedType reports whether typ is an exported type.
+// It is imprecise, and will err on the side of returning true,
+// such as for composite types.
+func exportedType(typ types.Type) bool {
+	switch T := typ.(type) {
+	case *types.Named:
+		// Builtin types have no package.
+		return T.Obj().Pkg() == nil || T.Obj().Exported()
+	case *types.Map:
+		return exportedType(T.Key()) && exportedType(T.Elem())
+	case interface {
+		Elem() types.Type
+	}: // array, slice, pointer, chan
+		return exportedType(T.Elem())
+	}
+	// Be conservative about other types, such as struct, interface, etc.
+	return true
+}
+
+// timeSuffixes is a list of name suffixes that imply a time unit.
+// This is not an exhaustive list.
+var timeSuffixes = []string{
+	"Sec", "Secs", "Seconds",
+	"Msec", "Msecs",
+	"Milli", "Millis", "Milliseconds",
+	"Usec", "Usecs", "Microseconds",
+	"MS", "Ms",
+}
+
+func (f *file) lintTimeNames() {
+	f.walk(func(node ast.Node) bool {
+		v, ok := node.(*ast.ValueSpec)
+		if !ok {
+			return true
+		}
+		for _, name := range v.Names {
+			origTyp := f.pkg.typeOf(name)
+			// Look for time.Duration or *time.Duration;
+			// the latter is common when using flag.Duration.
+			typ := origTyp
+			if pt, ok := typ.(*types.Pointer); ok {
+				typ = pt.Elem()
+			}
+			if !f.pkg.isNamedType(typ, "time", "Duration") {
+				continue
+			}
+			suffix := ""
+			for _, suf := range timeSuffixes {
+				if strings.HasSuffix(name.Name, suf) {
+					suffix = suf
+					break
+				}
+			}
+			if suffix == "" {
+				continue
+			}
+			f.errorf(v, 0.9, category("time"), "var %s is of type %v; don't use unit-specific suffix %q", name.Name, origTyp, suffix)
+		}
+		return true
+	})
+}
+
+// lintContextKeyTypes checks for call expressions to context.WithValue with
+// basic types used for the key argument.
+// See: https://golang.org/issue/17293
+func (f *file) lintContextKeyTypes() {
+	f.walk(func(node ast.Node) bool {
+		switch node := node.(type) {
+		case *ast.CallExpr:
+			f.checkContextKeyType(node)
+		}
+
+		return true
+	})
+}
+
+// checkContextKeyType reports an error if the call expression calls
+// context.WithValue with a key argument of basic type.
+func (f *file) checkContextKeyType(x *ast.CallExpr) {
+	sel, ok := x.Fun.(*ast.SelectorExpr)
+	if !ok {
+		return
+	}
+	pkg, ok := sel.X.(*ast.Ident)
+	if !ok || pkg.Name != "context" {
+		return
+	}
+	if sel.Sel.Name != "WithValue" {
+		return
+	}
+
+	// key is second argument to context.WithValue
+	if len(x.Args) != 3 {
+		return
+	}
+	key := f.pkg.typesInfo.Types[x.Args[1]]
+
+	if ktyp, ok := key.Type.(*types.Basic); ok && ktyp.Kind() != types.Invalid {
+		f.errorf(x, 1.0, category("context"), fmt.Sprintf("should not use basic type %s as key in context.WithValue", key.Type))
+	}
+}
+
+// lintContextArgs examines function declarations that contain an
+// argument with a type of context.Context
+// It complains if that argument isn't the first parameter.
+func (f *file) lintContextArgs() {
+	f.walk(func(n ast.Node) bool {
+		fn, ok := n.(*ast.FuncDecl)
+		if !ok || len(fn.Type.Params.List) <= 1 {
+			return true
+		}
+		// A context.Context should be the first parameter of a function.
+		// Flag any that show up after the first.
+		for _, arg := range fn.Type.Params.List[1:] {
+			if isPkgDot(arg.Type, "context", "Context") {
+				f.errorf(fn, 0.9, link("https://golang.org/pkg/context/"), category("arg-order"), "context.Context should be the first parameter of a function")
+				break // only flag one
+			}
+		}
+		return true
+	})
+}
+
+// containsComments returns whether the interval [start, end) contains any
+// comments without "// MATCH " prefix.
+func (f *file) containsComments(start, end token.Pos) bool {
+	for _, cgroup := range f.f.Comments {
+		comments := cgroup.List
+		if comments[0].Slash >= end {
+			// All comments starting with this group are after end pos.
+			return false
+		}
+		if comments[len(comments)-1].Slash < start {
+			// Comments group ends before start pos.
+			continue
+		}
+		for _, c := range comments {
+			if start <= c.Slash && c.Slash < end && !strings.HasPrefix(c.Text, "// MATCH ") {
+				return true
+			}
+		}
+	}
+	return false
+}
+
+// receiverType returns the named type of the method receiver, sans "*",
+// or "invalid-type" if fn.Recv is ill formed.
+func receiverType(fn *ast.FuncDecl) string {
+	switch e := fn.Recv.List[0].Type.(type) {
+	case *ast.Ident:
+		return e.Name
+	case *ast.StarExpr:
+		if id, ok := e.X.(*ast.Ident); ok {
+			return id.Name
+		}
+	}
+	// The parser accepts much more than just the legal forms.
+	return "invalid-type"
+}
+
+func (f *file) walk(fn func(ast.Node) bool) {
+	ast.Walk(walker(fn), f.f)
+}
+
+func (f *file) render(x interface{}) string {
+	var buf bytes.Buffer
+	if err := printer.Fprint(&buf, f.fset, x); err != nil {
+		panic(err)
+	}
+	return buf.String()
+}
+
+func (f *file) debugRender(x interface{}) string {
+	var buf bytes.Buffer
+	if err := ast.Fprint(&buf, f.fset, x, nil); err != nil {
+		panic(err)
+	}
+	return buf.String()
+}
+
+// walker adapts a function to satisfy the ast.Visitor interface.
+// The function return whether the walk should proceed into the node's children.
+type walker func(ast.Node) bool
+
+func (w walker) Visit(node ast.Node) ast.Visitor {
+	if w(node) {
+		return w
+	}
+	return nil
+}
+
+func isIdent(expr ast.Expr, ident string) bool {
+	id, ok := expr.(*ast.Ident)
+	return ok && id.Name == ident
+}
+
+// isBlank returns whether id is the blank identifier "_".
+// If id == nil, the answer is false.
+func isBlank(id *ast.Ident) bool { return id != nil && id.Name == "_" }
+
+func isPkgDot(expr ast.Expr, pkg, name string) bool {
+	sel, ok := expr.(*ast.SelectorExpr)
+	return ok && isIdent(sel.X, pkg) && isIdent(sel.Sel, name)
+}
+
+func isOne(expr ast.Expr) bool {
+	lit, ok := expr.(*ast.BasicLit)
+	return ok && lit.Kind == token.INT && lit.Value == "1"
+}
+
+func isCgoExported(f *ast.FuncDecl) bool {
+	if f.Recv != nil || f.Doc == nil {
+		return false
+	}
+
+	cgoExport := regexp.MustCompile(fmt.Sprintf("(?m)^//export %s$", regexp.QuoteMeta(f.Name.Name)))
+	for _, c := range f.Doc.List {
+		if cgoExport.MatchString(c.Text) {
+			return true
+		}
+	}
+	return false
+}
+
+var basicTypeKinds = map[types.BasicKind]string{
+	types.UntypedBool:    "bool",
+	types.UntypedInt:     "int",
+	types.UntypedRune:    "rune",
+	types.UntypedFloat:   "float64",
+	types.UntypedComplex: "complex128",
+	types.UntypedString:  "string",
+}
+
+// isUntypedConst reports whether expr is an untyped constant,
+// and indicates what its default type is.
+// scope may be nil.
+func (f *file) isUntypedConst(expr ast.Expr) (defType string, ok bool) {
+	// Re-evaluate expr outside of its context to see if it's untyped.
+	// (An expr evaluated within, for example, an assignment context will get the type of the LHS.)
+	exprStr := f.render(expr)
+	tv, err := types.Eval(f.fset, f.pkg.typesPkg, expr.Pos(), exprStr)
+	if err != nil {
+		return "", false
+	}
+	if b, ok := tv.Type.(*types.Basic); ok {
+		if dt, ok := basicTypeKinds[b.Kind()]; ok {
+			return dt, true
+		}
+	}
+
+	return "", false
+}
+
+// firstLineOf renders the given node and returns its first line.
+// It will also match the indentation of another node.
+func (f *file) firstLineOf(node, match ast.Node) string {
+	line := f.render(node)
+	if i := strings.Index(line, "\n"); i >= 0 {
+		line = line[:i]
+	}
+	return f.indentOf(match) + line
+}
+
+func (f *file) indentOf(node ast.Node) string {
+	line := srcLine(f.src, f.fset.Position(node.Pos()))
+	for i, r := range line {
+		switch r {
+		case ' ', '\t':
+		default:
+			return line[:i]
+		}
+	}
+	return line // unusual or empty line
+}
+
+func (f *file) srcLineWithMatch(node ast.Node, pattern string) (m []string) {
+	line := srcLine(f.src, f.fset.Position(node.Pos()))
+	line = strings.TrimSuffix(line, "\n")
+	rx := regexp.MustCompile(pattern)
+	return rx.FindStringSubmatch(line)
+}
+
+// imports returns true if the current file imports the specified package path.
+func (f *file) imports(importPath string) bool {
+	all := astutil.Imports(f.fset, f.f)
+	for _, p := range all {
+		for _, i := range p {
+			uq, err := strconv.Unquote(i.Path.Value)
+			if err == nil && importPath == uq {
+				return true
+			}
+		}
+	}
+	return false
+}
+
+// srcLine returns the complete line at p, including the terminating newline.
+func srcLine(src []byte, p token.Position) string {
+	// Run to end of line in both directions if not at line start/end.
+	lo, hi := p.Offset, p.Offset+1
+	for lo > 0 && src[lo-1] != '\n' {
+		lo--
+	}
+	for hi < len(src) && src[hi-1] != '\n' {
+		hi++
+	}
+	return string(src[lo:hi])
+}
diff --git a/vendor/knative.dev/hack/library.sh b/vendor/knative.dev/hack/library.sh
index 10220e298..4781e8e23 100644
--- a/vendor/knative.dev/hack/library.sh
+++ b/vendor/knative.dev/hack/library.sh
@@ -557,7 +557,11 @@ function go_update_deps() {
   echo "--- Removing unwanted vendor files"
 
   # Remove unwanted vendor files
-  find vendor/ \( -name "OWNERS" -o -name "OWNERS_ALIASES" -o -name "BUILD" -o -name "BUILD.bazel" -o -name "*_test.go" \) -print0 | xargs -0 rm -f
+  find vendor/ \( -name "OWNERS" \
+    -o -name "OWNERS_ALIASES" \
+    -o -name "BUILD" \
+    -o -name "BUILD.bazel" \
+    -o -name "*_test.go" \) -exec rm -f {} +
 
   export GOFLAGS=-mod=vendor
 
diff --git a/vendor/knative.dev/pkg/apis/duck/verify.go b/vendor/knative.dev/pkg/apis/duck/verify.go
index cbcc51117..e3f5abab4 100644
--- a/vendor/knative.dev/pkg/apis/duck/verify.go
+++ b/vendor/knative.dev/pkg/apis/duck/verify.go
@@ -79,17 +79,17 @@ func roundTrip(instance interface{}, input, output Populatable) error {
 	// Serialize the input to JSON and deserialize that into the provided instance
 	// of the type that we are checking.
 	if before, err := json.Marshal(input); err != nil {
-		return fmt.Errorf("error serializing duck type %T error: %s", input, err)
+		return fmt.Errorf("error serializing duck type %T error: %w", input, err)
 	} else if err := json.Unmarshal(before, instance); err != nil {
-		return fmt.Errorf("error deserializing duck type %T into %T error: %s", input, instance, err)
+		return fmt.Errorf("error deserializing duck type %T into %T error: %w", input, instance, err)
 	}
 
 	// Serialize the instance we are checking to JSON and deserialize that into the
 	// output resource.
 	if after, err := json.Marshal(instance); err != nil {
-		return fmt.Errorf("error serializing %T error: %s", instance, err)
+		return fmt.Errorf("error serializing %T error: %w", instance, err)
 	} else if err := json.Unmarshal(after, output); err != nil {
-		return fmt.Errorf("error deserializing %T into duck type %T error: %s", instance, output, err)
+		return fmt.Errorf("error deserializing %T into duck type %T error: %w", instance, output, err)
 	}
 
 	return nil
diff --git a/vendor/knative.dev/pkg/controller/controller.go b/vendor/knative.dev/pkg/controller/controller.go
index 8ccee7a14..b0ecb2e9b 100644
--- a/vendor/knative.dev/pkg/controller/controller.go
+++ b/vendor/knative.dev/pkg/controller/controller.go
@@ -582,6 +582,7 @@ func IsPermanentError(err error) bool {
 // Is implements the Is() interface of error. It returns whether the target
 // error can be treated as equivalent to a permanentError.
 func (permanentError) Is(target error) bool {
+	//nolint: errorlint // This check is actually fine.
 	_, ok := target.(permanentError)
 	return ok
 }
diff --git a/vendor/knative.dev/pkg/depcheck/depcheck.go b/vendor/knative.dev/pkg/depcheck/depcheck.go
index 8febf632f..14d5c6674 100644
--- a/vendor/knative.dev/pkg/depcheck/depcheck.go
+++ b/vendor/knative.dev/pkg/depcheck/depcheck.go
@@ -104,7 +104,7 @@ func buildGraph(importpaths ...string) (graph, error) {
 func CheckNoDependency(ip string, banned []string) error {
 	g, err := buildGraph(ip)
 	if err != nil {
-		return fmt.Errorf("buildGraph(queue) = %v", err)
+		return fmt.Errorf("buildGraph(queue) = %w", err)
 	}
 	for _, dip := range banned {
 		if g.contains(dip) {
@@ -136,7 +136,7 @@ func AssertNoDependency(t *testing.T, banned map[string][]string) {
 func CheckOnlyDependencies(ip string, allowed map[string]struct{}) error {
 	g, err := buildGraph(ip)
 	if err != nil {
-		return fmt.Errorf("buildGraph(queue) = %v", err)
+		return fmt.Errorf("buildGraph(queue) = %w", err)
 	}
 	for _, name := range g.order() {
 		if _, ok := allowed[name]; !ok {
diff --git a/vendor/knative.dev/pkg/injection/sharedmain/main.go b/vendor/knative.dev/pkg/injection/sharedmain/main.go
index f9b66efb4..72cab9496 100644
--- a/vendor/knative.dev/pkg/injection/sharedmain/main.go
+++ b/vendor/knative.dev/pkg/injection/sharedmain/main.go
@@ -18,7 +18,9 @@ package sharedmain
 
 import (
 	"context"
+	"errors"
 	"flag"
+	"fmt"
 	"log"
 	"net/http"
 	"os"
@@ -73,12 +75,12 @@ func GetLoggingConfig(ctx context.Context) (*logging.Config, error) {
 	var loggingConfigMap *corev1.ConfigMap
 	// These timeout and retry interval are set by heuristics.
 	// e.g. istio sidecar needs a few seconds to configure the pod network.
+	var lastErr error
 	if err := wait.PollImmediate(1*time.Second, 5*time.Second, func() (bool, error) {
-		var err error
-		loggingConfigMap, err = kubeclient.Get(ctx).CoreV1().ConfigMaps(system.Namespace()).Get(ctx, logging.ConfigMapName(), metav1.GetOptions{})
-		return err == nil || apierrors.IsNotFound(err), nil
+		loggingConfigMap, lastErr = kubeclient.Get(ctx).CoreV1().ConfigMaps(system.Namespace()).Get(ctx, logging.ConfigMapName(), metav1.GetOptions{})
+		return lastErr == nil || apierrors.IsNotFound(lastErr), nil
 	}); err != nil {
-		return nil, err
+		return nil, fmt.Errorf("timed out waiting for the condition: %w", lastErr)
 	}
 	if loggingConfigMap == nil {
 		return logging.NewConfigFromMap(nil)
@@ -241,7 +243,7 @@ func MainWithConfig(ctx context.Context, component string, cfg *rest.Config, cto
 
 	profilingServer.Shutdown(context.Background())
 	// Don't forward ErrServerClosed as that indicates we're already shutting down.
-	if err := eg.Wait(); err != nil && err != http.ErrServerClosed {
+	if err := eg.Wait(); err != nil && !errors.Is(err, http.ErrServerClosed) {
 		logger.Errorw("Error while running server", zap.Error(err))
 	}
 }
diff --git a/vendor/knative.dev/pkg/logging/config.go b/vendor/knative.dev/pkg/logging/config.go
index 5162eec5c..2b5eb696d 100644
--- a/vendor/knative.dev/pkg/logging/config.go
+++ b/vendor/knative.dev/pkg/logging/config.go
@@ -212,7 +212,7 @@ func UpdateLevelFromConfigMap(logger *zap.SugaredLogger, atomicLevel zap.AtomicL
 			// reset to global level
 			loggingCfg, err := zapConfigFromJSON(config.LoggingConfig)
 			switch {
-			case err == errEmptyLoggerConfig:
+			case errors.Is(err, errEmptyLoggerConfig):
 				level = zap.NewAtomicLevel().Level()
 			case err != nil:
 				logger.With(zap.Error(err)).Errorf("Failed to parse logger configuration. "+
diff --git a/vendor/knative.dev/pkg/metrics/opencensus_exporter.go b/vendor/knative.dev/pkg/metrics/opencensus_exporter.go
index 403449e23..eaeac4a56 100644
--- a/vendor/knative.dev/pkg/metrics/opencensus_exporter.go
+++ b/vendor/knative.dev/pkg/metrics/opencensus_exporter.go
@@ -85,7 +85,7 @@ func getOpenCensusSecret(component string, lister SecretFetcher) (*corev1.Secret
 		secret, err = lister("opencensus")
 	}
 	if err != nil {
-		return nil, fmt.Errorf("unable to fetch opencensus secret for %q, cannot use requireSecure=true: %+v", component, err)
+		return nil, fmt.Errorf("unable to fetch opencensus secret for %q, cannot use requireSecure=true: %w", component, err)
 	}
 
 	return secret, nil
diff --git a/vendor/knative.dev/pkg/metrics/stackdriver_exporter.go b/vendor/knative.dev/pkg/metrics/stackdriver_exporter.go
index 101d96bb2..ab14ef266 100644
--- a/vendor/knative.dev/pkg/metrics/stackdriver_exporter.go
+++ b/vendor/knative.dev/pkg/metrics/stackdriver_exporter.go
@@ -363,7 +363,7 @@ func getStackdriverSecret(ctx context.Context, secretFetcher SecretFetcher) (*co
 	}
 
 	if secErr != nil {
-		return nil, fmt.Errorf("error getting Secret [%v] in namespace [%v]: %v", secretName, secretNamespace, secErr)
+		return nil, fmt.Errorf("error getting Secret [%v] in namespace [%v]: %w", secretName, secretNamespace, secErr)
 	}
 
 	return sec, nil
diff --git a/vendor/knative.dev/pkg/network/transports.go b/vendor/knative.dev/pkg/network/transports.go
index 64ce11845..c37b99d57 100644
--- a/vendor/knative.dev/pkg/network/transports.go
+++ b/vendor/knative.dev/pkg/network/transports.go
@@ -18,6 +18,7 @@ package network
 
 import (
 	"context"
+	"errors"
 	"fmt"
 	"net"
 	"net/http"
@@ -76,7 +77,8 @@ func dialBackOffHelper(ctx context.Context, network, address string, bo wait.Bac
 	for {
 		c, err := dialer.DialContext(ctx, network, address)
 		if err != nil {
-			if err, ok := err.(net.Error); ok && err.Timeout() {
+			var errNet net.Error
+			if errors.As(err, &errNet) && errNet.Timeout() {
 				if bo.Steps < 1 {
 					break
 				}
diff --git a/vendor/knative.dev/pkg/reconciler/events.go b/vendor/knative.dev/pkg/reconciler/events.go
index 54a6e52a2..611ba2dc1 100644
--- a/vendor/knative.dev/pkg/reconciler/events.go
+++ b/vendor/knative.dev/pkg/reconciler/events.go
@@ -75,7 +75,8 @@ var _ error = (*ReconcilerEvent)(nil)
 // Is returns if the target error is a ReconcilerEvent type checking that
 // EventType and Reason match.
 func (e *ReconcilerEvent) Is(target error) bool {
-	if t, ok := target.(*ReconcilerEvent); ok {
+	var t *ReconcilerEvent
+	if errors.As(target, &t) {
 		if t != nil && t.EventType == e.EventType && t.Reason == e.Reason {
 			return true
 		}
diff --git a/vendor/knative.dev/pkg/webhook/webhook.go b/vendor/knative.dev/pkg/webhook/webhook.go
index ba04b8e1a..ba37d385b 100644
--- a/vendor/knative.dev/pkg/webhook/webhook.go
+++ b/vendor/knative.dev/pkg/webhook/webhook.go
@@ -209,7 +209,7 @@ func (wh *Webhook) Run(stop <-chan struct{}) error {
 
 	eg, ctx := errgroup.WithContext(ctx)
 	eg.Go(func() error {
-		if err := server.ListenAndServeTLS("", ""); err != nil && err != http.ErrServerClosed {
+		if err := server.ListenAndServeTLS("", ""); err != nil && !errors.Is(err, http.ErrServerClosed) {
 			logger.Errorw("ListenAndServeTLS for admission webhook returned error", zap.Error(err))
 			return err
 		}
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 0c1d225e8..d05d8aeae 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -7,12 +7,12 @@ cloud.google.com/go/trace/apiv2
 contrib.go.opencensus.io/exporter/ocagent
 # contrib.go.opencensus.io/exporter/prometheus v0.2.1-0.20200609204449-6bcf6f8577f0
 contrib.go.opencensus.io/exporter/prometheus
-# contrib.go.opencensus.io/exporter/stackdriver v0.13.2
+# contrib.go.opencensus.io/exporter/stackdriver v0.13.4
 contrib.go.opencensus.io/exporter/stackdriver
 contrib.go.opencensus.io/exporter/stackdriver/monitoredresource
 contrib.go.opencensus.io/exporter/stackdriver/monitoredresource/aws
 contrib.go.opencensus.io/exporter/stackdriver/monitoredresource/gcp
-# contrib.go.opencensus.io/exporter/zipkin v0.1.1
+# contrib.go.opencensus.io/exporter/zipkin v0.1.2
 contrib.go.opencensus.io/exporter/zipkin
 # github.com/Azure/azure-sdk-for-go v42.3.0+incompatible
 github.com/Azure/azure-sdk-for-go/services/containerregistry/mgmt/2019-05-01/containerregistry
@@ -243,7 +243,7 @@ github.com/modern-go/concurrent
 github.com/modern-go/reflect2
 # github.com/opencontainers/runc v0.1.1
 github.com/opencontainers/runc/libcontainer/user
-# github.com/openzipkin/zipkin-go v0.2.2
+# github.com/openzipkin/zipkin-go v0.2.5
 github.com/openzipkin/zipkin-go
 github.com/openzipkin/zipkin-go/idgenerator
 github.com/openzipkin/zipkin-go/model
@@ -327,7 +327,11 @@ go.uber.org/atomic
 go.uber.org/automaxprocs/internal/cgroups
 go.uber.org/automaxprocs/internal/runtime
 go.uber.org/automaxprocs/maxprocs
-# go.uber.org/multierr v1.5.0
+# go.uber.org/goleak v1.1.10
+## explicit
+go.uber.org/goleak
+go.uber.org/goleak/internal/stack
+# go.uber.org/multierr v1.6.0
 go.uber.org/multierr
 # go.uber.org/zap v1.16.0
 ## explicit
@@ -350,6 +354,9 @@ golang.org/x/crypto/openpgp/s2k
 golang.org/x/crypto/pkcs12
 golang.org/x/crypto/pkcs12/internal/rc2
 golang.org/x/crypto/ssh/terminal
+# golang.org/x/lint v0.0.0-20200302205851-738671d3881b
+golang.org/x/lint
+golang.org/x/lint/golint
 # golang.org/x/mod v0.3.0
 golang.org/x/mod/module
 golang.org/x/mod/semver
@@ -944,7 +951,7 @@ k8s.io/utils/buffer
 k8s.io/utils/integer
 k8s.io/utils/pointer
 k8s.io/utils/trace
-# knative.dev/caching v0.0.0-20201027231233-cc1d9d2e090f
+# knative.dev/caching v0.0.0-20201029165635-7983fcd03d68
 ## explicit
 knative.dev/caching/config
 knative.dev/caching/pkg/apis/caching
@@ -965,10 +972,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-20201027221733-0d7f2f064b7b
+# knative.dev/hack v0.0.0-20201028205534-fe80f1c8af68
 ## explicit
 knative.dev/hack
-# knative.dev/networking v0.0.0-20201027230234-f0e013a2a1e2
+# knative.dev/networking v0.0.0-20201029132834-0fb5d8bc0634
 ## explicit
 knative.dev/networking/config
 knative.dev/networking/pkg
@@ -1001,7 +1008,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-20201028121234-58d43f05028e
+# knative.dev/pkg v0.0.0-20201030122234-256ae893994a
 ## 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 b29503e35..d7291daa3 100644
--- a/.github/workflows/kind-e2e.yaml
+++ b/.github/workflows/kind-e2e.yaml
@@ -36,8 +36,7 @@ jobs:
           kind-version: v0.9.0
           kind-image-sha: sha256:5240a7a2c34bf241afb54ac05669f8a46661912eab05705d660971eeb12f6555
           kingress: istio
-          # TODO(https://github.com/knative/serving/issues/9750): net-istio breaks on non-default suffixes.
-          cluster-suffix: cluster.local
+          cluster-suffix: c${{ github.run_id }}.local
         - k8s-version: v1.18.8
           kind-version: v0.9.0
           kind-image-sha: sha256:f4bcc97a0ad6e7abaf3f643d890add7efe6ee4ab90baeb374b4f41a4c95567eb
@@ -255,6 +254,7 @@ jobs:
         KNATIVE_DEFAULT_NAMESPACE="knative-serving"
         SYSTEM_NAMESPACE=$KNATIVE_DEFAULT_NAMESPACE
         export KIND=true
+        export CLUSTER_DOMAIN="${{ matrix.cluster-suffix }}"
         install_istio $PATCHED_YAML
 
         echo "GATEWAY_NAMESPACE_OVERRIDE=istio-system" >> $GITHUB_ENV
diff --git a/pkg/activator/handler/handler_test.go b/pkg/activator/handler/handler_test.go
index 12b184e30..ea35298e5 100644
--- a/pkg/activator/handler/handler_test.go
+++ b/pkg/activator/handler/handler_test.go
@@ -85,7 +85,6 @@ func TestActivationHandler(t *testing.T) {
 		name:      "active endpoint",
 		wantBody:  wantBody,
 		wantCode:  http.StatusOK,
-		wantErr:   nil,
 		throttler: fakeThrottler{},
 	}, {
 		name:      "request error",
@@ -97,13 +96,11 @@ func TestActivationHandler(t *testing.T) {
 		name:      "throttler timeout",
 		wantBody:  context.DeadlineExceeded.Error() + "\n",
 		wantCode:  http.StatusServiceUnavailable,
-		wantErr:   nil,
 		throttler: fakeThrottler{err: context.DeadlineExceeded},
 	}, {
 		name:      "overflow",
 		wantBody:  "pending request queue full\n",
 		wantCode:  http.StatusServiceUnavailable,
-		wantErr:   nil,
 		throttler: fakeThrottler{err: queue.ErrRequestQueueFull},
 	}}
 	for _, test := range tests {
@@ -151,7 +148,7 @@ func TestActivationHandler(t *testing.T) {
 				t.Fatal("Error reading body:", err)
 			}
 			if string(gotBody) != test.wantBody {
-				t.Errorf("Unexpected response body. Response body %q, want %q", gotBody, test.wantBody)
+				t.Errorf("Response body = %q, want: %q", gotBody, test.wantBody)
 			}
 		})
 	}
@@ -183,10 +180,10 @@ func TestActivationHandlerProxyHeader(t *testing.T) {
 	select {
 	case httpReq := <-interceptCh:
 		if got := httpReq.Header.Get(network.ProxyHeaderName); got != activator.Name {
-			t.Errorf("Header %q = %q, want:  %q", network.ProxyHeaderName, got, activator.Name)
+			t.Errorf("Header %q = %q, want: %q", network.ProxyHeaderName, got, activator.Name)
 		}
 	case <-time.After(1 * time.Second):
-		t.Fatal("Timed out waiting for a request to be intercepted")
+		t.Error("Timed out waiting for a request to be intercepted")
 	}
 }
 
@@ -201,16 +198,15 @@ func TestActivationHandlerTraceSpans(t *testing.T) {
 		traceBackend: tracingconfig.Zipkin,
 	}, {
 		name:         "trace disabled",
-		wantSpans:    0,
 		traceBackend: tracingconfig.None,
 	}}
 
+	spanNames := []string{"throttler_try", "/", "activator_proxy"}
 	for _, tc := range testcases {
 		t.Run(tc.name, func(t *testing.T) {
 			// Setup transport
 			fakeRT := activatortest.FakeRoundTripper{
 				RequestResponse: &activatortest.FakeResponse{
-					Err:  nil,
 					Code: http.StatusOK,
 					Body: wantBody,
 				},
@@ -256,13 +252,12 @@ func TestActivationHandlerTraceSpans(t *testing.T) {
 
 			gotSpans := reporter.Flush()
 			if len(gotSpans) != tc.wantSpans {
-				t.Errorf("Got %d spans, expected %d", len(gotSpans), tc.wantSpans)
+				t.Errorf("NumSpans = %d, want: %d", len(gotSpans), tc.wantSpans)
 			}
 
-			spanNames := []string{"throttler_try", "/", "activator_proxy"}
 			for i, spanName := range spanNames[0:tc.wantSpans] {
 				if gotSpans[i].Name != spanName {
-					t.Errorf("Got span %d named %q, expected %q", i, gotSpans[i].Name, spanName)
+					t.Errorf("Span[%d] = %q, expected %q", i, gotSpans[i].Name, spanName)
 				}
 			}
 		})
@@ -303,7 +298,7 @@ func setupConfigStore(t *testing.T, logger *zap.SugaredLogger) *activatorconfig.
 
 func BenchmarkHandler(b *testing.B) {
 	ctx, cancel, _ := rtesting.SetupFakeContextWithCancel(&testing.T{})
-	defer cancel()
+	b.Cleanup(cancel)
 	configStore := setupConfigStore(&testing.T{}, logging.FromContext(ctx))
 
 	// bodyLength is in kilobytes.
@@ -374,15 +369,13 @@ type responseRecorder struct {
 	size atomic.Int32
 }
 
-func (rr *responseRecorder) Flush() {}
-
 func (rr *responseRecorder) Header() http.Header {
 	return http.Header{}
 }
 
 func (rr *responseRecorder) Write(p []byte) (int, error) {
 	rr.size.Add(int32(len(p)))
-	return ioutil.Discard.Write(p)
+	return len(p), nil
 }
 
 func (rr *responseRecorder) WriteHeader(code int) {
diff --git a/pkg/activator/net/throttler_test.go b/pkg/activator/net/throttler_test.go
index d60c6d43d..f2ac91cc1 100644
--- a/pkg/activator/net/throttler_test.go
+++ b/pkg/activator/net/throttler_test.go
@@ -243,7 +243,7 @@ func TestThrottlerErrorNoRevision(t *testing.T) {
 
 	// Make sure errors are propagated correctly.
 	innerError := errors.New("inner")
-	if err := throttler.Try(ctx, func(string) error { return innerError }); err != innerError {
+	if err := throttler.Try(ctx, func(string) error { return innerError }); !errors.Is(err, innerError) {
 		t.Fatalf("Try() = %v, want %v", err, innerError)
 	}
 
@@ -299,7 +299,7 @@ func TestThrottlerErrorOneTimesOut(t *testing.T) {
 	})
 
 	// The first result will be a timeout because of the locking logic.
-	if result := <-resultChan; result.err != context.DeadlineExceeded {
+	if result := <-resultChan; !errors.Is(result.err, context.DeadlineExceeded) {
 		t.Fatalf("err = %v, want %v", err, context.DeadlineExceeded)
 	}
 
@@ -811,7 +811,7 @@ func TestMultipleActivators(t *testing.T) {
 	})
 
 	// The first result will be a timeout because of the locking logic.
-	if result := <-resultChan; result.err != context.DeadlineExceeded {
+	if result := <-resultChan; !errors.Is(result.err, context.DeadlineExceeded) {
 		t.Fatalf("err = %v, want %v", err, context.DeadlineExceeded)
 	}
 
diff --git a/pkg/apis/autoscaling/v1alpha1/pa_defaults_test.go b/pkg/apis/autoscaling/v1alpha1/pa_defaults_test.go
index 2f4a078d5..4fd0a85ea 100644
--- a/pkg/apis/autoscaling/v1alpha1/pa_defaults_test.go
+++ b/pkg/apis/autoscaling/v1alpha1/pa_defaults_test.go
@@ -21,7 +21,7 @@ import (
 	"testing"
 
 	"github.com/google/go-cmp/cmp"
-	v1 "k8s.io/api/core/v1"
+	corev1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	logtesting "knative.dev/pkg/logging/testing"
 	"knative.dev/serving/pkg/apis/autoscaling"
@@ -54,19 +54,19 @@ func TestPodAutoscalerDefaulting(t *testing.T) {
 		in:   &PodAutoscaler{},
 		wc: func(ctx context.Context) context.Context {
 			s := config.NewStore(logtesting.TestLogger(t))
-			s.OnConfigChanged(&v1.ConfigMap{
+			s.OnConfigChanged(&corev1.ConfigMap{
 				ObjectMeta: metav1.ObjectMeta{
 					Name: config.DefaultsConfigName,
 				},
 				Data: map[string]string{},
 			})
-			s.OnConfigChanged(&v1.ConfigMap{
+			s.OnConfigChanged(&corev1.ConfigMap{
 				ObjectMeta: metav1.ObjectMeta{
 					Name: config.FeaturesConfigName,
 				},
 				Data: map[string]string{},
 			})
-			s.OnConfigChanged(&v1.ConfigMap{
+			s.OnConfigChanged(&corev1.ConfigMap{
 				ObjectMeta: metav1.ObjectMeta{
 					Name: autoscalerconfig.ConfigName,
 				},
diff --git a/pkg/apis/autoscaling/v1alpha1/pa_validation_test.go b/pkg/apis/autoscaling/v1alpha1/pa_validation_test.go
index bec85047c..e5cd7b9e3 100644
--- a/pkg/apis/autoscaling/v1alpha1/pa_validation_test.go
+++ b/pkg/apis/autoscaling/v1alpha1/pa_validation_test.go
@@ -22,7 +22,7 @@ import (
 
 	"github.com/google/go-cmp/cmp"
 	corev1 "k8s.io/api/core/v1"
-	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 
 	net "knative.dev/networking/pkg/apis/networking"
 	"knative.dev/pkg/apis"
@@ -157,7 +157,7 @@ func TestPodAutoscalerValidation(t *testing.T) {
 	}{{
 		name: "valid",
 		r: &PodAutoscaler{
-			ObjectMeta: v1.ObjectMeta{
+			ObjectMeta: metav1.ObjectMeta{
 				Name: "valid",
 			},
 			Spec: PodAutoscalerSpec{
@@ -173,7 +173,7 @@ func TestPodAutoscalerValidation(t *testing.T) {
 	}, {
 		name: "bad protocol",
 		r: &PodAutoscaler{
-			ObjectMeta: v1.ObjectMeta{
+			ObjectMeta: metav1.ObjectMeta{
 				Name: "valid",
 				Annotations: map[string]string{
 					autoscaling.MinScaleAnnotationKey: "2",
@@ -192,7 +192,7 @@ func TestPodAutoscalerValidation(t *testing.T) {
 	}, {
 		name: "bad scale bounds",
 		r: &PodAutoscaler{
-			ObjectMeta: v1.ObjectMeta{
+			ObjectMeta: metav1.ObjectMeta{
 				Name: "valid",
 				Annotations: map[string]string{
 					autoscaling.MinScaleAnnotationKey: "FOO",
@@ -211,7 +211,7 @@ func TestPodAutoscalerValidation(t *testing.T) {
 	}, {
 		name: "empty spec",
 		r: &PodAutoscaler{
-			ObjectMeta: v1.ObjectMeta{
+			ObjectMeta: metav1.ObjectMeta{
 				Name: "valid",
 			},
 		},
@@ -219,7 +219,7 @@ func TestPodAutoscalerValidation(t *testing.T) {
 	}, {
 		name: "nested spec error",
 		r: &PodAutoscaler{
-			ObjectMeta: v1.ObjectMeta{
+			ObjectMeta: metav1.ObjectMeta{
 				Name: "valid",
 			},
 			Spec: PodAutoscalerSpec{
diff --git a/pkg/autoscaler/metrics/collector_test.go b/pkg/autoscaler/metrics/collector_test.go
index ac30be39e..ea7868baf 100644
--- a/pkg/autoscaler/metrics/collector_test.go
+++ b/pkg/autoscaler/metrics/collector_test.go
@@ -78,7 +78,7 @@ func TestMetricCollectorCRUD(t *testing.T) {
 		coll := NewMetricCollector(failingFactory, logger)
 		got := coll.CreateOrUpdate(&defaultMetric)
 
-		if got != want {
+		if !errors.Is(got, want) {
 			t.Errorf("Create() = %v, want %v", got, want)
 		}
 	})
@@ -284,10 +284,10 @@ func TestMetricCollectorScraper(t *testing.T) {
 
 	// Deleting the metric should cause a calculation error.
 	coll.Delete(defaultNamespace, defaultName)
-	if _, _, err := coll.StableAndPanicConcurrency(metricKey, now); err != ErrNotCollecting {
+	if _, _, err := coll.StableAndPanicConcurrency(metricKey, now); !errors.Is(err, ErrNotCollecting) {
 		t.Errorf("StableAndPanicConcurrency() = %v, want %v", err, ErrNotCollecting)
 	}
-	if _, _, err := coll.StableAndPanicRPS(metricKey, now); err != ErrNotCollecting {
+	if _, _, err := coll.StableAndPanicRPS(metricKey, now); !errors.Is(err, ErrNotCollecting) {
 		t.Errorf("StableAndPanicRPS() = %v, want %v", err, ErrNotCollecting)
 	}
 }
@@ -392,10 +392,10 @@ func TestMetricCollectorNoDataError(t *testing.T) {
 	// Verify correct error is returned if ScrapeTarget is set
 	_, _, errCon := coll.StableAndPanicConcurrency(metricKey, now)
 	_, _, errRPS := coll.StableAndPanicRPS(metricKey, now)
-	if errCon != ErrNoData {
+	if !errors.Is(errCon, ErrNoData) {
 		t.Error("StableAndPanicConcurrency() =", errCon)
 	}
-	if errRPS != ErrNoData {
+	if !errors.Is(errRPS, ErrNoData) {
 		t.Error("StableAndPanicRPS() =", errRPS)
 	}
 }
@@ -562,7 +562,7 @@ func TestMetricCollectorError(t *testing.T) {
 			}
 
 			// Make sure the error is surfaced via 'CreateOrUpdate', which is called in the reconciler.
-			if err := coll.CreateOrUpdate(testMetric); err != test.expectedError {
+			if err := coll.CreateOrUpdate(testMetric); !errors.Is(err, test.expectedError) {
 				t.Fatalf("CreateOrUpdate = %v, want %v", err, test.expectedError)
 			}
 
diff --git a/pkg/autoscaler/statforwarder/forwarder_test.go b/pkg/autoscaler/statforwarder/forwarder_test.go
index 4b3e23ceb..44398dc67 100644
--- a/pkg/autoscaler/statforwarder/forwarder_test.go
+++ b/pkg/autoscaler/statforwarder/forwarder_test.go
@@ -24,7 +24,7 @@ import (
 
 	"github.com/google/go-cmp/cmp"
 	coordinationv1 "k8s.io/api/coordination/v1"
-	v1 "k8s.io/api/core/v1"
+	corev1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/runtime"
 	"k8s.io/apimachinery/pkg/types"
@@ -115,14 +115,14 @@ func TestForwarderReconcile(t *testing.T) {
 		t.Fatal("Timeout to get the Service:", lastErr)
 	}
 
-	wantSubsets := []v1.EndpointSubset{{
-		Addresses: []v1.EndpointAddress{{
+	wantSubsets := []corev1.EndpointSubset{{
+		Addresses: []corev1.EndpointAddress{{
 			IP: testIP1,
 		}},
-		Ports: []v1.EndpointPort{{
+		Ports: []corev1.EndpointPort{{
 			Name:     autoscalerPortName,
 			Port:     autoscalerPort,
-			Protocol: v1.ProtocolTCP,
+			Protocol: corev1.ProtocolTCP,
 		}}},
 	}
 
@@ -284,7 +284,7 @@ func TestForwarderRetryOnEndpointsUpdateFailure(t *testing.T) {
 		},
 	)
 
-	e := &v1.Endpoints{
+	e := &corev1.Endpoints{
 		ObjectMeta: metav1.ObjectMeta{
 			Name:      bucket1,
 			Namespace: testNs,
diff --git a/pkg/autoscaler/statserver/server_test.go b/pkg/autoscaler/statserver/server_test.go
index 845297a0b..5ea4d5339 100644
--- a/pkg/autoscaler/statserver/server_test.go
+++ b/pkg/autoscaler/statserver/server_test.go
@@ -19,16 +19,17 @@ package statserver
 import (
 	"bytes"
 	"encoding/json"
+	"errors"
 	"fmt"
 	"net"
 	"net/http"
 	"net/url"
-	"runtime"
 	"testing"
 	"time"
 
 	"github.com/google/go-cmp/cmp"
 	"github.com/gorilla/websocket"
+	"go.uber.org/goleak"
 	"go.uber.org/zap"
 	"golang.org/x/sync/errgroup"
 	network "knative.dev/networking/pkg"
@@ -134,8 +135,7 @@ func TestServerShutdown(t *testing.T) {
 	}
 
 	// Check the statistic was not received
-	_, ok := <-statsCh
-	if ok {
+	if _, ok := <-statsCh; ok {
 		t.Fatal("Received statistic after shutdown")
 	}
 
@@ -143,12 +143,12 @@ func TestServerShutdown(t *testing.T) {
 	if _, _, err := statSink.NextReader(); err == nil {
 		t.Fatal("Connection not closed")
 	} else {
-		err, ok := err.(*websocket.CloseError)
-		if !ok {
+		var errClose *websocket.CloseError
+		if !errors.As(err, &errClose) {
 			t.Fatal("CloseError not received")
 		}
-		if err.Code != 1012 {
-			t.Fatalf("CloseError with unexpected close code %d received", err.Code)
+		if errClose.Code != 1012 {
+			t.Fatalf("CloseError with unexpected close code %d received", errClose.Code)
 		}
 	}
 
@@ -167,7 +167,8 @@ func TestServerDoesNotLeakGoroutines(t *testing.T) {
 
 	go server.listenAndServe()
 
-	originalGoroutines := runtime.NumGoroutine()
+	// Check the number of goroutines eventually reduces to the number there were before the connection was created
+	defer goleak.VerifyNone(t, goleak.IgnoreCurrent())
 
 	listenAddr := server.listenAddr()
 	statSink := dialOK(t, listenAddr)
@@ -175,18 +176,6 @@ func TestServerDoesNotLeakGoroutines(t *testing.T) {
 	assertReceivedProto(t, both, statSink, statsCh)
 
 	closeSink(t, statSink)
-
-	// Check the number of goroutines eventually reduces to the number there were before the connection was created
-	for i := 1000; i >= 0; i-- {
-		currentGoRoutines := runtime.NumGoroutine()
-		if currentGoRoutines <= originalGoroutines {
-			break
-		}
-		time.Sleep(5 * time.Millisecond)
-		if i == 0 {
-			t.Fatalf("Current number of goroutines %d is not equal to the original number %d", currentGoRoutines, originalGoroutines)
-		}
-	}
 }
 
 func TestServerNotBucketHost(t *testing.T) {
@@ -229,9 +218,8 @@ func TestServerNotOwnerForBucketHost(t *testing.T) {
 
 	go server.listenAndServe()
 
-	_, err := dial(server.listenAddr())
-	if err == nil {
-		t.Error("Want error from Dial but got none")
+	if _, err := dial(server.listenAddr()); err == nil {
+		t.Error("Want an error from Dial but got none")
 	}
 }
 
diff --git a/pkg/http/handler/timeout_test.go b/pkg/http/handler/timeout_test.go
index 8df88affd..1b9b25d55 100644
--- a/pkg/http/handler/timeout_test.go
+++ b/pkg/http/handler/timeout_test.go
@@ -17,6 +17,7 @@ limitations under the License.
 package handler
 
 import (
+	"errors"
 	"io"
 	"net/http"
 	"net/http/httptest"
@@ -67,7 +68,7 @@ func TestTimeoutWriterErrorsWriteAfterTimeout(t *testing.T) {
 	recorder := httptest.NewRecorder()
 	handler := &timeoutWriter{w: recorder}
 	handler.timeoutAndWriteError("error")
-	if _, err := handler.Write([]byte("hello")); err != http.ErrHandlerTimeout {
+	if _, err := handler.Write([]byte("hello")); !errors.Is(err, http.ErrHandlerTimeout) {
 		t.Errorf("ErrHandlerTimeout got %v, want: %s", err, http.ErrHandlerTimeout)
 	}
 }
@@ -148,7 +149,7 @@ func TestTimeToFirstByteTimeoutHandler(t *testing.T) {
 
 			defer func() {
 				if test.wantPanic {
-					if recovered := recover(); recovered != http.ErrAbortHandler {
+					if recovered := recover(); recovered != http.ErrAbortHandler { //nolint // False positive for errors.Is check
 						t.Errorf("Recover = %v, want: %v", recovered, http.ErrAbortHandler)
 					}
 				}
@@ -167,7 +168,7 @@ func TestTimeToFirstByteTimeoutHandler(t *testing.T) {
 			}
 
 			if test.wantWriteError {
-				if err := <-writeErrors; err != http.ErrHandlerTimeout {
+				if err := <-writeErrors; !errors.Is(err, http.ErrHandlerTimeout) {
 					t.Error("Expected a timeout error, got", err)
 				}
 			}
diff --git a/pkg/queue/breaker_test.go b/pkg/queue/breaker_test.go
index 70b0a8711..ce8ead764 100644
--- a/pkg/queue/breaker_test.go
+++ b/pkg/queue/breaker_test.go
@@ -18,6 +18,7 @@ package queue
 
 import (
 	"context"
+	"errors"
 	"fmt"
 	"testing"
 	"time"
@@ -277,7 +278,7 @@ func TestSemaphoreRelease(t *testing.T) {
 	if err := sem.release(); err != nil {
 		t.Errorf("release = %v; want: %v", err, nil)
 	}
-	if err := sem.release(); err != ErrRelease {
+	if err := sem.release(); !errors.Is(err, ErrRelease) {
 		t.Errorf("release = %v; want: %v", err, ErrRelease)
 	}
 }
diff --git a/pkg/reconciler/route/resources/labels/labels_test.go b/pkg/reconciler/route/resources/labels/labels_test.go
index 0e3363108..10d8ab84c 100644
--- a/pkg/reconciler/route/resources/labels/labels_test.go
+++ b/pkg/reconciler/route/resources/labels/labels_test.go
@@ -20,7 +20,7 @@ import (
 	"testing"
 
 	"github.com/google/go-cmp/cmp"
-	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	network "knative.dev/networking/pkg"
 	"knative.dev/serving/pkg/apis/serving"
 )
@@ -28,29 +28,29 @@ import (
 func TestIsObjectLocalVisibility(t *testing.T) {
 	tests := []struct {
 		name string
-		meta *v1.ObjectMeta
+		meta *metav1.ObjectMeta
 		want bool
 	}{{
 		name: "nil",
-		meta: &v1.ObjectMeta{},
+		meta: &metav1.ObjectMeta{},
 	}, {
 		name: "empty labels",
-		meta: &v1.ObjectMeta{
+		meta: &metav1.ObjectMeta{
 			Labels: map[string]string{},
 		},
 	}, {
 		name: "no matching labels",
-		meta: &v1.ObjectMeta{
+		meta: &metav1.ObjectMeta{
 			Labels: map[string]string{"frankie-goes": "to-hollywood"},
 		},
 	}, {
 		name: "false",
-		meta: &v1.ObjectMeta{
+		meta: &metav1.ObjectMeta{
 			Labels: map[string]string{network.VisibilityLabelKey: ""},
 		},
 	}, {
 		name: "true",
-		meta: &v1.ObjectMeta{
+		meta: &metav1.ObjectMeta{
 			Labels: map[string]string{network.VisibilityLabelKey: "set"},
 		},
 		want: true,
@@ -68,30 +68,30 @@ func TestIsObjectLocalVisibility(t *testing.T) {
 func TestDeleteLabel(t *testing.T) {
 	tests := []struct {
 		name string
-		meta *v1.ObjectMeta
+		meta *metav1.ObjectMeta
 		key  string
-		want v1.ObjectMeta
+		want metav1.ObjectMeta
 	}{{
 		name: "No labels in object meta",
-		meta: &v1.ObjectMeta{},
+		meta: &metav1.ObjectMeta{},
 		key:  "key",
-		want: v1.ObjectMeta{},
+		want: metav1.ObjectMeta{},
 	}, {
 		name: "No matching key",
-		meta: &v1.ObjectMeta{
+		meta: &metav1.ObjectMeta{
 			Labels: map[string]string{"some label": "some value"},
 		},
 		key: "unknown",
-		want: v1.ObjectMeta{
+		want: metav1.ObjectMeta{
 			Labels: map[string]string{"some label": "some value"},
 		},
 	}, {
 		name: "Has matching key",
-		meta: &v1.ObjectMeta{
+		meta: &metav1.ObjectMeta{
 			Labels: map[string]string{"some label": "some value"},
 		},
 		key: "some label",
-		want: v1.ObjectMeta{
+		want: metav1.ObjectMeta{
 			Labels: map[string]string{},
 		},
 	}}
@@ -110,36 +110,36 @@ func TestDeleteLabel(t *testing.T) {
 func TestSetLabel(t *testing.T) {
 	tests := []struct {
 		name  string
-		meta  *v1.ObjectMeta
+		meta  *metav1.ObjectMeta
 		key   string
 		value string
-		want  v1.ObjectMeta
+		want  metav1.ObjectMeta
 	}{{
 		name:  "No labels in object meta",
-		meta:  &v1.ObjectMeta{},
+		meta:  &metav1.ObjectMeta{},
 		key:   "key",
 		value: "value",
-		want: v1.ObjectMeta{
+		want: metav1.ObjectMeta{
 			Labels: map[string]string{"key": "value"},
 		},
 	}, {
 		name: "Empty labels",
-		meta: &v1.ObjectMeta{
+		meta: &metav1.ObjectMeta{
 			Labels: map[string]string{},
 		},
 		key:   "key",
 		value: "value",
-		want: v1.ObjectMeta{
+		want: metav1.ObjectMeta{
 			Labels: map[string]string{"key": "value"},
 		},
 	}, {
 		name: "Conflicting labels",
-		meta: &v1.ObjectMeta{
+		meta: &metav1.ObjectMeta{
 			Labels: map[string]string{"key": "old value"},
 		},
 		key:   "key",
 		value: "new value",
-		want: v1.ObjectMeta{
+		want: metav1.ObjectMeta{
 			Labels: map[string]string{"key": "new value"},
 		},
 	}}
@@ -158,18 +158,18 @@ func TestSetLabel(t *testing.T) {
 func TestSetVisibility(t *testing.T) {
 	tests := []struct {
 		name           string
-		meta           *v1.ObjectMeta
+		meta           *metav1.ObjectMeta
 		isClusterLocal bool
-		want           v1.ObjectMeta
+		want           metav1.ObjectMeta
 	}{{
 		name:           "Set cluster local true",
-		meta:           &v1.ObjectMeta{},
+		meta:           &metav1.ObjectMeta{},
 		isClusterLocal: true,
-		want:           v1.ObjectMeta{Labels: map[string]string{network.VisibilityLabelKey: serving.VisibilityClusterLocal}},
+		want:           metav1.ObjectMeta{Labels: map[string]string{network.VisibilityLabelKey: serving.VisibilityClusterLocal}},
 	}, {
 		name: "Set cluster local false",
-		meta: &v1.ObjectMeta{Labels: map[string]string{network.VisibilityLabelKey: serving.VisibilityClusterLocal}},
-		want: v1.ObjectMeta{Labels: map[string]string{}},
+		meta: &metav1.ObjectMeta{Labels: map[string]string{network.VisibilityLabelKey: serving.VisibilityClusterLocal}},
+		want: metav1.ObjectMeta{Labels: map[string]string{}},
 	}}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
diff --git a/pkg/reconciler/route/traffic/rollout_test.go b/pkg/reconciler/route/traffic/rollout_test.go
new file mode 100644
index 000000000..d9bd0281f
--- /dev/null
+++ b/pkg/reconciler/route/traffic/rollout_test.go
@@ -0,0 +1,327 @@
+/*
+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.
+*/
+
+// rollout.go contains the types and functions to deal with
+// gradual rollout of the new revision for a configuration target.
+// The types in this file are expected to be serialized as strings
+// and used as annotations for progressive rollout logic.
+
+package traffic
+
+import (
+	"testing"
+
+	"github.com/google/go-cmp/cmp"
+)
+
+func TestRoll(t *testing.T) {
+	tests := []struct {
+		name            string
+		prev, cur, want *Rollout
+	}{{
+		name: "no prev",
+		cur:  &Rollout{},
+		prev: nil,
+		want: &Rollout{},
+	}, {
+		name: "simplest, same",
+		cur: &Rollout{
+			Configurations: []ConfigurationRollout{{
+				ConfigurationName: "mick",
+				Percent:           100,
+				Revisions: []RevisionRollout{{
+					RevisionName: "let-it-bleed",
+					Percent:      100,
+				}},
+			}},
+		},
+		prev: &Rollout{
+			Configurations: []ConfigurationRollout{{
+				ConfigurationName: "mick",
+				Percent:           100,
+				Revisions: []RevisionRollout{{
+					RevisionName: "let-it-bleed",
+					Percent:      100,
+				}},
+			}},
+		},
+		want: &Rollout{
+			Configurations: []ConfigurationRollout{{
+				ConfigurationName: "mick",
+				Percent:           100,
+				Revisions: []RevisionRollout{{
+					RevisionName: "let-it-bleed",
+					Percent:      100,
+				}},
+			}},
+		},
+	}, {
+		name: "simplest, roll",
+		cur: &Rollout{
+			Configurations: []ConfigurationRollout{{
+				ConfigurationName: "mick",
+				Percent:           100,
+				Revisions: []RevisionRollout{{
+					RevisionName: "let-it-bleed",
+					Percent:      100,
+				}},
+			}},
+		},
+		prev: &Rollout{
+			Configurations: []ConfigurationRollout{{
+				ConfigurationName: "mick",
+				Percent:           100,
+				Revisions: []RevisionRollout{{
+					RevisionName: "goat-head-soup",
+					Percent:      100,
+				}},
+			}},
+		},
+		want: &Rollout{
+			Configurations: []ConfigurationRollout{{
+				ConfigurationName: "mick",
+				Percent:           100,
+				Revisions: []RevisionRollout{{
+					RevisionName: "goat-head-soup",
+					Percent:      99,
+				}, {
+					RevisionName: "let-it-bleed",
+					Percent:      1,
+				}},
+			}},
+		},
+	}, {
+		name: "roll with two existing, no deletes",
+		cur: &Rollout{
+			Configurations: []ConfigurationRollout{{
+				ConfigurationName: "mick",
+				Percent:           100,
+				Revisions: []RevisionRollout{{
+					RevisionName: "sticky-fingers",
+					Percent:      100,
+				}},
+			}},
+		},
+		prev: &Rollout{
+			Configurations: []ConfigurationRollout{{
+				ConfigurationName: "mick",
+				Percent:           100,
+				Revisions: []RevisionRollout{{
+					RevisionName: "goat-head-soup",
+					Percent:      95,
+				}, {
+					RevisionName: "beggars-banquet",
+					Percent:      5, // 5 should become 4.
+				}},
+			}},
+		},
+		want: &Rollout{
+			Configurations: []ConfigurationRollout{{
+				ConfigurationName: "mick",
+				Percent:           100,
+				Revisions: []RevisionRollout{{
+					RevisionName: "goat-head-soup",
+					Percent:      95,
+				}, {
+					RevisionName: "beggars-banquet",
+					Percent:      4,
+				}, {
+					RevisionName: "sticky-fingers",
+					Percent:      1,
+				}},
+			}},
+		},
+	}, {
+		name: "roll with delete (two fast successive rolls)",
+		cur: &Rollout{
+			Configurations: []ConfigurationRollout{{
+				ConfigurationName: "mick",
+				Percent:           100,
+				Revisions: []RevisionRollout{{
+					RevisionName: "between-the-buttons",
+					Percent:      100,
+				}},
+			}},
+		},
+		prev: &Rollout{
+			Configurations: []ConfigurationRollout{{
+				ConfigurationName: "mick",
+				Percent:           100,
+				Revisions: []RevisionRollout{{
+					RevisionName: "goat-head-soup",
+					Percent:      99,
+				}, {
+					RevisionName: "bridges-to-babylon",
+					Percent:      1,
+				}},
+			}},
+		},
+		want: &Rollout{
+			Configurations: []ConfigurationRollout{{
+				ConfigurationName: "mick",
+				Percent:           100,
+				Revisions: []RevisionRollout{{
+					RevisionName: "goat-head-soup",
+					Percent:      99,
+				}, {
+					RevisionName: "between-the-buttons",
+					Percent:      1,
+				}},
+			}},
+		},
+	}, {
+		name: "new tag, no roll", // just attached a tag to an existing route.
+		cur: &Rollout{
+			Configurations: []ConfigurationRollout{{
+				ConfigurationName: "mick",
+				Percent:           100,
+				Revisions: []RevisionRollout{{
+					RevisionName: "black-on-blue",
+					Percent:      100,
+				}},
+			}, {
+				ConfigurationName: "mick",
+				Tag:               "jagger",
+				Percent:           100,
+				Revisions: []RevisionRollout{{
+					RevisionName: "black-on-blue",
+					Percent:      100,
+				}},
+			}},
+		},
+		prev: &Rollout{
+			Configurations: []ConfigurationRollout{{
+				ConfigurationName: "mick",
+				Percent:           100,
+				Revisions: []RevisionRollout{{
+					RevisionName: "black-on-blue",
+					Percent:      100,
+				}},
+			}},
+		},
+		want: &Rollout{
+			Configurations: []ConfigurationRollout{{
+				ConfigurationName: "mick",
+				Percent:           100,
+				Revisions: []RevisionRollout{{
+					RevisionName: "black-on-blue",
+					Percent:      100,
+				}},
+			}, {
+				ConfigurationName: "mick",
+				Tag:               "jagger",
+				Percent:           100,
+				Revisions: []RevisionRollout{{
+					RevisionName: "black-on-blue",
+					Percent:      100,
+				}},
+			}},
+		},
+	}, {
+		name: "deleted config, no roll",
+		cur: &Rollout{
+			Configurations: []ConfigurationRollout{{
+				ConfigurationName: "mick",
+				Percent:           100,
+				Revisions: []RevisionRollout{{
+					RevisionName: "it's-only-rock-n-roll",
+					Percent:      100,
+				}},
+			}},
+		},
+		prev: &Rollout{
+			Configurations: []ConfigurationRollout{{
+				ConfigurationName: "keith",
+				Percent:           50,
+				Revisions: []RevisionRollout{{
+					RevisionName: "black-on-blue",
+					Percent:      50,
+				}},
+			}, {
+				ConfigurationName: "mick",
+				Percent:           50,
+				Revisions: []RevisionRollout{{
+					RevisionName: "it's-only-rock-n-roll",
+					Percent:      50,
+				}},
+			}},
+		},
+		want: &Rollout{
+			Configurations: []ConfigurationRollout{{
+				ConfigurationName: "mick",
+				Percent:           100,
+				Revisions: []RevisionRollout{{
+					RevisionName: "it's-only-rock-n-roll",
+					Percent:      100,
+				}},
+			}},
+		},
+	}, {
+		name: "new config, no roll",
+		cur: &Rollout{
+			Configurations: []ConfigurationRollout{{
+				ConfigurationName: "keith",
+				Percent:           50,
+				Revisions: []RevisionRollout{{
+					RevisionName: "black-on-blue",
+					Percent:      50,
+				}},
+			}, {
+				ConfigurationName: "mick",
+				Percent:           50,
+				Revisions: []RevisionRollout{{
+					RevisionName: "it's-only-rock-n-roll",
+					Percent:      50,
+				}},
+			}},
+		},
+		prev: &Rollout{
+			Configurations: []ConfigurationRollout{{
+				ConfigurationName: "mick",
+				Percent:           100,
+				Revisions: []RevisionRollout{{
+					RevisionName: "it's-only-rock-n-roll",
+					Percent:      100,
+				}},
+			}},
+		},
+		want: &Rollout{
+			Configurations: []ConfigurationRollout{{
+				ConfigurationName: "keith",
+				Percent:           50,
+				Revisions: []RevisionRollout{{
+					RevisionName: "black-on-blue",
+					Percent:      50,
+				}},
+			}, {
+				ConfigurationName: "mick",
+				Percent:           50,
+				Revisions: []RevisionRollout{{
+					RevisionName: "it's-only-rock-n-roll",
+					Percent:      50,
+				}},
+			}},
+		},
+	}}
+
+	for _, tc := range tests {
+		t.Run(tc.name, func(t *testing.T) {
+			if got, want := tc.cur.Step(tc.prev), tc.want; !cmp.Equal(got, want) {
+				t.Errorf("Wrong rolled rollout, diff(-want,+got):\n%s", cmp.Diff(want, got))
+			}
+		})
+	}
+}
diff --git a/pkg/reconciler/route/visibility/visibility_test.go b/pkg/reconciler/route/visibility/visibility_test.go
index 4b50a6f08..73620208d 100644
--- a/pkg/reconciler/route/visibility/visibility_test.go
+++ b/pkg/reconciler/route/visibility/visibility_test.go
@@ -435,7 +435,7 @@ func TestVisibility(t *testing.T) {
 			if got, want := visibility, tt.expected; !cmp.Equal(got, want) {
 				t.Errorf("Unexpected visibility diff (-want +got):\n%s", cmp.Diff(want, got))
 			}
-			if tt.expectedErr != err {
+			if !errors.Is(err, tt.expectedErr) {
 				t.Errorf("Err = %v, want: %v", err, tt.expectedErr)
 			}
 		})
diff --git a/test/clients.go b/test/clients.go
index 806268256..aa1ef925a 100644
--- a/test/clients.go
+++ b/test/clients.go
@@ -21,7 +21,7 @@ package test
 import (
 	"context"
 
-	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/client-go/dynamic"
 	"k8s.io/client-go/kubernetes"
 	"k8s.io/client-go/rest"
@@ -168,7 +168,7 @@ func newServingClients(cfg *rest.Config, namespace string) (*ServingClients, err
 func (clients *ServingClients) Delete(routes, configs, services []string) []error {
 	deletions := []struct {
 		client interface {
-			Delete(ctx context.Context, name string, options v1.DeleteOptions) error
+			Delete(ctx context.Context, name string, options metav1.DeleteOptions) error
 		}
 		items []string
 	}{
@@ -179,8 +179,8 @@ func (clients *ServingClients) Delete(routes, configs, services []string) []erro
 		{clients.Configs, configs},
 	}
 
-	propPolicy := v1.DeletePropagationForeground
-	dopt := v1.DeleteOptions{
+	propPolicy := metav1.DeletePropagationForeground
+	dopt := metav1.DeleteOptions{
 		PropagationPolicy: &propPolicy,
 	}
 
diff --git a/test/config/chaosduck.yaml b/test/config/chaosduck.yaml
index 574a276ed..eda81fa76 100644
--- a/test/config/chaosduck.yaml
+++ b/test/config/chaosduck.yaml
@@ -81,6 +81,8 @@ spec:
         # Disable chaos on the Istio components.
         - "-disable=istio-webhook"
         - "-disable=networking-istio"
+        # Disable chaos on Kourier components.
+        - "-disable=3scale-kourier-control"
         # Disable chaos on webhooks until https://github.com/knative/pkg/issues/1509 is
         # sorted out.
         - "-disable=webhook"
diff --git a/test/conformance/api/v1/revision_timeout_test.go b/test/conformance/api/v1/revision_timeout_test.go
index 71d929258..211a64c91 100644
--- a/test/conformance/api/v1/revision_timeout_test.go
+++ b/test/conformance/api/v1/revision_timeout_test.go
@@ -101,6 +101,8 @@ func TestRevisionTimeout(t *testing.T) {
 
 	for _, tc := range testCases {
 		t.Run(tc.name, func(t *testing.T) {
+			t.Parallel()
+
 			names := test.ResourceNames{
 				Service: test.ObjectNameForTest(t),
 				Image:   test.Timeout,
diff --git a/test/conformance/runtime/envpropagation_test.go b/test/conformance/runtime/envpropagation_test.go
index 79fd2aa16..074e48f97 100644
--- a/test/conformance/runtime/envpropagation_test.go
+++ b/test/conformance/runtime/envpropagation_test.go
@@ -34,6 +34,8 @@ func TestSecretsViaEnv(t *testing.T) {
 	clients := test.Setup(t)
 
 	t.Run("env", func(t *testing.T) {
+		t.Parallel()
+
 		err := fetchEnvironmentAndVerify(t, clients, WithEnv(corev1.EnvVar{
 			Name: test.EnvKey,
 			ValueFrom: &corev1.EnvVarSource{
@@ -51,6 +53,8 @@ func TestSecretsViaEnv(t *testing.T) {
 	})
 
 	t.Run("envFrom", func(t *testing.T) {
+		t.Parallel()
+
 		err := fetchEnvironmentAndVerify(t, clients, WithEnvFrom(corev1.EnvFromSource{
 			SecretRef: &corev1.SecretEnvSource{
 				LocalObjectReference: corev1.LocalObjectReference{
@@ -70,6 +74,8 @@ func TestConfigsViaEnv(t *testing.T) {
 	clients := test.Setup(t)
 
 	t.Run("env", func(t *testing.T) {
+		t.Parallel()
+
 		err := fetchEnvironmentAndVerify(t, clients, WithEnv(corev1.EnvVar{
 			Name: test.EnvKey,
 			ValueFrom: &corev1.EnvVarSource{
@@ -87,6 +93,8 @@ func TestConfigsViaEnv(t *testing.T) {
 	})
 
 	t.Run("envFrom", func(t *testing.T) {
+		t.Parallel()
+
 		err := fetchEnvironmentAndVerify(t, clients, WithEnvFrom(corev1.EnvFromSource{
 			ConfigMapRef: &corev1.ConfigMapEnvSource{
 				LocalObjectReference: corev1.LocalObjectReference{
diff --git a/test/conformance/runtime/readiness_probe_test.go b/test/conformance/runtime/readiness_probe_test.go
index a76074555..882c4781a 100644
--- a/test/conformance/runtime/readiness_probe_test.go
+++ b/test/conformance/runtime/readiness_probe_test.go
@@ -30,7 +30,7 @@ import (
 )
 
 func TestProbeRuntime(t *testing.T) {
-
+	t.Parallel()
 	clients := test.Setup(t)
 
 	var testCases = []struct {
diff --git a/test/e2e-auto-tls-tests.sh b/test/e2e-auto-tls-tests.sh
index 1a4047dcb..824999b97 100755
--- a/test/e2e-auto-tls-tests.sh
+++ b/test/e2e-auto-tls-tests.sh
@@ -22,15 +22,15 @@ function knative_setup() {
 
 function setup_auto_tls_env_variables() {
   # DNS zone for the testing domain.
-  export DNS_ZONE="knative-e2e"
+  export AUTO_TLS_TEST_DNS_ZONE="knative-e2e"
   # Google Cloud project that hosts the DNS server for the testing domain `kn-e2e.dev`
-  export CLOUD_DNS_PROJECT="knative-e2e-dns"
+  export AUTO_TLS_TEST_CLOUD_DNS_PROJECT="knative-e2e-dns"
   # The service account credential file used to access the DNS server.
-  export CLOUD_DNS_SERVICE_ACCOUNT_KEY_FILE="${GOOGLE_APPLICATION_CREDENTIALS}"
+  export AUTO_TLS_TEST_CLOUD_DNS_SERVICE_ACCOUNT_KEY_FILE="${GOOGLE_APPLICATION_CREDENTIALS}"
 
-  export DOMAIN_NAME="kn-e2e.dev"
+  export AUTO_TLS_TEST_DOMAIN_NAME="kn-e2e.dev"
 
-  export CUSTOM_DOMAIN_SUFFIX="$(($RANDOM % 10000)).${E2E_PROJECT_ID}.${DOMAIN_NAME}"
+  export CUSTOM_DOMAIN_SUFFIX="$(($RANDOM % 10000)).${E2E_PROJECT_ID}.${AUTO_TLS_TEST_DOMAIN_NAME}"
 
   export TLS_TEST_NAMESPACE="tls"
 
@@ -43,7 +43,7 @@ function setup_auto_tls_env_variables() {
     INGRESS_SERVICE="istio-ingressgateway"
   fi
   local IP=$(kubectl get svc -n ${INGRESS_NAMESPACE} ${INGRESS_SERVICE} -o jsonpath="{.status.loadBalancer.ingress[0].ip}")
-  export INGRESS_IP=${IP}
+  export AUTO_TLS_TEST_INGRESS_IP=${IP}
 }
 
 function setup_custom_domain() {
@@ -86,7 +86,7 @@ function setup_http01_auto_tls() {
   # Rely on the built-in naming (for logstream)
   unset TLS_SERVICE_NAME
   # The full host name of the Knative Service. This is used to configure the DNS record.
-  export FULL_HOST_NAME="*.${TLS_TEST_NAMESPACE}.${CUSTOM_DOMAIN_SUFFIX}"
+  export AUTO_TLS_TEST_FULL_HOST_NAME="*.${TLS_TEST_NAMESPACE}.${CUSTOM_DOMAIN_SUFFIX}"
 
   kubectl delete kcert --all -n "${TLS_TEST_NAMESPACE}"
 
diff --git a/test/e2e-networking-library.sh b/test/e2e-networking-library.sh
index fba4bdafe..bc60fb39f 100644
--- a/test/e2e-networking-library.sh
+++ b/test/e2e-networking-library.sh
@@ -21,7 +21,7 @@ function install_istio() {
 
   if [[ -z "${NET_ISTIO_COMMIT}" ]]; then
     # TODO: Figure out the commit of net-istio.yaml from net-istio.yaml
-    readonly NET_ISTIO_COMMIT="6bbca066373b21689b5d90381c27920533809e82"
+    readonly NET_ISTIO_COMMIT="8102cd3d32f05be1c58260a9717d532a4a6d2f60"
   fi
 
   # And checkout the setup script based on that commit.
@@ -46,6 +46,10 @@ function install_istio() {
   ISTIO_PROFILE+="-mesh"
   ISTIO_PROFILE+=".yaml"
 
+  if [[ -n "$CLUSTER_DOMAIN" ]]; then
+    sed -ie "s/cluster\.local/${CLUSTER_DOMAIN}/g" ${NET_ISTIO_DIR}/third_party/istio-${ISTIO_VERSION}/${ISTIO_PROFILE}
+  fi
+
   echo ">> Installing Istio"
   echo "Istio version: ${ISTIO_VERSION}"
   echo "Istio profile: ${ISTIO_PROFILE}"
diff --git a/test/e2e/autotls/config/dnscleanup/main.go b/test/e2e/autotls/config/dnscleanup/main.go
index df00a0ffb..d998ffdd1 100644
--- a/test/e2e/autotls/config/dnscleanup/main.go
+++ b/test/e2e/autotls/config/dnscleanup/main.go
@@ -27,7 +27,7 @@ import (
 var env config.EnvConfig
 
 func main() {
-	if err := envconfig.Process("", &env); err != nil {
+	if err := envconfig.Process("auto_tls_test", &env); err != nil {
 		log.Fatalf("Failed to process environment variable: %v.", err)
 	}
 	record := &config.DNSRecord{
diff --git a/test/e2e/autotls/config/dnssetup/main.go b/test/e2e/autotls/config/dnssetup/main.go
index 304569398..94b42916d 100644
--- a/test/e2e/autotls/config/dnssetup/main.go
+++ b/test/e2e/autotls/config/dnssetup/main.go
@@ -36,7 +36,7 @@ import (
 var env config.EnvConfig
 
 func main() {
-	if err := envconfig.Process("", &env); err != nil {
+	if err := envconfig.Process("auto_tls_test", &env); err != nil {
 		log.Fatalf("Failed to process environment variable: %v.", err)
 	}
 	if err := setupDNSRecord(); err != nil {
diff --git a/test/e2e/autotls/util.go b/test/e2e/autotls/util.go
index f984d8812..751a29e7e 100644
--- a/test/e2e/autotls/util.go
+++ b/test/e2e/autotls/util.go
@@ -18,12 +18,12 @@ package autotls
 
 import (
 	"encoding/json"
+	"errors"
 	"fmt"
 	"io/ioutil"
 	"net"
 	"net/http"
 	"net/http/httputil"
-	"net/url"
 	"testing"
 
 	"k8s.io/apimachinery/pkg/util/sets"
@@ -116,9 +116,9 @@ 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"
 }
diff --git a/test/e2e/gc/gc_test.go b/test/e2e/gc/gc_test.go
index 2023779b2..ee3d596c1 100644
--- a/test/e2e/gc/gc_test.go
+++ b/test/e2e/gc/gc_test.go
@@ -20,6 +20,7 @@ package gc
 
 import (
 	"context"
+	"errors"
 	"testing"
 	"time"
 
@@ -86,7 +87,7 @@ func TestRevisionGC(t *testing.T) {
 		}
 		return false, err
 	})
-	if err == wait.ErrWaitTimeout {
+	if errors.Is(err, wait.ErrWaitTimeout) {
 		t.Fatalf("Got revision %v, expected not_found", originalRevision)
 	}
 	if err != nil {
diff --git a/test/e2e/grpc_test.go b/test/e2e/grpc_test.go
index 2ee2b76ab..099edd79e 100644
--- a/test/e2e/grpc_test.go
+++ b/test/e2e/grpc_test.go
@@ -20,6 +20,7 @@ package e2e
 
 import (
 	"context"
+	"errors"
 	"fmt"
 	"io"
 	"math"
@@ -150,7 +151,7 @@ func loadBalancingTest(ctx *TestContext, host, domain string) {
 				default:
 					got, err := pingGRPC(host, domain, wantPrefix)
 					if err != nil {
-						return fmt.Errorf("ping gRPC error: %v", err)
+						return fmt.Errorf("ping gRPC error: %w", err)
 					}
 					if !strings.HasPrefix(got, wantPrefix) {
 						return fmt.Errorf("response = %q, wantPrefix = %q", got, wantPrefix)
@@ -203,7 +204,7 @@ func generateGRPCTraffic(concurrentRequests int, host, domain string, stopChan c
 					got, err := pingGRPC(host, domain, want)
 
 					if err != nil {
-						return fmt.Errorf("ping gRPC error: %v", err)
+						return fmt.Errorf("ping gRPC error: %w", err)
 					}
 					if got != want {
 						return fmt.Errorf("response = %q, want = %q", got, want)
@@ -213,7 +214,7 @@ func generateGRPCTraffic(concurrentRequests int, host, domain string, stopChan c
 		})
 	}
 	if err := grp.Wait(); err != nil {
-		return fmt.Errorf("error processing requests %v", err)
+		return fmt.Errorf("error processing requests %w", err)
 	}
 	return nil
 }
@@ -230,7 +231,7 @@ func pingGRPC(host, domain, message string) (string, error) {
 
 	got, err := pc.Ping(context.Background(), want)
 	if err != nil {
-		return "", fmt.Errorf("could not send request: %v", err)
+		return "", fmt.Errorf("could not send request: %w", err)
 	}
 	return got.Msg, nil
 }
@@ -308,7 +309,7 @@ func streamTest(tc *TestContext, host, domain string) {
 	stream.CloseSend()
 
 	_, err = stream.Recv()
-	if err != io.EOF {
+	if !errors.Is(err, io.EOF) {
 		tc.t.Errorf("Expected EOF, got %v", err)
 	}
 }
diff --git a/test/e2e/minscale_readiness_test.go b/test/e2e/minscale_readiness_test.go
index 64da0eb07..be3048821 100644
--- a/test/e2e/minscale_readiness_test.go
+++ b/test/e2e/minscale_readiness_test.go
@@ -20,6 +20,7 @@ package e2e
 
 import (
 	"context"
+	"errors"
 	"fmt"
 	"strconv"
 	"testing"
@@ -227,9 +228,9 @@ func ensureDesiredScale(clients *test.Clients, t *testing.T, serviceName string,
 
 		return false, nil
 	})
-	if err != wait.ErrWaitTimeout {
+	if !errors.Is(err, wait.ErrWaitTimeout) {
 		t.Log("PollError =", err)
 	}
 
-	return latestReady, err == wait.ErrWaitTimeout
+	return latestReady, errors.Is(err, wait.ErrWaitTimeout)
 }
diff --git a/test/e2e/route_service_test.go b/test/e2e/route_service_test.go
index 59a89aeeb..9ae8d6f80 100644
--- a/test/e2e/route_service_test.go
+++ b/test/e2e/route_service_test.go
@@ -79,6 +79,8 @@ func TestRoutesNotReady(t *testing.T) {
 }
 
 func TestRouteVisibilityChanges(t *testing.T) {
+	t.Parallel()
+
 	testCases := []struct {
 		name            string
 		withTrafficSpec rtesting.ServiceOption
diff --git a/test/e2e/service_to_service_test.go b/test/e2e/service_to_service_test.go
index ba067f4dd..617ad3fee 100644
--- a/test/e2e/service_to_service_test.go
+++ b/test/e2e/service_to_service_test.go
@@ -209,6 +209,8 @@ func TestServiceToServiceCall(t *testing.T) {
 			Path:   resources.Route.Status.URL.Path,
 		}
 		t.Run(tc.name, func(t *testing.T) {
+			t.Parallel()
+
 			cancel := logstream.Start(t)
 			defer cancel()
 			testProxyToHelloworld(t, clients, helloworldURL, true /*inject*/, false /*accessible externally*/)
@@ -260,6 +262,8 @@ func TestSvcToSvcViaActivator(t *testing.T) {
 
 	for _, tc := range testInjection {
 		t.Run(tc.name, func(t *testing.T) {
+			t.Parallel()
+
 			cancel := logstream.Start(t)
 			defer cancel()
 			testSvcToSvcCallViaActivator(t, clients, tc.injectA, tc.injectB)
@@ -306,6 +310,8 @@ func TestCallToPublicService(t *testing.T) {
 
 	for _, tc := range gatewayTestCases {
 		t.Run(tc.name, func(t *testing.T) {
+			t.Parallel()
+
 			cancel := logstream.Start(t)
 			defer cancel()
 			testProxyToHelloworld(t, clients, tc.url, false /*inject*/, tc.accessibleExternally)
diff --git a/test/e2e/subroutes_test.go b/test/e2e/subroutes_test.go
index cc15ee4c7..8a4a63882 100644
--- a/test/e2e/subroutes_test.go
+++ b/test/e2e/subroutes_test.go
@@ -83,6 +83,7 @@ func TestSubrouteLocalSTS(t *testing.T) { // We can't use a longer more descript
 		helloworldURL := resources.Route.Status.Address.URL.URL()
 		helloworldURL.Host = strings.TrimSuffix(domain, tc.suffix)
 		t.Run(tc.name, func(t *testing.T) {
+			t.Parallel()
 			testProxyToHelloworld(t, clients, helloworldURL, true, false)
 		})
 	}
diff --git a/test/e2e/tagheader/tag_header_based_routing_test.go b/test/e2e/tagheader/tag_header_based_routing_test.go
index 596189d94..8ab3ebeb8 100644
--- a/test/e2e/tagheader/tag_header_based_routing_test.go
+++ b/test/e2e/tagheader/tag_header_based_routing_test.go
@@ -111,6 +111,8 @@ func TestTagHeaderBasedRouting(t *testing.T) {
 
 	for _, tt := range testCases {
 		t.Run(tt.name, func(t *testing.T) {
+			t.Parallel()
+
 			if _, err := pkgTest.WaitForEndpointState(
 				context.Background(),
 				clients.KubeClient,
diff --git a/test/performance/benchmarks/scale-from-zero/continuous/main.go b/test/performance/benchmarks/scale-from-zero/continuous/main.go
index ea72da452..f53806dab 100644
--- a/test/performance/benchmarks/scale-from-zero/continuous/main.go
+++ b/test/performance/benchmarks/scale-from-zero/continuous/main.go
@@ -65,7 +65,7 @@ const (
 func clientsFromConfig() (*test.Clients, error) {
 	cfg, err := injection.GetRESTConfig("", "")
 	if err != nil {
-		return nil, fmt.Errorf("error building kubeconfig: %v", err)
+		return nil, fmt.Errorf("error building kubeconfig: %w", err)
 	}
 	return test.NewClientsFromConfig(cfg, testNamespace)
 }
@@ -112,7 +112,7 @@ func createServices(clients *test.Clients, count int) ([]*v1test.ResourceObjects
 		g.Go(func() error {
 			var err error
 			if objs[ndx], err = v1test.CreateServiceReady(&testing.T{}, clients, testNames[ndx], sos...); err != nil {
-				return fmt.Errorf("%02d: failed to create Ready service: %v", ndx, err)
+				return fmt.Errorf("%02d: failed to create Ready service: %w", ndx, err)
 			}
 			return nil
 		})
diff --git a/test/performance/performance.go b/test/performance/performance.go
index b559d0a86..1c235defe 100644
--- a/test/performance/performance.go
+++ b/test/performance/performance.go
@@ -23,7 +23,7 @@ import (
 	"net/http"
 	"time"
 
-	v1 "k8s.io/api/core/v1"
+	corev1 "k8s.io/api/core/v1"
 	"k8s.io/apimachinery/pkg/labels"
 	"k8s.io/apimachinery/pkg/util/wait"
 
@@ -69,7 +69,7 @@ func WaitForScaleToZero(ctx context.Context, namespace string, selector labels.S
 		}
 		for _, pod := range pods {
 			// Pending or Running w/o deletion timestamp (i.e. terminating).
-			if pod.Status.Phase == v1.PodPending || pod.Status.Phase == v1.PodRunning && pod.ObjectMeta.DeletionTimestamp == nil {
+			if pod.Status.Phase == corev1.PodPending || pod.Status.Phase == corev1.PodRunning && pod.ObjectMeta.DeletionTimestamp == nil {
 				return false, nil
 			}
 		}
diff --git a/test/test_images/autoscale/autoscale.go b/test/test_images/autoscale/autoscale.go
index 541057b48..c1e176944 100644
--- a/test/test_images/autoscale/autoscale.go
+++ b/test/test_images/autoscale/autoscale.go
@@ -17,6 +17,7 @@ limitations under the License.
 package main
 
 import (
+	"errors"
 	"fmt"
 	"math"
 	"math/rand"
@@ -140,7 +141,7 @@ func handler(w http.ResponseWriter, r *http.Request) {
 	if err != nil {
 		// If it is a numeric error and it's parsing error, then
 		// try to parse it as a duration
-		if nerr, ok := err.(*strconv.NumError); ok && nerr.Err == strconv.ErrSyntax {
+		if errors.Is(err, strconv.ErrSyntax) {
 			ms, hasMs, err = parseDurationParam(r, "sleep")
 			if err != nil {
 				http.Error(w, err.Error(), http.StatusBadRequest)
diff --git a/test/test_images/grpc-ping/main.go b/test/test_images/grpc-ping/main.go
index 257d5342b..236a0dd58 100644
--- a/test/test_images/grpc-ping/main.go
+++ b/test/test_images/grpc-ping/main.go
@@ -18,6 +18,7 @@ package main
 
 import (
 	"context"
+	"errors"
 	"io"
 	"log"
 	"net/http"
@@ -58,7 +59,7 @@ func (s *server) PingStream(stream ping.PingService_PingStreamServer) error {
 	log.Printf("Starting stream")
 	for {
 		req, err := stream.Recv()
-		if err == io.EOF {
+		if errors.Is(err, io.EOF) {
 			log.Printf("Ending stream")
 			return nil
 		}
diff --git a/test/test_images/runtime/handlers/proc.go b/test/test_images/runtime/handlers/proc.go
index 606a6ee3f..c490f41fa 100644
--- a/test/test_images/runtime/handlers/proc.go
+++ b/test/test_images/runtime/handlers/proc.go
@@ -17,6 +17,7 @@ limitations under the License.
 package handlers
 
 import (
+	"errors"
 	"io"
 	"os"
 
@@ -26,7 +27,7 @@ import (
 // stdin attempts to read bytes from the stdin file descriptor and returns the result.
 func stdin() *types.Stdin {
 	_, err := os.Stdin.Read(make([]byte, 1))
-	if err == io.EOF {
+	if errors.Is(err, io.EOF) {
 		return &types.Stdin{EOF: &yes}
 	}
 	if err != nil {
diff --git a/third_party/cert-manager-latest/net-certmanager.yaml b/third_party/cert-manager-latest/net-certmanager.yaml
index 9a50534e6..035115f59 100644
--- a/third_party/cert-manager-latest/net-certmanager.yaml
+++ b/third_party/cert-manager-latest/net-certmanager.yaml
@@ -18,7 +18,7 @@ metadata:
   # These are the permissions needed by the `cert-manager` `Certificate` implementation.
   name: knative-serving-certmanager
   labels:
-    serving.knative.dev/release: "v20201028-6d22680"
+    serving.knative.dev/release: "v20201029-48615be"
     serving.knative.dev/controller: "true"
     networking.knative.dev/certificate-provider: cert-manager
 rules:
@@ -49,7 +49,7 @@ kind: ValidatingWebhookConfiguration
 metadata:
   name: config.webhook.net-certmanager.networking.internal.knative.dev
   labels:
-    serving.knative.dev/release: "v20201028-6d22680"
+    serving.knative.dev/release: "v20201029-48615be"
 webhooks:
   - admissionReviewVersions:
       - v1beta1
@@ -86,7 +86,7 @@ metadata:
   name: net-certmanager-webhook-certs
   namespace: knative-serving
   labels:
-    serving.knative.dev/release: "v20201028-6d22680"
+    serving.knative.dev/release: "v20201029-48615be"
 
 ---
 # Copyright 2020 The Knative Authors
@@ -109,7 +109,7 @@ metadata:
   name: config-certmanager
   namespace: knative-serving
   labels:
-    serving.knative.dev/release: "v20201028-6d22680"
+    serving.knative.dev/release: "v20201029-48615be"
     networking.knative.dev/certificate-provider: cert-manager
 data:
   _example: |
@@ -156,7 +156,7 @@ metadata:
   name: networking-certmanager
   namespace: knative-serving
   labels:
-    serving.knative.dev/release: "v20201028-6d22680"
+    serving.knative.dev/release: "v20201029-48615be"
     networking.knative.dev/certificate-provider: cert-manager
 spec:
   selector:
@@ -168,14 +168,14 @@ spec:
         cluster-autoscaler.kubernetes.io/safe-to-evict: "true"
       labels:
         app: networking-certmanager
-        serving.knative.dev/release: "v20201028-6d22680"
+        serving.knative.dev/release: "v20201029-48615be"
     spec:
       serviceAccountName: controller
       containers:
         - name: networking-certmanager
           # This is the Go import path for the binary that is containerized
           # and substituted here.
-          image: gcr.io/knative-nightly/knative.dev/net-certmanager/cmd/controller@sha256:a156cd7ffd73b7c03f0878b865999f105ce760e32e8d0a7b7cbf511cc8ef3388
+          image: gcr.io/knative-nightly/knative.dev/net-certmanager/cmd/controller@sha256:a8b7c934df2bd19495e34cb40feea830193ae7d6655e2b59250a33eb501f5feb
           resources:
             requests:
               cpu: 30m
@@ -197,6 +197,11 @@ spec:
               value: knative.dev/serving
           securityContext:
             allowPrivilegeEscalation: false
+            readOnlyRootFilesystem: true
+            runAsNonRoot: true
+            capabilities:
+              drop:
+                - all
           ports:
             - name: metrics
               containerPort: 9090
@@ -208,7 +213,7 @@ kind: Service
 metadata:
   labels:
     app: networking-certmanager
-    serving.knative.dev/release: "v20201028-6d22680"
+    serving.knative.dev/release: "v20201029-48615be"
     networking.knative.dev/certificate-provider: cert-manager
   name: networking-certmanager
   namespace: knative-serving
@@ -245,7 +250,7 @@ metadata:
   name: net-certmanager-webhook
   namespace: knative-serving
   labels:
-    serving.knative.dev/release: "v20201028-6d22680"
+    serving.knative.dev/release: "v20201029-48615be"
 spec:
   selector:
     matchLabels:
@@ -258,14 +263,14 @@ spec:
       labels:
         app: net-certmanager-webhook
         role: net-certmanager-webhook
-        serving.knative.dev/release: "v20201028-6d22680"
+        serving.knative.dev/release: "v20201029-48615be"
     spec:
       serviceAccountName: controller
       containers:
         - name: webhook
           # This is the Go import path for the binary that is containerized
           # and substituted here.
-          image: gcr.io/knative-nightly/knative.dev/net-certmanager/cmd/webhook@sha256:b45aacfed54aa5701ef4d4f736582a9a295b491d96ca5ab7452dbde4037ead26
+          image: gcr.io/knative-nightly/knative.dev/net-certmanager/cmd/webhook@sha256:b9c8ae97b4e74d400fc6842d24ac40b112504498e509a37aaf055a531486845a
           resources:
             requests:
               cpu: 20m
@@ -289,6 +294,11 @@ spec:
               value: net-certmanager-webhook
           securityContext:
             allowPrivilegeEscalation: false
+            readOnlyRootFilesystem: true
+            runAsNonRoot: true
+            capabilities:
+              drop:
+                - all
           ports:
             - name: metrics
               containerPort: 9090
@@ -319,7 +329,7 @@ metadata:
   namespace: knative-serving
   labels:
     role: net-certmanager-webhook
-    serving.knative.dev/release: "v20201028-6d22680"
+    serving.knative.dev/release: "v20201029-48615be"
 spec:
   ports:
     # Define metrics and profiling for them to be accessible within service meshes.
diff --git a/third_party/contour-latest/contour.yaml b/third_party/contour-latest/contour.yaml
index 6836f3b19..c2b4df555 100644
--- a/third_party/contour-latest/contour.yaml
+++ b/third_party/contour-latest/contour.yaml
@@ -1482,7 +1482,7 @@ spec:
     spec:
       containers:
         - name: contour
-          image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:5bcfaee357822e2dbfdd2ea3d90e4a93151ecc89597baea7d0eb47e0d3b6b59e
+          image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:d691d5e3c0a3bf60d796667cb1418ef6a2db806052c16f3f9cbb0579cefc41eb
           imagePullPolicy: Always
           command:
             - contour
@@ -1709,7 +1709,7 @@ spec:
             - --contour-key-file=/certs/tls.key
             - --config-path=/config/contour.yaml
           command: ["contour"]
-          image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:5bcfaee357822e2dbfdd2ea3d90e4a93151ecc89597baea7d0eb47e0d3b6b59e
+          image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:d691d5e3c0a3bf60d796667cb1418ef6a2db806052c16f3f9cbb0579cefc41eb
           imagePullPolicy: IfNotPresent
           name: contour
           ports:
@@ -1795,7 +1795,7 @@ spec:
           args:
             - envoy
             - shutdown-manager
-          image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:5bcfaee357822e2dbfdd2ea3d90e4a93151ecc89597baea7d0eb47e0d3b6b59e
+          image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:d691d5e3c0a3bf60d796667cb1418ef6a2db806052c16f3f9cbb0579cefc41eb
           imagePullPolicy: IfNotPresent
           lifecycle:
             preStop:
@@ -1871,7 +1871,7 @@ spec:
             - --envoy-key-file=/certs/tls.key
           command:
             - contour
-          image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:5bcfaee357822e2dbfdd2ea3d90e4a93151ecc89597baea7d0eb47e0d3b6b59e
+          image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:d691d5e3c0a3bf60d796667cb1418ef6a2db806052c16f3f9cbb0579cefc41eb
           imagePullPolicy: IfNotPresent
           name: envoy-initconfig
           volumeMounts:
@@ -3381,7 +3381,7 @@ spec:
     spec:
       containers:
         - name: contour
-          image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:5bcfaee357822e2dbfdd2ea3d90e4a93151ecc89597baea7d0eb47e0d3b6b59e
+          image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:d691d5e3c0a3bf60d796667cb1418ef6a2db806052c16f3f9cbb0579cefc41eb
           imagePullPolicy: Always
           command:
             - contour
@@ -3608,7 +3608,7 @@ spec:
             - --contour-key-file=/certs/tls.key
             - --config-path=/config/contour.yaml
           command: ["contour"]
-          image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:5bcfaee357822e2dbfdd2ea3d90e4a93151ecc89597baea7d0eb47e0d3b6b59e
+          image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:d691d5e3c0a3bf60d796667cb1418ef6a2db806052c16f3f9cbb0579cefc41eb
           imagePullPolicy: IfNotPresent
           name: contour
           ports:
@@ -3694,7 +3694,7 @@ spec:
           args:
             - envoy
             - shutdown-manager
-          image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:5bcfaee357822e2dbfdd2ea3d90e4a93151ecc89597baea7d0eb47e0d3b6b59e
+          image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:d691d5e3c0a3bf60d796667cb1418ef6a2db806052c16f3f9cbb0579cefc41eb
           imagePullPolicy: IfNotPresent
           lifecycle:
             preStop:
@@ -3770,7 +3770,7 @@ spec:
             - --envoy-key-file=/certs/tls.key
           command:
             - contour
-          image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:5bcfaee357822e2dbfdd2ea3d90e4a93151ecc89597baea7d0eb47e0d3b6b59e
+          image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:d691d5e3c0a3bf60d796667cb1418ef6a2db806052c16f3f9cbb0579cefc41eb
           imagePullPolicy: IfNotPresent
           name: envoy-initconfig
           volumeMounts:
diff --git a/third_party/contour-latest/net-contour.yaml b/third_party/contour-latest/net-contour.yaml
index fb07408e0..1618d34d6 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: "v20201027-babf82a0"
+    serving.knative.dev/release: "v20201029-dd6e0ede"
 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:61cf3120ee3b65b5f9660418746d7cf095e2533dc2f689e8798b016ae1402c66
+          image: gcr.io/knative-nightly/knative.dev/net-contour/cmd/controller@sha256:5c016c66ab7017e6927b2b74966cc74f67aebb16e480d4b0de5009902573d487
           resources:
             requests:
               cpu: 40m
@@ -131,5 +131,10 @@ spec:
               containerPort: 8008
           securityContext:
             allowPrivilegeEscalation: false
+            readOnlyRootFilesystem: true
+            runAsNonRoot: true
+            capabilities:
+              drop:
+                - all
 
 ---
diff --git a/third_party/kourier-latest/README.md b/third_party/kourier-latest/README.md
deleted file mode 100644
index c4fcf438c..000000000
--- a/third_party/kourier-latest/README.md
+++ /dev/null
@@ -1,5 +0,0 @@
-The kourier.yaml file is generated by running
-
-```
-./download-kourier.sh
-```
diff --git a/third_party/kourier-latest/download-kourier.sh b/third_party/kourier-latest/download-kourier.sh
deleted file mode 100755
index 9bf25ff50..000000000
--- a/third_party/kourier-latest/download-kourier.sh
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/usr/bin/env bash
-
-# Copyright 2019 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.
-
-set -ex
-
-# Download Kourier
-KOURIER_VERSION=0.3.12
-KOURIER_YAML=kourier-knative.yaml
-DOWNLOAD_URL=https://raw.githubusercontent.com/3scale/kourier/v${KOURIER_VERSION}/deploy/${KOURIER_YAML}
-
-wget -O kourier.yaml ${DOWNLOAD_URL}
diff --git a/vendor/go.uber.org/goleak/testmain.go b/vendor/go.uber.org/goleak/testmain.go
new file mode 100644
index 000000000..316f6e1ba
--- /dev/null
+++ b/vendor/go.uber.org/goleak/testmain.go
@@ -0,0 +1,63 @@
+// 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.
+
+package goleak
+
+import (
+	"fmt"
+	"io"
+	"os"
+)
+
+// Variables for stubbing in unit tests.
+var (
+	_osExit             = os.Exit
+	_osStderr io.Writer = os.Stderr
+)
+
+// TestingM is the minimal subset of testing.M that we use.
+type TestingM interface {
+	Run() int
+}
+
+// VerifyTestMain can be used in a TestMain function for package tests to
+// verify that there were no goroutine leaks.
+// To use it, your TestMain function should look like:
+//
+//  func TestMain(m *testing.M) {
+//    goleak.VerifyTestMain(m)
+//  }
+//
+// See https://golang.org/pkg/testing/#hdr-Main for more details.
+//
+// This will run all tests as per normal, and if they were successful, look
+// for any goroutine leaks and fail the tests if any leaks were found.
+func VerifyTestMain(m TestingM, options ...Option) {
+	exitCode := m.Run()
+
+	if exitCode == 0 {
+		if err := Find(options...); err != nil {
+			fmt.Fprintf(_osStderr, "goleak: Errors on successful test run: %v\n", err)
+			exitCode = 1
+		}
+	}
+
+	_osExit(exitCode)
+}
diff --git a/vendor/knative.dev/pkg/reconciler/testing/reactions.go b/vendor/knative.dev/pkg/reconciler/testing/reactions.go
index 09caae767..d66b41a71 100644
--- a/vendor/knative.dev/pkg/reconciler/testing/reactions.go
+++ b/vendor/knative.dev/pkg/reconciler/testing/reactions.go
@@ -32,6 +32,11 @@ import (
 //      // Makes calls to create revisions return an error.
 //      InduceFailure("create", "revisions"),
 //   },
+// Or to target a subresource, say a patch to InMemoryChannel.Status, you would add:
+//   WithReactors: []clientgotesting.ReactionFunc{
+//      // Makes calls to patch inmemorychannels status subresource return an error.
+//      InduceFailure("patch", "inmemorychannels/status"),
+//   },
 func InduceFailure(verb, resource string) clientgotesting.ReactionFunc {
 	return func(action clientgotesting.Action) (handled bool, ret runtime.Object, err error) {
 		if !action.Matches(verb, resource) {
diff --git a/vendor/knative.dev/pkg/test/ghutil/client.go b/vendor/knative.dev/pkg/test/ghutil/client.go
index 8f6466eb7..8c14509f1 100644
--- a/vendor/knative.dev/pkg/test/ghutil/client.go
+++ b/vendor/knative.dev/pkg/test/ghutil/client.go
@@ -20,6 +20,7 @@ package ghutil
 
 import (
 	"context"
+	"errors"
 	"fmt"
 	"io/ioutil"
 	"log"
@@ -119,10 +120,11 @@ func (gc *GithubClient) retry(message string, maxRetries int, call func() (*gith
 		if resp, err = call(); nil == err {
 			return resp, nil
 		}
-		switch err := err.(type) {
-		case *github.RateLimitError:
-			gc.waitForRateReset(&err.Rate)
-		default:
+
+		var errRateLimit *github.RateLimitError
+		if errors.As(err, &errRateLimit) {
+			gc.waitForRateReset(&errRateLimit.Rate)
+		} else {
 			return resp, err
 		}
 		log.Printf("error %s: %v. Will retry.\n", message, err)
diff --git a/vendor/knative.dev/pkg/test/gke/client.go b/vendor/knative.dev/pkg/test/gke/client.go
index 443d5fefe..b1713860e 100644
--- a/vendor/knative.dev/pkg/test/gke/client.go
+++ b/vendor/knative.dev/pkg/test/gke/client.go
@@ -45,7 +45,7 @@ type sdkClient struct {
 func NewSDKClient(opts ...option.ClientOption) (SDKOperations, error) {
 	containerService, err := container.NewService(context.Background(), opts...)
 	if err != nil {
-		return nil, fmt.Errorf("failed to create container service: '%v'", err)
+		return nil, fmt.Errorf("failed to create container service: %w", err)
 	}
 	return &sdkClient{containerService}, nil
 }
@@ -110,7 +110,7 @@ func (gsc *sdkClient) ListClustersInProject(project string) ([]*container.Cluste
 	projectFullPath := fmt.Sprintf("projects/%s/locations/-", project)
 	resp, err := gsc.Projects.Locations.Clusters.List(projectFullPath).Do()
 	if err != nil {
-		return clusters, fmt.Errorf("failed to list clusters under project %s: %v", project, err)
+		return clusters, fmt.Errorf("failed to list clusters under project %s: %w", project, err)
 	}
 	return resp.Clusters, nil
 }
diff --git a/vendor/knative.dev/pkg/test/mako/config/benchmark.go b/vendor/knative.dev/pkg/test/mako/config/benchmark.go
index 74bcbe928..3ddff5cdd 100644
--- a/vendor/knative.dev/pkg/test/mako/config/benchmark.go
+++ b/vendor/knative.dev/pkg/test/mako/config/benchmark.go
@@ -51,6 +51,7 @@ func getBenchmark() (*mpb.BenchmarkInfo, error) {
 	if koerr != nil {
 		data, err = ioutil.ReadFile(filepath.Join(configMako, env+".config"))
 		if err != nil {
+			//nolint: errorlint // It's fine not to wrap here.
 			return nil, fmt.Errorf("cannot load both from kodata and from config mako config map: %s, %s", koerr.Error(), err.Error())
 		}
 	}
diff --git a/vendor/knative.dev/pkg/test/presubmit-tests.sh b/vendor/knative.dev/pkg/test/presubmit-tests.sh
index dcae993bc..3348f253d 100644
--- a/vendor/knative.dev/pkg/test/presubmit-tests.sh
+++ b/vendor/knative.dev/pkg/test/presubmit-tests.sh
@@ -37,16 +37,4 @@ function pre_build_tests() {
   return 0
 }
 
-# Run the unit tests with an additional flag '-mod=vendor' to avoid
-# downloading the deps in unit tests CI job
-function unit_tests() {
-  # Run the default way.
-  default_unit_test_runner || failed=1
-
-  # Run unit testing select packages without race detection,
-  # so that they may use: // +build !race
-  report_go_test ./leaderelection || failed=1
-
-}
-
 main $@
diff --git a/vendor/knative.dev/pkg/test/spoof/error_checks.go b/vendor/knative.dev/pkg/test/spoof/error_checks.go
index 8a913b99d..e152e11d7 100644
--- a/vendor/knative.dev/pkg/test/spoof/error_checks.go
+++ b/vendor/knative.dev/pkg/test/spoof/error_checks.go
@@ -19,13 +19,20 @@ limitations under the License.
 package spoof
 
 import (
+	"errors"
 	"net"
 	"strings"
 )
 
-func isTCPTimeout(e error) bool {
-	err, ok := e.(net.Error)
-	return err != nil && ok && err.Timeout()
+func isTCPTimeout(err error) bool {
+	if err == nil {
+		return false
+	}
+	var errNet net.Error
+	if !errors.As(err, &errNet) {
+		return false
+	}
+	return errNet.Timeout()
 }
 
 func isDNSError(err error) bool {
diff --git a/vendor/knative.dev/pkg/test/spoof/spoof.go b/vendor/knative.dev/pkg/test/spoof/spoof.go
index f8c5b9498..e69b39c28 100644
--- a/vendor/knative.dev/pkg/test/spoof/spoof.go
+++ b/vendor/knative.dev/pkg/test/spoof/spoof.go
@@ -237,7 +237,8 @@ func (sc *SpoofingClient) logZipkinTrace(spoofResp *Response) {
 
 	json, err := zipkin.JSONTrace(traceID /* We don't know the expected number of spans */, -1, 5*time.Second)
 	if err != nil {
-		if _, ok := err.(*zipkin.TimeoutError); !ok {
+		var errTimeout *zipkin.TimeoutError
+		if !errors.As(err, &errTimeout) {
 			sc.Logf("Error getting zipkin trace: %v", err)
 		}
 	}