Repository: knative/serving
Pull request #10248 (2020-12-02 20:58:59)

Add new TLS-related conditions to DomainMapping condset
Part 1 of #10247 

<!-- Please include the 'why' behind your changes if no issue exists -->
## Proposed Changes

* Add new TLS-related conditions to DomainMapping condset

**Release Note**

<!-- Enter your extended release note in the below block. If the PR requires
additional action from users switching to the new release, include the string
"action required". If no release note is required, write "NONE". -->

```release-note
NONE
```


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

This pull-request has been approved by: *<a href="https://github.com/knative/serving/pull/10248#" title="Author self-approved">tcnghia</a>*

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

The pull request process is described [here](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process)

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

- ~~[pkg/apis/OWNERS](https://github.com/knative/serving/blob/master/pkg/apis/OWNERS)~~ [tcnghia]
- ~~[pkg/reconciler/OWNERS](https://github.com/knative/serving/blob/master/pkg/reconciler/OWNERS)~~ [tcnghia]

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":[]} -->
tcnghia: /assign @YoussB 
/assign @julz 
codecov[bot]: # [Codecov](https://codecov.io/gh/knative/serving/pull/10248?src=pr&el=h1) Report
> Merging [#10248](https://codecov.io/gh/knative/serving/pull/10248?src=pr&el=desc) (b0ea510) into [master](https://codecov.io/gh/knative/serving/commit/0a8bcbf34abe5dead0c32284a40c55acbdb8c9de?el=desc) (0a8bcbf) will **increase** coverage by `0.09%`.
> The diff coverage is `93.75%`.

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

```diff
@@            Coverage Diff             @@
##           master   #10248      +/-   ##
==========================================
+ Coverage   88.10%   88.19%   +0.09%     
==========================================
  Files         184      184              
  Lines        8619     8635      +16     
==========================================
+ Hits         7594     7616      +22     
+ Misses        787      785       -2     
+ Partials      238      234       -4     
```


| [Impacted Files](https://codecov.io/gh/knative/serving/pull/10248?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [pkg/apis/serving/v1alpha1/domainmapping\_types.go](https://codecov.io/gh/knative/serving/pull/10248/diff?src=pr&el=tree#diff-cGtnL2FwaXMvc2VydmluZy92MWFscGhhMS9kb21haW5tYXBwaW5nX3R5cGVzLmdv) | `100.00% <ø> (ø)` | |
| [...g/apis/serving/v1alpha1/domainmapping\_lifecycle.go](https://codecov.io/gh/knative/serving/pull/10248/diff?src=pr&el=tree#diff-cGtnL2FwaXMvc2VydmluZy92MWFscGhhMS9kb21haW5tYXBwaW5nX2xpZmVjeWNsZS5nbw==) | `85.71% <93.33%> (+4.23%)` | :arrow_up: |
| [pkg/reconciler/domainmapping/reconciler.go](https://codecov.io/gh/knative/serving/pull/10248/diff?src=pr&el=tree#diff-cGtnL3JlY29uY2lsZXIvZG9tYWlubWFwcGluZy9yZWNvbmNpbGVyLmdv) | `89.33% <100.00%> (+0.14%)` | :arrow_up: |
| [pkg/reconciler/revision/reconcile\_resources.go](https://codecov.io/gh/knative/serving/pull/10248/diff?src=pr&el=tree#diff-cGtnL3JlY29uY2lsZXIvcmV2aXNpb24vcmVjb25jaWxlX3Jlc291cmNlcy5nbw==) | `83.13% <0.00%> (+2.40%)` | :arrow_up: |
| [pkg/reconciler/configuration/configuration.go](https://codecov.io/gh/knative/serving/pull/10248/diff?src=pr&el=tree#diff-cGtnL3JlY29uY2lsZXIvY29uZmlndXJhdGlvbi9jb25maWd1cmF0aW9uLmdv) | `88.28% <0.00%> (+3.90%)` | :arrow_up: |

------

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


Patch:
diff --git a/.github/workflows/knative-releasability.yaml b/.github/workflows/knative-releasability.yaml
index f13cc479a..ca0820a6e 100644
--- a/.github/workflows/knative-releasability.yaml
+++ b/.github/workflows/knative-releasability.yaml
@@ -142,7 +142,7 @@ jobs:
           echo 'SLACK_TITLE=Releasability for ${{ github.repository }} @ ${{ env.RELEASE }} is NO-GO!' >> $GITHUB_ENV
 
       - name: Post status to Slack
-        if: steps.exists.outputs.release-branch == 'false'
+        if: ${{ secrets.SLACK_WEBHOOK != '' && steps.exists.outputs.release-branch == 'false' }}
         uses: rtCamp/action-slack-notify@v2.1.0
         env:
           SLACK_ICON: http://github.com/knative.png?size=48
diff --git a/.github/workflows/knative-style.yaml b/.github/workflows/knative-style.yaml
index 56360215f..5d3d3163e 100644
--- a/.github/workflows/knative-style.yaml
+++ b/.github/workflows/knative-style.yaml
@@ -100,7 +100,7 @@ jobs:
 
       - name: Install Tools
         env:
-          WOKE_VERSION: v0.1.15
+          WOKE_VERSION: v0.4.1
         run: |
           TEMP_PATH="$(mktemp -d)"
           cd $TEMP_PATH
diff --git a/OWNERS_ALIASES b/OWNERS_ALIASES
index 5ac75d31a..5ab36ed92 100644
--- a/OWNERS_ALIASES
+++ b/OWNERS_ALIASES
@@ -24,7 +24,6 @@ aliases:
   - dprotaso        # API
   - markusthoemmes  # Scaling
   - mattmoor        # API
-  - mdemirhan       # Network
   - tcnghia         # Network
   - vagababov       # Scaling
 
@@ -35,7 +34,6 @@ aliases:
   - grantr          # TOC
   - markusthoemmes  # Scaling/TOC
   - mattmoor        # API/TOC
-  - mdemirhan       # Network
   - nak3            # Network
   - tcnghia         # Network/TOC
   - ZhiminXiang     # Network
@@ -43,13 +41,11 @@ aliases:
 
   autoscaling-approvers:
   - markusthoemmes
-  - mdemirhan
   - vagababov
   - julz
   autoscaling-reviewers:
   - julz
   - markusthoemmes
-  - mdemirhan
   - taragu
   - vagababov
   - yanweiguo
@@ -74,7 +70,6 @@ aliases:
   networking-approvers:
   - JRBANCEL
   - markusthoemmes
-  - mdemirhan
   - nak3
   - tcnghia
   - vagababov
@@ -83,7 +78,6 @@ aliases:
   - andrew-su
   - JRBANCEL
   - markusthoemmes
-  - mdemirhan
   - nak3
   - shashwathi
   - tcnghia
diff --git a/config/core/configmaps/logging.yaml b/config/core/configmaps/logging.yaml
index c6acaa972..b8d95c0de 100644
--- a/config/core/configmaps/logging.yaml
+++ b/config/core/configmaps/logging.yaml
@@ -20,7 +20,7 @@ metadata:
   labels:
     serving.knative.dev/release: devel
   annotations:
-    knative.dev/example-checksum: "23eed3d8"
+    knative.dev/example-checksum: "56c59cba"
 data:
   _example: |
     ################################
@@ -47,11 +47,11 @@ data:
         "errorOutputPaths": ["stderr"],
         "encoding": "json",
         "encoderConfig": {
-          "timeKey": "ts",
-          "levelKey": "level",
+          "timeKey": "timestamp",
+          "levelKey": "severity",
           "nameKey": "logger",
           "callerKey": "caller",
-          "messageKey": "msg",
+          "messageKey": "message",
           "stacktraceKey": "stacktrace",
           "lineEnding": "",
           "levelEncoder": "",
diff --git a/go.mod b/go.mod
index b823081e6..71819088c 100644
--- a/go.mod
+++ b/go.mod
@@ -34,8 +34,8 @@ require (
 	k8s.io/client-go v0.18.12
 	k8s.io/code-generator v0.18.12
 	k8s.io/kube-openapi v0.0.0-20200410145947-bcb3869e6f29
-	knative.dev/caching v0.0.0-20201125150135-91fb5833c3c6
+	knative.dev/caching v0.0.0-20201204024709-8decac65dea7
 	knative.dev/hack v0.0.0-20201201234937-fddbf732e450
-	knative.dev/networking v0.0.0-20201125133435-4b21f11ccfa7
-	knative.dev/pkg v0.0.0-20201130192436-e5346d90e980
+	knative.dev/networking v0.0.0-20201203234509-4cd0793eed11
+	knative.dev/pkg v0.0.0-20201204175509-c9bac6be76ca
 )
diff --git a/go.sum b/go.sum
index 6d21f16db..ac9251412 100644
--- a/go.sum
+++ b/go.sum
@@ -134,6 +134,8 @@ github.com/blang/semver v3.5.0+incompatible h1:CGxCgetQ64DKk7rdZ++Vfnb1+ogGNnB17
 github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
 github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
 github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
+github.com/blendle/zapdriver v1.3.1 h1:C3dydBOWYRiOk+B8X9IVZ5IOe+7cl+tGOexN4QqHfpE=
+github.com/blendle/zapdriver v1.3.1/go.mod h1:mdXfREi6u5MArG4j9fewC+FGnXaBR+T4Ox4J2u4eHCc=
 github.com/bmizerany/perks v0.0.0-20141205001514-d9a9656a3a4b h1:AP/Y7sqYicnjGDfD5VcY4CIfh1hRXBUavxrvELjTiOE=
 github.com/bmizerany/perks v0.0.0-20141205001514-d9a9656a3a4b/go.mod h1:ac9efd0D1fsDb3EJvhqgXRbFx7bs2wqZ10HQPeU8U/Q=
 github.com/c2h5oh/datasize v0.0.0-20171227191756-4eba002a5eae/go.mod h1:S/7n9copUssQ56c7aAgHqftWO4LTf4xY6CGWt8Bc+3M=
@@ -1214,18 +1216,16 @@ k8s.io/legacy-cloud-providers v0.18.8/go.mod h1:tgp4xYf6lvjrWnjQwTOPvWQE9IVqSBGP
 k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
 k8s.io/utils v0.0.0-20200603063816-c1c6865ac451 h1:v8ud2Up6QK1lNOKFgiIVrZdMg7MpmSnvtrOieolJKoE=
 k8s.io/utils v0.0.0-20200603063816-c1c6865ac451/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
-knative.dev/caching v0.0.0-20201125150135-91fb5833c3c6 h1:W1R7UnGSGJmL6btl8AY8AVCT2cEwgHzRtlort7icB5M=
-knative.dev/caching v0.0.0-20201125150135-91fb5833c3c6/go.mod h1:IocU4F1XK8udXpTRC4m9KWyEVtT928sSP+T7Oy34UDg=
-knative.dev/hack v0.0.0-20201120192952-353db687ec5b h1:Lc+AKgwhAZUD98mN++qTHeeaP6FRmS8fcwc/rXkP8G0=
-knative.dev/hack v0.0.0-20201120192952-353db687ec5b/go.mod h1:PHt8x8yX5Z9pPquBEfIj0X66f8iWkWfR0S/sarACJrI=
+knative.dev/caching v0.0.0-20201204024709-8decac65dea7 h1:ZGlDPyF7ycBjKZ/kBFQNAYKJORvtVo88ofk5RQVUAw4=
+knative.dev/caching v0.0.0-20201204024709-8decac65dea7/go.mod h1:addawKx4UeuW2pSFGXQPDJ8w+OZmG3MQ+rdT3jjvCxU=
 knative.dev/hack v0.0.0-20201201234937-fddbf732e450 h1:IyitWF7OzfunCgE4b9ZsJAeIRoQ6JOyqDrz/19X4iS4=
 knative.dev/hack v0.0.0-20201201234937-fddbf732e450/go.mod h1:PHt8x8yX5Z9pPquBEfIj0X66f8iWkWfR0S/sarACJrI=
-knative.dev/networking v0.0.0-20201125133435-4b21f11ccfa7 h1:O40i4ZCYfpaw7m1yUwtmRhBOdT0HRp3MYD4PWaRzYqI=
-knative.dev/networking v0.0.0-20201125133435-4b21f11ccfa7/go.mod h1:EpImbpW3gu85Mg39GT7gUJTVYLtFYWDsZQCZlKFmGUM=
-knative.dev/pkg v0.0.0-20201125095035-9bf616d2f46a h1:pdJpLaq50mLKrPWYSQgTH2p64Dk7Fq/xID6l0F69cVY=
-knative.dev/pkg v0.0.0-20201125095035-9bf616d2f46a/go.mod h1:wXZqP8MXCxb51yNFlecA13BwG7Hk370SWDFWV4dx4ug=
-knative.dev/pkg v0.0.0-20201130192436-e5346d90e980 h1:44zakwrFjbivCM/YR+ni70e9u1ELtwA7VF1HSmUcj+g=
-knative.dev/pkg v0.0.0-20201130192436-e5346d90e980/go.mod h1:wXZqP8MXCxb51yNFlecA13BwG7Hk370SWDFWV4dx4ug=
+knative.dev/networking v0.0.0-20201203234509-4cd0793eed11 h1:sogSEftyYRTNZ3g2Ynmvw8djj9X0RwBNa9GCDDLQMr4=
+knative.dev/networking v0.0.0-20201203234509-4cd0793eed11/go.mod h1:vj8h8ODz+HnStJgIgvAY2pyc146SJA1CaB9iKFpSjiM=
+knative.dev/pkg v0.0.0-20201203193109-a536174bdf99 h1:92aXqHzL90KS8KG/8tw90cUs+nEDssZXmeux7LLfrMs=
+knative.dev/pkg v0.0.0-20201203193109-a536174bdf99/go.mod h1:Jtbz2/1gB8EZgZA4VvabTxM+AcDt2WL2P0RaFnKcOX8=
+knative.dev/pkg v0.0.0-20201204175509-c9bac6be76ca h1:A8Nly0CAT2J+oVs37pzRIqOiBqSGWPMGNXCNwGoUwkQ=
+knative.dev/pkg v0.0.0-20201204175509-c9bac6be76ca/go.mod h1:Jtbz2/1gB8EZgZA4VvabTxM+AcDt2WL2P0RaFnKcOX8=
 modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw=
 modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk=
 modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k=
diff --git a/hack/update-codegen.sh b/hack/update-codegen.sh
index 0e637c93f..fa7aacff4 100755
--- a/hack/update-codegen.sh
+++ b/hack/update-codegen.sh
@@ -18,18 +18,15 @@ set -o errexit
 set -o nounset
 set -o pipefail
 
-export GO111MODULE=on
+source $(dirname $0)/../vendor/knative.dev/hack/codegen-library.sh
+
 # If we run with -mod=vendor here, then generate-groups.sh looks for vendor files in the wrong place.
 export GOFLAGS=-mod=
 
-if [ -z "${GOPATH:-}" ]; then
-  export GOPATH=$(go env GOPATH)
-fi
-
-source $(dirname $0)/../vendor/knative.dev/hack/library.sh
-
 boilerplate="${REPO_ROOT_DIR}/hack/boilerplate/boilerplate.go.txt"
 
+echo "=== Update Codegen for $MODULE_NAME"
+
 # Parse flags to determine if we should generate protobufs.
 generate_protobufs=0
 while [[ $# -ne 0 ]]; do
@@ -43,7 +40,7 @@ done
 readonly generate_protobufs
 
 if (( generate_protobufs )); then
-  echo "Generating protocol buffer code"
+  group "Generating protocol buffer code"
   protos=$(find "${REPO_ROOT_DIR}/pkg" "${REPO_ROOT_DIR}/test" -name '*.proto')
   for proto in $protos
   do
@@ -57,14 +54,11 @@ if (( generate_protobufs )); then
   done
 fi
 
-echo "Generating checksums for configmap _example keys"
-${REPO_ROOT_DIR}/hack/update-checksums.sh
+group "Generating checksums for configmap _example keys"
 
-CODEGEN_PKG=${CODEGEN_PKG:-$(cd ${REPO_ROOT_DIR}; ls -d -1 $(dirname $0)/../vendor/k8s.io/code-generator 2>/dev/null || echo ../code-generator)}
-KNATIVE_CODEGEN_PKG=${KNATIVE_CODEGEN_PKG:-$(cd ${REPO_ROOT_DIR}; ls -d -1 $(dirname $0)/../vendor/knative.dev/pkg 2>/dev/null || echo ../pkg)}
+${REPO_ROOT_DIR}/hack/update-checksums.sh
 
-chmod +x ${CODEGEN_PKG}/generate-groups.sh
-chmod +x ${KNATIVE_CODEGEN_PKG}/hack/generate-knative.sh
+group "Kubernetes Codegen"
 
 # generate the code with:
 # --output-base    because this script should also be able to run inside the vendor dir of
@@ -75,12 +69,16 @@ ${CODEGEN_PKG}/generate-groups.sh "deepcopy,client,informer,lister" \
   "serving:v1 serving:v1alpha1 autoscaling:v1alpha1" \
   --go-header-file "${boilerplate}"
 
+group "Knative Codegen"
+
 # Knative Injection
 ${KNATIVE_CODEGEN_PKG}/hack/generate-knative.sh "injection" \
   knative.dev/serving/pkg/client knative.dev/serving/pkg/apis \
   "serving:v1 serving:v1alpha1 autoscaling:v1alpha1" \
   --go-header-file "${boilerplate}"
 
+group "Deepcopy Gen"
+
 # Depends on generate-groups.sh to install bin/deepcopy-gen
 ${GOPATH}/bin/deepcopy-gen \
   -O zz_generated.deepcopy \
@@ -98,5 +96,7 @@ ${GOPATH}/bin/deepcopy-gen \
   -i knative.dev/serving/pkg/logging \
   -i knative.dev/serving/pkg/metrics
 
+group "Update deps post-codegen"
+
 # Make sure our dependencies are up-to-date
 ${REPO_ROOT_DIR}/hack/update-deps.sh
diff --git a/pkg/activator/net/revision_backends.go b/pkg/activator/net/revision_backends.go
index 1dc4431a8..8e4e8001d 100644
--- a/pkg/activator/net/revision_backends.go
+++ b/pkg/activator/net/revision_backends.go
@@ -40,12 +40,12 @@ import (
 
 	network "knative.dev/networking/pkg"
 	pkgnet "knative.dev/networking/pkg/apis/networking"
+	"knative.dev/networking/pkg/prober"
 	endpointsinformer "knative.dev/pkg/client/injection/kube/informers/core/v1/endpoints"
 	serviceinformer "knative.dev/pkg/client/injection/kube/informers/core/v1/service"
 	"knative.dev/pkg/controller"
 	"knative.dev/pkg/logging"
 	"knative.dev/pkg/logging/logkey"
-	"knative.dev/pkg/network/prober"
 	"knative.dev/pkg/reconciler"
 	"knative.dev/serving/pkg/apis/serving"
 	revisioninformer "knative.dev/serving/pkg/client/injection/informers/serving/v1/revision"
diff --git a/pkg/apis/serving/v1alpha1/domainmapping_lifecycle.go b/pkg/apis/serving/v1alpha1/domainmapping_lifecycle.go
index 0f9f9e494..4ab88d439 100644
--- a/pkg/apis/serving/v1alpha1/domainmapping_lifecycle.go
+++ b/pkg/apis/serving/v1alpha1/domainmapping_lifecycle.go
@@ -27,6 +27,7 @@ var domainMappingCondSet = apis.NewLivingConditionSet(
 	DomainMappingConditionDomainClaimed,
 	DomainMappingConditionReferenceResolved,
 	DomainMappingConditionIngressReady,
+	DomainMappingConditionCertificateProvisioned,
 )
 
 // GetConditionSet retrieves the condition set for this resource. Implements the KRShaped interface.
@@ -57,6 +58,60 @@ func (dms *DomainMappingStatus) InitializeConditions() {
 	domainMappingCondSet.Manage(dms).InitializeConditions()
 }
 
+const (
+	// AutoTLSNotEnabledMessage is the message which is set on the
+	// DomainMappingConditionCertificateProvisioned condition when it is set to True
+	// because AutoTLS was not enabled.
+	AutoTLSNotEnabledMessage = "autoTLS is not enabled"
+)
+
+// MarkTLSNotEnabled sets DomainMappingConditionCertificateProvisioned to true when
+// certificate provisioning was skipped because TLS was not enabled.
+func (dms *DomainMappingStatus) MarkTLSNotEnabled(msg string) {
+	domainMappingCondSet.Manage(dms).MarkTrueWithReason(DomainMappingConditionCertificateProvisioned,
+		"TLSNotEnabled", msg)
+}
+
+// MarkCertificateReady marks the DomainMappingConditionCertificateProvisioned
+// condition to indicate that the Certificate is ready.
+func (dms *DomainMappingStatus) MarkCertificateReady(name string) {
+	domainMappingCondSet.Manage(dms).MarkTrue(DomainMappingConditionCertificateProvisioned)
+}
+
+// MarkCertificateNotReady marks the DomainMappingConditionCertificateProvisioned
+// condition to indicate that the Certificate is not ready.
+func (dms *DomainMappingStatus) MarkCertificateNotReady(name string) {
+	domainMappingCondSet.Manage(dms).MarkUnknown(DomainMappingConditionCertificateProvisioned,
+		"CertificateNotReady",
+		"Certificate %s is not ready.", name)
+}
+
+// MarkCertificateNotOwned changes the DomainMappingConditionCertificateProvisioned
+// status to be false with the reason being that there is an existing
+// certificate with the name we wanted to use.
+func (dms *DomainMappingStatus) MarkCertificateNotOwned(name string) {
+	domainMappingCondSet.Manage(dms).MarkFalse(DomainMappingConditionCertificateProvisioned,
+		"CertificateNotOwned",
+		"There is an existing certificate %s that we don't own.", name)
+}
+
+// MarkCertificateProvisionFailed marks the
+// DomainMappingConditionCertificateProvisioned condition to indicate that the
+// Certificate provisioning failed.
+func (dms *DomainMappingStatus) MarkCertificateProvisionFailed(name string) {
+	domainMappingCondSet.Manage(dms).MarkFalse(DomainMappingConditionCertificateProvisioned,
+		"CertificateProvisionFailed",
+		"Certificate %s failed to be provisioned.", name)
+}
+
+// MarkHTTPDowngrade sets DomainMappingConditionCertificateProvisioned to true when plain
+// HTTP is enabled even when Certificate is not ready.
+func (dms *DomainMappingStatus) MarkHTTPDowngrade(name string) {
+	domainMappingCondSet.Manage(dms).MarkTrueWithReason(DomainMappingConditionCertificateProvisioned,
+		"HTTPDowngrade",
+		"Certificate %s is not ready downgrade HTTP.", name)
+}
+
 // MarkIngressNotConfigured changes the IngressReady condition to be unknown to reflect
 // that the Ingress does not yet have a Status.
 func (dms *DomainMappingStatus) MarkIngressNotConfigured() {
diff --git a/pkg/apis/serving/v1alpha1/domainmapping_types.go b/pkg/apis/serving/v1alpha1/domainmapping_types.go
index 8421afdf0..0fa82ca95 100644
--- a/pkg/apis/serving/v1alpha1/domainmapping_types.go
+++ b/pkg/apis/serving/v1alpha1/domainmapping_types.go
@@ -106,6 +106,10 @@ const (
 	// DomainMappingConditionDomainClaimed reflects that the ClusterDomainClaim
 	// for this DomainMapping exists, and is owned by this DomainMapping.
 	DomainMappingConditionDomainClaimed apis.ConditionType = "DomainClaimed"
+
+	// DomainMappingConditionCertificateProvisioned is set to False when the
+	// Knative Certificates fail to be provisioned for the DomainMapping.
+	DomainMappingConditionCertificateProvisioned apis.ConditionType = "CertificateProvisioned"
 )
 
 // GetStatus retrieves the status of the DomainMapping. Implements the KRShaped interface.
diff --git a/pkg/reconciler/autoscaling/kpa/scaler.go b/pkg/reconciler/autoscaling/kpa/scaler.go
index 00954607e..104d1eae6 100644
--- a/pkg/reconciler/autoscaling/kpa/scaler.go
+++ b/pkg/reconciler/autoscaling/kpa/scaler.go
@@ -29,8 +29,8 @@ import (
 	network "knative.dev/networking/pkg"
 	"knative.dev/networking/pkg/apis/networking"
 	nv1a1 "knative.dev/networking/pkg/apis/networking/v1alpha1"
+	"knative.dev/networking/pkg/prober"
 	pkgnet "knative.dev/pkg/network"
-	"knative.dev/pkg/network/prober"
 	"knative.dev/serving/pkg/activator"
 	pav1alpha1 "knative.dev/serving/pkg/apis/autoscaling/v1alpha1"
 	"knative.dev/serving/pkg/autoscaler/config/autoscalerconfig"
diff --git a/pkg/reconciler/domainmapping/reconciler.go b/pkg/reconciler/domainmapping/reconciler.go
index 17ec099b6..f0da3bdfa 100644
--- a/pkg/reconciler/domainmapping/reconciler.go
+++ b/pkg/reconciler/domainmapping/reconciler.go
@@ -58,6 +58,9 @@ func (r *Reconciler) ReconcileKind(ctx context.Context, dm *v1alpha1.DomainMappi
 	logger := logging.FromContext(ctx)
 	logger.Debugf("Reconciling DomainMapping %s/%s", dm.Namespace, dm.Name)
 
+	// TODO(https://github.com/knative/serving/issues/10247)
+	dm.Status.MarkTLSNotEnabled("AutoTLS for DomainMapping is not implemented")
+
 	// Defensively assume the ingress is not configured until we manage to
 	// successfully reconcile it below. This avoids error cases where we fail
 	// before we've reconciled the ingress and get a new ObservedGeneration but
diff --git a/pkg/reconciler/route/reconcile_resources.go b/pkg/reconciler/route/reconcile_resources.go
index 14a91c791..e84c373b5 100644
--- a/pkg/reconciler/route/reconcile_resources.go
+++ b/pkg/reconciler/route/reconcile_resources.go
@@ -21,7 +21,9 @@ import (
 	"encoding/json"
 	"fmt"
 
+	"github.com/google/go-cmp/cmp"
 	"go.uber.org/zap"
+	"go.uber.org/zap/zapcore"
 	"golang.org/x/sync/errgroup"
 	corev1 "k8s.io/api/core/v1"
 	"k8s.io/apimachinery/pkg/api/equality"
@@ -77,9 +79,19 @@ func (c *Reconciler) reconcileIngress(
 		// And recompute the rollout state.
 		effectiveRO := curRO.Step(prevRO, int(c.clock.Now().UnixNano()))
 
+		// Comparing and diffing isn't cheap so do it only if we're going
+		// to actually log the message.
+		// Those are well known types, cmp won't panic.
+		logger := logging.FromContext(ctx).Desugar()
+		if logger.Core().Enabled(zapcore.DebugLevel) && !cmp.Equal(prevRO, effectiveRO) {
+			logger.Debug("Rollout diff:(-was,+now)",
+				zap.String("diff", cmp.Diff(prevRO, effectiveRO)))
+		}
+
 		// Now check if the ingress status changed from not ready to ready.
 		rtView := r.Status.GetCondition(v1.RouteConditionIngressReady)
 		if ingress.IsReady() && !rtView.IsTrue() {
+			logger.Debug("Observing Ingress not-ready to ready switch condition for rollout")
 			effectiveRO.ObserveReady(int(c.clock.Now().UnixNano()))
 		}
 
@@ -92,13 +104,14 @@ func (c *Reconciler) reconcileIngress(
 		if !equality.Semantic.DeepEqual(ingress.Spec, desired.Spec) ||
 			!equality.Semantic.DeepEqual(ingress.Annotations, desired.Annotations) ||
 			!equality.Semantic.DeepEqual(ingress.Labels, desired.Labels) {
+
 			// It is notable that one reason for differences here may be defaulting.
 			// When that is the case, the Update will end up being a nop because the
 			// webhook will bring them into alignment and no new reconciliation will occur.
 			// Also, compare annotation and label in case ingress.Class or parent route's labels
 			// is updated.
 
-			// Don't modify the informers copy
+			// Don't modify the informers copy.
 			origin := ingress.DeepCopy()
 			origin.Spec = desired.Spec
 			origin.Annotations = desired.Annotations
diff --git a/pkg/reconciler/route/traffic/rollout.go b/pkg/reconciler/route/traffic/rollout.go
index 3616159af..c9ac44c38 100644
--- a/pkg/reconciler/route/traffic/rollout.go
+++ b/pkg/reconciler/route/traffic/rollout.go
@@ -67,14 +67,17 @@ type ConfigurationRollout struct {
 	// This is required to compute step time and deadline.
 	StartTime int `json:"starttime,omitempty"`
 
-	// LastStepTimeStamp is the Unix timestamp when the last
-	// rollout step was performed.
-	LastStepTime int `json:"lastStep,omitempty"`
+	// NextStepTime is the Unix timestamp when the next
+	// rollout step should performed.
+	NextStepTime int `json:"nextStepTime,omitempty"`
 
 	// StepDuration is a rounded up number of seconds how long it took
 	// for ingress to successfully move first 1% of traffic to the new revision.
 	// Note, that his number does not include any coldstart, etc timing.
 	StepDuration int `json:"stepDuration,omitempty"`
+
+	// How much traffic to move in a single step.
+	StepSize int `json:"stepSize,omitempty"`
 }
 
 // RevisionRollout describes the revision in the config rollout.
@@ -89,9 +92,9 @@ type RevisionRollout struct {
 
 // Done returns true if there is no active rollout going on
 // for the configuration.
-func (cr *ConfigurationRollout) Done() bool {
+func (cur *ConfigurationRollout) Done() bool {
 	// Zero or just one revision.
-	return len(cr.Revisions) < 2
+	return len(cur.Revisions) < 2
 }
 
 // Validate validates current rollout for inconsistencies.
@@ -115,15 +118,21 @@ func (cur *Rollout) Validate() bool {
 	return true
 }
 
+// TODO(vagababov): default fake rollout duration in use, while we
+// only modify the annotation and do not actually modify the traffic.
+const durationSecs = 120.0
+
 // ObserveReady traverses the configs and the ones that are in rollout
 // but have not observed step time yet, will have it set, to
-// max(1, nowTS-cfg.StartTime). nowTS is unix timestamp in ns.
+// max(1, nowTS-cfg.StartTime).
 func (cur *Rollout) ObserveReady(nowTS int) {
 	for i := range cur.Configurations {
 		c := &cur.Configurations[i]
 		if c.StepDuration == 0 && c.StartTime > 0 {
-			c.StepDuration = int(math.Max(1,
-				math.Ceil(time.Duration(nowTS-c.StartTime).Seconds())))
+			// In really ceil(nowTS-c.StartTime) should always give 1s, but
+			// given possible time drift, we'll ensure that at least 1s is returned.
+			minStepSec := math.Max(1, math.Ceil(time.Duration(nowTS-c.StartTime).Seconds()))
+			c.computeProperties(float64(nowTS), minStepSec, durationSecs)
 		}
 	}
 }
@@ -133,7 +142,6 @@ func (cur *Rollout) ObserveReady(nowTS int) {
 // 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.
-// nowTS is unix timestamp in ns.
 func (cur *Rollout) Step(prev *Rollout, nowTS int) *Rollout {
 	if prev == nil || len(prev.Configurations) == 0 {
 		return cur
@@ -188,7 +196,7 @@ func (cur *Rollout) Step(prev *Rollout, nowTS int) *Rollout {
 				j++
 			case ccfgs[i].ConfigurationName < pcfgs[j].ConfigurationName:
 				// A new config, has been added. No action for rollout though.
-				// Keep it if it will receive traffic.
+				// Keep it for future rollout actions.
 				if ccfgs[i].Percent != 0 {
 					ret = append(ret, *ccfgs[i])
 				}
@@ -214,6 +222,8 @@ func (cur *Rollout) Step(prev *Rollout, nowTS int) *Rollout {
 // the older revisions.
 func adjustPercentage(goal int, cr *ConfigurationRollout) {
 	switch diff := goal - cr.Percent; {
+	case goal == 0:
+		cr.Revisions = nil // No traffic, no rollout.
 	case diff > 0:
 		cr.Revisions[len(cr.Revisions)-1].Percent += diff
 	case diff < 0:
@@ -233,6 +243,65 @@ func adjustPercentage(goal int, cr *ConfigurationRollout) {
 	}
 }
 
+// stepRevisions performs re-adjustment of percentages on the revisions
+// to rollout more traffic to the last one.
+func stepRevisions(goal *ConfigurationRollout, nowTS int) {
+	// Not yet ready to adjust the steps or we're done
+	// (shouldn't really be here, but better be defensive).
+	if nowTS < goal.NextStepTime || len(goal.Revisions) < 2 {
+		return
+	}
+
+	revLen := len(goal.Revisions)
+	remaining := goal.StepSize
+	writePos := revLen - 1
+	// readPos is guaranteed to be >= 0, due to the check above.
+	readPos := revLen - 2
+
+	// If step > totalPercent then remaining will always be > 0
+	// even after readPos == -1.
+	// This is the case when config's target is reduced below step size.
+	// E.g. was: R1 = 40 R2 = 10 Step = 10 Total=60
+	// Now = Total = 15;
+	// After adjust percentage: R1 = 5 R2 = 10
+	// Then after first iteration R1 = 0, remaining = 5.
+	// We'll handle this situation below.
+	for remaining > 0 && readPos >= 0 {
+		// If this revision's allocation is strictly larger than the goal,
+		// just subtract the different and we're done.
+		if goal.Revisions[readPos].Percent > remaining {
+			goal.Revisions[readPos].Percent -= remaining
+			break
+		}
+		// Otherwise subtract what is possible and update
+		// write position since this revision will no longer
+		// receive traffic.
+		remaining -= goal.Revisions[readPos].Percent
+		writePos--
+		readPos--
+	}
+	// Copy the last one to the write pos
+	goal.Revisions[writePos] = goal.Revisions[revLen-1]
+
+	goal.Revisions[writePos].Percent += goal.StepSize
+	// This can happen if step is now larger than total allocation, see the
+	// note above.
+	// E.g. with example above R2 = 20, and ro we have to cap it at 15.
+	if goal.Revisions[writePos].Percent > goal.Percent {
+		goal.Revisions[writePos].Percent = goal.Percent
+	}
+	// And cull the tail portion of it.
+	goal.Revisions = goal.Revisions[:writePos+1]
+	// Also set the next time.
+	if len(goal.Revisions) > 1 {
+		goal.NextStepTime = nowTS + goal.StepDuration
+	} else {
+		// This is the last step, we're done!
+		goal.NextStepTime = 0
+		goal.StartTime = 0
+	}
+}
+
 // stepConfig takes previous and goal configuration shapes and returns a new
 // config rollout, after computing the percetage allocations.
 func stepConfig(goal, prev *ConfigurationRollout, nowTS int) *ConfigurationRollout {
@@ -254,22 +323,37 @@ func stepConfig(goal, prev *ConfigurationRollout, nowTS int) *ConfigurationRollo
 	// If it matches the last revision of the previous rollout state (or there were no revisions)
 	// then no new rollout has begun for this configuration.
 	if len(prev.Revisions) == 0 || goal.Revisions[0].RevisionName == prev.Revisions[pc-1].RevisionName {
-		if len(prev.Revisions) > 0 {
+		// So if |prev.revisions| == 0 => then there was no rollout —
+		// nothing is required to step.
+		// If |prev.revisions| == 1 and it matches current revision then
+		// we're done.
+		// Thus we need to perform work only if there is more than one
+		// revision in the previous state.
+		if len(prev.Revisions) > 1 {
 			ret.Revisions = prev.Revisions
 
-			// 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.
-			// Copy the duration info from the previous when no new revision
+			// Copy various rollout stats from the previous when no new revision
 			// has been created.
+			ret.StartTime = prev.StartTime
 			ret.Deadline = prev.Deadline
-			ret.LastStepTime = prev.LastStepTime
+			ret.NextStepTime = prev.NextStepTime
 			ret.StepDuration = prev.StepDuration
-			ret.StartTime = prev.StartTime
+			ret.StepSize = prev.StepSize
+			// We might end up here before `ObserveReady` is called.
+			// In that case don't step individual revisions just yet.
+			if ret.StepSize > 0 {
+				// adjustPercentage above would've already accounted if target for the
+				// whole Configuration changed up or down. So here we should just redistribute
+				// the existing values.
+				stepRevisions(ret, nowTS)
+			}
 		}
 		return ret
 	}
 
-	// Otherwise we start a rollout, which means we need to stamp the starttime.
+	// Otherwise we start a rollout, which means we need to stamp the starttime,
+	// the rest of the fields will remain unset and `ObserveReady` will
+	// compute them when the ingress becomes ready.
 	ret.StartTime = nowTS
 
 	// Go backwards and find first revision with traffic assignment > 0.
@@ -304,6 +388,40 @@ func stepConfig(goal, prev *ConfigurationRollout, nowTS int) *ConfigurationRollo
 	return ret
 }
 
+// computeProperties computes the time between steps, each step size
+// and next reconcile time. This is invoked when the rollout just starts.
+// nowTS current unix timestamp in ns.
+// Pre: minStepSec >= 1, in seconds.
+// Pre: durationSecs > 1, in seconds.
+func (cur *ConfigurationRollout) computeProperties(nowTS, minStepSec, durationSecs float64) {
+	// First compute number of steps.
+	numSteps := durationSecs / minStepSec
+	pf := float64(cur.Percent)
+
+	// The smallest step is 1%, so if we can fit more steps
+	// than we have percents, we'll make c.Percent-1 steps
+	// each equal to 1%. -1, since we already moved 1% of the traffic.
+	if pf < numSteps {
+		numSteps = pf - 1
+	}
+
+	// We're moving traffic in equal steps.
+	// The last step can be larger, since it's more likely to
+	// easily accommodate the traffic jump, due to built in
+	// spare capacity.
+	// E.g. 100% in 4 steps. 1% -> 25% -> 49% -> 74% -> 100%, last jump being 26%.
+	stepSize := math.Floor((pf - 1) / numSteps)
+
+	// The time we sleep between the steps.
+	// We round up here since it's better to roll slightly longer,
+	// than slightly shorter.
+	stepDuration := math.Ceil(durationSecs / numSteps)
+
+	cur.StepDuration = int(stepDuration)
+	cur.StepSize = int(stepSize)
+	cur.NextStepTime = int(nowTS + stepDuration*float64(time.Second))
+}
+
 // 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) {
diff --git a/third_party/VENDOR-LICENSE/github.com/blendle/zapdriver/LICENSE b/third_party/VENDOR-LICENSE/github.com/blendle/zapdriver/LICENSE
new file mode 100644
index 000000000..7db456775
--- /dev/null
+++ b/third_party/VENDOR-LICENSE/github.com/blendle/zapdriver/LICENSE
@@ -0,0 +1,15 @@
+ISC License
+
+Copyright (c) Blendle
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/vendor/github.com/blendle/zapdriver/.gitignore b/vendor/github.com/blendle/zapdriver/.gitignore
new file mode 100644
index 000000000..48b8bf907
--- /dev/null
+++ b/vendor/github.com/blendle/zapdriver/.gitignore
@@ -0,0 +1,1 @@
+vendor/
diff --git a/vendor/github.com/blendle/zapdriver/LICENSE b/vendor/github.com/blendle/zapdriver/LICENSE
new file mode 100644
index 000000000..7db456775
--- /dev/null
+++ b/vendor/github.com/blendle/zapdriver/LICENSE
@@ -0,0 +1,15 @@
+ISC License
+
+Copyright (c) Blendle
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/vendor/github.com/blendle/zapdriver/README.md b/vendor/github.com/blendle/zapdriver/README.md
new file mode 100644
index 000000000..8044c5523
--- /dev/null
+++ b/vendor/github.com/blendle/zapdriver/README.md
@@ -0,0 +1,347 @@
+# :zap: Zapdriver
+
+Blazing fast, [Zap][zap]-based [Stackdriver][stackdriver] logging.
+
+[zap]: https://github.com/uber-go/zap
+[stackdriver]: https://cloud.google.com/stackdriver/
+
+## Usage
+
+This package provides three building blocks to support the full array of
+structured logging capabilities of Stackdriver:
+
+* [Special purpose logging fields](#special-purpose-logging-fields)
+* [Pre-configured Stackdriver-optimized encoder](#pre-configured-stackdriver-optimized-encoder)
+* [Custom Stackdriver Zap core](#custom-stackdriver-zap-core)
+* [Using Error Reporting](#using-error-reporting)
+
+The above components can be used separately, but to start, you can create a new
+Zap logger with all of the above included:
+
+```golang
+logger, err := zapdriver.NewProduction() // with sampling
+logger, err := zapdriver.NewDevelopment() // with `development` set to `true`
+```
+
+The above functions give back a pointer to a `zap.Logger` object, so you can use
+[Zap][zap] like you've always done, except that it now logs in the proper
+[Stackdriver][stackdriver] format.
+
+You can also create a configuration struct, and build your logger from there:
+
+```golang
+config := zapdriver.NewProductionConfig()
+config := zapdriver.NewDevelopmentConfig()
+```
+
+Or, get the Zapdriver encoder, and build your own configuration struct from
+that:
+
+```golang
+encoder := zapdriver.NewProductionEncoderConfig()
+encoder := zapdriver.NewDevelopmentEncoderConfig()
+```
+
+Read on to learn more about the available Stackdriver-specific log fields, and
+how to use the above-mentioned components.
+
+### Special purpose logging fields
+
+You can use the following fields to add extra information to your log entries.
+These fields are parsed by Stackdriver to make it easier to query your logs or
+to use the log details in the Stackdriver monitoring interface.
+
+* [`HTTP`](#http)
+* [`Label`](#label)
+* [`SourceLocation`](#sourcelocation)
+* [`Operation`](#operation)
+* [`TraceContext`](#tracecontext)
+
+#### HTTP
+
+You can log HTTP request/response cycles using the following field:
+
+```golang
+HTTP(req *HTTPPayload) zap.Field
+```
+
+You can either manually build the request payload:
+
+```golang
+req := &HTTPPayload{
+  RequestMethod: "GET",
+  RequestURL: "/",
+  Status: 200,
+}
+```
+
+Or, you can auto generate the struct, based on the available request and
+response objects:
+
+```golang
+NewHTTP(req *http.Request, res *http.Response) *HTTPPayload
+```
+
+You are free to pass in `nil` for either the request or response object, if one
+of them is unavailable to you at the point of logging. Any field depending on
+one or the other will be omitted if `nil` is passed in.
+
+Note that there are some fields that are not populated by either the request or
+response object, and need to be set manually:
+
+* `ServerIP string`
+* `Latency string`
+* `CacheLookup bool`
+* `CacheHit bool`
+* `CacheValidatedWithOriginServer bool`
+* `CacheFillBytes string`
+
+If you have no need for those fields, the quickest way to get started is like
+so:
+
+```golang
+logger.Info("Request Received.", zapdriver.HTTP(zapdriver.NewHTTP(req, res)))
+```
+
+#### Label
+
+You can add a "label" to your payload as follows:
+
+```golang
+Label(key, value string) zap.Field
+```
+
+Note that underwater, this sets the key to `labels.<key>`. You need to be using
+the `zapdriver.Core` core for this to be converted to the proper format for
+Stackdriver to recognize the labels.
+
+See "Custom Stackdriver Zap core" for more details.
+
+If you have a reason not to use the provided Core, you can still wrap labels in
+the right `labels` namespace by using the available function:
+
+```golang
+Labels(fields ...zap.Field) zap.Field
+```
+
+Like so:
+
+```golang
+logger.Info(
+  "Did something.",
+  zapdriver.Labels(
+    zapdriver.Label("hello", "world"),
+    zapdriver.Label("hi", "universe"),
+  ),
+)
+```
+
+Again, wrapping the `Label` calls in `Labels` is not required if you use the
+supplied Zap Core.
+
+#### SourceLocation
+
+You can add a source code location to your log lines to be picked up by
+Stackdriver.
+
+Note that you can set this manually, or use `zapdriver.Core` to automatically
+add this. If you set it manually, _and_ use `zapdriver.Core`, the manual call
+stack will be preserved over the automated one.
+
+```golang
+SourceLocation(pc uintptr, file string, line int, ok bool) zap.Field
+```
+
+Note that the function signature equals that of the return values of
+`runtime.Caller()`. This allows you to catch the stack frame at one location,
+while logging it at a different location, like so:
+
+```golang
+pc, file, line, ok := runtime.Caller(0)
+
+// do other stuff...
+
+logger.Error("Something happened!", zapdriver.SourceLocation(pc, file, line, ok))
+```
+
+If you use `zapdriver.Core`, the above use-case is the only use-case where you
+would want to manually set the source location. In all other situations, you can
+simply omit this field, and it will be added automatically, using the stack
+frame at the location where the log line is triggered.
+
+If you don't use `zapdriver.Core`, and still want to add the source location at
+the frame of the triggered log line, you'd do it like this:
+
+```golang
+logger.Error("Something happened!", zapdriver.SourceLocation(runtime.Caller(0)))
+```
+
+#### Operation
+
+The `Operation` log field allows you to group log lines into a single
+"operation" performed by the application:
+
+```golang
+Operation(id, producer string, first, last bool) zap.Field
+```
+
+For a pair of logs that belong to the same operation, you should use the same
+`id` between them. The `producer` is an arbitrary identifier that should be
+globally unique amongst all the logs of all your applications (meaning it should
+probably be the unique name of the current application). You should set `first`
+to true for the first log in the operation, and `last` to true for the final log
+of the operation.
+
+```golang
+logger.Info("Started.", zapdriver.Operation("3g4d3g", "my-app", true, false))
+logger.Debug("Progressing.", zapdriver.Operation("3g4d3g", "my-app", false, false))
+logger.Info("Done.", zapdriver.Operation("3g4d3g", "my-app", false, true))
+```
+
+Instead of defining the "start" and "end" booleans, you can also use these three
+convenience functions:
+
+```golang
+OperationStart(id, producer string) zap.Field
+OperationCont(id, producer string) zap.Field
+OperationEnd(id, producer string) zap.Field
+```
+
+#### TraceContext
+
+You can add trace context information to your log lines to be picked up by
+Stackdriver.
+
+```golang
+TraceContext(trace string, spanId string, sampled bool, projectName string) []zap.Field
+```
+
+Like so:
+
+```golang
+logger.Error("Something happened!", zapdriver.TraceContext("105445aa7843bc8bf206b120001000", "0", true, "my-project-name")...)
+```
+
+### Pre-configured Stackdriver-optimized encoder
+
+The Stackdriver encoder maps all Zap log levels to the appropriate
+[Stackdriver-supported levels][levels]:
+
+> DEBUG     (100) Debug or trace information.
+>
+> INFO      (200) Routine information, such as ongoing status or performance.
+>
+> WARNING   (400) Warning events might cause problems.
+>
+> ERROR     (500) Error events are likely to cause problems.
+>
+> CRITICAL  (600) Critical events cause more severe problems or outages.
+>
+> ALERT     (700) A person must take an action immediately.
+>
+> EMERGENCY (800) One or more systems are unusable.
+
+[levels]: https://cloud.google.com/logging/docs/reference/v2/rest/v2/LogEntry#LogSeverity
+
+It also sets some of the default keys to use [the right names][names], such as
+`timestamp`, `severity`, and `message`.
+
+[names]: https://cloud.google.com/logging/docs/reference/v2/rest/v2/LogEntry
+
+You can use this encoder if you want to build your Zap logger configuration
+manually:
+
+```golang
+zapdriver.NewProductionEncoderConfig()
+```
+
+For parity-sake, there's also `zapdriver.NewDevelopmentEncoderConfig()`, but it
+returns the exact same encoder right now.
+
+### Custom Stackdriver Zap core
+
+A custom Zap core is included in this package to support some special use-cases.
+
+First of all, if you use `zapdriver.NewProduction()` (or `NewDevelopment`) , you
+already have this core enabled, so everything _just works_ ™.
+
+There are two use-cases which require this core:
+
+1. If you use `zapdriver.Label("hello", "world")`, it will initially end up in
+   your log with the key `labels.hello` and value `world`. Now if you have two
+   labels, you could also have `labels.hi` with value `universe`. This works as-
+   is, but for this to be correctly parsed by Stackdriver as true "labels", you
+   need to use the Zapdriver core, so that both of these fields get rewritten,
+   to use the namespace `labels`, and use the keys `hello` and `hi` within that
+   namespace. This is done automatically.
+
+2. If you don't want to use `zapdriver.SourceLocation()` on every log call, you
+   can use this core for the source location to be automatically added to
+   each log entry.
+
+When building a logger, you can inject the Zapdriver core as follows:
+
+```golang
+config := &zap.Config{}
+logger, err := config.Build(zapdriver.WrapCore())
+```
+
+### Using Error Reporting
+
+To report errors using StackDriver's Error Reporting tool, a log line needs to follow a separate log format described in the [Error Reporting][errorreporting] documentation.
+
+[errorreporting]: https://cloud.google.com/error-reporting/docs/formatting-error-messages
+
+The simplest way to do this is by using `NewProductionWithCore`:
+
+```golang
+logger, err := zapdriver.NewProductionWithCore(zapdriver.WrapCore(
+  zapdriver.ReportAllErrors(true),
+  zapdriver.ServiceName("my service"),
+))
+```
+
+For parity-sake, there's also `zapdriver.NewDevelopmentWithCore()`
+
+If you are building a custom logger, you can use `WrapCore()` to configure the driver core:
+
+```golang
+config := &zap.Config{}
+logger, err := config.Build(zapdriver.WrapCore(
+  zapdriver.ReportAllErrors(true),
+  zapdriver.ServiceName("my service"),
+))
+```
+
+Configuring this way, every error log entry will be reported to Stackdriver's Error Reporting tool.
+
+#### Reporting errors manually
+
+If you do not want every error to be reported, you can attach `ErrorReport()` to log call manually:
+
+```golang
+logger.Error("An error to be reported!", zapdriver.ErrorReport(runtime.Caller(0)))
+// Or get Caller details
+pc, file, line, ok := runtime.Caller(0)
+// do other stuff... and log elsewhere
+logger.Error("Another error to be reported!", zapdriver.ErrorReport(pc, file, line, ok))
+```
+
+Please keep in mind that ErrorReport needs a ServiceContext attached to the log
+entry. If you did not configure this using `WrapCore`, error reports will
+get attached using service name as `unknown`. To prevent this from happeneing,
+either configure your core or attach service context before (or when) using
+the logger:
+
+```golang
+logger.Error(
+  "An error to be reported!",
+  zapdriver.ErrorReport(runtime.Caller(0)),
+  zapdriver.ServiceContext("my service"),
+)
+
+// Or permanently attach it to your logger
+logger = logger.With(zapdriver.ServiceContext("my service"))
+// and then use it
+logger.Error("An error to be reported!", zapdriver.ErrorReport(runtime.Caller(0)))
+```
diff --git a/vendor/github.com/blendle/zapdriver/config.go b/vendor/github.com/blendle/zapdriver/config.go
new file mode 100644
index 000000000..fe901ce3b
--- /dev/null
+++ b/vendor/github.com/blendle/zapdriver/config.go
@@ -0,0 +1,55 @@
+package zapdriver
+
+import (
+	"go.uber.org/zap"
+	"go.uber.org/zap/zapcore"
+)
+
+// NewProductionEncoderConfig returns an opinionated EncoderConfig for
+// production environments.
+func NewProductionEncoderConfig() zapcore.EncoderConfig {
+	return encoderConfig
+}
+
+// NewDevelopmentEncoderConfig returns an opinionated EncoderConfig for
+// development environments.
+func NewDevelopmentEncoderConfig() zapcore.EncoderConfig {
+	return encoderConfig
+}
+
+// NewProductionConfig is a reasonable production logging configuration.
+// Logging is enabled at InfoLevel and above.
+//
+// It uses a JSON encoder, writes to standard error, and enables sampling.
+// Stacktraces are automatically included on logs of ErrorLevel and above.
+func NewProductionConfig() zap.Config {
+	return zap.Config{
+		Level:       zap.NewAtomicLevelAt(zap.InfoLevel),
+		Development: false,
+		Sampling: &zap.SamplingConfig{
+			Initial:    100,
+			Thereafter: 100,
+		},
+		Encoding:         "json",
+		EncoderConfig:    NewProductionEncoderConfig(),
+		OutputPaths:      []string{"stderr"},
+		ErrorOutputPaths: []string{"stderr"},
+	}
+}
+
+// NewDevelopmentConfig is a reasonable development logging configuration.
+// Logging is enabled at DebugLevel and above.
+//
+// It enables development mode (which makes DPanicLevel logs panic), uses a
+// console encoder, writes to standard error, and disables sampling.
+// Stacktraces are automatically included on logs of WarnLevel and above.
+func NewDevelopmentConfig() zap.Config {
+	return zap.Config{
+		Level:            zap.NewAtomicLevelAt(zap.DebugLevel),
+		Development:      true,
+		Encoding:         "json",
+		EncoderConfig:    NewDevelopmentEncoderConfig(),
+		OutputPaths:      []string{"stderr"},
+		ErrorOutputPaths: []string{"stderr"},
+	}
+}
diff --git a/vendor/github.com/blendle/zapdriver/core.go b/vendor/github.com/blendle/zapdriver/core.go
new file mode 100644
index 000000000..bcb7660f7
--- /dev/null
+++ b/vendor/github.com/blendle/zapdriver/core.go
@@ -0,0 +1,243 @@
+package zapdriver
+
+import (
+	"strings"
+
+	"go.uber.org/zap"
+	"go.uber.org/zap/zapcore"
+)
+
+// driverConfig is used to configure core.
+type driverConfig struct {
+	// Report all logs with level error or above to stackdriver using
+	// `ErrorReport()` when set to true
+	ReportAllErrors bool
+
+	// ServiceName is added as `ServiceContext()` to all logs when set
+	ServiceName string
+}
+
+// Core is a zapdriver specific core wrapped around the default zap core. It
+// allows to merge all defined labels
+type core struct {
+	zapcore.Core
+
+	// permLabels is a collection of labels that have been added to the logger
+	// through the use of `With()`. These labels should never be cleared after
+	// logging a single entry, unlike `tempLabel`.
+	permLabels *labels
+
+	// tempLabels keeps a record of all the labels that need to be applied to the
+	// current log entry. Zap serializes log fields at different parts of the
+	// stack, one such location is when calling `core.With` and the other one is
+	// when calling `core.Write`. This makes it impossible to (for example) take
+	// all `labels.xxx` fields, and wrap them in the `labels` namespace in one go.
+	//
+	// Instead, we have to filter out these labels at both locations, and then add
+	// them back in the proper format right before we call `Write` on the original
+	// Zap core.
+	tempLabels *labels
+
+	// Configuration for the zapdriver core
+	config driverConfig
+}
+
+// zapdriver core option to report all logs with level error or above to stackdriver
+// using `ErrorReport()` when set to true
+func ReportAllErrors(report bool) func(*core) {
+	return func(c *core) {
+		c.config.ReportAllErrors = report
+	}
+}
+
+// zapdriver core option to add `ServiceContext()` to all logs with `name` as
+// service name
+func ServiceName(name string) func(*core) {
+	return func(c *core) {
+		c.config.ServiceName = name
+	}
+}
+
+// WrapCore returns a `zap.Option` that wraps the default core with the
+// zapdriver one.
+func WrapCore(options ...func(*core)) zap.Option {
+	return zap.WrapCore(func(c zapcore.Core) zapcore.Core {
+		newcore := &core{
+			Core:       c,
+			permLabels: newLabels(),
+			tempLabels: newLabels(),
+		}
+		for _, option := range options {
+			option(newcore)
+		}
+		return newcore
+	})
+}
+
+// With adds structured context to the Core.
+func (c *core) With(fields []zap.Field) zapcore.Core {
+	var lbls *labels
+	lbls, fields = c.extractLabels(fields)
+
+	lbls.mutex.RLock()
+	c.permLabels.mutex.Lock()
+	for k, v := range lbls.store {
+		c.permLabels.store[k] = v
+	}
+	c.permLabels.mutex.Unlock()
+	lbls.mutex.RUnlock()
+
+	return &core{
+		Core:       c.Core.With(fields),
+		permLabels: c.permLabels,
+		tempLabels: newLabels(),
+		config:     c.config,
+	}
+}
+
+// Check determines whether the supplied Entry should be logged (using the
+// embedded LevelEnabler and possibly some extra logic). If the entry
+// should be logged, the Core adds itself to the CheckedEntry and returns
+// the result.
+//
+// Callers must use Check before calling Write.
+func (c *core) Check(ent zapcore.Entry, ce *zapcore.CheckedEntry) *zapcore.CheckedEntry {
+	if c.Enabled(ent.Level) {
+		return ce.AddCore(ent, c)
+	}
+
+	return ce
+}
+
+func (c *core) Write(ent zapcore.Entry, fields []zapcore.Field) error {
+	var lbls *labels
+	lbls, fields = c.extractLabels(fields)
+
+	lbls.mutex.RLock()
+	c.tempLabels.mutex.Lock()
+	for k, v := range lbls.store {
+		c.tempLabels.store[k] = v
+	}
+	c.tempLabels.mutex.Unlock()
+	lbls.mutex.RUnlock()
+
+	fields = append(fields, labelsField(c.allLabels()))
+	fields = c.withSourceLocation(ent, fields)
+	if c.config.ServiceName != "" {
+		fields = c.withServiceContext(c.config.ServiceName, fields)
+	}
+	if c.config.ReportAllErrors && zapcore.ErrorLevel.Enabled(ent.Level) {
+		fields = c.withErrorReport(ent, fields)
+		if c.config.ServiceName == "" {
+			// A service name was not set but error report needs it
+			// So attempt to add a generic service name
+			fields = c.withServiceContext("unknown", fields)
+		}
+	}
+
+	c.tempLabels.reset()
+
+	return c.Core.Write(ent, fields)
+}
+
+// Sync flushes buffered logs (if any).
+func (c *core) Sync() error {
+	return c.Core.Sync()
+}
+
+func (c *core) allLabels() *labels {
+	lbls := newLabels()
+
+	lbls.mutex.Lock()
+	c.permLabels.mutex.RLock()
+	for k, v := range c.permLabels.store {
+		lbls.store[k] = v
+	}
+	c.permLabels.mutex.RUnlock()
+
+	c.tempLabels.mutex.RLock()
+	for k, v := range c.tempLabels.store {
+		lbls.store[k] = v
+	}
+	c.tempLabels.mutex.RUnlock()
+	lbls.mutex.Unlock()
+
+	return lbls
+}
+
+func (c *core) extractLabels(fields []zapcore.Field) (*labels, []zapcore.Field) {
+	lbls := newLabels()
+	out := []zapcore.Field{}
+
+	lbls.mutex.Lock()
+	for i := range fields {
+		if !isLabelField(fields[i]) {
+			out = append(out, fields[i])
+			continue
+		}
+
+		lbls.store[strings.Replace(fields[i].Key, "labels.", "", 1)] = fields[i].String
+	}
+	lbls.mutex.Unlock()
+
+	return lbls, out
+}
+
+func (c *core) withLabels(fields []zapcore.Field) []zapcore.Field {
+	lbls := newLabels()
+	out := []zapcore.Field{}
+
+	lbls.mutex.Lock()
+	for i := range fields {
+		if isLabelField(fields[i]) {
+			lbls.store[strings.Replace(fields[i].Key, "labels.", "", 1)] = fields[i].String
+			continue
+		}
+
+		out = append(out, fields[i])
+	}
+	lbls.mutex.Unlock()
+
+	return append(out, labelsField(lbls))
+}
+
+func (c *core) withSourceLocation(ent zapcore.Entry, fields []zapcore.Field) []zapcore.Field {
+	// If the source location was manually set, don't overwrite it
+	for i := range fields {
+		if fields[i].Key == sourceKey {
+			return fields
+		}
+	}
+
+	if !ent.Caller.Defined {
+		return fields
+	}
+
+	return append(fields, SourceLocation(ent.Caller.PC, ent.Caller.File, ent.Caller.Line, true))
+}
+
+func (c *core) withServiceContext(name string, fields []zapcore.Field) []zapcore.Field {
+	// If the service context was manually set, don't overwrite it
+	for i := range fields {
+		if fields[i].Key == serviceContextKey {
+			return fields
+		}
+	}
+
+	return append(fields, ServiceContext(name))
+}
+
+func (c *core) withErrorReport(ent zapcore.Entry, fields []zapcore.Field) []zapcore.Field {
+	// If the error report was manually set, don't overwrite it
+	for i := range fields {
+		if fields[i].Key == contextKey {
+			return fields
+		}
+	}
+
+	if !ent.Caller.Defined {
+		return fields
+	}
+
+	return append(fields, ErrorReport(ent.Caller.PC, ent.Caller.File, ent.Caller.Line, true))
+}
diff --git a/vendor/github.com/blendle/zapdriver/encoder.go b/vendor/github.com/blendle/zapdriver/encoder.go
new file mode 100644
index 000000000..eec571fb8
--- /dev/null
+++ b/vendor/github.com/blendle/zapdriver/encoder.go
@@ -0,0 +1,59 @@
+package zapdriver
+
+import (
+	"time"
+
+	"go.uber.org/zap/zapcore"
+)
+
+// logLevelSeverity maps the Zap log levels to the correct level names as
+// defined by Stackdriver.
+//
+// DEFAULT     (0) The log entry has no assigned severity level.
+// DEBUG     (100) Debug or trace information.
+// INFO      (200) Routine information, such as ongoing status or performance.
+// NOTICE    (300) Normal but significant events, such as start up, shut down, or a configuration change.
+// WARNING   (400) Warning events might cause problems.
+// ERROR     (500) Error events are likely to cause problems.
+// CRITICAL  (600) Critical events cause more severe problems or outages.
+// ALERT     (700) A person must take an action immediately.
+// EMERGENCY (800) One or more systems are unusable.
+//
+// See: https://cloud.google.com/logging/docs/reference/v2/rest/v2/LogEntry#LogSeverity
+var logLevelSeverity = map[zapcore.Level]string{
+	zapcore.DebugLevel:  "DEBUG",
+	zapcore.InfoLevel:   "INFO",
+	zapcore.WarnLevel:   "WARNING",
+	zapcore.ErrorLevel:  "ERROR",
+	zapcore.DPanicLevel: "CRITICAL",
+	zapcore.PanicLevel:  "ALERT",
+	zapcore.FatalLevel:  "EMERGENCY",
+}
+
+// encoderConfig is the default encoder configuration, slightly tweaked to use
+// the correct fields for Stackdriver to parse them.
+var encoderConfig = zapcore.EncoderConfig{
+	TimeKey:        "timestamp",
+	LevelKey:       "severity",
+	NameKey:        "logger",
+	CallerKey:      "caller",
+	MessageKey:     "message",
+	StacktraceKey:  "stacktrace",
+	LineEnding:     zapcore.DefaultLineEnding,
+	EncodeLevel:    EncodeLevel,
+	EncodeTime:     RFC3339NanoTimeEncoder,
+	EncodeDuration: zapcore.SecondsDurationEncoder,
+	EncodeCaller:   zapcore.ShortCallerEncoder,
+}
+
+// EncodeLevel maps the internal Zap log level to the appropriate Stackdriver
+// level.
+func EncodeLevel(l zapcore.Level, enc zapcore.PrimitiveArrayEncoder) {
+	enc.AppendString(logLevelSeverity[l])
+}
+
+// RFC3339NanoTimeEncoder serializes a time.Time to an RFC3339Nano-formatted
+// string with nanoseconds precision.
+func RFC3339NanoTimeEncoder(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
+	enc.AppendString(t.Format(time.RFC3339Nano))
+}
diff --git a/vendor/github.com/blendle/zapdriver/go.mod b/vendor/github.com/blendle/zapdriver/go.mod
new file mode 100644
index 000000000..aecbd4f12
--- /dev/null
+++ b/vendor/github.com/blendle/zapdriver/go.mod
@@ -0,0 +1,12 @@
+module github.com/blendle/zapdriver
+
+go 1.12
+
+require (
+	github.com/davecgh/go-spew v1.1.1 // indirect
+	github.com/pkg/errors v0.8.1 // indirect
+	github.com/stretchr/testify v1.3.0
+	go.uber.org/atomic v1.4.0 // indirect
+	go.uber.org/multierr v1.1.0 // indirect
+	go.uber.org/zap v1.10.0
+)
diff --git a/vendor/github.com/blendle/zapdriver/go.sum b/vendor/github.com/blendle/zapdriver/go.sum
new file mode 100644
index 000000000..237b5d2e2
--- /dev/null
+++ b/vendor/github.com/blendle/zapdriver/go.sum
@@ -0,0 +1,16 @@
+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/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
+github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+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.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU=
+go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
+go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI=
+go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
+go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM=
+go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
diff --git a/vendor/github.com/blendle/zapdriver/http.go b/vendor/github.com/blendle/zapdriver/http.go
new file mode 100644
index 000000000..441e58590
--- /dev/null
+++ b/vendor/github.com/blendle/zapdriver/http.go
@@ -0,0 +1,160 @@
+package zapdriver
+
+// "Broker: Request timed out"
+// https://console.cloud.google.com/logs/viewer?project=bnl-blendle&minLogLevel=
+// 0&expandAll=false&timestamp=2018-05-23T22:21:56.142000000Z&customFacets=&limi
+// tCustomFacetWidth=true&dateRangeEnd=2018-05-23T22:21:52.545Z&interval=PT1H&re
+// source=container%2Fcluster_name%2Fblendle-2%2Fnamespace_id%2Fstream-
+// composition-analytic-events-
+// backfill&scrollTimestamp=2018-05-23T05:29:33.000000000Z&logName=projects
+// %2Fbnl-blendle%2Flogs%2Fstream-composition-analytic-events-
+// pipe-1&dateRangeUnbound=backwardInTime
+
+import (
+	"bytes"
+	"io"
+	"net/http"
+	"strconv"
+
+	"go.uber.org/zap"
+	"go.uber.org/zap/zapcore"
+)
+
+// HTTP adds the correct Stackdriver "HTTP" field.
+//
+// see: https://cloud.google.com/logging/docs/reference/v2/rest/v2/LogEntry#HttpRequest
+func HTTP(req *HTTPPayload) zap.Field {
+	return zap.Object("httpRequest", req)
+}
+
+// HTTPPayload is the complete payload that can be interpreted by
+// Stackdriver as a HTTP request.
+type HTTPPayload struct {
+	// The request method. Examples: "GET", "HEAD", "PUT", "POST".
+	RequestMethod string `json:"requestMethod"`
+
+	// The scheme (http, https), the host name, the path and the query portion of
+	// the URL that was requested.
+	//
+	// Example: "http://example.com/some/info?color=red".
+	RequestURL string `json:"requestUrl"`
+
+	// The size of the HTTP request message in bytes, including the request
+	// headers and the request body.
+	RequestSize string `json:"requestSize"`
+
+	// The response code indicating the status of response.
+	//
+	// Examples: 200, 404.
+	Status int `json:"status"`
+
+	// The size of the HTTP response message sent back to the client, in bytes,
+	// including the response headers and the response body.
+	ResponseSize string `json:"responseSize"`
+
+	// The user agent sent by the client.
+	//
+	// Example: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Q312461; .NET CLR 1.0.3705)".
+	UserAgent string `json:"userAgent"`
+
+	// The IP address (IPv4 or IPv6) of the client that issued the HTTP request.
+	//
+	// Examples: "192.168.1.1", "FE80::0202:B3FF:FE1E:8329".
+	RemoteIP string `json:"remoteIp"`
+
+	// The IP address (IPv4 or IPv6) of the origin server that the request was
+	// sent to.
+	ServerIP string `json:"serverIp"`
+
+	// The referrer URL of the request, as defined in HTTP/1.1 Header Field
+	// Definitions.
+	Referer string `json:"referer"`
+
+	// The request processing latency on the server, from the time the request was
+	// received until the response was sent.
+	//
+	// A duration in seconds with up to nine fractional digits, terminated by 's'.
+	//
+	// Example: "3.5s".
+	Latency string `json:"latency"`
+
+	// Whether or not a cache lookup was attempted.
+	CacheLookup bool `json:"cacheLookup"`
+
+	// Whether or not an entity was served from cache (with or without
+	// validation).
+	CacheHit bool `json:"cacheHit"`
+
+	// Whether or not the response was validated with the origin server before
+	// being served from cache. This field is only meaningful if cacheHit is True.
+	CacheValidatedWithOriginServer bool `json:"cacheValidatedWithOriginServer"`
+
+	// The number of HTTP response bytes inserted into cache. Set only when a
+	// cache fill was attempted.
+	CacheFillBytes string `json:"cacheFillBytes"`
+
+	// Protocol used for the request.
+	//
+	// Examples: "HTTP/1.1", "HTTP/2", "websocket"
+	Protocol string `json:"protocol"`
+}
+
+// NewHTTP returns a new HTTPPayload struct, based on the passed
+// in http.Request and http.Response objects.
+func NewHTTP(req *http.Request, res *http.Response) *HTTPPayload {
+	if req == nil {
+		req = &http.Request{}
+	}
+
+	if res == nil {
+		res = &http.Response{}
+	}
+
+	sdreq := &HTTPPayload{
+		RequestMethod: req.Method,
+		Status:        res.StatusCode,
+		UserAgent:     req.UserAgent(),
+		RemoteIP:      req.RemoteAddr,
+		Referer:       req.Referer(),
+		Protocol:      req.Proto,
+	}
+
+	if req.URL != nil {
+		sdreq.RequestURL = req.URL.String()
+	}
+
+	buf := &bytes.Buffer{}
+	if req.Body != nil {
+		n, _ := io.Copy(buf, req.Body) // nolint: gas
+		sdreq.RequestSize = strconv.FormatInt(n, 10)
+	}
+
+	if res.Body != nil {
+		buf.Reset()
+		n, _ := io.Copy(buf, res.Body) // nolint: gas
+		sdreq.ResponseSize = strconv.FormatInt(n, 10)
+	}
+
+	return sdreq
+}
+
+// MarshalLogObject implements zapcore.ObjectMarshaller interface.
+func (req HTTPPayload) MarshalLogObject(enc zapcore.ObjectEncoder) error {
+	enc.AddString("requestMethod", req.RequestMethod)
+	enc.AddString("requestUrl", req.RequestURL)
+	enc.AddString("requestSize", req.RequestSize)
+	enc.AddInt("status", req.Status)
+	enc.AddString("responseSize", req.ResponseSize)
+	enc.AddString("userAgent", req.UserAgent)
+	enc.AddString("remoteIp", req.RemoteIP)
+	enc.AddString("serverIp", req.ServerIP)
+	enc.AddString("referer", req.Referer)
+	enc.AddString("latency", req.Latency)
+	enc.AddBool("cacheLookup", req.CacheLookup)
+	enc.AddBool("cacheHit", req.CacheHit)
+	enc.AddBool("cacheValidatedWithOriginServer", req.CacheValidatedWithOriginServer)
+	enc.AddString("cacheFillBytes", req.CacheFillBytes)
+	enc.AddString("protocol", req.Protocol)
+
+	return nil
+}
diff --git a/vendor/github.com/blendle/zapdriver/label.go b/vendor/github.com/blendle/zapdriver/label.go
new file mode 100644
index 000000000..723864209
--- /dev/null
+++ b/vendor/github.com/blendle/zapdriver/label.go
@@ -0,0 +1,77 @@
+package zapdriver
+
+import (
+	"strings"
+	"sync"
+
+	"go.uber.org/zap"
+	"go.uber.org/zap/zapcore"
+)
+
+const labelsKey = "logging.googleapis.com/labels"
+
+// Label adds an optional label to the payload.
+//
+// Labels are a set of user-defined (key, value) data that provides additional
+// information about the log entry.
+//
+// Example: { "name": "wrench", "mass": "1.3kg", "count": "3" }.
+func Label(key, value string) zap.Field {
+	return zap.String("labels."+key, value)
+}
+
+// Labels takes Zap fields, filters the ones that have their key start with the
+// string `labels.` and their value type set to StringType. It then wraps those
+// key/value pairs in a top-level `labels` namespace.
+func Labels(fields ...zap.Field) zap.Field {
+	lbls := newLabels()
+
+	lbls.mutex.Lock()
+	for i := range fields {
+		if isLabelField(fields[i]) {
+			lbls.store[strings.Replace(fields[i].Key, "labels.", "", 1)] = fields[i].String
+		}
+	}
+	lbls.mutex.Unlock()
+
+	return labelsField(lbls)
+}
+
+func isLabelField(field zap.Field) bool {
+	return strings.HasPrefix(field.Key, "labels.") && field.Type == zapcore.StringType
+}
+
+func labelsField(l *labels) zap.Field {
+	return zap.Object(labelsKey, l)
+}
+
+type labels struct {
+	store map[string]string
+	mutex *sync.RWMutex
+}
+
+func newLabels() *labels {
+	return &labels{store: map[string]string{}, mutex: &sync.RWMutex{}}
+}
+
+func (l *labels) Add(key, value string) {
+	l.mutex.Lock()
+	l.store[key] = value
+	l.mutex.Unlock()
+}
+
+func (l *labels) reset() {
+	l.mutex.Lock()
+	l.store = map[string]string{}
+	l.mutex.Unlock()
+}
+
+func (l labels) MarshalLogObject(enc zapcore.ObjectEncoder) error {
+	l.mutex.RLock()
+	for k, v := range l.store {
+		enc.AddString(k, v)
+	}
+	l.mutex.RUnlock()
+
+	return nil
+}
diff --git a/vendor/github.com/blendle/zapdriver/logger.go b/vendor/github.com/blendle/zapdriver/logger.go
new file mode 100644
index 000000000..59c10993e
--- /dev/null
+++ b/vendor/github.com/blendle/zapdriver/logger.go
@@ -0,0 +1,39 @@
+package zapdriver
+
+import (
+	"go.uber.org/zap"
+)
+
+// NewProduction builds a sensible production Logger that writes InfoLevel and
+// above logs to standard error as JSON.
+//
+// It's a shortcut for NewProductionConfig().Build(...Option).
+func NewProduction(options ...zap.Option) (*zap.Logger, error) {
+	options = append(options, WrapCore())
+
+	return NewProductionConfig().Build(options...)
+}
+
+// NewProductionWithCore is same as NewProduction but accepts a custom configured core
+func NewProductionWithCore(core zap.Option, options ...zap.Option) (*zap.Logger, error) {
+	options = append(options, core)
+
+	return NewProductionConfig().Build(options...)
+}
+
+// NewDevelopment builds a development Logger that writes DebugLevel and above
+// logs to standard error in a human-friendly format.
+//
+// It's a shortcut for NewDevelopmentConfig().Build(...Option).
+func NewDevelopment(options ...zap.Option) (*zap.Logger, error) {
+	options = append(options, WrapCore())
+
+	return NewDevelopmentConfig().Build(options...)
+}
+
+// NewDevelopmentWithCore is same as NewDevelopment but accepts a custom configured core
+func NewDevelopmentWithCore(core zap.Option, options ...zap.Option) (*zap.Logger, error) {
+	options = append(options, core)
+
+	return NewDevelopmentConfig().Build(options...)
+}
diff --git a/vendor/github.com/blendle/zapdriver/operation.go b/vendor/github.com/blendle/zapdriver/operation.go
new file mode 100644
index 000000000..e8b862f79
--- /dev/null
+++ b/vendor/github.com/blendle/zapdriver/operation.go
@@ -0,0 +1,72 @@
+package zapdriver
+
+import (
+	"go.uber.org/zap"
+	"go.uber.org/zap/zapcore"
+)
+
+const operationKey = "logging.googleapis.com/operation"
+
+// Operation adds the correct Stackdriver "operation" field.
+//
+// Additional information about a potentially long-running operation with which
+// a log entry is associated.
+//
+// see: https://cloud.google.com/logging/docs/reference/v2/rest/v2/LogEntry#LogEntryOperation
+func Operation(id, producer string, first, last bool) zap.Field {
+	op := &operation{
+		ID:       id,
+		Producer: producer,
+		First:    first,
+		Last:     last,
+	}
+
+	return zap.Object(operationKey, op)
+}
+
+// OperationStart is a convenience function for `Operation`. It should be called
+// for the first operation log.
+func OperationStart(id, producer string) zap.Field {
+	return Operation(id, producer, true, false)
+}
+
+// OperationCont is a convenience function for `Operation`. It should be called
+// for any non-start/end operation log.
+func OperationCont(id, producer string) zap.Field {
+	return Operation(id, producer, false, false)
+}
+
+// OperationEnd is a convenience function for `Operation`. It should be called
+// for the last operation log.
+func OperationEnd(id, producer string) zap.Field {
+	return Operation(id, producer, false, true)
+}
+
+// operation is the complete payload that can be interpreted by Stackdriver as
+// an operation.
+type operation struct {
+	// Optional. An arbitrary operation identifier. Log entries with the same
+	// identifier are assumed to be part of the same operation.
+	ID string `json:"id"`
+
+	// Optional. An arbitrary producer identifier. The combination of id and
+	// producer must be globally unique. Examples for producer:
+	// "MyDivision.MyBigCompany.com", "github.com/MyProject/MyApplication".
+	Producer string `json:"producer"`
+
+	// Optional. Set this to True if this is the first log entry in the operation.
+	First bool `json:"first"`
+
+	// Optional. Set this to True if this is the last log entry in the operation.
+	Last bool `json:"last"`
+}
+
+// MarshalLogObject implements zapcore.ObjectMarshaller interface.
+func (op operation) MarshalLogObject(enc zapcore.ObjectEncoder) error {
+	enc.AddString("id", op.ID)
+	enc.AddString("producer", op.Producer)
+	enc.AddBool("first", op.First)
+	enc.AddBool("last", op.Last)
+
+	return nil
+}
diff --git a/vendor/github.com/blendle/zapdriver/report.go b/vendor/github.com/blendle/zapdriver/report.go
new file mode 100644
index 000000000..1bb8ac761
--- /dev/null
+++ b/vendor/github.com/blendle/zapdriver/report.go
@@ -0,0 +1,70 @@
+package zapdriver
+
+import (
+	"runtime"
+	"strconv"
+
+	"go.uber.org/zap"
+	"go.uber.org/zap/zapcore"
+)
+
+const contextKey = "context"
+
+// ErrorReport adds the correct Stackdriver "context" field for getting the log line
+// reported as error.
+//
+// see: https://cloud.google.com/error-reporting/docs/formatting-error-messages
+func ErrorReport(pc uintptr, file string, line int, ok bool) zap.Field {
+	return zap.Object(contextKey, newReportContext(pc, file, line, ok))
+}
+
+// reportLocation is the source code location information associated with the log entry
+// for the purpose of reporting an error,
+// if any.
+type reportLocation struct {
+	File     string `json:"filePath"`
+	Line     string `json:"lineNumber"`
+	Function string `json:"functionName"`
+}
+
+// MarshalLogObject implements zapcore.ObjectMarshaller interface.
+func (location reportLocation) MarshalLogObject(enc zapcore.ObjectEncoder) error {
+	enc.AddString("filePath", location.File)
+	enc.AddString("lineNumber", location.Line)
+	enc.AddString("functionName", location.Function)
+
+	return nil
+}
+
+// reportContext is the context information attached to a log for reporting errors
+type reportContext struct {
+	ReportLocation reportLocation `json:"reportLocation"`
+}
+
+// MarshalLogObject implements zapcore.ObjectMarshaller interface.
+func (context reportContext) MarshalLogObject(enc zapcore.ObjectEncoder) error {
+	enc.AddObject("reportLocation", context.ReportLocation)
+
+	return nil
+}
+
+func newReportContext(pc uintptr, file string, line int, ok bool) *reportContext {
+	if !ok {
+		return nil
+	}
+
+	var function string
+	if fn := runtime.FuncForPC(pc); fn != nil {
+		function = fn.Name()
+	}
+
+	context := &reportContext{
+		ReportLocation: reportLocation{
+			File:     file,
+			Line:     strconv.Itoa(line),
+			Function: function,
+		},
+	}
+
+	return context
+}
diff --git a/vendor/github.com/blendle/zapdriver/service.go b/vendor/github.com/blendle/zapdriver/service.go
new file mode 100644
index 000000000..134ff3634
--- /dev/null
+++ b/vendor/github.com/blendle/zapdriver/service.go
@@ -0,0 +1,36 @@
+package zapdriver
+
+import (
+	"go.uber.org/zap"
+	"go.uber.org/zap/zapcore"
+)
+
+const serviceContextKey = "serviceContext"
+
+// ServiceContext adds the correct service information adding the log line
+// It is a required field if an error needs to be reported.
+//
+// see: https://cloud.google.com/error-reporting/reference/rest/v1beta1/ServiceContext
+// see: https://cloud.google.com/error-reporting/docs/formatting-error-messages
+func ServiceContext(name string) zap.Field {
+	return zap.Object(serviceContextKey, newServiceContext(name))
+}
+
+// serviceContext describes a running service that sends errors.
+// Currently it only describes a service name.
+type serviceContext struct {
+	Name string `json:"service"`
+}
+
+// MarshalLogObject implements zapcore.ObjectMarshaller interface.
+func (service_context serviceContext) MarshalLogObject(enc zapcore.ObjectEncoder) error {
+	enc.AddString("service", service_context.Name)
+
+	return nil
+}
+
+func newServiceContext(name string) *serviceContext {
+	return &serviceContext{
+		Name: name,
+	}
+}
diff --git a/vendor/github.com/blendle/zapdriver/source.go b/vendor/github.com/blendle/zapdriver/source.go
new file mode 100644
index 000000000..ff5ecf765
--- /dev/null
+++ b/vendor/github.com/blendle/zapdriver/source.go
@@ -0,0 +1,66 @@
+package zapdriver
+
+import (
+	"runtime"
+	"strconv"
+
+	"go.uber.org/zap"
+	"go.uber.org/zap/zapcore"
+)
+
+const sourceKey = "logging.googleapis.com/sourceLocation"
+
+// SourceLocation adds the correct Stackdriver "SourceLocation" field.
+//
+// see: https://cloud.google.com/logging/docs/reference/v2/rest/v2/LogEntry#LogEntrySourceLocation
+func SourceLocation(pc uintptr, file string, line int, ok bool) zap.Field {
+	return zap.Object(sourceKey, newSource(pc, file, line, ok))
+}
+
+// source is the source code location information associated with the log entry,
+// if any.
+type source struct {
+	// Optional. Source file name. Depending on the runtime environment, this
+	// might be a simple name or a fully-qualified name.
+	File string `json:"file"`
+
+	// Optional. Line within the source file. 1-based; 0 indicates no line number
+	// available.
+	Line string `json:"line"`
+
+	// Optional. Human-readable name of the function or method being invoked, with
+	// optional context such as the class or package name. This information may be
+	// used in contexts such as the logs viewer, where a file and line number are
+	// less meaningful.
+	//
+	// The format should be dir/package.func.
+	Function string `json:"function"`
+}
+
+// MarshalLogObject implements zapcore.ObjectMarshaller interface.
+func (source source) MarshalLogObject(enc zapcore.ObjectEncoder) error {
+	enc.AddString("file", source.File)
+	enc.AddString("line", source.Line)
+	enc.AddString("function", source.Function)
+
+	return nil
+}
+
+func newSource(pc uintptr, file string, line int, ok bool) *source {
+	if !ok {
+		return nil
+	}
+
+	var function string
+	if fn := runtime.FuncForPC(pc); fn != nil {
+		function = fn.Name()
+	}
+
+	source := &source{
+		File:     file,
+		Line:     strconv.Itoa(line),
+		Function: function,
+	}
+
+	return source
+}
diff --git a/vendor/github.com/blendle/zapdriver/trace.go b/vendor/github.com/blendle/zapdriver/trace.go
new file mode 100644
index 000000000..7e1e2e8ab
--- /dev/null
+++ b/vendor/github.com/blendle/zapdriver/trace.go
@@ -0,0 +1,24 @@
+package zapdriver
+
+import (
+	"fmt"
+
+	"go.uber.org/zap"
+)
+
+const (
+	traceKey        = "logging.googleapis.com/trace"
+	spanKey         = "logging.googleapis.com/spanId"
+	traceSampledKey = "logging.googleapis.com/trace_sampled"
+)
+
+// TraceContext adds the correct Stackdriver "trace", "span", "trace_sampled fields
+//
+// see: https://cloud.google.com/logging/docs/reference/v2/rest/v2/LogEntry
+func TraceContext(trace string, spanId string, sampled bool, projectName string) []zap.Field {
+	return []zap.Field{
+		zap.String(traceKey, fmt.Sprintf("projects/%s/traces/%s", projectName, trace)),
+		zap.String(spanKey, spanId),
+		zap.Bool(traceSampledKey, sampled),
+	}
+}
diff --git a/vendor/knative.dev/pkg/network/prober/doc.go b/vendor/knative.dev/networking/pkg/prober/doc.go
similarity index 100%
rename from vendor/knative.dev/pkg/network/prober/doc.go
rename to vendor/knative.dev/networking/pkg/prober/doc.go
diff --git a/vendor/knative.dev/pkg/network/prober/prober.go b/vendor/knative.dev/networking/pkg/prober/prober.go
similarity index 99%
rename from vendor/knative.dev/pkg/network/prober/prober.go
rename to vendor/knative.dev/networking/pkg/prober/prober.go
index 74b9de406..5b97a78f5 100644
--- a/vendor/knative.dev/pkg/network/prober/prober.go
+++ b/vendor/knative.dev/networking/pkg/prober/prober.go
@@ -1,5 +1,5 @@
 /*
-Copyright 2019 The Knative Authors
+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.
diff --git a/vendor/knative.dev/pkg/logging/config.go b/vendor/knative.dev/pkg/logging/config.go
index e1480033d..65b50395a 100644
--- a/vendor/knative.dev/pkg/logging/config.go
+++ b/vendor/knative.dev/pkg/logging/config.go
@@ -23,6 +23,7 @@ import (
 	"os"
 	"strings"
 
+	"github.com/blendle/zapdriver"
 	"go.uber.org/zap"
 	"go.uber.org/zap/zapcore"
 	corev1 "k8s.io/api/core/v1"
@@ -54,14 +55,14 @@ func NewLogger(configJSON string, levelOverride string, opts ...zap.Option) (*za
 		return enrichLoggerWithCommitID(logger), atomicLevel
 	}
 
-	loggingCfg := zap.NewProductionConfig()
+	loggingCfg := zapdriver.NewProductionConfig()
 	if levelOverride != "" {
 		if level, err := levelFromString(levelOverride); err == nil {
 			loggingCfg.Level = zap.NewAtomicLevelAt(*level)
 		}
 	}
 
-	logger, err2 := loggingCfg.Build(opts...)
+	logger, err2 := loggingCfg.Build(append(opts, zapdriver.WrapCore())...)
 	if err2 != nil {
 		panic(err2)
 	}
@@ -105,7 +106,7 @@ func newLoggerFromConfig(configJSON string, levelOverride string, opts []zap.Opt
 		}
 	}
 
-	logger, err := loggingCfg.Build(opts...)
+	logger, err := loggingCfg.Build(append(opts, zapdriver.WrapCore())...)
 	if err != nil {
 		return nil, zap.AtomicLevel{}, err
 	}
@@ -116,15 +117,13 @@ func newLoggerFromConfig(configJSON string, levelOverride string, opts []zap.Opt
 }
 
 func zapConfigFromJSON(configJSON string) (*zap.Config, error) {
-	if configJSON == "" {
-		return nil, errEmptyLoggerConfig
-	}
-
-	loggingCfg := &zap.Config{}
-	if err := json.Unmarshal([]byte(configJSON), loggingCfg); err != nil {
-		return nil, err
+	loggingCfg := zapdriver.NewProductionConfig()
+	if configJSON != "" {
+		if err := json.Unmarshal([]byte(configJSON), &loggingCfg); err != nil {
+			return nil, err
+		}
 	}
-	return loggingCfg, nil
+	return &loggingCfg, nil
 }
 
 // Config contains the configuration defined in the logging ConfigMap.
@@ -134,31 +133,9 @@ type Config struct {
 	LoggingLevel  map[string]zapcore.Level
 }
 
-const defaultZLC = `{
-  "level": "info",
-  "development": false,
-  "outputPaths": ["stdout"],
-  "errorOutputPaths": ["stderr"],
-  "encoding": "json",
-  "encoderConfig": {
-    "timeKey": "ts",
-    "levelKey": "level",
-    "nameKey": "logger",
-    "callerKey": "caller",
-    "messageKey": "msg",
-    "stacktraceKey": "stacktrace",
-    "lineEnding": "",
-    "levelEncoder": "",
-    "timeEncoder": "iso8601",
-    "durationEncoder": "",
-    "callerEncoder": ""
-  }
-}`
-
 func defaultConfig() *Config {
 	return &Config{
-		LoggingConfig: defaultZLC,
-		LoggingLevel:  make(map[string]zapcore.Level),
+		LoggingLevel: make(map[string]zapcore.Level),
 	}
 }
 
diff --git a/vendor/knative.dev/pkg/network/handlers/error.go b/vendor/knative.dev/pkg/network/handlers/error.go
deleted file mode 100644
index a6bd3bd03..000000000
--- a/vendor/knative.dev/pkg/network/handlers/error.go
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
-Copyright 2020 The Knative Authors
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package handlers
-
-import "knative.dev/pkg/network"
-
-// Error sets up a handler suitable for use with the ErrorHandler field on
-// httputil's reverse proxy, which logs /proc/net/sockstat data.
-var Error = network.ErrorHandler
diff --git a/vendor/modules.txt b/vendor/modules.txt
index ae2f927e9..45951769b 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -85,6 +85,8 @@ github.com/aws/aws-sdk-go/service/sts/stsiface
 github.com/beorn7/perks/quantile
 # github.com/blang/semver/v4 v4.0.0
 github.com/blang/semver/v4
+# github.com/blendle/zapdriver v1.3.1
+github.com/blendle/zapdriver
 # github.com/c2h5oh/datasize v0.0.0-20200112174442-28bbd4740fee
 github.com/c2h5oh/datasize
 # github.com/census-instrumentation/opencensus-proto v0.3.0
@@ -952,7 +954,7 @@ k8s.io/utils/buffer
 k8s.io/utils/integer
 k8s.io/utils/pointer
 k8s.io/utils/trace
-# knative.dev/caching v0.0.0-20201125150135-91fb5833c3c6
+# knative.dev/caching v0.0.0-20201204024709-8decac65dea7
 ## explicit
 knative.dev/caching/config
 knative.dev/caching/pkg/apis/caching
@@ -976,7 +978,7 @@ knative.dev/caching/pkg/client/listers/caching/v1alpha1
 # knative.dev/hack v0.0.0-20201201234937-fddbf732e450
 ## explicit
 knative.dev/hack
-# knative.dev/networking v0.0.0-20201125133435-4b21f11ccfa7
+# knative.dev/networking v0.0.0-20201203234509-4cd0793eed11
 ## explicit
 knative.dev/networking/config
 knative.dev/networking/pkg
@@ -1004,12 +1006,13 @@ knative.dev/networking/pkg/client/injection/informers/networking/v1alpha1/server
 knative.dev/networking/pkg/client/injection/reconciler/networking/v1alpha1/serverlessservice
 knative.dev/networking/pkg/client/listers/networking/v1alpha1
 knative.dev/networking/pkg/ingress
+knative.dev/networking/pkg/prober
 knative.dev/networking/test
 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-20201130192436-e5346d90e980
+# knative.dev/pkg v0.0.0-20201204175509-c9bac6be76ca
 ## explicit
 knative.dev/pkg/apiextensions/storageversion
 knative.dev/pkg/apiextensions/storageversion/cmd/migrate
@@ -1078,7 +1081,6 @@ knative.dev/pkg/metrics/metricstest
 knative.dev/pkg/metrics/testing
 knative.dev/pkg/network
 knative.dev/pkg/network/handlers
-knative.dev/pkg/network/prober
 knative.dev/pkg/pool
 knative.dev/pkg/profiling
 knative.dev/pkg/ptr


Test patch:
diff --git a/pkg/apis/serving/v1alpha1/domainmapping_lifecycle_test.go b/pkg/apis/serving/v1alpha1/domainmapping_lifecycle_test.go
index bbcb3ecc5..675c44836 100644
--- a/pkg/apis/serving/v1alpha1/domainmapping_lifecycle_test.go
+++ b/pkg/apis/serving/v1alpha1/domainmapping_lifecycle_test.go
@@ -71,6 +71,7 @@ func TestDomainClaimConditions(t *testing.T) {
 	dms := &DomainMappingStatus{}
 
 	dms.InitializeConditions()
+	dms.MarkTLSNotEnabled("AutoTLS not yet available for DomainMapping")
 	apistest.CheckConditionOngoing(dms, DomainMappingConditionDomainClaimed, t)
 	apistest.CheckConditionOngoing(dms, DomainMappingConditionReady, t)
 
@@ -102,6 +103,7 @@ func TestReferenceResolvedCondition(t *testing.T) {
 	dms := &DomainMappingStatus{}
 
 	dms.InitializeConditions()
+	dms.MarkTLSNotEnabled("AutoTLS not yet available for DomainMapping")
 	apistest.CheckConditionOngoing(dms, DomainMappingConditionReferenceResolved, t)
 	apistest.CheckConditionOngoing(dms, DomainMappingConditionReady, t)
 
@@ -129,10 +131,53 @@ func TestReferenceResolvedCondition(t *testing.T) {
 	apistest.CheckConditionFailed(dms, DomainMappingConditionReady, t)
 }
 
+func TestCertificateNotReady(t *testing.T) {
+	dms := &DomainMappingStatus{}
+
+	dms.InitializeConditions()
+	dms.MarkCertificateNotReady("cert pending")
+
+	apistest.CheckConditionOngoing(dms, DomainMappingConditionCertificateProvisioned, t)
+}
+
+func TestCertificateProvisionFailed(t *testing.T) {
+	dms := &DomainMappingStatus{}
+
+	dms.InitializeConditions()
+	dms.MarkCertificateProvisionFailed("cert failed")
+
+	apistest.CheckConditionFailed(dms, DomainMappingConditionCertificateProvisioned, t)
+}
+
+func TestDomainMappingNotOwnCertificate(t *testing.T) {
+	dms := &DomainMappingStatus{}
+	dms.InitializeConditions()
+	dms.MarkCertificateNotOwned("cert not owned")
+
+	apistest.CheckConditionFailed(dms, DomainMappingConditionCertificateProvisioned, t)
+}
+
+func TestDomainMappingAutoTLSNotEnabled(t *testing.T) {
+	dms := &DomainMappingStatus{}
+	dms.InitializeConditions()
+	dms.MarkTLSNotEnabled(AutoTLSNotEnabledMessage)
+
+	apistest.CheckConditionSucceeded(dms, DomainMappingConditionCertificateProvisioned, t)
+}
+
+func TestDomainMappingHTTPDowngrade(t *testing.T) {
+	dms := &DomainMappingStatus{}
+	dms.InitializeConditions()
+	dms.MarkHTTPDowngrade("downgraded to HTTP because we can't obtain cert")
+
+	apistest.CheckConditionSucceeded(dms, DomainMappingConditionCertificateProvisioned, t)
+}
+
 func TestPropagateIngressStatus(t *testing.T) {
 	dms := &DomainMappingStatus{}
 
 	dms.InitializeConditions()
+	dms.MarkTLSNotEnabled("AutoTLS not yet available for DomainMapping")
 	apistest.CheckConditionOngoing(dms, DomainMappingConditionIngressReady, t)
 	apistest.CheckConditionOngoing(dms, DomainMappingConditionReady, t)
 
diff --git a/pkg/reconciler/domainmapping/table_test.go b/pkg/reconciler/domainmapping/table_test.go
index 230ddca68..7243ae972 100644
--- a/pkg/reconciler/domainmapping/table_test.go
+++ b/pkg/reconciler/domainmapping/table_test.go
@@ -604,6 +604,7 @@ func withPropagatedStatus(status netv1alpha1.IngressStatus) domainMappingOption
 
 func withInitDomainMappingConditions(dm *v1alpha1.DomainMapping) {
 	dm.Status.InitializeConditions()
+	dm.Status.MarkTLSNotEnabled("AutoTLS for DomainMapping is not implemented")
 }
 
 func withDomainClaimNotOwned(dm *v1alpha1.DomainMapping) {
diff --git a/pkg/reconciler/route/table_test.go b/pkg/reconciler/route/table_test.go
index 3f2bcd5f1..ecc4b304b 100644
--- a/pkg/reconciler/route/table_test.go
+++ b/pkg/reconciler/route/table_test.go
@@ -381,6 +381,89 @@ func TestReconcile(t *testing.T) {
 			Eventf(corev1.EventTypeNormal, "Created", "Created placeholder service %q", "becomes-ready"),
 		},
 		Key: "default/becomes-ready",
+	}, {
+		Name: "simple route rollout when ingress becomes ready",
+		Objects: []runtime.Object{
+			Route("default", "becomes-ready", WithConfigTarget("config"),
+				WithRouteGeneration(2009), MarkIngressNotConfigured),
+			cfg("default", "config",
+				WithConfigGeneration(1), WithLatestCreated("config-00001"), WithLatestReady("config-00001")),
+			rev("default", "config", 1, MarkRevisionReady, WithRevName("config-00001")),
+			simpleReadyIngress(
+				Route("default", "becomes-ready", WithConfigTarget("config"), WithURL),
+				&traffic.Config{
+					Targets: map[string]traffic.RevisionTargets{
+						traffic.DefaultTarget: {{
+							TrafficTarget: v1.TrafficTarget{
+								ConfigurationName: "config",
+								RevisionName:      "config-00001",
+								Percent:           ptr.Int64(100),
+								LatestRevision:    ptr.Bool(true),
+							},
+						}},
+					},
+				},
+				simpleRollout("config", []traffic.RevisionRollout{{
+					RevisionName: "config-00000", Percent: 99,
+				}, {
+					RevisionName: "config-00001", Percent: 1,
+				}}, fakeCurTime.Add(-3*time.Second)),
+			),
+		},
+		WantCreates: []runtime.Object{
+			simplePlaceholderK8sService(getContext(), Route("default", "becomes-ready", WithConfigTarget("config")), ""),
+		},
+		WantUpdates: []clientgotesting.UpdateActionImpl{{
+			// ingress should be updated with the new rollout data.
+			Object: simpleReadyIngress(
+				Route("default", "becomes-ready", WithConfigTarget("config"), WithURL),
+				&traffic.Config{
+					Targets: map[string]traffic.RevisionTargets{
+						traffic.DefaultTarget: {{
+							TrafficTarget: v1.TrafficTarget{
+								ConfigurationName: "config",
+								RevisionName:      "config-00001",
+								Percent:           ptr.Int64(100),
+								LatestRevision:    ptr.Bool(true),
+							},
+						}},
+					},
+				},
+				simpleRollout("config", []traffic.RevisionRollout{{
+					RevisionName: "config-00000", Percent: 99,
+				}, {
+					RevisionName: "config-00001", Percent: 1,
+				}}, fakeCurTime.Add(-3*time.Second),
+					func(r *traffic.Rollout) {
+						// Step duration is 3s (now - (now-3s)).
+						r.Configurations[0].StepDuration = 3
+						// 120 / 3 = 40 steps. floor(100/40) = 2.
+						r.Configurations[0].StepSize = 2
+						// StepDuration is 3, and so next step is `now` + 3.
+						r.Configurations[0].NextStepTime = int(fakeCurTime.Add(3 * time.Second).UnixNano())
+					},
+				)),
+		}, {
+			Object: simpleK8sService(
+				Route("default", "becomes-ready", WithConfigTarget("config")),
+			),
+		}},
+		WantStatusUpdates: []clientgotesting.UpdateActionImpl{{
+			Object: Route("default", "becomes-ready", WithConfigTarget("config"),
+				// Populated by reconciliation when the route becomes ready.
+				WithURL, WithAddress, WithRouteConditionsAutoTLSDisabled,
+				WithRouteGeneration(2009), WithRouteObservedGeneration,
+				MarkTrafficAssigned, MarkIngressReady, WithStatusTraffic(
+					v1.TrafficTarget{
+						RevisionName:   "config-00001",
+						Percent:        ptr.Int64(100),
+						LatestRevision: ptr.Bool(true),
+					})),
+		}},
+		WantEvents: []string{
+			Eventf(corev1.EventTypeNormal, "Created", "Created placeholder service %q", "becomes-ready"),
+		},
+		Key: "default/becomes-ready",
 	}, {
 		Name: "failure creating k8s placeholder service",
 		// We induce a failure creating the placeholder service.
@@ -2603,7 +2686,10 @@ func url(s string) *apis.URL {
 	return url
 }
 
-func simpleRollout(cfg string, revs []traffic.RevisionRollout, now time.Time) IngressOption {
+type rolloutOption func(*traffic.Rollout)
+
+func simpleRollout(cfg string, revs []traffic.RevisionRollout,
+	now time.Time, ros ...rolloutOption) IngressOption {
 	return func(i *netv1alpha1.Ingress) {
 		r := &traffic.Rollout{
 			Configurations: []traffic.ConfigurationRollout{{
@@ -2613,6 +2699,9 @@ func simpleRollout(cfg string, revs []traffic.RevisionRollout, now time.Time) In
 				Revisions:         revs,
 			}},
 		}
+		for _, ro := range ros {
+			ro(r)
+		}
 		i.Annotations[networking.RolloutAnnotationKey] = func() string {
 			d, _ := json.Marshal(r)
 			return string(d)
diff --git a/pkg/reconciler/route/traffic/rollout_test.go b/pkg/reconciler/route/traffic/rollout_test.go
index 6ee8baaec..8927d5143 100644
--- a/pkg/reconciler/route/traffic/rollout_test.go
+++ b/pkg/reconciler/route/traffic/rollout_test.go
@@ -31,7 +31,7 @@ import (
 )
 
 func TestStep(t *testing.T) {
-	now := int(time.Now().UnixNano())
+	const now = 2020
 	tests := []struct {
 		name            string
 		prev, cur, want *Rollout
@@ -78,10 +78,11 @@ func TestStep(t *testing.T) {
 					RevisionName: "let-it-bleed",
 					Percent:      100,
 				}},
-				Deadline:     2006, // <- Those should be ignored.
-				LastStepTime: 2009,
+				Deadline:     2006, // <- Those should be kept.
+				NextStepTime: 2009,
 				StepDuration: 2020,
 				StartTime:    2004,
+				StepSize:     14,
 			}},
 		},
 		prev: &Rollout{
@@ -92,10 +93,6 @@ func TestStep(t *testing.T) {
 					RevisionName: "let-it-bleed",
 					Percent:      100,
 				}},
-				Deadline:     1982, // <- Those should be copied.
-				LastStepTime: 1984,
-				StepDuration: 1988,
-				StartTime:    1955,
 			}},
 		},
 		want: &Rollout{
@@ -106,10 +103,107 @@ func TestStep(t *testing.T) {
 					RevisionName: "let-it-bleed",
 					Percent:      100,
 				}},
-				Deadline:     1982,
-				LastStepTime: 1984,
-				StepDuration: 1988,
-				StartTime:    1955,
+			}},
+		},
+	}, {
+		name: "simplest, step",
+		cur: &Rollout{
+			Configurations: []ConfigurationRollout{{
+				ConfigurationName: "mick",
+				Percent:           100,
+				Revisions: []RevisionRollout{{
+					RevisionName: "let-it-bleed",
+					Percent:      100,
+				}},
+				NextStepTime: 2009,
+				StepDuration: 2020,
+				StartTime:    2004,
+				StepSize:     14,
+			}},
+		},
+		prev: &Rollout{
+			Configurations: []ConfigurationRollout{{
+				ConfigurationName: "mick",
+				Percent:           100,
+				NextStepTime:      2019,
+				StepDuration:      5,
+				StartTime:         2004,
+				StepSize:          3,
+				Revisions: []RevisionRollout{{
+					RevisionName: "their-satanic-majesties-request",
+					Percent:      95,
+				}, {
+					RevisionName: "let-it-bleed",
+					Percent:      5,
+				}},
+			}},
+		},
+		want: &Rollout{
+			Configurations: []ConfigurationRollout{{
+				ConfigurationName: "mick",
+				Percent:           100,
+				Revisions: []RevisionRollout{{
+					RevisionName: "their-satanic-majesties-request",
+					Percent:      92, // -3
+				}, {
+					RevisionName: "let-it-bleed",
+					Percent:      8, // +3
+				}},
+				NextStepTime: 2020 + 5, // now + duration.
+				StepDuration: 5,
+				StartTime:    2004,
+				StepSize:     3,
+			}},
+		},
+	}, {
+		name: "simplest, step, when stepsize=0",
+		cur: &Rollout{
+			Configurations: []ConfigurationRollout{{
+				ConfigurationName: "mick",
+				Percent:           100,
+				Revisions: []RevisionRollout{{
+					RevisionName: "let-it-bleed",
+					Percent:      100,
+				}},
+				Deadline:     2006,
+				NextStepTime: 2009,
+				StepDuration: 2020,
+				StartTime:    2004,
+				StepSize:     14,
+			}},
+		},
+		prev: &Rollout{
+			Configurations: []ConfigurationRollout{{
+				ConfigurationName: "mick",
+				Percent:           100,
+				NextStepTime:      2019, // <- Those should be reset and/or updated.
+				StartTime:         2004,
+				StepDuration:      5,
+				StepSize:          0,
+				Revisions: []RevisionRollout{{
+					RevisionName: "their-satanic-majesties-request",
+					Percent:      95,
+				}, {
+					RevisionName: "let-it-bleed",
+					Percent:      5,
+				}},
+			}},
+		},
+		want: &Rollout{
+			Configurations: []ConfigurationRollout{{
+				ConfigurationName: "mick",
+				Percent:           100,
+				Revisions: []RevisionRollout{{
+					RevisionName: "their-satanic-majesties-request",
+					Percent:      95,
+				}, {
+					RevisionName: "let-it-bleed",
+					Percent:      5,
+				}},
+				NextStepTime: 2019,
+				StartTime:    2004,
+				StepDuration: 5,
+				StepSize:     0,
 			}},
 		},
 	}, {
@@ -195,8 +289,9 @@ func TestStep(t *testing.T) {
 					Percent:      100,
 				}},
 				Deadline:     1982, // <- Those should be thrown out.
-				LastStepTime: 1984,
+				NextStepTime: 1984,
 				StepDuration: 1988,
+				StepSize:     11,
 			}},
 		},
 		want: &Rollout{
@@ -706,22 +801,58 @@ func TestObserveReady(t *testing.T) {
 	)
 	ro := Rollout{
 		Configurations: []ConfigurationRollout{{
+			Percent:           100,
 			ConfigurationName: "has-step",
 			StepDuration:      11,
 		}, {
 			ConfigurationName: "no-step-no-begin",
+			Percent:           100,
 		}, {
 			ConfigurationName: "step-begin < 1s",
 			StartTime:         200620092020,
+			Percent:           100,
 		}, {
 			ConfigurationName: "step-begin > 1s",
 			StartTime:         oldenDays,
+			Percent:           100,
+		}, {
+			ConfigurationName: "Percent not 100%",
+			StartTime:         oldenDays,
+			Percent:           50,
 		}},
 	}
 
-	want := ro
-	want.Configurations[2].StepDuration = 1
-	want.Configurations[3].StepDuration = 3 // 2.4 rounded up.
+	want := Rollout{
+		Configurations: []ConfigurationRollout{{
+			Percent:           100,
+			ConfigurationName: "has-step",
+			StepDuration:      11,
+		}, {
+			ConfigurationName: "no-step-no-begin",
+			Percent:           100,
+		}, {
+			ConfigurationName: "step-begin < 1s",
+			Percent:           100,
+			StartTime:         200620092020,
+			StepDuration:      2,
+			StepSize:          1,
+			NextStepTime:      now + int(2*time.Second),
+		}, {
+			ConfigurationName: "step-begin > 1s",
+			Percent:           100,
+			StartTime:         oldenDays,
+			StepDuration:      3,
+			StepSize:          100 / 40,
+			NextStepTime:      now + 3*int(time.Second),
+		}, {
+			ConfigurationName: "Percent not 100%",
+			Percent:           50,
+			StartTime:         oldenDays,
+			StepDuration:      3,
+			StepSize:          50 / 40,
+			NextStepTime:      now + 3*int(time.Second),
+		}},
+	}
 
 	// This works in place.
 	ro.ObserveReady(now)
@@ -981,7 +1112,7 @@ func TestJSONRoundtrip(t *testing.T) {
 			}},
 			StartTime:    1955,
 			Deadline:     2006,
-			LastStepTime: 1988,
+			NextStepTime: 1988,
 			StepDuration: 1984,
 		}, {
 			ConfigurationName: "no",
@@ -1014,3 +1145,175 @@ func TestJSONRoundtrip(t *testing.T) {
 			cmp.Diff(orig, deserialized, cmpopts.EquateEmpty()))
 	}
 }
+
+func TestStepRevisions(t *testing.T) {
+	tests := []struct {
+		name string
+		now  int
+		cfg  *ConfigurationRollout
+		want *ConfigurationRollout
+	}{{
+		name: "noop (1): too soon",
+		now:  1982,
+		cfg: &ConfigurationRollout{
+			NextStepTime: 1984,
+			StepSize:     10,
+			Revisions: []RevisionRollout{{
+				Percent: 10,
+			}, {
+				Percent: 5,
+			}, {
+				Percent: 60,
+			}},
+		},
+		want: &ConfigurationRollout{
+			NextStepTime: 1984,
+			StepSize:     10,
+			Revisions: []RevisionRollout{{
+				Percent: 10,
+			}, {
+				Percent: 5,
+			}, {
+				Percent: 60,
+			}},
+		},
+	}, {
+		name: "noop (2): done",
+		now:  1982,
+		cfg: &ConfigurationRollout{
+			NextStepTime: 1984,
+			StepDuration: 10,
+			StepSize:     10,
+			Revisions: []RevisionRollout{{
+				Percent: 10,
+			}},
+		},
+		want: &ConfigurationRollout{
+			NextStepTime: 1984,
+			StepDuration: 10,
+			StepSize:     10,
+			Revisions: []RevisionRollout{{
+				Percent: 10,
+			}},
+		},
+	}, {
+		name: "step last, exact time",
+		now:  1984,
+		cfg: &ConfigurationRollout{
+			NextStepTime: 1984,
+			StepSize:     10,
+			StepDuration: 55,
+			Percent:      90,
+			Revisions: []RevisionRollout{{
+				Percent: 30,
+			}, {
+				Percent: 60,
+			}},
+		},
+		want: &ConfigurationRollout{
+			Percent:      90,
+			NextStepTime: 1984 + 55,
+			StepDuration: 55,
+			StepSize:     10,
+			Revisions: []RevisionRollout{{
+				Percent: 20,
+			}, {
+				Percent: 70,
+			}},
+		},
+	}, {
+		name: "step last, delete some",
+		now:  1988,
+		cfg: &ConfigurationRollout{
+			Percent:      90,
+			NextStepTime: 1984,
+			StepSize:     10,
+			StepDuration: 55,
+			Revisions: []RevisionRollout{{
+				Percent: 22,
+			}, {
+				Percent: 5,
+			}, {
+				Percent: 3,
+			}, {
+				Percent: 60,
+			}},
+		},
+		want: &ConfigurationRollout{
+			Percent:      90,
+			NextStepTime: 1988 + 55,
+			StepDuration: 55,
+			StepSize:     10,
+			Revisions: []RevisionRollout{{
+				Percent: 20,
+			}, {
+				Percent: 70,
+			}},
+		},
+	}, {
+		name: "over target now",
+		now:  1988,
+		cfg: &ConfigurationRollout{
+			Percent:      15,
+			NextStepTime: 1984,
+			StepSize:     10,
+			StepDuration: 77,
+			Revisions: []RevisionRollout{{
+				Percent: 5,
+			}, {
+				Percent: 1,
+			}, {
+				Percent: 1,
+			}, {
+				Percent: 8,
+			}},
+		},
+		want: &ConfigurationRollout{
+			Percent:      15,
+			NextStepTime: 0,
+			StepDuration: 77,
+			StepSize:     10,
+			Revisions: []RevisionRollout{{
+				Percent: 15,
+			}},
+		},
+	}, {
+		name: "the very last step",
+		now:  2006,
+		cfg: &ConfigurationRollout{
+			NextStepTime: 1984,
+			Percent:      15,
+			StartTime:    1977,
+			StepDuration: 77,
+			StepSize:     8,
+			Revisions: []RevisionRollout{{
+				Percent: 5,
+			}, {
+				Percent: 1,
+			}, {
+				Percent: 1,
+			}, {
+				Percent: 8,
+			}},
+		},
+		want: &ConfigurationRollout{
+			NextStepTime: 0,
+			Percent:      15,
+			StartTime:    0,
+			StepDuration: 77,
+			StepSize:     8,
+			Revisions: []RevisionRollout{{
+				Percent: 15,
+			}},
+		},
+	}}
+
+	for _, tc := range tests {
+		t.Run(tc.name, func(t *testing.T) {
+			stepRevisions(tc.cfg, tc.now)
+			if got, want := tc.cfg, tc.want; !cmp.Equal(got, want) {
+				t.Errorf("Incorrect revision stepping: diff(-want,+got):\n%s", cmp.Diff(want, got))
+			}
+		})
+	}
+}
diff --git a/test/config/config-logging.yaml b/test/config/config-logging.yaml
index 188368cd3..cd9239452 100644
--- a/test/config/config-logging.yaml
+++ b/test/config/config-logging.yaml
@@ -29,11 +29,11 @@ data:
       "errorOutputPaths": ["stderr"],
       "encoding": "json",
       "encoderConfig": {
-        "timeKey": "ts",
-        "levelKey": "level",
+        "timeKey": "timestamp",
+        "levelKey": "severity",
         "nameKey": "logger",
         "callerKey": "caller",
-        "messageKey": "msg",
+        "messageKey": "message",
         "stacktraceKey": "stacktrace",
         "lineEnding": "",
         "levelEncoder": "",
diff --git a/test/config/security/authorization_service.yaml b/test/config/security/authorization_service.yaml
deleted file mode 100644
index fb45c3605..000000000
--- a/test/config/security/authorization_service.yaml
+++ /dev/null
@@ -1,43 +0,0 @@
-# Copyright 2020 The Knative Authors
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     https://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.
-
-apiVersion: security.istio.io/v1beta1
-kind: AuthorizationPolicy
-metadata:
-  name: deny-all
-  namespace: serving-tests
-  labels:
-    test.knative.dev/dependency: istio-sidecar
-spec:
-  {}
----
-apiVersion: security.istio.io/v1beta1
-kind: AuthorizationPolicy
-metadata:
-  name: allow-namespaces
-  namespace: serving-tests
-  labels:
-    test.knative.dev/dependency: istio-sidecar
-spec:
-  action: ALLOW
-  rules:
-  - from:
-    - source:
-       # knative-serving
-       # * This is for access to knative services from autoscaler and access via activator.
-       # istio-system
-       # * This is for access to k8s services from ingress-gateway in istio-system. e.g. conformance/ingress/*
-       # serving-tests
-       # * This is for access to k8s services from serving-tests. e.g TestVisibilitySplit
-       namespaces: ["knative-serving", "istio-system", "serving-tests"]
diff --git a/test/config/security/destinationrule.yaml b/test/config/security/destinationrule.yaml
deleted file mode 100644
index 728a57dd6..000000000
--- a/test/config/security/destinationrule.yaml
+++ /dev/null
@@ -1,39 +0,0 @@
-# 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
-#
-#     https://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.
-
-apiVersion: "networking.istio.io/v1alpha3"
-kind: "DestinationRule"
-metadata:
-  name: "mtls-services"
-  namespace: "serving-tests"
-  labels:
-    test.knative.dev/dependency: istio-sidecar
-spec:
-  host: "*.local"
-  trafficPolicy:
-    tls:
-      mode: ISTIO_MUTUAL
----
-apiVersion: "networking.istio.io/v1alpha3"
-kind: "DestinationRule"
-metadata:
-  name: "mtls-services"
-  namespace: "serving-tests-alt"
-  labels:
-    test.knative.dev/dependency: istio-sidecar
-spec:
-  host: "*.local"
-  trafficPolicy:
-    tls:
-      mode: ISTIO_MUTUAL
diff --git a/test/e2e-common.sh b/test/e2e-common.sh
index 2c65c7af0..e4f35aa59 100644
--- a/test/e2e-common.sh
+++ b/test/e2e-common.sh
@@ -429,9 +429,7 @@ function test_teardown() {
   local TEST_CONFIG_DIR=${TMP_DIR}/test/config
   echo ">> Removing test resources (${TEST_CONFIG_DIR}/)"
   ko delete --ignore-not-found=true --now -f ${TEST_CONFIG_DIR}/
-  if (( MESH )); then
-    ko delete --ignore-not-found=true --now -f ${TEST_CONFIG_DIR}/security/
-  fi
+
   echo ">> Ensuring test namespaces are clean"
   kubectl delete all --all --ignore-not-found --now --timeout 60s -n serving-tests
   kubectl delete --ignore-not-found --now --timeout 60s namespace serving-tests
diff --git a/third_party/cert-manager-latest/net-certmanager.yaml b/third_party/cert-manager-latest/net-certmanager.yaml
index 561c94430..4e51baf1c 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: "v20201127-fb3b3cd"
+    serving.knative.dev/release: "v20201208-3a1ba61"
     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: "v20201127-fb3b3cd"
+    serving.knative.dev/release: "v20201208-3a1ba61"
 webhooks:
   - admissionReviewVersions:
       - v1beta1
@@ -86,7 +86,7 @@ metadata:
   name: net-certmanager-webhook-certs
   namespace: knative-serving
   labels:
-    serving.knative.dev/release: "v20201127-fb3b3cd"
+    serving.knative.dev/release: "v20201208-3a1ba61"
 
 ---
 # Copyright 2020 The Knative Authors
@@ -109,7 +109,7 @@ metadata:
   name: config-certmanager
   namespace: knative-serving
   labels:
-    serving.knative.dev/release: "v20201127-fb3b3cd"
+    serving.knative.dev/release: "v20201208-3a1ba61"
     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: "v20201127-fb3b3cd"
+    serving.knative.dev/release: "v20201208-3a1ba61"
     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: "v20201127-fb3b3cd"
+        serving.knative.dev/release: "v20201208-3a1ba61"
     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:0f5f99a5fe5b527d8154da27ad5bf433ba615facab4f4fae08b640a9586bf4fe
+          image: gcr.io/knative-nightly/knative.dev/net-certmanager/cmd/controller@sha256:b9d86275283f61cec2a2c8d0433b3389f59742a45a47de7f2456caad4cea418b
           resources:
             requests:
               cpu: 30m
@@ -213,7 +213,7 @@ kind: Service
 metadata:
   labels:
     app: networking-certmanager
-    serving.knative.dev/release: "v20201127-fb3b3cd"
+    serving.knative.dev/release: "v20201208-3a1ba61"
     networking.knative.dev/certificate-provider: cert-manager
   name: networking-certmanager
   namespace: knative-serving
@@ -250,7 +250,7 @@ metadata:
   name: net-certmanager-webhook
   namespace: knative-serving
   labels:
-    serving.knative.dev/release: "v20201127-fb3b3cd"
+    serving.knative.dev/release: "v20201208-3a1ba61"
 spec:
   selector:
     matchLabels:
@@ -263,14 +263,14 @@ spec:
       labels:
         app: net-certmanager-webhook
         role: net-certmanager-webhook
-        serving.knative.dev/release: "v20201127-fb3b3cd"
+        serving.knative.dev/release: "v20201208-3a1ba61"
     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:40e5284e599c742e8cc439b15cc9ee49ef99c552c29fc2e6ed6934c0a94fa15e
+          image: gcr.io/knative-nightly/knative.dev/net-certmanager/cmd/webhook@sha256:255ac94c18a903babea3161e7faf506f5113fab96cd42c564811fd1ae7be1fa3
           resources:
             requests:
               cpu: 20m
@@ -329,7 +329,7 @@ metadata:
   namespace: knative-serving
   labels:
     role: net-certmanager-webhook
-    serving.knative.dev/release: "v20201127-fb3b3cd"
+    serving.knative.dev/release: "v20201208-3a1ba61"
 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 94e4b790f..5b49f8400 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:7f3205d7f42bfd2c9017eb3eab4a26a297ad74d1b8e4a3d2ce04c94281ec8a0f
+          image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:4d3c13bd373148befdd226eeb99d583ad33fee2ac275d742743a9f709be07a37
           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:7f3205d7f42bfd2c9017eb3eab4a26a297ad74d1b8e4a3d2ce04c94281ec8a0f
+          image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:4d3c13bd373148befdd226eeb99d583ad33fee2ac275d742743a9f709be07a37
           imagePullPolicy: IfNotPresent
           name: contour
           ports:
@@ -1798,7 +1798,7 @@ spec:
           args:
             - envoy
             - shutdown-manager
-          image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:7f3205d7f42bfd2c9017eb3eab4a26a297ad74d1b8e4a3d2ce04c94281ec8a0f
+          image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:4d3c13bd373148befdd226eeb99d583ad33fee2ac275d742743a9f709be07a37
           imagePullPolicy: IfNotPresent
           lifecycle:
             preStop:
@@ -1875,7 +1875,7 @@ spec:
             - --envoy-key-file=/certs/tls.key
           command:
             - contour
-          image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:7f3205d7f42bfd2c9017eb3eab4a26a297ad74d1b8e4a3d2ce04c94281ec8a0f
+          image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:4d3c13bd373148befdd226eeb99d583ad33fee2ac275d742743a9f709be07a37
           imagePullPolicy: IfNotPresent
           name: envoy-initconfig
           volumeMounts:
@@ -2097,7 +2097,7 @@ spec:
     spec:
       containers:
         - name: contour
-          image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:7f3205d7f42bfd2c9017eb3eab4a26a297ad74d1b8e4a3d2ce04c94281ec8a0f
+          image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:4d3c13bd373148befdd226eeb99d583ad33fee2ac275d742743a9f709be07a37
           imagePullPolicy: Always
           command:
             - contour
@@ -2217,7 +2217,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:7f3205d7f42bfd2c9017eb3eab4a26a297ad74d1b8e4a3d2ce04c94281ec8a0f
+          image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:4d3c13bd373148befdd226eeb99d583ad33fee2ac275d742743a9f709be07a37
           imagePullPolicy: IfNotPresent
           name: contour
           ports:
@@ -2306,7 +2306,7 @@ spec:
           args:
             - envoy
             - shutdown-manager
-          image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:7f3205d7f42bfd2c9017eb3eab4a26a297ad74d1b8e4a3d2ce04c94281ec8a0f
+          image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:4d3c13bd373148befdd226eeb99d583ad33fee2ac275d742743a9f709be07a37
           imagePullPolicy: IfNotPresent
           lifecycle:
             preStop:
@@ -2383,7 +2383,7 @@ spec:
             - --envoy-key-file=/certs/tls.key
           command:
             - contour
-          image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:7f3205d7f42bfd2c9017eb3eab4a26a297ad74d1b8e4a3d2ce04c94281ec8a0f
+          image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:4d3c13bd373148befdd226eeb99d583ad33fee2ac275d742743a9f709be07a37
           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 ff838385e..23bf5a790 100644
--- a/third_party/contour-latest/net-contour.yaml
+++ b/third_party/contour-latest/net-contour.yaml
@@ -33,7 +33,7 @@ metadata:
   namespace: knative-serving
   labels:
     networking.knative.dev/ingress-provider: contour
-    serving.knative.dev/release: "v20201201-5716387a"
+    serving.knative.dev/release: "v20201204-b12ac184"
 data:
   _example: |
     ################################
@@ -103,7 +103,7 @@ spec:
         - name: controller
           # This is the Go import path for the binary that is containerized
           # and substituted here.
-          image: gcr.io/knative-nightly/knative.dev/net-contour/cmd/controller@sha256:a79af5fd8c0089cafde29110bcd51ce38a153ec55cea39f0470e4cb61d924a32
+          image: gcr.io/knative-nightly/knative.dev/net-contour/cmd/controller@sha256:264111aa7b24595dbce9738883f668fa66f50a846ad49e3036f572d5090f8c0e
           resources:
             requests:
               cpu: 40m
diff --git a/third_party/istio-latest/net-istio.yaml b/third_party/istio-latest/net-istio.yaml
index b24ddea40..5412614a3 100644
--- a/third_party/istio-latest/net-istio.yaml
+++ b/third_party/istio-latest/net-istio.yaml
@@ -1,4 +1,4 @@
-# Generated when HEAD was 861d1ad147f4f7c0c79095447da9df8eefbf1497
+# Generated when HEAD was e87b1c73e380aa7798c73cd0a38ec32734af353a
 #
 # Copyright 2019 The Knative Authors
 #
@@ -20,7 +20,7 @@ metadata:
   # These are the permissions needed by the Istio Ingress implementation.
   name: knative-serving-istio
   labels:
-    serving.knative.dev/release: "v20201201-861d1ad1"
+    serving.knative.dev/release: "v20201208-e87b1c73"
     serving.knative.dev/controller: "true"
     networking.knative.dev/ingress-provider: istio
 rules:
@@ -50,7 +50,7 @@ metadata:
   name: knative-ingress-gateway
   namespace: knative-serving
   labels:
-    serving.knative.dev/release: "v20201201-861d1ad1"
+    serving.knative.dev/release: "v20201208-e87b1c73"
     networking.knative.dev/ingress-provider: istio
 spec:
   selector:
@@ -87,7 +87,7 @@ metadata:
   name: knative-local-gateway
   namespace: knative-serving
   labels:
-    serving.knative.dev/release: "v20201201-861d1ad1"
+    serving.knative.dev/release: "v20201208-e87b1c73"
     networking.knative.dev/ingress-provider: istio
 spec:
   selector:
@@ -106,7 +106,7 @@ metadata:
   name: knative-local-gateway
   namespace: istio-system
   labels:
-    serving.knative.dev/release: "v20201201-861d1ad1"
+    serving.knative.dev/release: "v20201208-e87b1c73"
     networking.knative.dev/ingress-provider: istio
 spec:
   type: ClusterIP
@@ -126,7 +126,7 @@ metadata:
   name: "webhook"
   namespace: "knative-serving"
   labels:
-    serving.knative.dev/release: "v20201201-861d1ad1"
+    serving.knative.dev/release: "v20201208-e87b1c73"
     networking.knative.dev/ingress-provider: istio
 spec:
   selector:
@@ -141,7 +141,7 @@ metadata:
   name: "istio-webhook"
   namespace: "knative-serving"
   labels:
-    serving.knative.dev/release: "v20201201-861d1ad1"
+    serving.knative.dev/release: "v20201208-e87b1c73"
     networking.knative.dev/ingress-provider: istio
 spec:
   selector:
@@ -170,7 +170,7 @@ kind: MutatingWebhookConfiguration
 metadata:
   name: webhook.istio.networking.internal.knative.dev
   labels:
-    serving.knative.dev/release: "v20201201-861d1ad1"
+    serving.knative.dev/release: "v20201208-e87b1c73"
     networking.knative.dev/ingress-provider: istio
 webhooks:
   - admissionReviewVersions:
@@ -206,7 +206,7 @@ kind: ValidatingWebhookConfiguration
 metadata:
   name: config.webhook.istio.networking.internal.knative.dev
   labels:
-    serving.knative.dev/release: "v20201201-861d1ad1"
+    serving.knative.dev/release: "v20201208-e87b1c73"
     networking.knative.dev/ingress-provider: istio
 webhooks:
   - admissionReviewVersions:
@@ -244,7 +244,7 @@ metadata:
   name: istio-webhook-certs
   namespace: knative-serving
   labels:
-    serving.knative.dev/release: "v20201201-861d1ad1"
+    serving.knative.dev/release: "v20201208-e87b1c73"
     networking.knative.dev/ingress-provider: istio
 
 ---
@@ -268,7 +268,7 @@ metadata:
   name: config-istio
   namespace: knative-serving
   labels:
-    serving.knative.dev/release: "v20201201-861d1ad1"
+    serving.knative.dev/release: "v20201208-e87b1c73"
     networking.knative.dev/ingress-provider: istio
 data:
   _example: |
@@ -338,7 +338,7 @@ metadata:
   name: networking-istio
   namespace: knative-serving
   labels:
-    serving.knative.dev/release: "v20201201-861d1ad1"
+    serving.knative.dev/release: "v20201208-e87b1c73"
     networking.knative.dev/ingress-provider: istio
 spec:
   selector:
@@ -354,14 +354,14 @@ spec:
         sidecar.istio.io/inject: "false"
       labels:
         app: networking-istio
-        serving.knative.dev/release: "v20201201-861d1ad1"
+        serving.knative.dev/release: "v20201208-e87b1c73"
     spec:
       serviceAccountName: controller
       containers:
         - name: networking-istio
           # This is the Go import path for the binary that is containerized
           # and substituted here.
-          image: gcr.io/knative-nightly/knative.dev/net-istio/cmd/controller@sha256:e16eb747220b1f910a4991529a88f867dc1534e099dbd7c2a7f354a3909e9479
+          image: gcr.io/knative-nightly/knative.dev/net-istio/cmd/controller@sha256:39fde178bac6f7994fe76871fae2c294bce5971627d3874be85176b421749233
           resources:
             requests:
               cpu: 30m
@@ -418,7 +418,7 @@ metadata:
   name: istio-webhook
   namespace: knative-serving
   labels:
-    serving.knative.dev/release: "v20201201-861d1ad1"
+    serving.knative.dev/release: "v20201208-e87b1c73"
     networking.knative.dev/ingress-provider: istio
 spec:
   selector:
@@ -432,14 +432,14 @@ spec:
       labels:
         app: istio-webhook
         role: istio-webhook
-        serving.knative.dev/release: "v20201201-861d1ad1"
+        serving.knative.dev/release: "v20201208-e87b1c73"
     spec:
       serviceAccountName: controller
       containers:
         - name: webhook
           # This is the Go import path for the binary that is containerized
           # and substituted here.
-          image: gcr.io/knative-nightly/knative.dev/net-istio/cmd/webhook@sha256:4f8b008593c7756c7e0fe7b58cb913e438e3688b969bce7eeeb6561916630b25
+          image: gcr.io/knative-nightly/knative.dev/net-istio/cmd/webhook@sha256:38dd61407135120cb3a452914e566e19bdc2fd90499ed1a9f32b824efa605710
           resources:
             requests:
               cpu: 20m
@@ -493,7 +493,7 @@ metadata:
   namespace: knative-serving
   labels:
     role: istio-webhook
-    serving.knative.dev/release: "v20201201-861d1ad1"
+    serving.knative.dev/release: "v20201208-e87b1c73"
     networking.knative.dev/ingress-provider: istio
 spec:
   ports:
diff --git a/third_party/kourier-latest/kourier.yaml b/third_party/kourier-latest/kourier.yaml
index 499be2cc9..866d513c8 100644
--- a/third_party/kourier-latest/kourier.yaml
+++ b/third_party/kourier-latest/kourier.yaml
@@ -18,7 +18,7 @@ metadata:
   name: kourier-system
   labels:
     networking.knative.dev/ingress-provider: kourier
-    serving.knative.dev/release: "v20201201-705eb930"
+    serving.knative.dev/release: "v20201208-105c052d"
 
 ---
 # Copyright 2020 The Knative Authors
@@ -42,7 +42,7 @@ metadata:
   namespace: knative-serving
   labels:
     networking.knative.dev/ingress-provider: kourier
-    serving.knative.dev/release: "v20201201-705eb930"
+    serving.knative.dev/release: "v20201208-105c052d"
 ---
 apiVersion: rbac.authorization.k8s.io/v1
 kind: ClusterRole
@@ -51,7 +51,7 @@ metadata:
   namespace: knative-serving
   labels:
     networking.knative.dev/ingress-provider: kourier
-    serving.knative.dev/release: "v20201201-705eb930"
+    serving.knative.dev/release: "v20201208-105c052d"
 rules:
   - apiGroups: [""]
     resources: ["events"]
@@ -78,7 +78,7 @@ metadata:
   name: 3scale-kourier
   labels:
     networking.knative.dev/ingress-provider: kourier
-    serving.knative.dev/release: "v20201201-705eb930"
+    serving.knative.dev/release: "v20201208-105c052d"
 roleRef:
   apiGroup: rbac.authorization.k8s.io
   kind: ClusterRole
@@ -110,7 +110,7 @@ metadata:
   namespace: knative-serving
   labels:
     networking.knative.dev/ingress-provider: kourier
-    serving.knative.dev/release: "v20201201-705eb930"
+    serving.knative.dev/release: "v20201208-105c052d"
 spec:
   replicas: 1
   selector:
@@ -122,7 +122,7 @@ spec:
         app: 3scale-kourier-control
     spec:
       containers:
-        - image: gcr.io/knative-nightly/knative.dev/net-kourier/cmd/kourier@sha256:35d1b40644372a71e98edf812f79806d44b167d58a3368558c1405fe1ed396d0
+        - image: gcr.io/knative-nightly/knative.dev/net-kourier/cmd/kourier@sha256:54167f3d5b79c5401c59e0747563940b9cf5d31f357bf8ed242d3955a2cd0b4a
           name: kourier-control
           env:
             - name: CERTS_SECRET_NAMESPACE
@@ -158,7 +158,7 @@ metadata:
   namespace: knative-serving
   labels:
     networking.knative.dev/ingress-provider: kourier
-    serving.knative.dev/release: "v20201201-705eb930"
+    serving.knative.dev/release: "v20201208-105c052d"
 spec:
   ports:
     - name: grpc-xds
@@ -191,7 +191,7 @@ metadata:
   namespace: kourier-system
   labels:
     networking.knative.dev/ingress-provider: kourier
-    serving.knative.dev/release: "v20201201-705eb930"
+    serving.knative.dev/release: "v20201208-105c052d"
 spec:
   selector:
     matchLabels:
@@ -257,7 +257,7 @@ metadata:
   namespace: kourier-system
   labels:
     networking.knative.dev/ingress-provider: kourier
-    serving.knative.dev/release: "v20201201-705eb930"
+    serving.knative.dev/release: "v20201208-105c052d"
 spec:
   ports:
     - name: http2
@@ -279,7 +279,7 @@ metadata:
   namespace: kourier-system
   labels:
     networking.knative.dev/ingress-provider: kourier
-    serving.knative.dev/release: "v20201201-705eb930"
+    serving.knative.dev/release: "v20201208-105c052d"
 spec:
   ports:
     - name: http2
@@ -297,7 +297,7 @@ metadata:
   namespace: kourier-system
   labels:
     networking.knative.dev/ingress-provider: kourier
-    serving.knative.dev/release: "v20201201-705eb930"
+    serving.knative.dev/release: "v20201208-105c052d"
 data:
   envoy-bootstrap.yaml: |
     dynamic_resources:
diff --git a/vendor/knative.dev/pkg/test/logstream/v2/stream.go b/vendor/knative.dev/pkg/test/logstream/v2/stream.go
index eb8ce263f..815519fed 100644
--- a/vendor/knative.dev/pkg/test/logstream/v2/stream.go
+++ b/vendor/knative.dev/pkg/test/logstream/v2/stream.go
@@ -172,12 +172,12 @@ const (
 func (s *namespaceSource) handleLine(l []byte, pod string) {
 	// This holds the standard structure of our logs.
 	var line struct {
-		Level      string    `json:"level"`
-		Timestamp  time.Time `json:"ts"`
+		Level      string    `json:"severity"`
+		Timestamp  time.Time `json:"timestamp"`
 		Controller string    `json:"knative.dev/controller"`
 		Caller     string    `json:"caller"`
 		Key        string    `json:"knative.dev/key"`
-		Message    string    `json:"msg"`
+		Message    string    `json:"message"`
 		Error      string    `json:"error"`
 
 		// TODO(mattmoor): Parse out more context.
@@ -205,20 +205,27 @@ func (s *namespaceSource) handleLine(l []byte, pod string) {
 		if site == "" {
 			site = line.Caller
 		}
-		// E 15:04:05.000 webhook-699b7b668d-9smk2 [route-controller] [default/testroute-xyz] this is my message
-		msg := fmt.Sprintf("%s %s %s [%s] [%s] %s",
-			strings.ToUpper(string(line.Level[0])),
-			line.Timestamp.Format(timeFormat),
-			pod,
-			site,
-			line.Key,
-			line.Message)
-
-		if line.Error != "" {
-			msg += " err=" + line.Error
-		}
+		func() {
+			defer func() {
+				if err := recover(); err != nil {
+					logf("Invalid log format for pod %s: %s", pod, string(l))
+				}
+			}()
+			// E 15:04:05.000 webhook-699b7b668d-9smk2 [route-controller] [default/testroute-xyz] this is my message
+			msg := fmt.Sprintf("%s %s %s [%s] [%s] %s",
+				strings.ToUpper(string(line.Level[0])),
+				line.Timestamp.Format(timeFormat),
+				pod,
+				site,
+				line.Key,
+				line.Message)
+
+			if line.Error != "" {
+				msg += " err=" + line.Error
+			}
 
-		logf(msg)
+			logf(msg)
+		}()
 	}
 }